diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 312fec39267..5ce4675d879 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -224,10 +224,18 @@ func runApply(cmd *cobra.Command, _ []string) error { return dialer.New(nil, validator, &net.Dialer{}) } newKubeUpgrader := func(w io.Writer, kubeConfigPath string, log debugLog) (kubernetesUpgrader, error) { - return kubecmd.New(w, kubeConfigPath, fileHandler, log) + kubeConfig, err := fileHandler.Read(kubeConfigPath) + if err != nil { + return nil, fmt.Errorf("reading kubeconfig: %w", err) + } + return kubecmd.New(w, kubeConfig, fileHandler, log) } newHelmClient := func(kubeConfigPath string, log debugLog) (helmApplier, error) { - return helm.NewClient(kubeConfigPath, log) + kubeConfig, err := fileHandler.Read(kubeConfigPath) + if err != nil { + return nil, fmt.Errorf("reading kubeconfig: %w", err) + } + return helm.NewClient(kubeConfig, log) } upgradeID := generateUpgradeID(upgradeCmdKindApply) diff --git a/cli/internal/cmd/status.go b/cli/internal/cmd/status.go index 72c23992233..642cfc5f62e 100644 --- a/cli/internal/cmd/status.go +++ b/cli/internal/cmd/status.go @@ -47,7 +47,12 @@ func runStatus(cmd *cobra.Command, _ []string) error { fileHandler := file.NewHandler(afero.NewOsFs()) - helmClient, err := helm.NewReleaseVersionClient(constants.AdminConfFilename, log) + kubeConfig, err := fileHandler.Read(constants.AdminConfFilename) + if err != nil { + return fmt.Errorf("reading kubeconfig: %w", err) + } + + helmClient, err := helm.NewReleaseVersionClient(kubeConfig, log) if err != nil { return fmt.Errorf("setting up helm client: %w", err) } @@ -56,7 +61,7 @@ func runStatus(cmd *cobra.Command, _ []string) error { } fetcher := attestationconfigapi.NewFetcher() - kubeClient, err := kubecmd.New(cmd.OutOrStdout(), constants.AdminConfFilename, fileHandler, log) + kubeClient, err := kubecmd.New(cmd.OutOrStdout(), kubeConfig, fileHandler, log) if err != nil { return fmt.Errorf("setting up kubernetes client: %w", err) } diff --git a/cli/internal/cmd/upgradecheck.go b/cli/internal/cmd/upgradecheck.go index 36b8022d42f..06e7399c547 100644 --- a/cli/internal/cmd/upgradecheck.go +++ b/cli/internal/cmd/upgradecheck.go @@ -116,10 +116,18 @@ func runUpgradeCheck(cmd *cobra.Command, _ []string) error { } defer cleanUp() - kubeChecker, err := kubecmd.New(cmd.OutOrStdout(), constants.AdminConfFilename, fileHandler, log) + kubeConfig, err := fileHandler.Read(constants.AdminConfFilename) + if err != nil { + return fmt.Errorf("reading kubeconfig: %w", err) + } + kubeChecker, err := kubecmd.New(cmd.OutOrStdout(), kubeConfig, fileHandler, log) if err != nil { return fmt.Errorf("setting up Kubernetes upgrader: %w", err) } + helmClient, err := helm.NewReleaseVersionClient(kubeConfig, log) + if err != nil { + return fmt.Errorf("setting up helm client: %w", err) + } versionfetcher := versionsapi.NewFetcher() rekor, err := sigstore.NewRekor() @@ -137,6 +145,7 @@ func runUpgradeCheck(cmd *cobra.Command, _ []string) error { rekor: rekor, flags: flags, cliVersion: constants.BinaryVersion(), + helmClient: helmClient, log: log, versionsapi: versionfetcher, }, @@ -327,6 +336,7 @@ type versionCollector struct { flags upgradeCheckFlags versionsapi versionFetcher cliVersion consemver.Semver + helmClient *helm.ReleaseVersionClient log debugLog } @@ -368,12 +378,7 @@ type currentVersionInfo struct { } func (v *versionCollector) currentVersions(ctx context.Context) (currentVersionInfo, error) { - helmClient, err := helm.NewReleaseVersionClient(constants.AdminConfFilename, v.log) - if err != nil { - return currentVersionInfo{}, fmt.Errorf("setting up helm client: %w", err) - } - - serviceVersions, err := helmClient.Versions() + serviceVersions, err := v.helmClient.Versions() if err != nil { return currentVersionInfo{}, fmt.Errorf("getting service versions: %w", err) } diff --git a/internal/helm/BUILD.bazel b/internal/helm/BUILD.bazel index 64a488adfe5..96f45ae9138 100644 --- a/internal/helm/BUILD.bazel +++ b/internal/helm/BUILD.bazel @@ -473,13 +473,18 @@ go_library( "//internal/state", "//internal/versions", "@com_github_pkg_errors//:errors", + "@io_k8s_apimachinery//pkg/api/meta", + "@io_k8s_client_go//discovery", + "@io_k8s_client_go//discovery/cached/memory", + "@io_k8s_client_go//rest", + "@io_k8s_client_go//restmapper", + "@io_k8s_client_go//tools/clientcmd", "@io_k8s_client_go//util/retry", "@sh_helm_helm//pkg/ignore", "@sh_helm_helm_v3//pkg/action", "@sh_helm_helm_v3//pkg/chart", "@sh_helm_helm_v3//pkg/chart/loader", "@sh_helm_helm_v3//pkg/chartutil", - "@sh_helm_helm_v3//pkg/cli", "@sh_helm_helm_v3//pkg/release", ], ) diff --git a/internal/helm/action.go b/internal/helm/action.go index fc49dffb437..0500e1df73d 100644 --- a/internal/helm/action.go +++ b/internal/helm/action.go @@ -14,9 +14,14 @@ import ( "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/discovery" + "k8s.io/client-go/discovery/cached/memory" + "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" + "k8s.io/client-go/tools/clientcmd" "helm.sh/helm/v3/pkg/action" - "helm.sh/helm/v3/pkg/cli" ) const applyRetryInterval = 30 * time.Second @@ -29,12 +34,9 @@ type applyAction interface { } // newActionConfig creates a new action configuration for helm actions. -func newActionConfig(kubeconfig string, logger debugLog) (*action.Configuration, error) { - settings := cli.New() - settings.KubeConfig = kubeconfig - +func newActionConfig(kubeConfig []byte, logger debugLog) (*action.Configuration, error) { actionConfig := &action.Configuration{} - if err := actionConfig.Init(settings.RESTClientGetter(), constants.HelmNamespace, + if err := actionConfig.Init(&clientGetter{kubeConfig: kubeConfig}, constants.HelmNamespace, "secret", logger.Debugf); err != nil { return nil, err } @@ -180,3 +182,37 @@ func saveChart(release release, chartsDir string, fileHandler file.Handler) erro return nil } + +type clientGetter struct { + kubeConfig []byte +} + +func (c *clientGetter) ToRESTConfig() (*rest.Config, error) { + return clientcmd.RESTConfigFromKubeConfig(c.kubeConfig) +} + +func (c *clientGetter) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { + config, err := c.ToRESTConfig() + if err != nil { + return nil, err + } + discoveryClient, err := discovery.NewDiscoveryClientForConfig(config) + if err != nil { + return nil, err + } + return memory.NewMemCacheClient(discoveryClient), nil +} + +func (c *clientGetter) ToRESTMapper() (meta.RESTMapper, error) { + discoveryClient, err := c.ToDiscoveryClient() + if err != nil { + return nil, err + } + mapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) + expander := restmapper.NewShortcutExpander(mapper, discoveryClient) + return expander, nil +} + +func (c *clientGetter) ToRawKubeConfigLoader() clientcmd.ClientConfig { + return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(&clientcmd.ClientConfigLoadingRules{}, &clientcmd.ConfigOverrides{}) +} diff --git a/internal/helm/helm.go b/internal/helm/helm.go index 2307cd98d04..542df8e48f2 100644 --- a/internal/helm/helm.go +++ b/internal/helm/helm.go @@ -61,12 +61,12 @@ type Client struct { } // NewClient returns a new Helm client. -func NewClient(kubeConfigPath string, log debugLog) (*Client, error) { - kubeClient, err := kubectl.NewFromConfig(kubeConfigPath) +func NewClient(kubeConfig []byte, log debugLog) (*Client, error) { + kubeClient, err := kubectl.NewFromConfig(kubeConfig) if err != nil { return nil, fmt.Errorf("initializing kubectl: %w", err) } - actionConfig, err := newActionConfig(kubeConfigPath, log) + actionConfig, err := newActionConfig(kubeConfig, log) if err != nil { return nil, fmt.Errorf("creating action config: %w", err) } diff --git a/internal/helm/versionlister.go b/internal/helm/versionlister.go index ae45e2d7663..526cfebe383 100644 --- a/internal/helm/versionlister.go +++ b/internal/helm/versionlister.go @@ -22,8 +22,8 @@ type ReleaseVersionClient struct { } // NewReleaseVersionClient creates a new ReleaseVersionClient. -func NewReleaseVersionClient(kubeConfigPath string, log debugLog) (*ReleaseVersionClient, error) { - config, err := newActionConfig(kubeConfigPath, log) +func NewReleaseVersionClient(kubeConfig []byte, log debugLog) (*ReleaseVersionClient, error) { + config, err := newActionConfig(kubeConfig, log) if err != nil { return nil, err } diff --git a/internal/kubecmd/kubecmd.go b/internal/kubecmd/kubecmd.go index 76cc51ee6da..d90e5218298 100644 --- a/internal/kubecmd/kubecmd.go +++ b/internal/kubecmd/kubecmd.go @@ -81,8 +81,8 @@ type KubeCmd struct { } // New returns a new KubeCmd. -func New(outWriter io.Writer, kubeConfigPath string, fileHandler file.Handler, log debugLog) (*KubeCmd, error) { - client, err := kubectl.NewFromConfig(kubeConfigPath) +func New(outWriter io.Writer, kubeConfig []byte, fileHandler file.Handler, log debugLog) (*KubeCmd, error) { + client, err := kubectl.NewFromConfig(kubeConfig) if err != nil { return nil, fmt.Errorf("creating kubectl client: %w", err) } diff --git a/internal/kubernetes/kubectl/kubectl.go b/internal/kubernetes/kubectl/kubectl.go index d2058a255b6..f6148808242 100644 --- a/internal/kubernetes/kubectl/kubectl.go +++ b/internal/kubernetes/kubectl/kubectl.go @@ -48,14 +48,10 @@ func NewUninitialized() *Kubectl { } // NewFromConfig returns a Kubectl client using the given kubeconfig. -func NewFromConfig(kubeconfigPath string) (*Kubectl, error) { - clientConfig, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) - if err != nil { - return nil, fmt.Errorf("creating k8s client from kubeconfig: %w", err) - } - k := &Kubectl{} - if err := k.initialize(clientConfig); err != nil { - return nil, fmt.Errorf("initializing kubectl: %w", err) +func NewFromConfig(kubeconfig []byte) (*Kubectl, error) { + k := NewUninitialized() + if err := k.Initialize(kubeconfig); err != nil { + return nil, err } return k, nil }