test: build e2e cleanup client from helm's own settings

Overriding only HELM_KUBECONTEXT still left the cleanup client able to
diverge from the helm subprocesses, which also honor HELM_KUBEAPISERVER,
HELM_KUBETOKEN, HELM_KUBECAFILE, HELM_KUBETLS_SERVER_NAME and
HELM_KUBEINSECURE_SKIP_TLS_VERIFY. Any of those could send the namespace
delete to a different endpoint, where NotFound reads as success and the
namespace leaks.

Resolve the client through cli.New().RESTClientGetter() instead, so it is
built exactly the way the subprocesses build theirs and stays in step
without mirroring each variable by hand.

Signed-off-by: Terry Howe <thowe@nvidia.com>
pull/31590/head
Terry Howe 2 weeks ago
parent b7bf07cdfd
commit 17440df526
No known key found for this signature in database

@ -65,10 +65,6 @@ const (
envKubernetes = "HELM_E2E_KUBERNETES" envKubernetes = "HELM_E2E_KUBERNETES"
// envNamespace is the namespace the Kubernetes tests install into. // envNamespace is the namespace the Kubernetes tests install into.
envNamespace = "HELM_E2E_NAMESPACE" envNamespace = "HELM_E2E_NAMESPACE"
// envHelmKubeContext is helm's own kubecontext variable. The tests do not
// set it, but helm subprocesses inherit it, so cleanup performed through
// the Kubernetes API has to honor it too.
envHelmKubeContext = "HELM_KUBECONTEXT"
) )
// harness carries the resolved configuration shared by the end-to-end tests. // harness carries the resolved configuration shared by the end-to-end tests.

@ -37,7 +37,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"helm.sh/helm/v4/pkg/cli"
) )
// TestOCIRegistryPushPull pushes chart archives to the configured OCI registry // TestOCIRegistryPushPull pushes chart archives to the configured OCI registry
@ -370,21 +371,15 @@ func archiveFiles(t *testing.T, path string) map[string][]byte {
func deleteNamespace(t *testing.T, namespace string) { func deleteNamespace(t *testing.T, namespace string) {
t.Helper() t.Helper()
// Select the same context the helm subprocesses used. They inherit // Resolve the cluster exactly the way the helm subprocesses do. They read
// HELM_KUBECONTEXT from the environment, so without this override the // their Kubernetes configuration from the environment (HELM_KUBECONTEXT,
// releases would be installed into one cluster while the namespace was // HELM_KUBEAPISERVER, HELM_KUBETOKEN, HELM_KUBECAFILE and friends), so
// deleted from whichever cluster the kubeconfig's current-context names. // building this client any other way risks installing releases into one
// A delete against the wrong cluster returns NotFound, which would look // cluster and sending the namespace delete to another. Such a delete
// like success while leaking the namespace. // returns NotFound, which would look like success while leaking the
overrides := &clientcmd.ConfigOverrides{} // namespace. Going through helm's own settings keeps the two in step
if kubeContext := os.Getenv(envHelmKubeContext); kubeContext != "" { // without having to mirror each variable here.
overrides.CurrentContext = kubeContext cfg, err := cli.New().RESTClientGetter().ToRESTConfig()
}
cfg, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
clientcmd.NewDefaultClientConfigLoadingRules(),
overrides,
).ClientConfig()
if err != nil { if err != nil {
t.Errorf("building kube client config to delete namespace %s: %v", namespace, err) t.Errorf("building kube client config to delete namespace %s: %v", namespace, err)
return return

Loading…
Cancel
Save