You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
portainer/api/platform/service.go

119 lines
2.9 KiB

package platform
import (
"errors"
"fmt"
"slices"
"strings"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/internal/endpointutils"
"github.com/rs/zerolog/log"
)
type Service interface {
GetLocalEnvironment() (*portainer.Endpoint, error)
GetPlatform() (ContainerPlatform, error)
}
type service struct {
dataStore dataservices.DataStore
environment *portainer.Endpoint
platform ContainerPlatform
}
func NewService(dataStore dataservices.DataStore) (Service, error) {
return &service{
dataStore: dataStore,
}, 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.environment = environment
service.platform = platform
}
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.environment = environment
service.platform = platform
}
return service.platform, nil
}
var platformToEndpointType = map[ContainerPlatform][]portainer.EndpointType{
PlatformDocker: {portainer.AgentOnDockerEnvironment, portainer.DockerEnvironment},
PlatformKubernetes: {portainer.KubernetesLocalEnvironment},
}
func guessLocalEnvironment(dataStore dataservices.DataStore) (*portainer.Endpoint, ContainerPlatform, error) {
platform := DetermineContainerPlatform()
if !slices.Contains([]ContainerPlatform{PlatformDocker, PlatformKubernetes}, platform) {
log.Debug().
Str("platform", string(platform)).
Msg("environment not supported for upgrade")
return nil, "", nil
}
endpoints, err := dataStore.Endpoint().Endpoints()
if err != nil {
return nil, "", fmt.Errorf("failed to retrieve environments: %w", err)
}
// skip guessing when there is no endpoints registered in DB
if len(endpoints) == 0 {
return nil, "", nil
}
endpointTypes, ok := platformToEndpointType[platform]
if !ok {
return nil, "", errors.New("failed to determine environment type")
}
for _, endpoint := range endpoints {
if slices.Contains(endpointTypes, endpoint.Type) {
if platform != PlatformDocker {
return &endpoint, platform, nil
}
dockerPlatform := checkDockerEnvTypeForUpgrade(&endpoint)
if dockerPlatform != "" {
return &endpoint, dockerPlatform, nil
}
}
}
return nil, "", errors.New("failed to find local environment")
}
func checkDockerEnvTypeForUpgrade(environment *portainer.Endpoint) ContainerPlatform {
if endpointutils.IsLocalEndpoint(environment) { // standalone
return PlatformDockerStandalone
}
if strings.HasPrefix(environment.URL, "tcp://tasks.") { // swarm
return PlatformDockerSwarm
}
return ""
}