@@ -54,6 +54,7 @@ import (
54
54
"github.com/fluxcd/pkg/runtime/patch"
55
55
"github.com/fluxcd/pkg/runtime/predicates"
56
56
"github.com/fluxcd/pkg/untar"
57
+ "github.com/hashicorp/go-multierror"
57
58
58
59
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
59
60
"github.com/fluxcd/source-controller/internal/cache"
@@ -510,7 +511,7 @@ func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *
510
511
}
511
512
512
513
// Initialize the chart repository
513
- var chartRepo chart.Repository
514
+ var chartRepo chart.Downloader
514
515
switch repo .Spec .Type {
515
516
case sourcev1 .HelmRepositoryTypeOCI :
516
517
if ! helmreg .IsOCI (repo .Spec .URL ) {
@@ -676,7 +677,7 @@ func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj
676
677
677
678
// Setup dependency manager
678
679
dm := chart .NewDependencyManager (
679
- chart .WithRepositoryCallback (r .namespacedChartRepositoryCallback (ctx , obj .GetName (), obj .GetNamespace ())),
680
+ chart .WithDownloaderCallback (r .namespacedChartRepositoryCallback (ctx , obj .GetName (), obj .GetNamespace ())),
680
681
)
681
682
defer dm .Clear ()
682
683
@@ -905,17 +906,21 @@ func (r *HelmChartReconciler) garbageCollect(ctx context.Context, obj *sourcev1.
905
906
return nil
906
907
}
907
908
908
- // namespacedChartRepositoryCallback returns a chart.GetChartRepositoryCallback scoped to the given namespace.
909
+ // namespacedChartRepositoryCallback returns a chart.GetChartDownloaderCallback scoped to the given namespace.
909
910
// The returned callback returns a repository.ChartRepository configured with the retrieved v1beta1.HelmRepository,
910
911
// 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 ) {
913
- var tlsConfig * tls.Config
912
+ func (r * HelmChartReconciler ) namespacedChartRepositoryCallback (ctx context.Context , name , namespace string ) chart.GetChartDownloaderCallback {
913
+ return func (url string ) (chart.CleanDownloader , string , error ) {
914
+ var (
915
+ tlsConfig * tls.Config
916
+ loginOpts []helmreg.LoginOption
917
+ credentialFile string
918
+ )
914
919
repo , err := r .resolveDependencyRepository (ctx , url , namespace )
915
920
if err != nil {
916
921
// Return Kubernetes client errors, but ignore others
917
922
if apierrs .ReasonForError (err ) != metav1 .StatusReasonUnknown {
918
- return nil , err
923
+ return nil , "" , err
919
924
}
920
925
repo = & sourcev1.HelmRepository {
921
926
Spec : sourcev1.HelmRepositorySpec {
@@ -931,35 +936,79 @@ func (r *HelmChartReconciler) namespacedChartRepositoryCallback(ctx context.Cont
931
936
}
932
937
if secret , err := r .getHelmRepositorySecret (ctx , repo ); secret != nil || err != nil {
933
938
if err != nil {
934
- return nil , err
939
+ return nil , "" , err
935
940
}
936
941
opts , err := getter .ClientOptionsFromSecret (* secret )
937
942
if err != nil {
938
- return nil , err
943
+ return nil , "" , err
939
944
}
940
945
clientOpts = append (clientOpts , opts ... )
941
946
942
947
tlsConfig , err = getter .TLSClientConfigFromSecret (* secret , repo .Spec .URL )
943
948
if err != nil {
944
- return nil , fmt .Errorf ("failed to create TLS client config for HelmRepository '%s': %w" , repo .Name , err )
949
+ return nil , "" , fmt .Errorf ("failed to create TLS client config for HelmRepository '%s': %w" , repo .Name , err )
945
950
}
946
- }
947
951
948
- chartRepo , err := repository .NewChartRepository (repo .Spec .URL , "" , r .Getters , tlsConfig , clientOpts )
949
- if err != nil {
950
- return nil , err
952
+ // Build registryClient options from secret
953
+ loginOpt , err := registry .LoginOptionFromSecret (repo .Spec .URL , * secret )
954
+ if err != nil {
955
+ return nil , "" , fmt .Errorf ("failed to create login options for HelmRepository '%s': %w" , repo .Name , err )
956
+ }
957
+
958
+ loginOpts = append ([]helmreg.LoginOption {}, loginOpt )
951
959
}
952
960
953
- // Ensure that the cache key is the same as the artifact path
954
- // otherwise don't enable caching. We don't want to cache indexes
955
- // for repositories that are not reconciled by the source controller.
956
- if repo .Status .Artifact != nil {
957
- chartRepo .CachePath = r .Storage .LocalPath (* repo .GetArtifact ())
958
- chartRepo .SetMemCache (r .Storage .LocalPath (* repo .GetArtifact ()), r .Cache , r .TTL , func (event string ) {
959
- r .IncCacheEvents (event , name , namespace )
960
- })
961
+ var chartRepo chart.CleanDownloader
962
+ if helmreg .IsOCI (repo .Spec .URL ) {
963
+ registryClient , file , err := r .RegistryClientGenerator (loginOpts != nil )
964
+ if err != nil {
965
+ return nil , "" , fmt .Errorf ("failed to create registry client for HelmRepository '%s': %w" , repo .Name , err )
966
+ }
967
+
968
+ var errs error
969
+ // Tell the chart repository to use the OCI client with the configured getter
970
+ clientOpts = append (clientOpts , helmgetter .WithRegistryClient (registryClient ))
971
+ ociChartRepo , err := repository .NewOCIChartRepository (repo .Spec .URL , repository .WithOCIGetter (r .Getters ), repository .WithOCIGetterOptions (clientOpts ), repository .WithOCIRegistryClient (registryClient ))
972
+ if err != nil {
973
+ // clean up the file
974
+ if err := os .Remove (file ); err != nil {
975
+ errs = multierror .Append (errs , err )
976
+ }
977
+ errs = multierror .Append (errs , fmt .Errorf ("failed to create OCI chart repository for HelmRepository '%s': %w" , repo .Name , err ))
978
+ return nil , "" , errs
979
+ }
980
+
981
+ // If login options are configured, use them to login to the registry
982
+ // The OCIGetter will later retrieve the stored credentials to pull the chart
983
+ if loginOpts != nil {
984
+ err = ociChartRepo .Login (loginOpts ... )
985
+ if err != nil {
986
+ return nil , "" , fmt .Errorf ("failed to login to OCI chart repository for HelmRepository '%s': %w" , repo .Name , err )
987
+ }
988
+ }
989
+
990
+ credentialFile = file
991
+ chartRepo = ociChartRepo
992
+ } else {
993
+ httpChartRepo , err := repository .NewChartRepository (repo .Spec .URL , "" , r .Getters , tlsConfig , clientOpts )
994
+ if err != nil {
995
+ return nil , "" , err
996
+ }
997
+
998
+ // Ensure that the cache key is the same as the artifact path
999
+ // otherwise don't enable caching. We don't want to cache indexes
1000
+ // for repositories that are not reconciled by the source controller.
1001
+ if repo .Status .Artifact != nil {
1002
+ httpChartRepo .CachePath = r .Storage .LocalPath (* repo .GetArtifact ())
1003
+ httpChartRepo .SetMemCache (r .Storage .LocalPath (* repo .GetArtifact ()), r .Cache , r .TTL , func (event string ) {
1004
+ r .IncCacheEvents (event , name , namespace )
1005
+ })
1006
+ }
1007
+
1008
+ chartRepo = httpChartRepo
961
1009
}
962
- return chartRepo , nil
1010
+
1011
+ return chartRepo , credentialFile , nil
963
1012
}
964
1013
}
965
1014
0 commit comments