From bea8acce1fa28bfb4df6fc3fb6f2cbd41a9ae45b Mon Sep 17 00:00:00 2001 From: andres-portainer <91705312+andres-portainer@users.noreply.github.com> Date: Mon, 25 Mar 2024 14:19:33 -0300 Subject: [PATCH] fix(kubernetes): avoid a deadlock EE-6901 (#11446) --- api/kubernetes/cli/client.go | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/api/kubernetes/cli/client.go b/api/kubernetes/cli/client.go index 9ce5366c7..70c114e54 100644 --- a/api/kubernetes/cli/client.go +++ b/api/kubernetes/cli/client.go @@ -80,22 +80,31 @@ func (factory *ClientFactory) RemoveKubeClient(endpointID portainer.EndpointID) // GetKubeClient checks if an existing client is already registered for the environment(endpoint) and returns it if one is found. // If no client is registered, it will create a new client, register it, and returns it. func (factory *ClientFactory) GetKubeClient(endpoint *portainer.Endpoint) (*KubeClient, error) { + factory.mu.Lock() + key := strconv.Itoa(int(endpoint.ID)) + if client, ok := factory.endpointClients[key]; ok { + factory.mu.Unlock() + return client, nil + } + factory.mu.Unlock() + + // EE-6901: Do not lock + client, err := factory.createCachedAdminKubeClient(endpoint) + if err != nil { + return nil, err + } + factory.mu.Lock() defer factory.mu.Unlock() - key := strconv.Itoa(int(endpoint.ID)) - client, ok := factory.endpointClients[key] - if !ok { - var err error - - client, err = factory.createCachedAdminKubeClient(endpoint) - if err != nil { - return nil, err - } - - factory.endpointClients[key] = client + // The lock was released before the client was created, + // so we need to check again + if c, ok := factory.endpointClients[key]; ok { + return c, nil } + factory.endpointClients[key] = client + return client, nil }