Skip to content

Commit 5b64acb

Browse files
committed
Enable multiple remote dependency
Signed-off-by: Soule BA <soule@weave.works>
1 parent 0a82a82 commit 5b64acb

7 files changed

+422
-106
lines changed

controllers/helmchart_controller.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *
510510
}
511511

512512
// Initialize the chart repository
513-
var chartRepo chart.Repository
513+
var chartRepo chart.Downloader
514514
switch repo.Spec.Type {
515515
case sourcev1.HelmRepositoryTypeOCI:
516516
if !helmreg.IsOCI(repo.Spec.URL) {
@@ -676,7 +676,7 @@ func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj
676676

677677
// Setup dependency manager
678678
dm := chart.NewDependencyManager(
679-
chart.WithRepositoryCallback(r.namespacedChartRepositoryCallback(ctx, obj.GetName(), obj.GetNamespace())),
679+
chart.WithDownloaderCallback(r.namespacedChartRepositoryCallback(ctx, obj.GetName(), obj.GetNamespace())),
680680
)
681681
defer dm.Clear()
682682

@@ -905,11 +905,11 @@ func (r *HelmChartReconciler) garbageCollect(ctx context.Context, obj *sourcev1.
905905
return nil
906906
}
907907

908-
// namespacedChartRepositoryCallback returns a chart.GetChartRepositoryCallback scoped to the given namespace.
908+
// namespacedChartRepositoryCallback returns a chart.GetChartDownloaderCallback scoped to the given namespace.
909909
// The returned callback returns a repository.ChartRepository configured with the retrieved v1beta1.HelmRepository,
910910
// or a shim with defaults if no object could be found.
911-
func (r *HelmChartReconciler) namespacedChartRepositoryCallback(ctx context.Context, name, namespace string) chart.GetChartRepositoryCallback {
912-
return func(url string) (*repository.ChartRepository, error) {
911+
func (r *HelmChartReconciler) namespacedChartRepositoryCallback(ctx context.Context, name, namespace string) chart.GetChartDownloaderCallback {
912+
return func(url string) (chart.CleanDownloader, error) {
913913
var tlsConfig *tls.Config
914914
repo, err := r.resolveDependencyRepository(ctx, url, namespace)
915915
if err != nil {

internal/helm/chart/builder_local_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func TestLocalBuilder_Build(t *testing.T) {
6767
reference Reference
6868
buildOpts BuildOptions
6969
valuesFiles []helmchart.File
70-
repositories map[string]*repository.ChartRepository
70+
repositories map[string]CleanDownloader
7171
dependentChartPaths []string
7272
wantValues chartutil.Values
7373
wantVersion string
@@ -146,7 +146,7 @@ fullnameOverride: "full-foo-name-override"`),
146146
{
147147
name: "chart with dependencies",
148148
reference: LocalReference{Path: "../testdata/charts/helmchartwithdeps"},
149-
repositories: map[string]*repository.ChartRepository{
149+
repositories: map[string]CleanDownloader{
150150
"https://grafana.github.io/helm-charts/": mockRepo(),
151151
},
152152
dependentChartPaths: []string{"./../testdata/charts/helmchart"},
@@ -165,7 +165,7 @@ fullnameOverride: "full-foo-name-override"`),
165165
{
166166
name: "v1 chart with dependencies",
167167
reference: LocalReference{Path: "../testdata/charts/helmchartwithdeps-v1"},
168-
repositories: map[string]*repository.ChartRepository{
168+
repositories: map[string]CleanDownloader{
169169
"https://grafana.github.io/helm-charts/": mockRepo(),
170170
},
171171
dependentChartPaths: []string{"../testdata/charts/helmchart-v1"},

internal/helm/chart/builder_remote.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,22 @@ import (
3636
"github.com/fluxcd/source-controller/internal/helm/chart/secureloader"
3737
)
3838

39-
// Repository is a repository.ChartRepository or a repository.OCIChartRepository.
40-
// It is used to download a chart from a remote Helm repository or OCI registry.
41-
type Repository interface {
42-
// GetChartVersion returns the repo.ChartVersion for the given name and version.
39+
// Downloader is used to download a chart from a remote Helm repository or OCI registry.
40+
type Downloader interface {
41+
// GetChartVersion returns the repo.ChartVersion for the given name and version
42+
// from the remote repository.ChartRepository.
4343
GetChartVersion(name, version string) (*repo.ChartVersion, error)
44-
// GetChartVersion returns a chart.ChartVersion from the remote repository.
44+
// DownloadChart downloads a chart from the remote Helm repository or OCI registry.
4545
DownloadChart(chart *repo.ChartVersion) (*bytes.Buffer, error)
4646
}
4747

4848
type remoteChartBuilder struct {
49-
remote Repository
49+
remote Downloader
5050
}
5151

5252
// NewRemoteBuilder returns a Builder capable of building a Helm
53-
// chart with a RemoteReference in the given repository.ChartRepository.
54-
func NewRemoteBuilder(repository Repository) Builder {
53+
// chart with a RemoteReference in the given Downloader.
54+
func NewRemoteBuilder(repository Downloader) Builder {
5555
return &remoteChartBuilder{
5656
remote: repository,
5757
}
@@ -132,7 +132,7 @@ func (b *remoteChartBuilder) Build(_ context.Context, ref Reference, p string, o
132132
return result, nil
133133
}
134134

135-
func (b *remoteChartBuilder) downloadFromRepository(remote Repository, remoteRef RemoteReference, opts BuildOptions) (*bytes.Buffer, *Build, error) {
135+
func (b *remoteChartBuilder) downloadFromRepository(remote Downloader, remoteRef RemoteReference, opts BuildOptions) (*bytes.Buffer, *Build, error) {
136136
// Get the current version for the RemoteReference
137137
cv, err := remote.GetChartVersion(remoteRef.Name, remoteRef.Version)
138138
if err != nil {

internal/helm/chart/dependency_manager.go

+33-35
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,29 @@ import (
3535
"github.com/fluxcd/source-controller/internal/helm/repository"
3636
)
3737

38-
// GetChartRepositoryCallback must return a repository.ChartRepository for the
38+
// CleanDownloader is a Downloader that cleans temporary files created by the downloader,
39+
// caching the files if the cache is configured,
40+
// and calling gc to remove unused files.
41+
type CleanDownloader interface {
42+
Clean() []error
43+
Downloader
44+
}
45+
46+
// GetChartDownloaderCallback must return a Downloader for the
3947
// URL, or an error describing why it could not be returned.
40-
type GetChartRepositoryCallback func(url string) (*repository.ChartRepository, error)
48+
type GetChartDownloaderCallback func(url string) (CleanDownloader, error)
4149

4250
// DependencyManager manages dependencies for a Helm chart.
4351
type DependencyManager struct {
44-
// repositories contains a map of repository.ChartRepository objects
52+
// downloaders contains a map of Downloader objects
4553
// indexed by their repository.NormalizeURL.
4654
// It is consulted as a lookup table for missing dependencies, based on
4755
// the (repository) URL the dependency refers to.
48-
repositories map[string]*repository.ChartRepository
56+
downloaders map[string]CleanDownloader
4957

50-
// getRepositoryCallback can be set to an on-demand GetChartRepositoryCallback
51-
// whose returned result is cached to repositories.
52-
getRepositoryCallback GetChartRepositoryCallback
58+
// getChartDownloaderCallback can be set to an on-demand GetChartDownloaderCallback
59+
// whose returned result is cached to downloaders.
60+
getChartDownloaderCallback GetChartDownloaderCallback
5361

5462
// concurrent is the number of concurrent chart-add operations during
5563
// Build. Defaults to 1 (non-concurrent).
@@ -64,16 +72,16 @@ type DependencyManagerOption interface {
6472
applyToDependencyManager(dm *DependencyManager)
6573
}
6674

67-
type WithRepositories map[string]*repository.ChartRepository
75+
type WithRepositories map[string]CleanDownloader
6876

6977
func (o WithRepositories) applyToDependencyManager(dm *DependencyManager) {
70-
dm.repositories = o
78+
dm.downloaders = o
7179
}
7280

73-
type WithRepositoryCallback GetChartRepositoryCallback
81+
type WithDownloaderCallback GetChartDownloaderCallback
7482

75-
func (o WithRepositoryCallback) applyToDependencyManager(dm *DependencyManager) {
76-
dm.getRepositoryCallback = GetChartRepositoryCallback(o)
83+
func (o WithDownloaderCallback) applyToDependencyManager(dm *DependencyManager) {
84+
dm.getChartDownloaderCallback = GetChartDownloaderCallback(o)
7785
}
7886

7987
type WithConcurrent int64
@@ -92,18 +100,12 @@ func NewDependencyManager(opts ...DependencyManagerOption) *DependencyManager {
92100
return dm
93101
}
94102

95-
// Clear iterates over the repositories, calling Unload and RemoveCache on all
96-
// items. It returns a collection of (cache removal) errors.
103+
// Clear iterates over the downloaders, calling Clean on all
104+
// items. It returns a collection of errors.
97105
func (dm *DependencyManager) Clear() []error {
98106
var errs []error
99-
for _, v := range dm.repositories {
100-
if err := v.CacheIndexInMemory(); err != nil {
101-
errs = append(errs, err)
102-
}
103-
v.Unload()
104-
if err := v.RemoveCache(); err != nil {
105-
errs = append(errs, err)
106-
}
107+
for _, v := range dm.downloaders {
108+
errs = append(errs, v.Clean()...)
107109
}
108110
return errs
109111
}
@@ -236,10 +238,6 @@ func (dm *DependencyManager) addRemoteDependency(chart *chartWithLock, dep *helm
236238
return err
237239
}
238240

239-
if err = repo.StrategicallyLoadIndex(); err != nil {
240-
return fmt.Errorf("failed to load index for '%s': %w", dep.Name, err)
241-
}
242-
243241
ver, err := repo.GetChartVersion(dep.Name, dep.Version)
244242
if err != nil {
245243
return err
@@ -259,27 +257,27 @@ func (dm *DependencyManager) addRemoteDependency(chart *chartWithLock, dep *helm
259257
return nil
260258
}
261259

262-
// resolveRepository first attempts to resolve the url from the repositories, falling back
263-
// to getRepositoryCallback if set. It returns the resolved Index, or an error.
264-
func (dm *DependencyManager) resolveRepository(url string) (_ *repository.ChartRepository, err error) {
260+
// resolveRepository first attempts to resolve the url from the downloaders, falling back
261+
// to getDownloaderCallback if set. It returns the resolved Index, or an error.
262+
func (dm *DependencyManager) resolveRepository(url string) (_ Downloader, err error) {
265263
dm.mu.Lock()
266264
defer dm.mu.Unlock()
267265

268266
nUrl := repository.NormalizeURL(url)
269-
if _, ok := dm.repositories[nUrl]; !ok {
270-
if dm.getRepositoryCallback == nil {
267+
if _, ok := dm.downloaders[nUrl]; !ok {
268+
if dm.getChartDownloaderCallback == nil {
271269
err = fmt.Errorf("no chart repository for URL '%s'", nUrl)
272270
return
273271
}
274-
if dm.repositories == nil {
275-
dm.repositories = map[string]*repository.ChartRepository{}
272+
if dm.downloaders == nil {
273+
dm.downloaders = map[string]CleanDownloader{}
276274
}
277-
if dm.repositories[nUrl], err = dm.getRepositoryCallback(nUrl); err != nil {
275+
if dm.downloaders[nUrl], err = dm.getChartDownloaderCallback(nUrl); err != nil {
278276
err = fmt.Errorf("failed to get chart repository for URL '%s': %w", nUrl, err)
279277
return
280278
}
281279
}
282-
return dm.repositories[nUrl], nil
280+
return dm.downloaders[nUrl], nil
283281
}
284282

285283
// secureLocalChartPath returns the secure absolute path of a local dependency.

0 commit comments

Comments
 (0)