From 74b1dd04d1fea0be99dc3a64598e0ff624885f3e Mon Sep 17 00:00:00 2001 From: Oscar Zhou <100548325+oscarzhou-portainer@users.noreply.github.com> Date: Tue, 30 Sep 2025 18:00:12 +1300 Subject: [PATCH] fix(k8s): memory leak during k8s stack deployment [BE-12281] (#1264) --- pkg/libkubectl/client.go | 3 +- pkg/libkubectl/client_test.go | 56 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 pkg/libkubectl/client_test.go diff --git a/pkg/libkubectl/client.go b/pkg/libkubectl/client.go index 0229c8167..e9a889559 100644 --- a/pkg/libkubectl/client.go +++ b/pkg/libkubectl/client.go @@ -46,7 +46,8 @@ func generateConfigFlags(token, server, namespace, kubeconfigPath string, insecu return nil, errors.New("must provide either a kubeconfig path or a server") } - configFlags := genericclioptions.NewConfigFlags(true) + // Pass 'false' to usePersistentConfig to prevent memory leaks. + configFlags := genericclioptions.NewConfigFlags(false) if namespace != "" { configFlags.Namespace = &namespace } diff --git a/pkg/libkubectl/client_test.go b/pkg/libkubectl/client_test.go new file mode 100644 index 000000000..4f2eae750 --- /dev/null +++ b/pkg/libkubectl/client_test.go @@ -0,0 +1,56 @@ +package libkubectl + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestGenerateConfigFlags(t *testing.T) { + config, err := generateConfigFlags("test-token", "https://api.example.com", "", "", false) + require.NoError(t, err) + require.NotNil(t, config) + + _, err = generateConfigFlags("test-token", "", "", "", false) + require.Error(t, err) +} + +func TestNewClient(t *testing.T) { + // Test with server and token + client, err := NewClient(&ClientAccess{ + Token: "test-token", + ServerUrl: "https://api.example.com", + }, "", "", false) + require.NoError(t, err) + require.NotNil(t, client) + + // Verify the client has the expected structure for a Kubernetes client + require.NotNil(t, client.factory, "Expected factory to be set") + require.NotNil(t, client.streams, "Expected streams to be set") + require.NotNil(t, client.out, "Expected output buffer to be set") +} + +func TestNewClientWithKubeconfig(t *testing.T) { + // Test with kubeconfig path + client, err := NewClient(&ClientAccess{ + Token: "", + ServerUrl: "", + }, "test-namespace", "/path/to/kubeconfig", true) + require.NoError(t, err) + require.NotNil(t, client) + + // Verify the client has the expected structure for a Kubernetes client + require.NotNil(t, client.factory, "Expected factory to be set") + require.NotNil(t, client.streams, "Expected streams to be set") + require.NotNil(t, client.out, "Expected output buffer to be set") +} + +func TestNewClientError(t *testing.T) { + // Test error case when both server and kubeconfig are empty + client, err := NewClient(&ClientAccess{ + Token: "", + ServerUrl: "", + }, "", "", false) + require.Error(t, err) + require.Nil(t, client) +}