diff --git a/pkg/helm/actions/config.go b/pkg/helm/actions/config.go index 2f88846154..be5d2c062a 100644 --- a/pkg/helm/actions/config.go +++ b/pkg/helm/actions/config.go @@ -50,6 +50,9 @@ func GetActionConfigurations(host, ns, token string, transport *http.RoundTrippe } conf := new(action.Configuration) conf.Init(confFlags, ns, "secrets", klog.Infof) - + err = GetDefaultOCIRegistry(conf) + if err != nil { + klog.V(4).Infof("Failed to get default OCI registry: %v", err) + } return conf } diff --git a/pkg/helm/actions/get_registry.go b/pkg/helm/actions/get_registry.go new file mode 100644 index 0000000000..a1014120d3 --- /dev/null +++ b/pkg/helm/actions/get_registry.go @@ -0,0 +1,42 @@ +package actions + +import ( + "crypto/tls" + "fmt" + "net/http" + + "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/registry" +) + +// newRegistryClient is a package-level variable to allow mocking in tests +var newRegistryClient = registry.NewClient + +func GetDefaultOCIRegistry(conf *action.Configuration) error { + return GetOCIRegistry(conf, false, false) +} + +func GetOCIRegistry(conf *action.Configuration, skipTLSVerify bool, plainHTTP bool) error { + if conf == nil { + return fmt.Errorf("action configuration cannot be nil") + } + opts := []registry.ClientOption{ + registry.ClientOptDebug(false), + } + if plainHTTP { + opts = append(opts, registry.ClientOptPlainHTTP()) + } + if skipTLSVerify { + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.TLSClientConfig = &tls.Config{ + InsecureSkipVerify: true, + } + opts = append(opts, registry.ClientOptHTTPClient(&http.Client{Transport: transport})) + } + registryClient, err := newRegistryClient(opts...) + if err != nil { + return fmt.Errorf("failed to create registry client: %w", err) + } + conf.RegistryClient = registryClient + return nil +} diff --git a/pkg/helm/actions/get_registry_test.go b/pkg/helm/actions/get_registry_test.go new file mode 100644 index 0000000000..73ee7e83a3 --- /dev/null +++ b/pkg/helm/actions/get_registry_test.go @@ -0,0 +1,132 @@ +package actions + +import ( + "errors" + "io" + "testing" + + "github.com/stretchr/testify/require" + "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/chartutil" + kubefake "helm.sh/helm/v3/pkg/kube/fake" + "helm.sh/helm/v3/pkg/registry" + "helm.sh/helm/v3/pkg/storage" + "helm.sh/helm/v3/pkg/storage/driver" +) + +func TestGetDefaultOCIRegistry_Success(t *testing.T) { + store := storage.Init(driver.NewMemory()) + conf := &action.Configuration{ + RESTClientGetter: FakeConfig{}, + Releases: store, + KubeClient: &kubefake.PrintingKubeClient{Out: io.Discard}, + Capabilities: chartutil.DefaultCapabilities, + } + require.Nil(t, conf.RegistryClient, "Registry Client should be nil") + + // Store original values + originalReleases := conf.Releases + originalKubeClient := conf.KubeClient + originalCapabilities := conf.Capabilities + + err := GetDefaultOCIRegistry(conf) + require.NoError(t, err) + require.NotNil(t, conf.RegistryClient, "Registry Client should not be nil") + + // Verify other configuration fields are not modified. + require.Equal(t, originalReleases, conf.Releases, "Releases should not be modified") + require.Equal(t, originalKubeClient, conf.KubeClient, "KubeClient should not be modified") + require.Equal(t, originalCapabilities, conf.Capabilities, "Capabilities should not be modified") + +} + +func TestGetOCIRegistry_NilConfig(t *testing.T) { + err := GetOCIRegistry(nil, false, false) + require.Error(t, err) + require.Contains(t, err.Error(), "action configuration cannot be nil") +} + +func TestGetOCIRegistry_Success(t *testing.T) { + tests := []struct { + name string + skipTLSVerify bool + plainHTTP bool + }{ + { + name: "default options", + skipTLSVerify: false, + plainHTTP: false, + }, + { + name: "with skipTLSVerify", + skipTLSVerify: true, + plainHTTP: false, + }, + { + name: "with plainHTTP", + skipTLSVerify: false, + plainHTTP: true, + }, + { + name: "with both skipTLSVerify and plainHTTP", + skipTLSVerify: true, + plainHTTP: true, + }, + } + originalNewRegistryClient := newRegistryClient + defer func() { + newRegistryClient = originalNewRegistryClient + }() + + for _, tt := range tests { + newRegistryClient = func(options ...registry.ClientOption) (*registry.Client, error) { + count := 0 + if tt.plainHTTP { + count += 1 + } + if tt.skipTLSVerify { + count += 1 + } + require.Equal(t, count, len(options)-1, "Expected %d options, got %d", count, len(options)) + return ®istry.Client{}, nil + } + t.Run(tt.name, func(t *testing.T) { + store := storage.Init(driver.NewMemory()) + conf := &action.Configuration{ + RESTClientGetter: FakeConfig{}, + Releases: store, + KubeClient: &kubefake.PrintingKubeClient{Out: io.Discard}, + Capabilities: chartutil.DefaultCapabilities, + } + require.Nil(t, conf.RegistryClient, "Registry Client should be nil initially") + + err := GetOCIRegistry(conf, tt.skipTLSVerify, tt.plainHTTP) + require.NoError(t, err) + require.NotNil(t, conf.RegistryClient, "Registry Client should not be nil after GetOCIRegistry") + }) + } +} + +func TestGetOCIRegistry_NewClientError(t *testing.T) { + // Save original function and restore after test + originalNewRegistryClient := newRegistryClient + defer func() { newRegistryClient = originalNewRegistryClient }() + + // Mock newRegistryClient to return an error + newRegistryClient = func(options ...registry.ClientOption) (*registry.Client, error) { + return nil, errors.New("mock registry client error") + } + + store := storage.Init(driver.NewMemory()) + conf := &action.Configuration{ + RESTClientGetter: FakeConfig{}, + Releases: store, + KubeClient: &kubefake.PrintingKubeClient{Out: io.Discard}, + Capabilities: chartutil.DefaultCapabilities, + } + + err := GetOCIRegistry(conf, false, false) + require.Error(t, err) + require.Contains(t, err.Error(), "failed to create registry client") + require.Contains(t, err.Error(), "mock registry client error") +}