pkg/api/orchestrators.go (177 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. package api import ( "strconv" "strings" "github.com/Azure/aks-engine-azurestack/pkg/api/common" "github.com/Azure/aks-engine-azurestack/pkg/api/vlabs" "github.com/blang/semver" "github.com/pkg/errors" ) type orchestratorsFunc func(*OrchestratorProfile, bool, bool) ([]*OrchestratorVersionProfile, error) var funcmap map[string]orchestratorsFunc var versionsMap map[string][]string var versionsMapAzureStack map[string][]string func init() { funcmap = map[string]orchestratorsFunc{ Kubernetes: kubernetesInfo, } versionsMap = map[string][]string{ Kubernetes: common.GetAllSupportedKubernetesVersions(true, false, false), } versionsMapAzureStack = map[string][]string{ Kubernetes: common.GetAllSupportedKubernetesVersions(true, false, true), } } func validate(orchestrator, version string) (string, error) { switch { case strings.EqualFold(orchestrator, Kubernetes): return Kubernetes, nil case orchestrator == "": if version != "" { return "", errors.Errorf("Must specify orchestrator for version '%s'", version) } default: return "", errors.Errorf("Unsupported orchestrator '%s'", orchestrator) } return "", nil } func isVersionSupported(csOrch *OrchestratorProfile, isAzureStackCloud bool) bool { supported := false versions := versionsMap[csOrch.OrchestratorType] if isAzureStackCloud { versions = versionsMapAzureStack[csOrch.OrchestratorType] } for _, version := range versions { if version == csOrch.OrchestratorVersion { supported = true break } } return supported } // GetOrchestratorVersionProfileListVLabs returns vlabs OrchestratorVersionProfileList object per (optionally) specified orchestrator and version func GetOrchestratorVersionProfileListVLabs(orchestrator, version string, windows bool, azureEnv string) (*vlabs.OrchestratorVersionProfileList, error) { apiOrchs, err := GetOrchestratorVersionProfileList(orchestrator, version, windows, azureEnv) if err != nil { return nil, err } orchList := &vlabs.OrchestratorVersionProfileList{} orchList.Orchestrators = []*vlabs.OrchestratorVersionProfile{} for _, orch := range apiOrchs { orchList.Orchestrators = append(orchList.Orchestrators, ConvertOrchestratorVersionProfileToVLabs(orch)) } return orchList, nil } // GetOrchestratorVersionProfileList returns a list of unversioned OrchestratorVersionProfile objects per (optionally) specified orchestrator and version func GetOrchestratorVersionProfileList(orchestrator, version string, windows bool, azureEnv string) ([]*OrchestratorVersionProfile, error) { var err error isAzureStackCloud := (strings.EqualFold(azureEnv, AzureStackCloud)) if orchestrator, err = validate(orchestrator, version); err != nil { return nil, err } orchs := []*OrchestratorVersionProfile{} if len(orchestrator) == 0 { // return all orchestrators for _, f := range funcmap { var arr []*OrchestratorVersionProfile arr, err = f(&OrchestratorProfile{}, false, isAzureStackCloud) if err != nil { return nil, err } orchs = append(orchs, arr...) } } else { if orchs, err = funcmap[orchestrator](&OrchestratorProfile{OrchestratorType: orchestrator, OrchestratorVersion: version}, windows, isAzureStackCloud); err != nil { return nil, err } } return orchs, nil } // GetOrchestratorVersionProfile returns orchestrator info for upgradable container service func GetOrchestratorVersionProfile(orch *OrchestratorProfile, hasWindows bool, isAzureStackCloud bool) (*OrchestratorVersionProfile, error) { if orch.OrchestratorVersion == "" { return nil, errors.New("Missing Orchestrator Version") } switch orch.OrchestratorType { case Kubernetes: arr, err := funcmap[orch.OrchestratorType](orch, hasWindows, isAzureStackCloud) if err != nil { return nil, err } // has to be exactly one element per specified orchestrator/version if len(arr) != 1 { return nil, errors.New("Ambiguous Orchestrator Versions") } return arr[0], nil default: return nil, errors.Errorf("Upgrade operation is not supported for '%s'", orch.OrchestratorType) } } func kubernetesInfo(csOrch *OrchestratorProfile, hasWindows bool, isAzureStackCloud bool) ([]*OrchestratorVersionProfile, error) { orchs := []*OrchestratorVersionProfile{} if csOrch.OrchestratorVersion == "" { // get info for all supported versions for _, ver := range common.GetAllSupportedKubernetesVersions(false, hasWindows, isAzureStackCloud) { upgrades, err := kubernetesUpgrades(&OrchestratorProfile{OrchestratorVersion: ver}, hasWindows, isAzureStackCloud) if err != nil { return nil, err } orchs = append(orchs, &OrchestratorVersionProfile{ OrchestratorProfile: OrchestratorProfile{ OrchestratorType: Kubernetes, OrchestratorVersion: ver, }, Default: ver == common.GetDefaultKubernetesVersion(hasWindows, isAzureStackCloud), Upgrades: upgrades, }) } } else { if !isVersionSupported(csOrch, isAzureStackCloud) { return nil, errors.Errorf("Kubernetes version %s is not supported", csOrch.OrchestratorVersion) } upgrades, err := kubernetesUpgrades(csOrch, hasWindows, isAzureStackCloud) if err != nil { return nil, err } orchs = append(orchs, &OrchestratorVersionProfile{ OrchestratorProfile: OrchestratorProfile{ OrchestratorType: Kubernetes, OrchestratorVersion: csOrch.OrchestratorVersion, }, Default: csOrch.OrchestratorVersion == common.GetDefaultKubernetesVersion(hasWindows, isAzureStackCloud), Upgrades: upgrades, }) } return orchs, nil } func kubernetesUpgrades(csOrch *OrchestratorProfile, hasWindows bool, isAzureStackCloud bool) ([]*OrchestratorProfile, error) { ret := []*OrchestratorProfile{} upgradeVersions, err := getKubernetesAvailableUpgradeVersions(csOrch.OrchestratorVersion, common.GetAllSupportedKubernetesVersions(false, hasWindows, isAzureStackCloud)) if err != nil { return nil, err } for _, ver := range upgradeVersions { ret = append(ret, &OrchestratorProfile{ OrchestratorType: Kubernetes, OrchestratorVersion: ver, }) } return ret, nil } func getKubernetesAvailableUpgradeVersions(orchestratorVersion string, supportedVersions []string) ([]string, error) { var skipUpgradeMinor string currentVer, err := semver.Make(orchestratorVersion) if err != nil { return nil, err } versionsGT := common.GetVersionsGt(supportedVersions, orchestratorVersion, false, true) if len(versionsGT) != 0 { min, err := semver.Make(common.GetMinVersion(versionsGT, true)) if err != nil { return nil, err } if currentVer.Major >= min.Major && currentVer.Minor+1 < min.Minor { skipUpgradeMinor = strconv.FormatUint(min.Major, 10) + "." + strconv.FormatUint(min.Minor+1, 10) + ".0-alpha.0" } else { skipUpgradeMinor = strconv.FormatUint(currentVer.Major, 10) + "." + strconv.FormatUint(currentVer.Minor+2, 10) + ".0-alpha.0" } return common.GetVersionsBetween(supportedVersions, orchestratorVersion, skipUpgradeMinor, false, true), nil } return []string{}, nil }