From 8d1c90f912b10ab59c64dacc9c5b2c9a290202c7 Mon Sep 17 00:00:00 2001 From: andres-portainer <91705312+andres-portainer@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:37:50 -0300 Subject: [PATCH] fix(platform): fix a data race in GetPlatform() BE-11522 (#253) --- api/platform/service.go | 63 ++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/api/platform/service.go b/api/platform/service.go index 42f751545..628e1cf9b 100644 --- a/api/platform/service.go +++ b/api/platform/service.go @@ -5,10 +5,12 @@ import ( "fmt" "slices" "strings" + "sync" portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/dataservices" "github.com/portainer/portainer/api/internal/endpointutils" + "github.com/rs/zerolog/log" ) @@ -21,38 +23,46 @@ type service struct { dataStore dataservices.DataStore environment *portainer.Endpoint platform ContainerPlatform + mu sync.Mutex } -func NewService(dataStore dataservices.DataStore) (Service, error) { +func NewService(dataStore dataservices.DataStore) (*service, error) { + return &service{dataStore: dataStore}, nil +} - return &service{ - dataStore: dataStore, - }, nil +func (service *service) loadEnvAndPlatform() error { + if service.environment != nil { + return nil + } + + environment, platform, err := guessLocalEnvironment(service.dataStore) + if err != nil { + return err + } + + service.environment = environment + service.platform = platform + + return nil } func (service *service) GetLocalEnvironment() (*portainer.Endpoint, error) { - if service.environment == nil { - environment, platform, err := guessLocalEnvironment(service.dataStore) - if err != nil { - return nil, err - } + service.mu.Lock() + defer service.mu.Unlock() - service.environment = environment - service.platform = platform + if err := service.loadEnvAndPlatform(); err != nil { + return nil, err } return service.environment, nil } func (service *service) GetPlatform() (ContainerPlatform, error) { - if service.environment == nil { - environment, platform, err := guessLocalEnvironment(service.dataStore) - if err != nil { - return "", err - } + service.mu.Lock() + defer service.mu.Unlock() - service.environment = environment - service.platform = platform + if err := service.loadEnvAndPlatform(); err != nil { + return "", err } return service.platform, nil @@ -90,15 +100,16 @@ func guessLocalEnvironment(dataStore dataservices.DataStore) (*portainer.Endpoin } for _, endpoint := range endpoints { - if slices.Contains(endpointTypes, endpoint.Type) { - if platform != PlatformDocker { - return &endpoint, platform, nil - } + if !slices.Contains(endpointTypes, endpoint.Type) { + continue + } - dockerPlatform := checkDockerEnvTypeForUpgrade(&endpoint) - if dockerPlatform != "" { - return &endpoint, dockerPlatform, nil - } + if platform != PlatformDocker { + return &endpoint, platform, nil + } + + if dockerPlatform := checkDockerEnvTypeForUpgrade(&endpoint); dockerPlatform != "" { + return &endpoint, dockerPlatform, nil } }