orchestrator upgrade: use ContainerService's OrchestratorProfile as a GoalState (#1407)

* eliminated duplicated structures
* added run-time check for upgradable clusters
* updated k8sUpgrade.json
* replaced proprietary implementation of orch. versions with semver package  
* updated API loader for the upgrade operation in ContainerService
* added pre-validation for the upgrade
* removed experimental flag from the upgrade operation
* deleted redundant UpgradeContainerService. Use OrchestratorProfile instead
This commit is contained in:
dmitsh 2017-09-11 18:41:42 -07:00 коммит произвёл GitHub
Родитель 95dca7c7e3
Коммит 4e734f08d4
31 изменённых файлов: 594 добавлений и 799 удалений

Просмотреть файл

@ -4,7 +4,7 @@ import (
"encoding/json"
"fmt"
"github.com/Azure/acs-engine/pkg/acsengine"
"github.com/Azure/acs-engine/pkg/api"
"github.com/spf13/cobra"
)
@ -40,7 +40,7 @@ func newOrchestratorsCmd() *cobra.Command {
}
func (oc *orchestratorsCmd) run(cmd *cobra.Command, args []string) error {
orchs, err := acsengine.GetOrchestratorVersionProfileList(oc.orchestrator, oc.release)
orchs, err := api.GetOrchestratorVersionProfileList(oc.orchestrator, oc.release)
if err != nil {
return err
}

Просмотреть файл

@ -1,8 +1,6 @@
package cmd
import (
"os"
"github.com/Azure/acs-engine/pkg/armhelpers"
"github.com/Azure/go-autorest/autorest/azure"
@ -42,10 +40,7 @@ func NewRootCmd() *cobra.Command {
rootCmd.AddCommand(newGenerateCmd())
rootCmd.AddCommand(newDeployCmd())
rootCmd.AddCommand(newOrchestratorsCmd())
if val := os.Getenv("ACSENGINE_EXPERIMENTAL_FEATURES"); val == "1" {
rootCmd.AddCommand(newUpgradeCmd())
}
rootCmd.AddCommand(newUpgradeCmd())
return rootCmd
}

Просмотреть файл

@ -8,6 +8,7 @@ import (
"path"
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/api/vlabs"
"github.com/Azure/acs-engine/pkg/armhelpers"
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/Azure/acs-engine/pkg/operations/kubernetesupgrade"
@ -34,11 +35,9 @@ type upgradeCmd struct {
apiVersion string
// derived
upgradeContainerService *api.UpgradeContainerService
upgradeAPIVersion string
client armhelpers.ACSEngineClient
locale *gotext.Locale
nameSuffix string
client armhelpers.ACSEngineClient
locale *gotext.Locale
nameSuffix string
}
// NewUpgradeCmd run a command to upgrade a Kubernetes cluster
@ -96,7 +95,7 @@ func (uc *upgradeCmd) validate(cmd *cobra.Command, args []string) {
// load apimodel from the deployment directory
apiModelPath := path.Join(uc.deploymentDirectory, "apimodel.json")
if _, err := os.Stat(apiModelPath); os.IsNotExist(err) {
if _, err = os.Stat(apiModelPath); os.IsNotExist(err) {
log.Fatalf("specified api model does not exist (%s)", apiModelPath)
}
@ -109,19 +108,17 @@ func (uc *upgradeCmd) validate(cmd *cobra.Command, args []string) {
if err != nil {
log.Fatalf("error parsing the api model: %s", err.Error())
}
if _, err := os.Stat(uc.upgradeModelFile); os.IsNotExist(err) {
if _, err = os.Stat(uc.upgradeModelFile); os.IsNotExist(err) {
log.Fatalf("specified upgrade model file does not exist (%s)", uc.upgradeModelFile)
}
upgradeapiloader := &api.UpgradeApiloader{
Translator: &i18n.Translator{
Locale: uc.locale,
},
}
uc.upgradeContainerService, uc.upgradeAPIVersion, err = upgradeapiloader.LoadUpgradeContainerServiceFromFile(uc.upgradeModelFile)
// validate upgrade and set the Goal State
contents, err := ioutil.ReadFile(uc.upgradeModelFile)
if err != nil {
log.Fatalf("error parsing the upgrade api model: %s", err.Error())
log.Fatalf("error reading file %s: %s", uc.upgradeModelFile, err.Error())
}
if err = apiloader.UpdateContainerServiceForUpgrade(contents, vlabs.APIVersion, uc.containerService, true); err != nil {
log.Fatalf("error loading ContainerService: %s", err.Error())
}
uc.client, err = uc.authArgs.getClient()
@ -135,7 +132,7 @@ func (uc *upgradeCmd) validate(cmd *cobra.Command, args []string) {
// user could have specified a name suffix instead of using the default
// value generated by ACS Engine
templatePath := path.Join(uc.deploymentDirectory, "azuredeploy.json")
contents, _ := ioutil.ReadFile(templatePath)
contents, _ = ioutil.ReadFile(templatePath)
var template interface{}
json.Unmarshal(contents, &template)
@ -159,7 +156,7 @@ func (uc *upgradeCmd) run(cmd *cobra.Command, args []string) error {
}
if err := upgradeCluster.UpgradeCluster(uc.authArgs.SubscriptionID, uc.resourceGroupName,
uc.containerService, uc.upgradeContainerService, uc.nameSuffix); err != nil {
uc.containerService, uc.nameSuffix); err != nil {
log.Fatalf("Error upgrading cluster: %s \n", err.Error())
}

Просмотреть файл

@ -3,13 +3,15 @@
## Overview
This document describes how to upgrade kubernetes version on a running cluster.
The upgrade is an **experimental** feature, and currently under development.
Supported scenario: upgrade from v1.5 to v1.6
Supported scenarios:
- upgrade from v1.5 to v1.6
- upgrade from v1.6 to v1.7
The cluster definition file examples demonstrate initial cluster configurations:
- **kubernetes1.5.json** - Kubernetes cluster v1.5 with Linux agent pool
- **kubernetes1.5-win.json** - Kubernetes cluster v1.5 with Windows agent pool
- **kubernetes1.5-hybrid.json** - Kubernetes cluster v1.5 with Linux and Windows agent pools
- **kubernetes1.6.json** - Kubernetes cluster v1.6 with Linux agent pool
The ***.env** files are used to set desired kubernetes version and instruct test framework to invoke post-deploy instructions implemented in **k8s-upgrade.sh** script.

Просмотреть файл

@ -2,8 +2,6 @@
set -e
export ACSENGINE_EXPERIMENTAL_FEATURES=1
# some tests set EXPECTED_ORCHESTRATOR_RELEASE in .env files
ENV_FILE="${CLUSTER_DEFINITION}.env"
if [ -e "${ENV_FILE}" ]; then
@ -17,11 +15,8 @@ K8S_UPGRADE_CONF="$OUTPUT/k8sUpgrade.json"
cat > $K8S_UPGRADE_CONF <<END
{
"apiVersion": "vlabs",
"orchestratorProfile": {
"orchestratorType": "Kubernetes",
"orchestratorRelease": "${EXPECTED_ORCHESTRATOR_RELEASE}"
}
"orchestratorType": "Kubernetes",
"orchestratorRelease": "${EXPECTED_ORCHESTRATOR_RELEASE}"
}
END

Просмотреть файл

@ -89,17 +89,6 @@ const (
DCOSPublicAgent DCOSNodeType = "DCOSPublicAgent"
)
const (
// SwarmVersion is the Swarm orchestrator version
SwarmVersion = "swarm:1.1.0"
// SwarmDockerComposeVersion is the Docker Compose version
SwarmDockerComposeVersion = "1.6.2"
// DockerCEVersion is the DockerCE orchestrator version
DockerCEVersion = "17.03.*"
// DockerCEDockerComposeVersion is the Docker Compose version
DockerCEDockerComposeVersion = "1.14.0"
)
// KubeConfigs represents Docker images used for Kubernetes components based on Kubernetes releases (major.minor)
// For instance, Kubernetes release "1.7" would contain the version "1.7.2"
var KubeConfigs = map[string]map[string]string{

Просмотреть файл

@ -784,10 +784,10 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat
return GetMasterAgentAllowedSizes()
},
"getSwarmVersions": func() string {
return getSwarmVersions(SwarmVersion, SwarmDockerComposeVersion)
return getSwarmVersions(api.SwarmVersion, api.SwarmDockerComposeVersion)
},
"GetSwarmModeVersions": func() string {
return getSwarmVersions(DockerCEVersion, DockerCEDockerComposeVersion)
return getSwarmVersions(api.DockerCEVersion, api.DockerCEDockerComposeVersion)
},
"GetSizeMap": func() string {
if t.ClassicMode {

Просмотреть файл

@ -1,277 +0,0 @@
package acsengine
import (
"fmt"
"strconv"
"strings"
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/api/common"
)
type orchestratorsFunc func(*api.OrchestratorEdition) ([]*api.OrchestratorVersionProfile, error)
var funcmap map[string]orchestratorsFunc
type versionNumber struct {
major, minor, patch int64
}
func (v *versionNumber) parse(ver string) (err error) {
arr := strings.Split(ver, ".")
if len(arr) != 3 {
return fmt.Errorf("Illegal version format '%s'", ver)
}
if v.major, err = strconv.ParseInt(arr[0], 10, 32); err != nil {
return
}
if v.minor, err = strconv.ParseInt(arr[1], 10, 32); err != nil {
return
}
if v.patch, err = strconv.ParseInt(arr[2], 10, 32); err != nil {
return
}
return nil
}
func (v *versionNumber) greaterThan(o *versionNumber) bool {
// check major
if v.major != o.major {
return v.major > o.major
}
// same major; check minor
if v.minor != o.minor {
return v.minor > o.minor
}
// same minor; check patch
return v.patch > o.patch
}
func init() {
funcmap = map[string]orchestratorsFunc{
api.Kubernetes: kubernetesInfo,
api.DCOS: dcosInfo,
api.Swarm: swarmInfo,
api.SwarmMode: dockerceInfo,
}
}
func validate(orchestrator, release string) (string, error) {
switch {
case strings.EqualFold(orchestrator, api.Kubernetes):
return api.Kubernetes, nil
case strings.EqualFold(orchestrator, api.DCOS):
return api.DCOS, nil
case strings.EqualFold(orchestrator, api.Swarm):
return api.Swarm, nil
case strings.EqualFold(orchestrator, api.SwarmMode):
return api.SwarmMode, nil
case len(orchestrator) == 0:
if len(release) > 0 {
return "", fmt.Errorf("Must specify orchestrator for release '%s'", release)
}
default:
return "", fmt.Errorf("Unsupported orchestrator '%s'", orchestrator)
}
return "", nil
}
// GetOrchestratorVersionProfileList returns OrchestratorVersionProfileList object per (optionally) specified orchestrator and release
func GetOrchestratorVersionProfileList(orchestrator, release string) (*api.OrchestratorVersionProfileList, error) {
var err error
if orchestrator, err = validate(orchestrator, release); err != nil {
return nil, err
}
orch := &api.OrchestratorVersionProfileList{}
if len(orchestrator) == 0 {
// return all orchestrators
orch.Orchestrators = []*api.OrchestratorVersionProfile{}
for _, f := range funcmap {
arr, err := f(&api.OrchestratorEdition{})
if err != nil {
return nil, err
}
orch.Orchestrators = append(orch.Orchestrators, arr...)
}
return orch, nil
}
if orch.Orchestrators, err = funcmap[orchestrator](&api.OrchestratorEdition{OrchestratorRelease: release}); err != nil {
return nil, err
}
return orch, nil
}
// GetOrchestratorVersionProfile returns orchestrator info for upgradable container service
func GetOrchestratorVersionProfile(cs *api.ContainerService) (*api.OrchestratorVersionProfile, error) {
if cs == nil || cs.Properties == nil || cs.Properties.OrchestratorProfile == nil {
return nil, fmt.Errorf("Incomplete ContainerService")
}
if len(cs.Properties.OrchestratorProfile.OrchestratorRelease) == 0 {
return nil, fmt.Errorf("Missing Orchestrator Release")
}
if cs.Properties.OrchestratorProfile.OrchestratorType != api.Kubernetes {
return nil, fmt.Errorf("Upgrade operation is not supported for '%s'", cs.Properties.OrchestratorProfile.OrchestratorType)
}
arr, err := kubernetesInfo(&api.OrchestratorEdition{
OrchestratorRelease: cs.Properties.OrchestratorProfile.OrchestratorRelease,
OrchestratorVersion: cs.Properties.OrchestratorProfile.OrchestratorVersion})
if err != nil {
return nil, err
}
// has to be exactly one element per specified orchestrator/release
if len(arr) != 1 {
return nil, fmt.Errorf("Umbiguous Orchestrator Releases")
}
return arr[0], nil
}
func kubernetesInfo(csOrch *api.OrchestratorEdition) ([]*api.OrchestratorVersionProfile, error) {
orchs := []*api.OrchestratorVersionProfile{}
if len(csOrch.OrchestratorRelease) == 0 {
// get info for all supported versions
for rel, ver := range common.KubeReleaseToVersion {
upgrades, err := kubernetesUpgrades(&api.OrchestratorEdition{OrchestratorRelease: rel, OrchestratorVersion: ver})
if err != nil {
return nil, err
}
orchs = append(orchs,
&api.OrchestratorVersionProfile{
OrchestratorType: api.Kubernetes,
OrchestratorEdition: api.OrchestratorEdition{
OrchestratorRelease: rel,
OrchestratorVersion: ver,
},
Default: rel == common.KubernetesDefaultRelease,
Upgradables: upgrades,
})
}
} else {
// get info for the specified release
ver, ok := common.KubeReleaseToVersion[csOrch.OrchestratorRelease]
if !ok {
return nil, fmt.Errorf("Kubernetes release %s is not supported", csOrch.OrchestratorRelease)
}
// set default version if empty
if len(csOrch.OrchestratorVersion) == 0 {
csOrch.OrchestratorVersion = ver
}
upgrades, err := kubernetesUpgrades(csOrch)
if err != nil {
return nil, err
}
orchs = append(orchs,
&api.OrchestratorVersionProfile{
OrchestratorType: api.Kubernetes,
OrchestratorEdition: api.OrchestratorEdition{
OrchestratorRelease: csOrch.OrchestratorRelease,
OrchestratorVersion: ver,
},
Default: csOrch.OrchestratorRelease == common.KubernetesDefaultRelease,
Upgradables: upgrades,
})
}
return orchs, nil
}
func kubernetesUpgrades(csOrch *api.OrchestratorEdition) ([]*api.OrchestratorEdition, error) {
ret := []*api.OrchestratorEdition{}
var csVer versionNumber
var err error
if err = csVer.parse(csOrch.OrchestratorVersion); err != nil {
return ret, err
}
switch csOrch.OrchestratorRelease {
case common.KubernetesRelease1Dot5:
// add next release
ret = append(ret, &api.OrchestratorEdition{
OrchestratorRelease: common.KubernetesRelease1Dot6,
OrchestratorVersion: common.KubeReleaseToVersion[common.KubernetesRelease1Dot6],
})
case common.KubernetesRelease1Dot6:
// check for patch upgrade
if ret, err = addPatchUpgrade(ret, &csVer, csOrch.OrchestratorRelease); err != nil {
return ret, err
}
// add next release
ret = append(ret, &api.OrchestratorEdition{
OrchestratorRelease: common.KubernetesRelease1Dot7,
OrchestratorVersion: common.KubeReleaseToVersion[common.KubernetesRelease1Dot7],
})
case common.KubernetesRelease1Dot7:
// check for patch upgrade
if ret, err = addPatchUpgrade(ret, &csVer, csOrch.OrchestratorRelease); err != nil {
return ret, err
}
}
return ret, nil
}
func addPatchUpgrade(upgrades []*api.OrchestratorEdition, csVer *versionNumber, release string) ([]*api.OrchestratorEdition, error) {
var pVer versionNumber
patchVersion := common.KubeReleaseToVersion[release]
if err := pVer.parse(patchVersion); err != nil {
return upgrades, err
}
if pVer.greaterThan(csVer) {
upgrades = append(upgrades, &api.OrchestratorEdition{OrchestratorRelease: release, OrchestratorVersion: patchVersion})
}
return upgrades, nil
}
func dcosInfo(csOrch *api.OrchestratorEdition) ([]*api.OrchestratorVersionProfile, error) {
orchs := []*api.OrchestratorVersionProfile{}
if len(csOrch.OrchestratorRelease) == 0 {
// get info for all supported versions
for rel, ver := range common.DCOSReleaseToVersion {
orchs = append(orchs,
&api.OrchestratorVersionProfile{
OrchestratorType: api.DCOS,
OrchestratorEdition: api.OrchestratorEdition{
OrchestratorRelease: rel,
OrchestratorVersion: ver,
},
Default: rel == common.DCOSDefaultRelease,
})
}
} else {
// get info for the specified release
ver, ok := common.DCOSReleaseToVersion[csOrch.OrchestratorRelease]
if !ok {
return nil, fmt.Errorf("DCOS release %s is not supported", csOrch.OrchestratorRelease)
}
orchs = append(orchs,
&api.OrchestratorVersionProfile{
OrchestratorType: api.DCOS,
OrchestratorEdition: api.OrchestratorEdition{
OrchestratorRelease: csOrch.OrchestratorRelease,
OrchestratorVersion: ver,
},
Default: csOrch.OrchestratorRelease == common.DCOSDefaultRelease,
})
}
return orchs, nil
}
func swarmInfo(csOrch *api.OrchestratorEdition) ([]*api.OrchestratorVersionProfile, error) {
return []*api.OrchestratorVersionProfile{
{
OrchestratorType: api.Swarm,
OrchestratorEdition: api.OrchestratorEdition{
OrchestratorVersion: SwarmVersion,
},
},
}, nil
}
func dockerceInfo(csOrch *api.OrchestratorEdition) ([]*api.OrchestratorVersionProfile, error) {
return []*api.OrchestratorVersionProfile{
{
OrchestratorType: api.SwarmMode,
OrchestratorEdition: api.OrchestratorEdition{
OrchestratorVersion: DockerCEVersion,
},
},
}, nil
}

Просмотреть файл

@ -1,119 +0,0 @@
package acsengine
import (
"testing"
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/api/common"
. "github.com/onsi/gomega"
)
func TestInvalidVersion(t *testing.T) {
RegisterTestingT(t)
invalid := []string{
"invalid number",
"invalid.number",
"a4.b7.c3",
"31.29.",
".17.02",
"43.156.89.",
"1.2.a"}
var ver versionNumber
for _, v := range invalid {
e := ver.parse(v)
Expect(e).NotTo(BeNil())
}
}
func TestVersionCompare(t *testing.T) {
RegisterTestingT(t)
type record struct {
v1, v2 string
isGreater bool
}
records := []record{
{"37.48.59", "37.48.59", false},
{"17.4.5", "3.1.1", true},
{"9.6.5", "9.45.5", false},
{"2.3.8", "2.3.24", false}}
var ver1, ver2 versionNumber
for _, r := range records {
e := ver1.parse(r.v1)
Expect(e).To(BeNil())
e = ver2.parse(r.v2)
Expect(e).To(BeNil())
Expect(r.isGreater).To(Equal(ver1.greaterThan(&ver2)))
}
}
func TestOrchestratorUpgradeInfo(t *testing.T) {
RegisterTestingT(t)
// 1.5.3 is upgradable to 1.6
cs := &api.ContainerService{
Properties: &api.Properties{
OrchestratorProfile: &api.OrchestratorProfile{
OrchestratorType: api.Kubernetes,
OrchestratorRelease: common.KubernetesRelease1Dot5,
OrchestratorVersion: "1.5.3",
},
},
}
orch, e := GetOrchestratorVersionProfile(cs)
Expect(e).To(BeNil())
Expect(len(orch.Upgradables)).To(Equal(1))
Expect(orch.Upgradables[0].OrchestratorRelease).To(Equal(common.KubernetesRelease1Dot6))
Expect(orch.Upgradables[0].OrchestratorVersion).To(Equal(common.KubeReleaseToVersion[common.KubernetesRelease1Dot6]))
// 1.6.0 is upgradable to 1.6 and 1.7
cs = &api.ContainerService{
Properties: &api.Properties{
OrchestratorProfile: &api.OrchestratorProfile{
OrchestratorType: api.Kubernetes,
OrchestratorRelease: common.KubernetesRelease1Dot6,
OrchestratorVersion: "1.6.0",
},
},
}
orch, e = GetOrchestratorVersionProfile(cs)
Expect(e).To(BeNil())
Expect(len(orch.Upgradables)).To(Equal(2))
Expect(orch.Upgradables[0].OrchestratorRelease).To(Equal(common.KubernetesRelease1Dot6))
Expect(orch.Upgradables[0].OrchestratorVersion).To(Equal(common.KubeReleaseToVersion[common.KubernetesRelease1Dot6]))
Expect(orch.Upgradables[1].OrchestratorRelease).To(Equal(common.KubernetesRelease1Dot7))
Expect(orch.Upgradables[1].OrchestratorVersion).To(Equal(common.KubeReleaseToVersion[common.KubernetesRelease1Dot7]))
// 1.7.0 is upgradable to 1.7
cs = &api.ContainerService{
Properties: &api.Properties{
OrchestratorProfile: &api.OrchestratorProfile{
OrchestratorType: api.Kubernetes,
OrchestratorRelease: common.KubernetesRelease1Dot7,
OrchestratorVersion: "1.7.0",
},
},
}
orch, e = GetOrchestratorVersionProfile(cs)
Expect(e).To(BeNil())
Expect(len(orch.Upgradables)).To(Equal(1))
Expect(orch.Upgradables[0].OrchestratorRelease).To(Equal(common.KubernetesRelease1Dot7))
Expect(orch.Upgradables[0].OrchestratorVersion).To(Equal(common.KubeReleaseToVersion[common.KubernetesRelease1Dot7]))
// 1.7 is not upgradable
cs = &api.ContainerService{
Properties: &api.Properties{
OrchestratorProfile: &api.OrchestratorProfile{
OrchestratorType: api.Kubernetes,
OrchestratorRelease: common.KubernetesRelease1Dot7,
OrchestratorVersion: common.KubeReleaseToVersion[common.KubernetesRelease1Dot7],
},
},
}
orch, e = GetOrchestratorVersionProfile(cs)
Expect(e).To(BeNil())
Expect(len(orch.Upgradables)).To(Equal(0))
}

Просмотреть файл

@ -4,6 +4,9 @@ import (
"encoding/json"
"io/ioutil"
"github.com/Azure/acs-engine/pkg/api/common"
"github.com/Azure/acs-engine/pkg/api/v20170930"
"github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20170831"
apvlabs "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/vlabs"
"github.com/Azure/acs-engine/pkg/api/v20160330"
@ -171,6 +174,64 @@ func (a *Apiloader) LoadContainerServiceForAgentPoolOnlyCluster(contents []byte,
}
}
// UpdateContainerServiceForUpgrade pre-validates upgrade operation and updates container service
func (a *Apiloader) UpdateContainerServiceForUpgrade(
contents []byte,
version string,
cs *ContainerService,
allowCurrentVersionUpgrade bool) error {
unverOrch := &OrchestratorProfile{}
switch version {
case v20170930.APIVersion:
up := &v20170930.OrchestratorProfile{}
if e := json.Unmarshal(contents, up); e != nil {
return a.Translator.Errorf(e.Error())
}
if e := up.ValidateForUpgrade(); e != nil {
return a.Translator.Errorf(e.Error())
}
convertV20170930OrchestratorProfile(up, unverOrch)
case vlabs.APIVersion:
up := &vlabs.OrchestratorProfile{}
if e := json.Unmarshal(contents, up); e != nil {
return a.Translator.Errorf(e.Error())
}
if e := up.ValidateForUpgrade(); e != nil {
return a.Translator.Errorf(e.Error())
}
convertVLabsOrchestratorProfile(up, unverOrch)
default:
return a.Translator.Errorf("unrecognized APIVersion in UpdateContainerServiceForUpgrade '%s'", version)
}
// get available upgrades for container service
orchestratorInfo, e := GetOrchestratorVersionProfile(cs.Properties.OrchestratorProfile)
if e != nil {
return e
}
// add current version if upgrade has failed
if allowCurrentVersionUpgrade {
release := cs.Properties.OrchestratorProfile.OrchestratorRelease
orchestratorInfo.Upgrades = append(orchestratorInfo.Upgrades, &OrchestratorProfile{
OrchestratorRelease: release,
OrchestratorVersion: common.KubeReleaseToVersion[release]})
}
// validate desired upgrade version and set goal state
for _, up := range orchestratorInfo.Upgrades {
if up.OrchestratorRelease == unverOrch.OrchestratorRelease {
cs.Properties.OrchestratorProfile.OrchestratorRelease = up.OrchestratorRelease
cs.Properties.OrchestratorProfile.OrchestratorVersion = up.OrchestratorVersion
return nil
}
}
return a.Translator.Errorf("Kubernetes %s cannot be upgraded to %s",
cs.Properties.OrchestratorProfile.OrchestratorRelease, unverOrch.OrchestratorRelease)
}
// SerializeContainerService takes an unversioned container service and returns the bytes
func (a *Apiloader) SerializeContainerService(containerService *ContainerService, version string) ([]byte, error) {
if containerService.Properties != nil && containerService.Properties.HostedMasterProfile != nil {

Просмотреть файл

@ -20,6 +20,17 @@ const (
Linux OSType = "Linux"
)
const (
// SwarmVersion is the Swarm orchestrator version
SwarmVersion = "swarm:1.1.0"
// SwarmDockerComposeVersion is the Docker Compose version
SwarmDockerComposeVersion = "1.6.2"
// DockerCEVersion is the DockerCE orchestrator version
DockerCEVersion = "17.03.*"
// DockerCEDockerComposeVersion is the Docker Compose version
DockerCEDockerComposeVersion = "1.14.0"
)
// validation values
const (
// MinAgentCount are the minimum number of agents per agent pool

Просмотреть файл

@ -136,10 +136,10 @@ func ConvertOrchestratorVersionProfileToV20170930(api *OrchestratorVersionProfil
vProfile.OrchestratorVersion = api.OrchestratorVersion
vProfile.OrchestratorRelease = api.OrchestratorRelease
vProfile.Default = api.Default
if api.Upgradables != nil {
vProfile.Upgradables = make([]*v20170930.OrchestratorEdition, len(api.Upgradables))
for i, h := range api.Upgradables {
vProfile.Upgradables[i] = &v20170930.OrchestratorEdition{
if api.Upgrades != nil {
vProfile.Upgrades = make([]*v20170930.OrchestratorProfile, len(api.Upgrades))
for i, h := range api.Upgrades {
vProfile.Upgrades[i] = &v20170930.OrchestratorProfile{
OrchestratorRelease: h.OrchestratorRelease,
OrchestratorVersion: h.OrchestratorVersion,
}
@ -164,10 +164,10 @@ func ConvertOrchestratorVersionProfileToVLabs(api *OrchestratorVersionProfile) *
vlabsProfile.OrchestratorVersion = api.OrchestratorVersion
vlabsProfile.OrchestratorRelease = api.OrchestratorRelease
vlabsProfile.Default = api.Default
if api.Upgradables != nil {
vlabsProfile.Upgradables = make([]*vlabs.OrchestratorEdition, len(api.Upgradables))
for i, h := range api.Upgradables {
vlabsProfile.Upgradables[i] = &vlabs.OrchestratorEdition{
if api.Upgrades != nil {
vlabsProfile.Upgrades = make([]*vlabs.OrchestratorProfile, len(api.Upgrades))
for i, h := range api.Upgrades {
vlabsProfile.Upgrades[i] = &vlabs.OrchestratorProfile{
OrchestratorRelease: h.OrchestratorRelease,
OrchestratorVersion: h.OrchestratorVersion,
}

Просмотреть файл

@ -1,27 +0,0 @@
package api
import "github.com/Azure/acs-engine/pkg/api/vlabs"
///////////////////////////////////////////////////////////
// The converter exposes functions to convert the top level
// ContainerService resource
//
// All other functions are internal helper functions used
// for converting.
///////////////////////////////////////////////////////////
// ConvertUpgradeContainerServiceToVLabs converts an unversioned ContainerService to a vlabs ContainerService
func ConvertUpgradeContainerServiceToVLabs(api *UpgradeContainerService) *vlabs.UpgradeContainerService {
vlabsUCS := &vlabs.UpgradeContainerService{}
vlabsUCS.OrchestratorProfile = &vlabs.OrchestratorProfile{}
convertUpgradeOrchestratorProfileToVLabs(api.OrchestratorProfile, vlabsUCS.OrchestratorProfile)
return vlabsUCS
}
func convertUpgradeOrchestratorProfileToVLabs(api *OrchestratorProfile, o *vlabs.OrchestratorProfile) {
o.OrchestratorType = api.OrchestratorType
if api.OrchestratorVersion != "" {
o.OrchestratorVersion = api.OrchestratorVersion
}
}

Просмотреть файл

@ -7,6 +7,7 @@ import (
"github.com/Azure/acs-engine/pkg/api/v20160930"
"github.com/Azure/acs-engine/pkg/api/v20170131"
"github.com/Azure/acs-engine/pkg/api/v20170701"
"github.com/Azure/acs-engine/pkg/api/v20170930"
"github.com/Azure/acs-engine/pkg/api/vlabs"
)
@ -528,6 +529,21 @@ func convertV20170131OrchestratorProfile(v20170131 *v20170131.OrchestratorProfil
}
}
func convertV20170930OrchestratorProfile(v *v20170930.OrchestratorProfile, api *OrchestratorProfile) {
switch v.OrchestratorType {
case v20170930.Kubernetes:
api.OrchestratorType = Kubernetes
case v20170930.DCOS:
api.OrchestratorType = DCOS
case v20170930.Swarm:
api.OrchestratorType = Swarm
case v20170930.DockerCE:
api.OrchestratorType = SwarmMode
}
api.OrchestratorRelease = v.OrchestratorRelease
api.OrchestratorVersion = v.OrchestratorVersion
}
func convertV20170701OrchestratorProfile(v20170701cs *v20170701.OrchestratorProfile, api *OrchestratorProfile) {
if v20170701cs.OrchestratorType == v20170701.DockerCE {
api.OrchestratorType = SwarmMode

Просмотреть файл

@ -1,19 +0,0 @@
package api
import "github.com/Azure/acs-engine/pkg/api/vlabs"
///////////////////////////////////////////////////////////
// The converter exposes functions to convert the top level
// UpgradeContainerService API model
//
// All other functions are internal helper functions used
// for converting.
///////////////////////////////////////////////////////////
// ConvertVLabsUpgradeContainerService converts a vlabs UpgradeContainerService to an unversioned UpgradeContainerService
func ConvertVLabsUpgradeContainerService(vlabs *vlabs.UpgradeContainerService) *UpgradeContainerService {
ucs := &UpgradeContainerService{}
ucs.OrchestratorProfile = &OrchestratorProfile{}
convertVLabsOrchestratorProfile(vlabs.OrchestratorProfile, ucs.OrchestratorProfile)
return ucs
}

242
pkg/api/orchestrators.go Normal file
Просмотреть файл

@ -0,0 +1,242 @@
package api
import (
"fmt"
"strings"
"github.com/Azure/acs-engine/pkg/api/common"
"github.com/Masterminds/semver"
)
type orchestratorsFunc func(*OrchestratorProfile) ([]*OrchestratorVersionProfile, error)
var funcmap map[string]orchestratorsFunc
func init() {
funcmap = map[string]orchestratorsFunc{
Kubernetes: kubernetesInfo,
DCOS: dcosInfo,
Swarm: swarmInfo,
SwarmMode: dockerceInfo,
}
}
func validate(orchestrator, release string) (string, error) {
switch {
case strings.EqualFold(orchestrator, Kubernetes):
return Kubernetes, nil
case strings.EqualFold(orchestrator, DCOS):
return DCOS, nil
case strings.EqualFold(orchestrator, Swarm):
return Swarm, nil
case strings.EqualFold(orchestrator, SwarmMode):
return SwarmMode, nil
case len(orchestrator) == 0:
if len(release) > 0 {
return "", fmt.Errorf("Must specify orchestrator for release '%s'", release)
}
default:
return "", fmt.Errorf("Unsupported orchestrator '%s'", orchestrator)
}
return "", nil
}
// GetOrchestratorVersionProfileList returns OrchestratorVersionProfileList object per (optionally) specified orchestrator and release
func GetOrchestratorVersionProfileList(orchestrator, release string) (*OrchestratorVersionProfileList, error) {
var err error
if orchestrator, err = validate(orchestrator, release); err != nil {
return nil, err
}
orch := &OrchestratorVersionProfileList{}
if len(orchestrator) == 0 {
// return all orchestrators
orch.Orchestrators = []*OrchestratorVersionProfile{}
for _, f := range funcmap {
arr, err := f(&OrchestratorProfile{})
if err != nil {
return nil, err
}
orch.Orchestrators = append(orch.Orchestrators, arr...)
}
return orch, nil
}
if orch.Orchestrators, err = funcmap[orchestrator](&OrchestratorProfile{OrchestratorRelease: release}); err != nil {
return nil, err
}
return orch, nil
}
// GetOrchestratorVersionProfile returns orchestrator info for upgradable container service
func GetOrchestratorVersionProfile(orch *OrchestratorProfile) (*OrchestratorVersionProfile, error) {
if len(orch.OrchestratorRelease) == 0 {
return nil, fmt.Errorf("Missing Orchestrator Release")
}
if orch.OrchestratorType != Kubernetes {
return nil, fmt.Errorf("Upgrade operation is not supported for '%s'", orch.OrchestratorType)
}
arr, err := kubernetesInfo(orch)
if err != nil {
return nil, err
}
// has to be exactly one element per specified orchestrator/release
if len(arr) != 1 {
return nil, fmt.Errorf("Umbiguous Orchestrator Releases")
}
return arr[0], nil
}
func kubernetesInfo(csOrch *OrchestratorProfile) ([]*OrchestratorVersionProfile, error) {
orchs := []*OrchestratorVersionProfile{}
if len(csOrch.OrchestratorRelease) == 0 {
// get info for all supported versions
for rel, ver := range common.KubeReleaseToVersion {
upgrades, err := kubernetesUpgrades(&OrchestratorProfile{OrchestratorRelease: rel, OrchestratorVersion: ver})
if err != nil {
return nil, err
}
orchs = append(orchs,
&OrchestratorVersionProfile{
OrchestratorProfile: OrchestratorProfile{
OrchestratorType: Kubernetes,
OrchestratorRelease: rel,
OrchestratorVersion: ver,
},
Default: rel == common.KubernetesDefaultRelease,
Upgrades: upgrades,
})
}
} else {
// get info for the specified release
ver, ok := common.KubeReleaseToVersion[csOrch.OrchestratorRelease]
if !ok {
return nil, fmt.Errorf("Kubernetes release %s is not supported", csOrch.OrchestratorRelease)
}
// set default version if empty
if len(csOrch.OrchestratorVersion) == 0 {
csOrch.OrchestratorVersion = ver
}
upgrades, err := kubernetesUpgrades(csOrch)
if err != nil {
return nil, err
}
orchs = append(orchs,
&OrchestratorVersionProfile{
OrchestratorProfile: OrchestratorProfile{
OrchestratorType: Kubernetes,
OrchestratorRelease: csOrch.OrchestratorRelease,
OrchestratorVersion: ver,
},
Default: csOrch.OrchestratorRelease == common.KubernetesDefaultRelease,
Upgrades: upgrades,
})
}
return orchs, nil
}
func kubernetesUpgrades(csOrch *OrchestratorProfile) ([]*OrchestratorProfile, error) {
ret := []*OrchestratorProfile{}
var err error
switch csOrch.OrchestratorRelease {
case common.KubernetesRelease1Dot5:
// add next release
ret = append(ret, &OrchestratorProfile{
OrchestratorType: Kubernetes,
OrchestratorRelease: common.KubernetesRelease1Dot6,
OrchestratorVersion: common.KubeReleaseToVersion[common.KubernetesRelease1Dot6],
})
case common.KubernetesRelease1Dot6:
// check for patch upgrade
if ret, err = addPatchUpgrade(ret, csOrch.OrchestratorRelease, csOrch.OrchestratorVersion); err != nil {
return ret, err
}
// add next release
ret = append(ret, &OrchestratorProfile{
OrchestratorType: Kubernetes,
OrchestratorRelease: common.KubernetesRelease1Dot7,
OrchestratorVersion: common.KubeReleaseToVersion[common.KubernetesRelease1Dot7],
})
case common.KubernetesRelease1Dot7:
// check for patch upgrade
if ret, err = addPatchUpgrade(ret, csOrch.OrchestratorRelease, csOrch.OrchestratorVersion); err != nil {
return ret, err
}
}
return ret, nil
}
func addPatchUpgrade(upgrades []*OrchestratorProfile, release, version string) ([]*OrchestratorProfile, error) {
patchVersion, ok := common.KubeReleaseToVersion[release]
if !ok {
return upgrades, fmt.Errorf("Kubernetes release %s is not supported", release)
}
pVer, err := semver.NewVersion(patchVersion)
if err != nil {
return upgrades, err
}
constraint, err := semver.NewConstraint(">" + version)
if err != nil {
return upgrades, err
}
if constraint.Check(pVer) {
upgrades = append(upgrades, &OrchestratorProfile{OrchestratorRelease: release, OrchestratorVersion: patchVersion})
}
return upgrades, nil
}
func dcosInfo(csOrch *OrchestratorProfile) ([]*OrchestratorVersionProfile, error) {
orchs := []*OrchestratorVersionProfile{}
if len(csOrch.OrchestratorRelease) == 0 {
// get info for all supported versions
for rel, ver := range common.DCOSReleaseToVersion {
orchs = append(orchs,
&OrchestratorVersionProfile{
OrchestratorProfile: OrchestratorProfile{
OrchestratorType: DCOS,
OrchestratorRelease: rel,
OrchestratorVersion: ver,
},
Default: rel == common.DCOSDefaultRelease,
})
}
} else {
// get info for the specified release
ver, ok := common.DCOSReleaseToVersion[csOrch.OrchestratorRelease]
if !ok {
return nil, fmt.Errorf("DCOS release %s is not supported", csOrch.OrchestratorRelease)
}
orchs = append(orchs,
&OrchestratorVersionProfile{
OrchestratorProfile: OrchestratorProfile{
OrchestratorType: DCOS,
OrchestratorRelease: csOrch.OrchestratorRelease,
OrchestratorVersion: ver,
},
Default: csOrch.OrchestratorRelease == common.DCOSDefaultRelease,
})
}
return orchs, nil
}
func swarmInfo(csOrch *OrchestratorProfile) ([]*OrchestratorVersionProfile, error) {
return []*OrchestratorVersionProfile{
{
OrchestratorProfile: OrchestratorProfile{
OrchestratorType: Swarm,
OrchestratorVersion: SwarmVersion,
},
},
}, nil
}
func dockerceInfo(csOrch *OrchestratorProfile) ([]*OrchestratorVersionProfile, error) {
return []*OrchestratorVersionProfile{
{
OrchestratorProfile: OrchestratorProfile{
OrchestratorType: SwarmMode,
OrchestratorVersion: DockerCEVersion,
},
},
}, nil
}

Просмотреть файл

@ -0,0 +1,101 @@
package api
import (
"testing"
"github.com/Azure/acs-engine/pkg/api/common"
"github.com/Masterminds/semver"
. "github.com/onsi/gomega"
)
func TestInvalidVersion(t *testing.T) {
RegisterTestingT(t)
invalid := []string{
"invalid number",
"invalid.number",
"a4.b7.c3",
"31.29.",
".17.02",
"43.156.89.",
"1.2.a"}
for _, v := range invalid {
_, e := semver.NewVersion(v)
Expect(e).NotTo(BeNil())
}
}
func TestVersionCompare(t *testing.T) {
RegisterTestingT(t)
type record struct {
v1, v2 string
isGreater bool
}
records := []record{
{"37.48.59", "37.48.59", false},
{"17.4.5", "3.1.1", true},
{"9.6.5", "9.45.5", false},
{"2.3.8", "2.3.24", false}}
for _, r := range records {
ver, e := semver.NewVersion(r.v1)
Expect(e).To(BeNil())
constraint, e := semver.NewConstraint(">" + r.v2)
Expect(e).To(BeNil())
Expect(r.isGreater).To(Equal(constraint.Check(ver)))
}
}
func TestOrchestratorUpgradeInfo(t *testing.T) {
RegisterTestingT(t)
// 1.5.3 is upgradable to 1.6
csOrch := &OrchestratorProfile{
OrchestratorType: Kubernetes,
OrchestratorRelease: common.KubernetesRelease1Dot5,
OrchestratorVersion: "1.5.3",
}
orch, e := GetOrchestratorVersionProfile(csOrch)
Expect(e).To(BeNil())
Expect(len(orch.Upgrades)).To(Equal(1))
Expect(orch.Upgrades[0].OrchestratorRelease).To(Equal(common.KubernetesRelease1Dot6))
Expect(orch.Upgrades[0].OrchestratorVersion).To(Equal(common.KubeReleaseToVersion[common.KubernetesRelease1Dot6]))
// 1.6.0 is upgradable to 1.6 and 1.7
csOrch = &OrchestratorProfile{
OrchestratorType: Kubernetes,
OrchestratorRelease: common.KubernetesRelease1Dot6,
OrchestratorVersion: "1.6.0",
}
orch, e = GetOrchestratorVersionProfile(csOrch)
Expect(e).To(BeNil())
Expect(len(orch.Upgrades)).To(Equal(2))
Expect(orch.Upgrades[0].OrchestratorRelease).To(Equal(common.KubernetesRelease1Dot6))
Expect(orch.Upgrades[0].OrchestratorVersion).To(Equal(common.KubeReleaseToVersion[common.KubernetesRelease1Dot6]))
Expect(orch.Upgrades[1].OrchestratorRelease).To(Equal(common.KubernetesRelease1Dot7))
Expect(orch.Upgrades[1].OrchestratorVersion).To(Equal(common.KubeReleaseToVersion[common.KubernetesRelease1Dot7]))
// 1.7.0 is upgradable to 1.7
csOrch = &OrchestratorProfile{
OrchestratorType: Kubernetes,
OrchestratorRelease: common.KubernetesRelease1Dot7,
OrchestratorVersion: "1.7.0",
}
orch, e = GetOrchestratorVersionProfile(csOrch)
Expect(e).To(BeNil())
Expect(len(orch.Upgrades)).To(Equal(1))
Expect(orch.Upgrades[0].OrchestratorRelease).To(Equal(common.KubernetesRelease1Dot7))
Expect(orch.Upgrades[0].OrchestratorVersion).To(Equal(common.KubeReleaseToVersion[common.KubernetesRelease1Dot7]))
// 1.7 is not upgradable
csOrch = &OrchestratorProfile{
OrchestratorType: Kubernetes,
OrchestratorRelease: common.KubernetesRelease1Dot7,
OrchestratorVersion: common.KubeReleaseToVersion[common.KubernetesRelease1Dot7],
}
orch, e = GetOrchestratorVersionProfile(csOrch)
Expect(e).To(BeNil())
Expect(len(orch.Upgrades)).To(Equal(0))
}

Просмотреть файл

@ -1,17 +1,10 @@
package api
// OrchestratorEdition contains version and release numbers
type OrchestratorEdition struct {
OrchestratorRelease string `json:"orchestratorRelease,omitempty"`
OrchestratorVersion string `json:"orchestratorVersion"`
}
// OrchestratorVersionProfile contains orchestrator version info
type OrchestratorVersionProfile struct {
OrchestratorType string `json:"orchestratorType"`
OrchestratorEdition
Default bool `json:"default,omitempty"`
Upgradables []*OrchestratorEdition `json:"upgradables,omitempty"`
OrchestratorProfile
Default bool `json:"default,omitempty"`
Upgrades []*OrchestratorProfile `json:"upgrades,omitempty"`
}
// OrchestratorVersionProfileList contains list of version profiles for supported orchestrators

Просмотреть файл

@ -130,6 +130,8 @@ const (
// Migrating means resource is being migrated from one subscription or
// resource group to another
Migrating ProvisioningState = "Migrating"
// Upgrading means an existing ContainerService resource is being upgraded
Upgrading ProvisioningState = "Upgrading"
)
// OrchestratorProfile contains Orchestrator properties
@ -253,7 +255,7 @@ type VMDiagnostics struct {
StorageURL *neturl.URL `json:"storageUrl"`
}
// JumpboxProfile dscribes properties of the jumpbox setup
// JumpboxProfile describes properties of the jumpbox setup
// in the ACS container cluster.
type JumpboxProfile struct {
OSType OSType `json:"osType"`
@ -362,14 +364,6 @@ type V20170701ARMContainerService struct {
*v20170701.ContainerService
}
// VlabsUpgradeContainerService is the type we read and write from file
// needed because the json that is sent to ARM and acs-engine
// is different from the json that the ACS RP Api gets from ARM
type VlabsUpgradeContainerService struct {
TypeMeta
*vlabs.UpgradeContainerService
}
// V20170831ARMManagedContainerService is the type we read and write from file
// needed because the json that is sent to ARM and acs-engine
// is different from the json that the ACS RP Api gets from ARM
@ -378,11 +372,6 @@ type V20170831ARMManagedContainerService struct {
*v20170831.ManagedCluster
}
// UpgradeContainerService API model
type UpgradeContainerService struct {
OrchestratorProfile *OrchestratorProfile `json:"orchestratorProfile,omitempty"`
}
// HasWindows returns true if the cluster contains windows
func (p *Properties) HasWindows() bool {
for _, agentPoolProfile := range p.AgentPoolProfiles {

Просмотреть файл

@ -1,72 +0,0 @@
package api
import (
"encoding/json"
"io/ioutil"
"github.com/Azure/acs-engine/pkg/api/vlabs"
"github.com/Azure/acs-engine/pkg/i18n"
)
// UpgradeApiloader represents the object that loads api model
type UpgradeApiloader struct {
Translator *i18n.Translator
}
// LoadUpgradeContainerServiceFromFile loads an ACS Cluster API Model from a JSON file
func (ua *UpgradeApiloader) LoadUpgradeContainerServiceFromFile(jsonFile string) (*UpgradeContainerService, string, error) {
contents, e := ioutil.ReadFile(jsonFile)
if e != nil {
return nil, "", ua.Translator.Errorf("error reading file %s: %s", jsonFile, e.Error())
}
return ua.DeserializeUpgradeContainerService(contents)
}
// DeserializeUpgradeContainerService loads an ACS Cluster API Model, validates it, and returns the unversioned representation
func (ua *UpgradeApiloader) DeserializeUpgradeContainerService(contents []byte) (*UpgradeContainerService, string, error) {
m := &TypeMeta{}
if err := json.Unmarshal(contents, &m); err != nil {
return nil, "", err
}
version := m.APIVersion
upgradecontainerservice, err := ua.LoadUpgradeContainerService(contents, version)
return upgradecontainerservice, version, err
}
// LoadUpgradeContainerService loads an ACS Cluster API Model, validates it, and returns the unversioned representation
func (ua *UpgradeApiloader) LoadUpgradeContainerService(contents []byte, version string) (*UpgradeContainerService, error) {
switch version {
case vlabs.APIVersion:
upgradecontainerService := &vlabs.UpgradeContainerService{}
if e := json.Unmarshal(contents, &upgradecontainerService); e != nil {
return nil, e
}
if e := upgradecontainerService.Validate(); e != nil {
return nil, e
}
return ConvertVLabsUpgradeContainerService(upgradecontainerService), nil
default:
return nil, ua.Translator.Errorf("unrecognized APIVersion '%s'", version)
}
}
// SerializeUpgradeContainerService takes an unversioned container service and returns the bytes
func (ua *UpgradeApiloader) SerializeUpgradeContainerService(upgradeContainerService *UpgradeContainerService, version string) ([]byte, error) {
switch version {
case vlabs.APIVersion:
vlabsUpgradeContainerService := ConvertUpgradeContainerServiceToVLabs(upgradeContainerService)
armUpgradeContainerService := &VlabsUpgradeContainerService{}
armUpgradeContainerService.UpgradeContainerService = vlabsUpgradeContainerService
armUpgradeContainerService.APIVersion = version
b, err := json.MarshalIndent(armUpgradeContainerService, "", " ")
if err != nil {
return nil, err
}
return b, nil
default:
return nil, ua.Translator.Errorf("invalid version %s for conversion back from unversioned object", version)
}
}

Просмотреть файл

@ -1,17 +1,17 @@
package v20170930
// OrchestratorEdition contains version and release numbers
type OrchestratorEdition struct {
OrchestratorRelease string `json:"orchestratorRelease,omitempty"`
// OrchestratorProfile contains Orchestrator properties
type OrchestratorProfile struct {
OrchestratorType string `json:"orchestratorType"`
OrchestratorRelease string `json:"orchestratorRelease"`
OrchestratorVersion string `json:"orchestratorVersion"`
}
// OrchestratorVersionProfile contains orchestrator version info
type OrchestratorVersionProfile struct {
OrchestratorType string `json:"orchestratorType"`
OrchestratorEdition
Default bool `json:"default,omitempty"`
Upgradables []*OrchestratorEdition `json:"upgradables,omitempty"`
OrchestratorProfile
Default bool `json:"default,omitempty"`
Upgrades []*OrchestratorProfile `json:"upgrades,omitempty"`
}
// OrchestratorVersionProfileList contains list of version profiles for supported orchestrators

Просмотреть файл

@ -12,14 +12,8 @@ func (o *OrchestratorVersionProfile) Validate() error {
switch {
case strings.EqualFold(o.OrchestratorType, Kubernetes):
o.OrchestratorType = Kubernetes
if _, ok := common.KubeReleaseToVersion[o.OrchestratorRelease]; !ok {
return fmt.Errorf("Unsupported Kubernetes release '%s'", o.OrchestratorRelease)
}
case strings.EqualFold(o.OrchestratorType, DCOS):
o.OrchestratorType = DCOS
if _, ok := common.DCOSReleaseToVersion[o.OrchestratorRelease]; !ok {
return fmt.Errorf("Unsupported DCOS release '%s'", o.OrchestratorRelease)
}
case strings.EqualFold(o.OrchestratorType, Swarm):
o.OrchestratorType = Swarm
case strings.EqualFold(o.OrchestratorType, DockerCE):
@ -29,3 +23,19 @@ func (o *OrchestratorVersionProfile) Validate() error {
}
return nil
}
// ValidateForUpgrade validates upgrade input data
func (o *OrchestratorProfile) ValidateForUpgrade() error {
switch o.OrchestratorType {
case DCOS, DockerCE, Swarm:
return fmt.Errorf("Upgrade is not supported for orchestrator %s", o.OrchestratorType)
case Kubernetes:
switch o.OrchestratorRelease {
case common.KubernetesRelease1Dot6:
case common.KubernetesRelease1Dot7:
default:
return fmt.Errorf("Upgrade to Kubernetes %s is not supported", o.OrchestratorRelease)
}
}
return nil
}

Просмотреть файл

@ -1,17 +1,10 @@
package vlabs
// OrchestratorEdition contains version and release numbers
type OrchestratorEdition struct {
OrchestratorRelease string `json:"orchestratorRelease,omitempty"`
OrchestratorVersion string `json:"orchestratorVersion"`
}
// OrchestratorVersionProfile contains orchestrator version info
type OrchestratorVersionProfile struct {
OrchestratorType string `json:"orchestratorType"`
OrchestratorEdition
Default bool `json:"default,omitempty"`
Upgradables []*OrchestratorEdition `json:"upgradables,omitempty"`
OrchestratorProfile
Default bool `json:"default,omitempty"`
Upgrades []*OrchestratorProfile `json:"upgrades,omitempty"`
}
// OrchestratorVersionProfileList contains list of version profiles for supported orchestrators

Просмотреть файл

@ -1,29 +0,0 @@
package vlabs
import (
"fmt"
"github.com/Azure/acs-engine/pkg/api/common"
)
// UpgradeContainerService API model
type UpgradeContainerService struct {
OrchestratorProfile *OrchestratorProfile `json:"orchestratorProfile,omitempty"`
}
// Validate implements APIObject
func (ucs *UpgradeContainerService) Validate() error {
switch ucs.OrchestratorProfile.OrchestratorType {
case DCOS, SwarmMode, Swarm:
return fmt.Errorf("Upgrade is not supported for orchestrator: %s", ucs.OrchestratorProfile.OrchestratorType)
case Kubernetes:
switch ucs.OrchestratorProfile.OrchestratorRelease {
case common.KubernetesRelease1Dot6:
case common.KubernetesRelease1Dot7:
default:
return fmt.Errorf("Upgrade is not supported to orchestrator release: %s", ucs.OrchestratorProfile.OrchestratorRelease)
}
}
return nil
}

Просмотреть файл

@ -153,6 +153,22 @@ func (o *OrchestratorVersionProfile) Validate() error {
return nil
}
// ValidateForUpgrade validates upgrade input data
func (o *OrchestratorProfile) ValidateForUpgrade() error {
switch o.OrchestratorType {
case DCOS, SwarmMode, Swarm:
return fmt.Errorf("Upgrade is not supported for orchestrator %s", o.OrchestratorType)
case Kubernetes:
switch o.OrchestratorRelease {
case common.KubernetesRelease1Dot6:
case common.KubernetesRelease1Dot7:
default:
return fmt.Errorf("Upgrade to Kubernetes %s is not supported", o.OrchestratorRelease)
}
}
return nil
}
func validateKeyVaultSecrets(secrets []KeyVaultSecrets, requireCertificateStore bool) error {
for _, s := range secrets {
if len(s.VaultCertificates) == 0 {

Просмотреть файл

@ -38,25 +38,20 @@ type AgentPoolTopology struct {
UpgradedAgentVMs *[]compute.VirtualMachine
}
// UpgradeCluster upgrades a cluster with Orchestrator version X
// (or X.X or X.X.X) to version y (or Y.Y or X.X.X). RIght now
// upgrades are supported for Kubernetes cluster only.
// UpgradeCluster upgrades a cluster with Orchestrator version X.X to version Y.Y.
// Right now upgrades are supported for Kubernetes cluster only.
type UpgradeCluster struct {
Translator *i18n.Translator
ClusterTopology
Client armhelpers.ACSEngineClient
UpgradeModel *api.UpgradeContainerService
}
// MasterVMNamePrefix is the prefix for all master VM names for Kubernetes clusters
const MasterVMNamePrefix = "k8s-master-"
// UpgradeCluster runs the workflow to upgrade a Kubernetes cluster.
// UpgradeContainerService contains target state of the cluster that
// the operation will drive towards.
func (uc *UpgradeCluster) UpgradeCluster(subscriptionID uuid.UUID, resourceGroup string,
cs *api.ContainerService, ucs *api.UpgradeContainerService, nameSuffix string) error {
cs *api.ContainerService, nameSuffix string) error {
uc.ClusterTopology = ClusterTopology{}
uc.ResourceGroup = resourceGroup
uc.DataModel = cs
@ -65,42 +60,35 @@ func (uc *UpgradeCluster) UpgradeCluster(subscriptionID uuid.UUID, resourceGroup
uc.UpgradedMasterVMs = &[]compute.VirtualMachine{}
uc.AgentPools = make(map[string]*AgentPoolTopology)
uc.UpgradeModel = ucs
if err := uc.getClusterNodeStatus(subscriptionID, resourceGroup); err != nil {
return uc.Translator.Errorf("Error while querying ARM for resources: %+v", err)
}
var upgrader UpgradeWorkFlow
log.Infoln(fmt.Sprintf("Upgrading to Kubernetes release %s", ucs.OrchestratorProfile.OrchestratorRelease))
switch ucs.OrchestratorProfile.OrchestratorRelease {
log.Infoln(fmt.Sprintf("Upgrading to Kubernetes release %s", uc.DataModel.Properties.OrchestratorProfile.OrchestratorRelease))
switch uc.DataModel.Properties.OrchestratorProfile.OrchestratorRelease {
case api.KubernetesRelease1Dot6:
upgrader16 := &Kubernetes16upgrader{}
upgrader16.Init(uc.Translator, uc.ClusterTopology, uc.UpgradeModel, uc.Client)
upgrader16.Init(uc.Translator, uc.ClusterTopology, uc.Client)
upgrader = upgrader16
case api.KubernetesRelease1Dot7:
upgrader17 := &Kubernetes17upgrader{}
upgrader17.Init(uc.Translator, uc.ClusterTopology, uc.UpgradeModel, uc.Client)
upgrader17.Init(uc.Translator, uc.ClusterTopology, uc.Client)
upgrader = upgrader17
default:
return uc.Translator.Errorf("Upgrade to Kubernetes release: %s is not supported from release: %s",
ucs.OrchestratorProfile.OrchestratorRelease,
return uc.Translator.Errorf("Upgrade to Kubernetes release %s is not supported",
uc.DataModel.Properties.OrchestratorProfile.OrchestratorRelease)
}
if err := upgrader.ClusterPreflightCheck(); err != nil {
return err
}
if err := upgrader.RunUpgrade(); err != nil {
return err
}
log.Infoln(fmt.Sprintf("Cluster upraded successfully to Kubernetes release %s, version: %s",
ucs.OrchestratorProfile.OrchestratorRelease,
ucs.OrchestratorProfile.OrchestratorVersion))
uc.DataModel.Properties.OrchestratorProfile.OrchestratorRelease,
uc.DataModel.Properties.OrchestratorProfile.OrchestratorVersion))
return nil
}
@ -110,10 +98,8 @@ func (uc *UpgradeCluster) getClusterNodeStatus(subscriptionID uuid.UUID, resourc
return err
}
orchestratorTypeVersion := fmt.Sprintf("%s:%s", uc.DataModel.Properties.OrchestratorProfile.OrchestratorType,
targetOrchestratorTypeVersion := fmt.Sprintf("%s:%s", uc.DataModel.Properties.OrchestratorProfile.OrchestratorType,
uc.DataModel.Properties.OrchestratorProfile.OrchestratorVersion)
targetOrchestratorTypeVersion := fmt.Sprintf("%s:%s", uc.UpgradeModel.OrchestratorProfile.OrchestratorType,
uc.UpgradeModel.OrchestratorProfile.OrchestratorVersion)
for _, vm := range *vmListResult.Value {
if vm.Tags == nil {
@ -122,25 +108,28 @@ func (uc *UpgradeCluster) getClusterNodeStatus(subscriptionID uuid.UUID, resourc
}
vmOrchestratorTypeAndVersion := *(*vm.Tags)["orchestrator"]
if vmOrchestratorTypeAndVersion == orchestratorTypeVersion {
if vmOrchestratorTypeAndVersion != targetOrchestratorTypeVersion {
if strings.Contains(*(vm.Name), MasterVMNamePrefix) {
if !strings.Contains(*(vm.Name), uc.NameSuffix) {
log.Infoln(fmt.Sprintf("Skipping VM: %s for upgrade as it does not belong to cluster with expected name suffix: %s",
*vm.Name, uc.NameSuffix))
continue
}
if err := uc.upgradable(vmOrchestratorTypeAndVersion); err != nil {
return err
}
log.Infoln(fmt.Sprintf("Master VM name: %s, orchestrator: %s (MasterVMs)", *vm.Name, vmOrchestratorTypeAndVersion))
*uc.MasterVMs = append(*uc.MasterVMs, vm)
} else {
uc.addVMToAgentPool(vm, true)
}
} else if vmOrchestratorTypeAndVersion == targetOrchestratorTypeVersion {
if !strings.Contains(*(vm.Name), uc.NameSuffix) {
log.Infoln(fmt.Sprintf("Not adding VM: %s to upgraded list as it does not belong to cluster with expected name suffix: %s",
*vm.Name, uc.NameSuffix))
continue
}
if strings.Contains(*(vm.Name), MasterVMNamePrefix) {
if !strings.Contains(*(vm.Name), uc.NameSuffix) {
log.Infoln(fmt.Sprintf("Not adding VM: %s to upgraded list as it does not belong to cluster with expected name suffix: %s",
*vm.Name, uc.NameSuffix))
continue
}
log.Infoln(fmt.Sprintf("Master VM name: %s, orchestrator: %s (UpgradedMasterVMs)", *vm.Name, vmOrchestratorTypeAndVersion))
*uc.UpgradedMasterVMs = append(*uc.UpgradedMasterVMs, vm)
} else {
@ -152,6 +141,35 @@ func (uc *UpgradeCluster) getClusterNodeStatus(subscriptionID uuid.UUID, resourc
return nil
}
func (uc *UpgradeCluster) upgradable(vmOrchestratorTypeAndVersion string) error {
arr := strings.Split(vmOrchestratorTypeAndVersion, ":")
if len(arr) != 2 {
return fmt.Errorf("Unsupported orchestrator tag format %s", vmOrchestratorTypeAndVersion)
}
currentVer := arr[1]
arr = strings.Split(currentVer, ".")
if len(arr) != 3 {
return fmt.Errorf("Unsupported orchestrator version format %s", currentVer)
}
currentRel := fmt.Sprintf("%s.%s", arr[0], arr[1])
csOrch := &api.OrchestratorProfile{
OrchestratorType: api.Kubernetes,
OrchestratorRelease: currentRel,
OrchestratorVersion: currentVer,
}
orch, err := api.GetOrchestratorVersionProfile(csOrch)
if err != nil {
return err
}
for _, up := range orch.Upgrades {
if up.OrchestratorRelease == uc.DataModel.Properties.OrchestratorProfile.OrchestratorRelease {
return nil
}
}
return fmt.Errorf("%s in non-upgradable to %s", vmOrchestratorTypeAndVersion, uc.DataModel.Properties.OrchestratorProfile.OrchestratorRelease)
}
func (uc *UpgradeCluster) addVMToAgentPool(vm compute.VirtualMachine, isUpgradableVM bool) error {
var poolIdentifier string
var poolPrefix string

Просмотреть файл

@ -25,8 +25,10 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
})
It("Should return error message when failing to list VMs during upgrade operation", func() {
cs := api.ContainerService{}
ucs := api.UpgradeContainerService{}
cs := createContainerService("testcluster", api.KubernetesRelease1Dot5, 1, 1)
cs.Properties.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
cs.Properties.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
uc := UpgradeCluster{
Translator: &i18n.Translator{},
@ -38,7 +40,7 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4")
err := uc.UpgradeCluster(subID, "TestRg", &cs, &ucs, "12345678")
err := uc.UpgradeCluster(subID, "TestRg", cs, "12345678")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(Equal("Error while querying ARM for resources: ListVirtualMachines failed"))
@ -49,11 +51,8 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
It("Should return error message when failing to detete VMs during upgrade operation", func() {
cs := createContainerService("testcluster", api.KubernetesRelease1Dot5, 1, 1)
ucs := api.UpgradeContainerService{}
ucs.OrchestratorProfile = &api.OrchestratorProfile{}
ucs.OrchestratorProfile.OrchestratorType = api.Kubernetes
ucs.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
ucs.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
cs.Properties.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
cs.Properties.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
uc := UpgradeCluster{
Translator: &i18n.Translator{},
@ -65,8 +64,7 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4")
err := uc.UpgradeCluster(subID, "TestRg", cs, &ucs, "12345678")
err := uc.UpgradeCluster(subID, "TestRg", cs, "12345678")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(Equal("DeleteVirtualMachine failed"))
})
@ -74,11 +72,8 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
It("Should return error message when failing to deploy template during upgrade operation", func() {
cs := createContainerService("testcluster", api.KubernetesRelease1Dot6, 1, 1)
ucs := api.UpgradeContainerService{}
ucs.OrchestratorProfile = &api.OrchestratorProfile{}
ucs.OrchestratorProfile.OrchestratorType = api.Kubernetes
ucs.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
ucs.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
cs.Properties.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
cs.Properties.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
uc := UpgradeCluster{
Translator: &i18n.Translator{},
@ -90,7 +85,7 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4")
err := uc.UpgradeCluster(subID, "TestRg", cs, &ucs, "12345678")
err := uc.UpgradeCluster(subID, "TestRg", cs, "12345678")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(Equal("DeployTemplate failed"))
})
@ -98,11 +93,8 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
It("Should return error message when failing to get a virtual machine during upgrade operation", func() {
cs := createContainerService("testcluster", api.KubernetesRelease1Dot5, 1, 6)
ucs := api.UpgradeContainerService{}
ucs.OrchestratorProfile = &api.OrchestratorProfile{}
ucs.OrchestratorProfile.OrchestratorType = api.Kubernetes
ucs.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
ucs.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
cs.Properties.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
cs.Properties.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
uc := UpgradeCluster{
Translator: &i18n.Translator{},
@ -114,7 +106,7 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4")
err := uc.UpgradeCluster(subID, "TestRg", cs, &ucs, "12345678")
err := uc.UpgradeCluster(subID, "TestRg", cs, "12345678")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(Equal("GetVirtualMachine failed"))
})
@ -122,11 +114,8 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
It("Should return error message when failing to get storage client during upgrade operation", func() {
cs := createContainerService("testcluster", api.KubernetesRelease1Dot5, 5, 1)
ucs := api.UpgradeContainerService{}
ucs.OrchestratorProfile = &api.OrchestratorProfile{}
ucs.OrchestratorProfile.OrchestratorType = api.Kubernetes
ucs.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
ucs.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
cs.Properties.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
cs.Properties.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
uc := UpgradeCluster{
Translator: &i18n.Translator{},
@ -138,7 +127,7 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4")
err := uc.UpgradeCluster(subID, "TestRg", cs, &ucs, "12345678")
err := uc.UpgradeCluster(subID, "TestRg", cs, "12345678")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(Equal("GetStorageClient failed"))
})
@ -146,11 +135,8 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
It("Should return error message when failing to delete network interface during upgrade operation", func() {
cs := createContainerService("testcluster", api.KubernetesRelease1Dot5, 3, 2)
ucs := api.UpgradeContainerService{}
ucs.OrchestratorProfile = &api.OrchestratorProfile{}
ucs.OrchestratorProfile.OrchestratorType = api.Kubernetes
ucs.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
ucs.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
cs.Properties.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
cs.Properties.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
uc := UpgradeCluster{
Translator: &i18n.Translator{},
@ -162,7 +148,7 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4")
err := uc.UpgradeCluster(subID, "TestRg", cs, &ucs, "12345678")
err := uc.UpgradeCluster(subID, "TestRg", cs, "12345678")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(Equal("DeleteNetworkInterface failed"))
})
@ -170,11 +156,8 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
It("Should return error message when failing on ClusterPreflightCheck operation", func() {
cs := createContainerService("testcluster", api.KubernetesRelease1Dot5, 3, 3)
ucs := api.UpgradeContainerService{}
ucs.OrchestratorProfile = &api.OrchestratorProfile{}
ucs.OrchestratorProfile.OrchestratorType = api.Kubernetes
ucs.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot7
ucs.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot7]
cs.Properties.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot7
cs.Properties.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot7]
uc := UpgradeCluster{
Translator: &i18n.Translator{},
@ -185,32 +168,9 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4")
err := uc.UpgradeCluster(subID, "TestRg", cs, &ucs, "12345678")
err := uc.UpgradeCluster(subID, "TestRg", cs, "12345678")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(Equal("Upgrade to Kubernetes 1.7 is not supported from orchestrator release: 1.5"))
})
It("Should return error message when failing on ClusterPreflightCheck operation", func() {
cs := createContainerService("testcluster", api.KubernetesRelease1Dot7, 3, 3)
ucs := api.UpgradeContainerService{}
ucs.OrchestratorProfile = &api.OrchestratorProfile{}
ucs.OrchestratorProfile.OrchestratorType = api.Kubernetes
ucs.OrchestratorProfile.OrchestratorRelease = api.KubernetesRelease1Dot6
ucs.OrchestratorProfile.OrchestratorVersion = api.KubernetesReleaseToVersion[api.KubernetesRelease1Dot6]
uc := UpgradeCluster{
Translator: &i18n.Translator{},
}
mockClient := armhelpers.MockACSEngineClient{}
uc.Client = &mockClient
subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4")
err := uc.UpgradeCluster(subID, "TestRg", cs, &ucs, "12345678")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(Equal("Upgrade to Kubernetes 1.6 is not supported from orchestrator release: 1.7"))
Expect(err.Error()).To(Equal("Error while querying ARM for resources: Kubernetes:1.5.7 in non-upgradable to 1.7"))
})
})

Просмотреть файл

@ -15,28 +15,18 @@ import (
type Upgrader struct {
Translator *i18n.Translator
ClusterTopology
GoalStateDataModel *api.ContainerService
UpgradeModel *api.UpgradeContainerService
Client armhelpers.ACSEngineClient
Client armhelpers.ACSEngineClient
}
// Init initializes an upgrader struct
func (ku *Upgrader) Init(translator *i18n.Translator, clusterTopology ClusterTopology, upgradeModel *api.UpgradeContainerService, client armhelpers.ACSEngineClient) {
func (ku *Upgrader) Init(translator *i18n.Translator, clusterTopology ClusterTopology, client armhelpers.ACSEngineClient) {
ku.Translator = translator
ku.ClusterTopology = clusterTopology
ku.UpgradeModel = upgradeModel
ku.Client = client
}
// RunUpgrade runs the upgrade pipeline
func (ku *Upgrader) RunUpgrade() error {
ku.GoalStateDataModel = ku.ClusterTopology.DataModel
ku.GoalStateDataModel.Properties.OrchestratorProfile = &api.OrchestratorProfile{
OrchestratorType: api.Kubernetes,
OrchestratorRelease: ku.UpgradeModel.OrchestratorProfile.OrchestratorRelease,
OrchestratorVersion: api.KubernetesReleaseToVersion[ku.UpgradeModel.OrchestratorProfile.OrchestratorRelease],
}
if err := ku.upgradeMasterNodes(); err != nil {
return err
}
@ -54,9 +44,9 @@ func (ku *Upgrader) Validate() error {
}
func (ku *Upgrader) upgradeMasterNodes() error {
log.Infoln(fmt.Sprintf("Master nodes StorageProfile: %s", ku.GoalStateDataModel.Properties.MasterProfile.StorageProfile))
log.Infoln(fmt.Sprintf("Master nodes StorageProfile: %s", ku.ClusterTopology.DataModel.Properties.MasterProfile.StorageProfile))
// Upgrade Master VMs
templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.GoalStateDataModel)
templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.ClusterTopology.DataModel)
if err != nil {
return ku.Translator.Errorf("error generating upgrade template: %s", err.Error())
}
@ -76,11 +66,11 @@ func (ku *Upgrader) upgradeMasterNodes() error {
}
upgradeMasterNode.TemplateMap = templateMap
upgradeMasterNode.ParametersMap = parametersMap
upgradeMasterNode.UpgradeContainerService = ku.GoalStateDataModel
upgradeMasterNode.UpgradeContainerService = ku.ClusterTopology.DataModel
upgradeMasterNode.ResourceGroup = ku.ClusterTopology.ResourceGroup
upgradeMasterNode.Client = ku.Client
expectedMasterCount := ku.GoalStateDataModel.Properties.MasterProfile.Count
expectedMasterCount := ku.ClusterTopology.DataModel.Properties.MasterProfile.Count
mastersUpgradedCount := len(*ku.ClusterTopology.UpgradedMasterVMs)
mastersToUgradeCount := expectedMasterCount - mastersUpgradedCount
@ -171,7 +161,7 @@ func (ku *Upgrader) upgradeMasterNodes() error {
func (ku *Upgrader) upgradeAgentPools() error {
for _, agentPool := range ku.ClusterTopology.AgentPools {
// Upgrade Agent VMs
templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.GoalStateDataModel)
templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.ClusterTopology.DataModel)
if err != nil {
return ku.Translator.Errorf("error generating upgrade template: %s", err.Error())
}
@ -188,7 +178,7 @@ func (ku *Upgrader) upgradeAgentPools() error {
}
var agentCount int
for _, app := range ku.GoalStateDataModel.Properties.AgentPoolProfiles {
for _, app := range ku.ClusterTopology.DataModel.Properties.AgentPoolProfiles {
if app.Name == *agentPool.Name {
agentCount = app.Count
break
@ -200,7 +190,7 @@ func (ku *Upgrader) upgradeAgentPools() error {
}
upgradeAgentNode.TemplateMap = templateMap
upgradeAgentNode.ParametersMap = parametersMap
upgradeAgentNode.UpgradeContainerService = ku.GoalStateDataModel
upgradeAgentNode.UpgradeContainerService = ku.ClusterTopology.DataModel
upgradeAgentNode.ResourceGroup = ku.ClusterTopology.ResourceGroup
upgradeAgentNode.Client = ku.Client

Просмотреть файл

@ -3,8 +3,6 @@ package kubernetesupgrade
// UpgradeWorkFlow outlines various individual high level steps
// that need to be run (one or more times) in the upgrade workflow.
type UpgradeWorkFlow interface {
ClusterPreflightCheck() error
// upgrade masters
// upgrade agent nodes
RunUpgrade() error

Просмотреть файл

@ -1,11 +1,5 @@
package kubernetesupgrade
import (
"fmt"
"github.com/Azure/acs-engine/pkg/api"
)
// Compiler to verify QueueMessageProcessor implements OperationsProcessor
var _ UpgradeWorkFlow = &Kubernetes16upgrader{}
@ -13,16 +7,3 @@ var _ UpgradeWorkFlow = &Kubernetes16upgrader{}
type Kubernetes16upgrader struct {
Upgrader
}
// ClusterPreflightCheck does preflight check
func (ku *Kubernetes16upgrader) ClusterPreflightCheck() error {
// Check that current cluster is 1.5 or 1.6
switch ku.DataModel.Properties.OrchestratorProfile.OrchestratorRelease {
case api.KubernetesRelease1Dot5:
case api.KubernetesRelease1Dot6:
default:
return fmt.Errorf("Upgrade to Kubernetes 1.6 is not supported from orchestrator release: %s",
ku.DataModel.Properties.OrchestratorProfile.OrchestratorRelease)
}
return nil
}

Просмотреть файл

@ -1,11 +1,5 @@
package kubernetesupgrade
import (
"fmt"
"github.com/Azure/acs-engine/pkg/api"
)
// Compiler to verify QueueMessageProcessor implements OperationsProcessor
var _ UpgradeWorkFlow = &Kubernetes17upgrader{}
@ -13,16 +7,3 @@ var _ UpgradeWorkFlow = &Kubernetes17upgrader{}
type Kubernetes17upgrader struct {
Upgrader
}
// ClusterPreflightCheck does preflight check
func (ku *Kubernetes17upgrader) ClusterPreflightCheck() error {
// Check that current cluster is 1.6 or 1.7
switch ku.DataModel.Properties.OrchestratorProfile.OrchestratorRelease {
case api.KubernetesRelease1Dot6:
case api.KubernetesRelease1Dot7:
default:
return fmt.Errorf("Upgrade to Kubernetes 1.7 is not supported from orchestrator release: %s",
ku.DataModel.Properties.OrchestratorProfile.OrchestratorRelease)
}
return nil
}