Skip to content

Commit a0ce7e2

Browse files
committed
Empty docker creds file errors out on Helm 4
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
1 parent ca5e1a9 commit a0ce7e2

File tree

6 files changed

+54
-158
lines changed

6 files changed

+54
-158
lines changed

internal/controller/helmchart_controller.go

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import (
7070
serror "github.com/fluxcd/source-controller/internal/error"
7171
"github.com/fluxcd/source-controller/internal/helm/chart"
7272
"github.com/fluxcd/source-controller/internal/helm/getter"
73+
"github.com/fluxcd/source-controller/internal/helm/registry"
7374
"github.com/fluxcd/source-controller/internal/helm/repository"
7475
soci "github.com/fluxcd/source-controller/internal/oci"
7576
scosign "github.com/fluxcd/source-controller/internal/oci/cosign"
@@ -132,10 +133,9 @@ type HelmChartReconciler struct {
132133
kuberecorder.EventRecorder
133134
helper.Metrics
134135

135-
RegistryClientGenerator RegistryClientGeneratorFunc
136-
Storage *storage.Storage
137-
Getters helmgetter.Providers
138-
ControllerName string
136+
Storage *storage.Storage
137+
Getters helmgetter.Providers
138+
ControllerName string
139139

140140
Cache *cache.Cache
141141
TTL time.Duration
@@ -148,7 +148,7 @@ type HelmChartReconciler struct {
148148
// and an optional file name.
149149
// The file is used to store the registry client credentials.
150150
// The caller is responsible for deleting the file.
151-
type RegistryClientGeneratorFunc func(tlsConfig *tls.Config, isLogin, insecure bool) (*helmreg.Client, string, error)
151+
type RegistryClientGeneratorFunc func(tlsConfig *tls.Config, isLogin, insecure bool) (*helmreg.Client, error)
152152

153153
func (r *HelmChartReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
154154
return r.SetupWithManagerAndOptions(ctx, mgr, HelmChartReconcilerOptions{})
@@ -557,7 +557,7 @@ func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *
557557
// this is needed because otherwise the credentials are stored in ~/.docker/config.json.
558558
// TODO@souleb: remove this once the registry move to Oras v2
559559
// or rework to enable reusing credentials to avoid the unneccessary handshake operations
560-
registryClient, credentialsFile, err := r.RegistryClientGenerator(clientOpts.TlsConfig, clientOpts.MustLoginToRegistry(), repo.Spec.Insecure)
560+
registryClient, err := registry.NewClient(clientOpts.TlsConfig, repo.Spec.Insecure)
561561
if err != nil {
562562
e := serror.NewGeneric(
563563
fmt.Errorf("failed to construct Helm client: %w", err),
@@ -567,15 +567,6 @@ func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *
567567
return sreconcile.ResultEmpty, e
568568
}
569569

570-
if credentialsFile != "" {
571-
defer func() {
572-
if err := os.Remove(credentialsFile); err != nil {
573-
r.eventLogf(ctx, obj, corev1.EventTypeWarning, meta.FailedReason,
574-
"failed to delete temporary credentials file: %s", err)
575-
}
576-
}()
577-
}
578-
579570
var verifiers []soci.Verifier
580571
if obj.Spec.Verify != nil {
581572
provider := obj.Spec.Verify.Provider
@@ -1027,7 +1018,7 @@ func (r *HelmChartReconciler) namespacedChartRepositoryCallback(ctx context.Cont
10271018

10281019
var chartRepo repository.Downloader
10291020
if helmreg.IsOCI(normalizedURL) {
1030-
registryClient, credentialsFile, err := r.RegistryClientGenerator(clientOpts.TlsConfig, clientOpts.MustLoginToRegistry(), obj.Spec.Insecure)
1021+
registryClient, err := registry.NewClient(clientOpts.TlsConfig, obj.Spec.Insecure)
10311022
if err != nil {
10321023
return nil, fmt.Errorf("failed to create registry client: %w", err)
10331024
}
@@ -1038,17 +1029,9 @@ func (r *HelmChartReconciler) namespacedChartRepositoryCallback(ctx context.Cont
10381029
ociChartRepo, err := repository.NewOCIChartRepository(normalizedURL, repository.WithOCIGetter(r.Getters),
10391030
repository.WithOCIGetterOptions(getterOpts),
10401031
repository.WithOCIRegistryClient(registryClient),
1041-
repository.WithCertificatesStore(certsTmpDir),
1042-
repository.WithCredentialsFile(credentialsFile))
1032+
repository.WithCertificatesStore(certsTmpDir))
10431033
if err != nil {
1044-
errs = append(errs, fmt.Errorf("failed to create OCI chart repository: %w", err))
1045-
// clean up the credentialsFile
1046-
if credentialsFile != "" {
1047-
if err := os.Remove(credentialsFile); err != nil {
1048-
errs = append(errs, err)
1049-
}
1050-
}
1051-
return nil, kerrors.NewAggregate(errs)
1034+
return nil, fmt.Errorf("failed to create OCI chart repository: %w", err)
10521035
}
10531036

10541037
// If login options are configured, use them to login to the registry

internal/controller/helmchart_controller_test.go

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ import (
7575
serror "github.com/fluxcd/source-controller/internal/error"
7676
"github.com/fluxcd/source-controller/internal/helm/chart"
7777
"github.com/fluxcd/source-controller/internal/helm/chart/secureloader"
78-
"github.com/fluxcd/source-controller/internal/helm/registry"
7978
"github.com/fluxcd/source-controller/internal/oci"
8079
snotation "github.com/fluxcd/source-controller/internal/oci/notation"
8180
sreconcile "github.com/fluxcd/source-controller/internal/reconcile"
@@ -1371,12 +1370,11 @@ func TestHelmChartReconciler_buildFromOCIHelmRepository(t *testing.T) {
13711370
}
13721371

13731372
r := &HelmChartReconciler{
1374-
Client: clientBuilder.Build(),
1375-
EventRecorder: record.NewFakeRecorder(32),
1376-
Getters: testGetters,
1377-
Storage: st,
1378-
RegistryClientGenerator: registry.ClientGenerator,
1379-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
1373+
Client: clientBuilder.Build(),
1374+
EventRecorder: record.NewFakeRecorder(32),
1375+
Getters: testGetters,
1376+
Storage: st,
1377+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
13801378
}
13811379

13821380
repository := &sourcev1.HelmRepository{
@@ -1615,11 +1613,10 @@ func TestHelmChartReconciler_buildFromTarballArtifact(t *testing.T) {
16151613
WithScheme(testEnv.Scheme()).
16161614
WithStatusSubresource(&sourcev1.HelmChart{}).
16171615
Build(),
1618-
EventRecorder: record.NewFakeRecorder(32),
1619-
Storage: st,
1620-
Getters: testGetters,
1621-
RegistryClientGenerator: registry.ClientGenerator,
1622-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
1616+
EventRecorder: record.NewFakeRecorder(32),
1617+
Storage: st,
1618+
Getters: testGetters,
1619+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
16231620
}
16241621

16251622
obj := &sourcev1.HelmChart{
@@ -2687,11 +2684,10 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_authStrategy(t *testing.T) {
26872684
}
26882685

26892686
r := &HelmChartReconciler{
2690-
Client: clientBuilder.Build(),
2691-
EventRecorder: record.NewFakeRecorder(32),
2692-
Getters: testGetters,
2693-
RegistryClientGenerator: registry.ClientGenerator,
2694-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
2687+
Client: clientBuilder.Build(),
2688+
EventRecorder: record.NewFakeRecorder(32),
2689+
Getters: testGetters,
2690+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
26952691
}
26962692

26972693
var b chart.Build
@@ -2844,12 +2840,11 @@ func TestHelmChartRepository_reconcileSource_verifyOCISourceSignature_keyless(t
28442840
clientBuilder.WithObjects(repository)
28452841

28462842
r := &HelmChartReconciler{
2847-
Client: clientBuilder.Build(),
2848-
EventRecorder: record.NewFakeRecorder(32),
2849-
Getters: testGetters,
2850-
Storage: testStorage,
2851-
RegistryClientGenerator: registry.ClientGenerator,
2852-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
2843+
Client: clientBuilder.Build(),
2844+
EventRecorder: record.NewFakeRecorder(32),
2845+
Getters: testGetters,
2846+
Storage: testStorage,
2847+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
28532848
}
28542849

28552850
obj := &sourcev1.HelmChart{
@@ -3150,12 +3145,11 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureNotation(t *t
31503145
clientBuilder.WithObjects(repository, secret, caSecret)
31513146

31523147
r := &HelmChartReconciler{
3153-
Client: clientBuilder.Build(),
3154-
EventRecorder: record.NewFakeRecorder(32),
3155-
Getters: testGetters,
3156-
Storage: st,
3157-
RegistryClientGenerator: registry.ClientGenerator,
3158-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
3148+
Client: clientBuilder.Build(),
3149+
EventRecorder: record.NewFakeRecorder(32),
3150+
Getters: testGetters,
3151+
Storage: st,
3152+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
31593153
}
31603154

31613155
obj := &sourcev1.HelmChart{
@@ -3402,12 +3396,11 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureCosign(t *tes
34023396
clientBuilder.WithObjects(repository, secret)
34033397

34043398
r := &HelmChartReconciler{
3405-
Client: clientBuilder.Build(),
3406-
EventRecorder: record.NewFakeRecorder(32),
3407-
Getters: testGetters,
3408-
Storage: st,
3409-
RegistryClientGenerator: registry.ClientGenerator,
3410-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
3399+
Client: clientBuilder.Build(),
3400+
EventRecorder: record.NewFakeRecorder(32),
3401+
Getters: testGetters,
3402+
Storage: st,
3403+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
34113404
}
34123405

34133406
obj := &sourcev1.HelmChart{

internal/helm/chart/dependency_manager_test.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,7 @@ func (g *mockGetter) Get(_ string, _ ...helmgetter.Option) (*bytes.Buffer, error
7676
func TestDependencyManager_Clear(t *testing.T) {
7777
g := NewWithT(t)
7878

79-
file, err := os.CreateTemp("", "")
80-
g.Expect(err).ToNot(HaveOccurred())
81-
ociRepoWithCreds, err := repository.NewOCIChartRepository("oci://example.com", repository.WithCredentialsFile(file.Name()))
79+
ociRepoWithCreds, err := repository.NewOCIChartRepository("oci://example.com")
8280
g.Expect(err).ToNot(HaveOccurred())
8381

8482
downloaders := map[string]repository.Downloader{
@@ -99,14 +97,9 @@ func TestDependencyManager_Clear(t *testing.T) {
9997
case *repository.ChartRepository:
10098
g.Expect(v.Index).To(BeNil())
10199
case *repository.OCIChartRepository:
102-
g.Expect(v.HasCredentials()).To(BeFalse())
100+
// nothing to check
103101
}
104102
}
105-
106-
if _, err := os.Stat(file.Name()); !errors.Is(err, os.ErrNotExist) {
107-
err = os.Remove(file.Name())
108-
g.Expect(err).ToNot(HaveOccurred())
109-
}
110103
}
111104

112105
func TestDependencyManager_Build(t *testing.T) {

internal/helm/registry/client.go

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,48 +20,11 @@ import (
2020
"crypto/tls"
2121
"io"
2222
"net/http"
23-
"os"
2423

2524
"helm.sh/helm/v4/pkg/registry"
26-
"k8s.io/apimachinery/pkg/util/errors"
2725
)
2826

29-
// ClientGenerator generates a registry client and a temporary credential file.
30-
// The client is meant to be used for a single reconciliation.
31-
// The file is meant to be used for a single reconciliation and deleted after.
32-
func ClientGenerator(tlsConfig *tls.Config, isLogin, insecureHTTP bool) (*registry.Client, string, error) {
33-
if isLogin {
34-
// create a temporary file to store the credentials
35-
// this is needed because otherwise the credentials are stored in ~/.docker/config.json.
36-
credentialsFile, err := os.CreateTemp("", "credentials")
37-
if err != nil {
38-
return nil, "", err
39-
}
40-
41-
var errs []error
42-
rClient, err := newClient(credentialsFile.Name(), tlsConfig, insecureHTTP)
43-
if err != nil {
44-
errs = append(errs, err)
45-
// attempt to delete the temporary file
46-
if credentialsFile != nil {
47-
err := os.Remove(credentialsFile.Name())
48-
if err != nil {
49-
errs = append(errs, err)
50-
}
51-
}
52-
return nil, "", errors.NewAggregate(errs)
53-
}
54-
return rClient, credentialsFile.Name(), nil
55-
}
56-
57-
rClient, err := newClient("", tlsConfig, insecureHTTP)
58-
if err != nil {
59-
return nil, "", err
60-
}
61-
return rClient, "", nil
62-
}
63-
64-
func newClient(credentialsFile string, tlsConfig *tls.Config, insecureHTTP bool) (*registry.Client, error) {
27+
func NewClient(tlsConfig *tls.Config, insecureHTTP bool) (*registry.Client, error) {
6528
opts := []registry.ClientOption{
6629
registry.ClientOptWriter(io.Discard),
6730
}
@@ -75,9 +38,5 @@ func newClient(credentialsFile string, tlsConfig *tls.Config, insecureHTTP bool)
7538
Transport: t,
7639
}))
7740
}
78-
if credentialsFile != "" {
79-
opts = append(opts, registry.ClientOptCredentialsFile(credentialsFile))
80-
}
81-
8241
return registry.NewClient(opts...)
8342
}

internal/helm/repository/oci_chart_repository.go

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"bytes"
2121
"context"
2222
"crypto/tls"
23-
"errors"
2423
"fmt"
2524
"net/url"
2625
"os"
@@ -67,9 +66,6 @@ type OCIChartRepository struct {
6766
// RegistryClient is a client to use while downloading tags or charts from a registry.
6867
RegistryClient RegistryClient
6968

70-
// credentialsFile is a temporary credentials file to use while downloading tags or charts from a registry.
71-
credentialsFile string
72-
7369
// certificatesStore is a temporary store to use while downloading tags or charts from a registry.
7470
certificatesStore string
7571

@@ -127,14 +123,6 @@ func WithOCIGetterOptions(getterOpts []getter.Option) OCIChartRepositoryOption {
127123
}
128124
}
129125

130-
// WithCredentialsFile returns a ChartRepositoryOption that will set the credentials file
131-
func WithCredentialsFile(credentialsFile string) OCIChartRepositoryOption {
132-
return func(r *OCIChartRepository) error {
133-
r.credentialsFile = credentialsFile
134-
return nil
135-
}
136-
}
137-
138126
// WithCertificatesStore returns a ChartRepositoryOption that will set the certificates store
139127
func WithCertificatesStore(store string) OCIChartRepositoryOption {
140128
return func(r *OCIChartRepository) error {
@@ -281,31 +269,13 @@ func (r *OCIChartRepository) Logout() error {
281269
return nil
282270
}
283271

284-
// HasCredentials returns true if the OCIChartRepository has credentials.
285-
func (r *OCIChartRepository) HasCredentials() bool {
286-
return r.credentialsFile != ""
287-
}
288-
289-
// Clear deletes the OCI registry credentials file.
272+
// Clear deletes the OCI registry certificates store.
290273
func (r *OCIChartRepository) Clear() error {
291-
var errs error
292-
// clean the credentials file if it exists
293-
if r.credentialsFile != "" {
294-
if err := os.Remove(r.credentialsFile); err != nil {
295-
errs = errors.Join(errs, err)
296-
}
274+
if s := r.certificatesStore; s != "" {
275+
r.certificatesStore = ""
276+
return os.RemoveAll(s)
297277
}
298-
r.credentialsFile = ""
299-
300-
// clean the certificates store if it exists
301-
if r.certificatesStore != "" {
302-
if err := os.RemoveAll(r.certificatesStore); err != nil {
303-
errs = errors.Join(errs, err)
304-
}
305-
}
306-
r.certificatesStore = ""
307-
308-
return errs
278+
return nil
309279
}
310280

311281
// getLastMatchingVersionOrConstraint returns the last version that matches the given version string.

main.go

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ import (
6363
"github.com/fluxcd/source-controller/internal/controller"
6464
"github.com/fluxcd/source-controller/internal/features"
6565
"github.com/fluxcd/source-controller/internal/helm"
66-
"github.com/fluxcd/source-controller/internal/helm/registry"
6766
)
6867

6968
const controllerName = "source-controller"
@@ -259,16 +258,15 @@ func main() {
259258
}
260259

261260
if err := (&controller.HelmChartReconciler{
262-
Client: mgr.GetClient(),
263-
RegistryClientGenerator: registry.ClientGenerator,
264-
Storage: storage,
265-
Getters: getters,
266-
EventRecorder: eventRecorder,
267-
Metrics: metrics,
268-
ControllerName: controllerName,
269-
Cache: helmIndexCache,
270-
TTL: helmIndexCacheItemTTL,
271-
CacheRecorder: cacheRecorder,
261+
Client: mgr.GetClient(),
262+
Storage: storage,
263+
Getters: getters,
264+
EventRecorder: eventRecorder,
265+
Metrics: metrics,
266+
ControllerName: controllerName,
267+
Cache: helmIndexCache,
268+
TTL: helmIndexCacheItemTTL,
269+
CacheRecorder: cacheRecorder,
272270
}).SetupWithManagerAndOptions(ctx, mgr, controller.HelmChartReconcilerOptions{
273271
RateLimiter: helper.GetRateLimiter(rateLimiterOptions),
274272
}); err != nil {

0 commit comments

Comments
 (0)