Skip to content

Commit

Permalink
Complete cluster upgrader implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
g-gaston committed Oct 5, 2021
1 parent eb29630 commit 90d60f6
Show file tree
Hide file tree
Showing 4 changed files with 315 additions and 12 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ mocks: ## Generate mocks
${GOPATH}/bin/mockgen -destination=pkg/providers/vsphere/internal/tags/mocks/govc.go -package=mocks -source "pkg/providers/vsphere/internal/tags/factory.go" GovcClient
${GOPATH}/bin/mockgen -destination=pkg/validations/upgradevalidations/mocks/upgradevalidations.go -package=mocks -source "pkg/validations/upgradevalidations/upgradevalidations.go" ValidationsKubectlClient
${GOPATH}/bin/mockgen -destination=pkg/diagnostics/interfaces/mocks/diagnostics.go -package=mocks -source "pkg/diagnostics/interfaces.go" DiagnosticBundle,AnalyzerFactory,CollectorFactory
${GOPATH}/bin/mockgen -destination=pkg/clusterapi/mocks/capiclient.go -package=mocks -source "pkg/clusterapi/upgrader.go" CAPIClient

.PHONY: verify-mocks
verify-mocks: mocks ## Verify if mocks need to be updated
Expand Down
52 changes: 52 additions & 0 deletions pkg/clusterapi/mocks/capiclient.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

89 changes: 77 additions & 12 deletions pkg/clusterapi/upgrader.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,26 @@ import (
"fmt"

"github.com/aws/eks-anywhere/pkg/cluster"
"github.com/aws/eks-anywhere/pkg/providers"
"github.com/aws/eks-anywhere/pkg/types"
)

type Upgrader struct {
capiClient capiClient
capiClient CAPIClient
}

type capiClient interface {
type CAPIClient interface {
Upgrade(ctx context.Context, managementCluster *types.Cluster, newSpec *cluster.Spec, changeDiff *CAPIChangeDiff) error
}

func (u *Upgrader) Upgrade(ctx context.Context, managementCluster *types.Cluster, currentSpec, newSpec *cluster.Spec) error {
changeDiff := u.capiChangeDiff(currentSpec, newSpec)
func NewUpgrader(client CAPIClient) *Upgrader {
return &Upgrader{
capiClient: client,
}
}

func (u *Upgrader) Upgrade(ctx context.Context, managementCluster *types.Cluster, provider providers.Provider, currentSpec, newSpec *cluster.Spec) error {
changeDiff := u.capiChangeDiff(currentSpec, newSpec, provider)
if changeDiff == nil {
return nil
}
Expand All @@ -36,13 +43,71 @@ type CAPIChangeDiff struct {
InfrastructureProvider *types.ComponentChangeDiff
}

func (u *Upgrader) capiChangeDiff(currentSpec, newSpec *cluster.Spec) *CAPIChangeDiff {
// TODO: check version changes for all providers
return nil
}
func (u *Upgrader) capiChangeDiff(currentSpec, newSpec *cluster.Spec, provider providers.Provider) *CAPIChangeDiff {
changeDiff := &CAPIChangeDiff{}
somethingChanged := false

func (u *Upgrader) ChangeDiff(currentSpec, newSpec *cluster.Spec) *types.ChangeDiff {
u.capiChangeDiff(currentSpec, newSpec)
// TODO: convert from capiChangeDiff to generic changeDiff
return nil
if currentSpec.VersionsBundle.ClusterAPI.Version != newSpec.VersionsBundle.ClusterAPI.Version {
changeDiff.Core = &types.ComponentChangeDiff{
ComponentName: "cluster-api",
NewVersion: newSpec.VersionsBundle.ClusterAPI.Version,
OldVersion: currentSpec.VersionsBundle.ClusterAPI.Version,
}
somethingChanged = true
}

if currentSpec.VersionsBundle.ControlPlane.Version != newSpec.VersionsBundle.ControlPlane.Version {
changeDiff.ControlPlane = &types.ComponentChangeDiff{
ComponentName: "kubeadm",
NewVersion: newSpec.VersionsBundle.ControlPlane.Version,
OldVersion: currentSpec.VersionsBundle.ControlPlane.Version,
}
somethingChanged = true
}

if currentSpec.VersionsBundle.Bootstrap.Version != newSpec.VersionsBundle.Bootstrap.Version {
changeDiff.BootstrapProviders = append(changeDiff.BootstrapProviders,
types.ComponentChangeDiff{
ComponentName: "kubeadm",
NewVersion: newSpec.VersionsBundle.Bootstrap.Version,
OldVersion: currentSpec.VersionsBundle.Bootstrap.Version,
},
)
somethingChanged = true
}

if newSpec.Spec.ExternalEtcdConfiguration != nil {
if currentSpec.VersionsBundle.ExternalEtcdBootstrap.Version != newSpec.VersionsBundle.ExternalEtcdBootstrap.Version {
changeDiff.BootstrapProviders = append(changeDiff.BootstrapProviders,
types.ComponentChangeDiff{
ComponentName: "etcdadm-bootstrap",
NewVersion: newSpec.VersionsBundle.ExternalEtcdBootstrap.Version,
OldVersion: currentSpec.VersionsBundle.ExternalEtcdBootstrap.Version,
},
)
somethingChanged = true
}

if currentSpec.VersionsBundle.ExternalEtcdController.Version != newSpec.VersionsBundle.ExternalEtcdController.Version {
changeDiff.BootstrapProviders = append(changeDiff.BootstrapProviders,
types.ComponentChangeDiff{
ComponentName: "etcdadm-controller",
NewVersion: newSpec.VersionsBundle.ExternalEtcdController.Version,
OldVersion: currentSpec.VersionsBundle.ExternalEtcdController.Version,
},
)
somethingChanged = true
}
}

if providerChangeDiff := provider.ChangeDiff(currentSpec, newSpec); providerChangeDiff != nil {
changeDiff.InfrastructureProvider = providerChangeDiff
somethingChanged = true
}

if !somethingChanged {
return nil
}

return changeDiff
}
185 changes: 185 additions & 0 deletions pkg/clusterapi/upgrader_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package clusterapi_test

import (
"context"
"errors"
"testing"

"github.com/aws/eks-anywhere/pkg/api/v1alpha1"
providerMocks "github.com/aws/eks-anywhere/pkg/providers/mocks"

"github.com/aws/eks-anywhere/internal/test"
"github.com/aws/eks-anywhere/pkg/cluster"
"github.com/aws/eks-anywhere/pkg/clusterapi"
"github.com/aws/eks-anywhere/pkg/clusterapi/mocks"
"github.com/aws/eks-anywhere/pkg/types"
"github.com/golang/mock/gomock"
. "github.com/onsi/gomega"
)

type upgraderTest struct {
*WithT
ctx context.Context
capiClient *mocks.MockCAPIClient
upgrader *clusterapi.Upgrader
currentSpec *cluster.Spec
newSpec *cluster.Spec
cluster *types.Cluster
provider *providerMocks.MockProvider
providerChangeDiff *types.ComponentChangeDiff
}

func newUpgraderTest(t *testing.T) *upgraderTest {
ctrl := gomock.NewController(t)
capiClient := mocks.NewMockCAPIClient(ctrl)

currentSpec := test.NewClusterSpec(func(s *cluster.Spec) {
s.Bundles.Spec.Number = 1
s.VersionsBundle.ClusterAPI.Version = "v0.1.0"
s.VersionsBundle.ControlPlane.Version = "v0.1.0"
s.VersionsBundle.Bootstrap.Version = "v0.1.0"
s.VersionsBundle.ExternalEtcdBootstrap.Version = "v0.1.0"
s.VersionsBundle.ExternalEtcdController.Version = "v0.1.0"
})

return &upgraderTest{
WithT: NewWithT(t),
ctx: context.Background(),
capiClient: capiClient,
upgrader: clusterapi.NewUpgrader(capiClient),
currentSpec: currentSpec,
newSpec: currentSpec.DeepCopy(),
cluster: &types.Cluster{
Name: "cluster-name",
KubeconfigFile: "k.kubeconfig",
},
provider: providerMocks.NewMockProvider(ctrl),
providerChangeDiff: &types.ComponentChangeDiff{
ComponentName: "vsphere",
NewVersion: "v0.2.0",
OldVersion: "v0.1.0",
},
}
}

func TestUpgraderUpgradeNoChanges(t *testing.T) {
tt := newUpgraderTest(t)
tt.provider.EXPECT().ChangeDiff(tt.currentSpec, tt.newSpec).Return(nil)

tt.Expect(tt.upgrader.Upgrade(tt.ctx, tt.cluster, tt.provider, tt.currentSpec, tt.newSpec)).To(Succeed())
}

func TestUpgraderUpgradeProviderChanges(t *testing.T) {
tt := newUpgraderTest(t)
changeDiff := &clusterapi.CAPIChangeDiff{
InfrastructureProvider: tt.providerChangeDiff,
}
tt.provider.EXPECT().ChangeDiff(tt.currentSpec, tt.newSpec).Return(tt.providerChangeDiff)
tt.capiClient.EXPECT().Upgrade(tt.ctx, tt.cluster, tt.newSpec, changeDiff)

tt.Expect(tt.upgrader.Upgrade(tt.ctx, tt.cluster, tt.provider, tt.currentSpec, tt.newSpec)).To(Succeed())
}

func TestUpgraderUpgradeCoreChanges(t *testing.T) {
tt := newUpgraderTest(t)
tt.newSpec.VersionsBundle.ClusterAPI.Version = "v0.2.0"
changeDiff := &clusterapi.CAPIChangeDiff{
Core: &types.ComponentChangeDiff{
ComponentName: "cluster-api",
NewVersion: "v0.2.0",
OldVersion: "v0.1.0",
},
}
tt.provider.EXPECT().ChangeDiff(tt.currentSpec, tt.newSpec).Return(nil)
tt.capiClient.EXPECT().Upgrade(tt.ctx, tt.cluster, tt.newSpec, changeDiff)

tt.Expect(tt.upgrader.Upgrade(tt.ctx, tt.cluster, tt.provider, tt.currentSpec, tt.newSpec)).To(Succeed())
}

func TestUpgraderUpgradeEverythingChangesStackedEtcd(t *testing.T) {
tt := newUpgraderTest(t)
tt.newSpec.VersionsBundle.ClusterAPI.Version = "v0.2.0"
tt.newSpec.VersionsBundle.ControlPlane.Version = "v0.2.0"
tt.newSpec.VersionsBundle.Bootstrap.Version = "v0.2.0"
tt.newSpec.VersionsBundle.ExternalEtcdBootstrap.Version = "v0.2.0"
tt.newSpec.VersionsBundle.ExternalEtcdController.Version = "v0.2.0"
changeDiff := &clusterapi.CAPIChangeDiff{
Core: &types.ComponentChangeDiff{
ComponentName: "cluster-api",
NewVersion: "v0.2.0",
OldVersion: "v0.1.0",
},
ControlPlane: &types.ComponentChangeDiff{
ComponentName: "kubeadm",
NewVersion: "v0.2.0",
OldVersion: "v0.1.0",
},
BootstrapProviders: []types.ComponentChangeDiff{
{
ComponentName: "kubeadm",
NewVersion: "v0.2.0",
OldVersion: "v0.1.0",
},
},
InfrastructureProvider: tt.providerChangeDiff,
}
tt.provider.EXPECT().ChangeDiff(tt.currentSpec, tt.newSpec).Return(tt.providerChangeDiff)
tt.capiClient.EXPECT().Upgrade(tt.ctx, tt.cluster, tt.newSpec, changeDiff)

tt.Expect(tt.upgrader.Upgrade(tt.ctx, tt.cluster, tt.provider, tt.currentSpec, tt.newSpec)).To(Succeed())
}

func TestUpgraderUpgradeEverythingChangesExternalEtcd(t *testing.T) {
tt := newUpgraderTest(t)
tt.newSpec.Spec.ExternalEtcdConfiguration = &v1alpha1.ExternalEtcdConfiguration{}
tt.newSpec.VersionsBundle.ClusterAPI.Version = "v0.2.0"
tt.newSpec.VersionsBundle.ControlPlane.Version = "v0.2.0"
tt.newSpec.VersionsBundle.Bootstrap.Version = "v0.2.0"
tt.newSpec.VersionsBundle.ExternalEtcdBootstrap.Version = "v0.2.0"
tt.newSpec.VersionsBundle.ExternalEtcdController.Version = "v0.2.0"
changeDiff := &clusterapi.CAPIChangeDiff{
Core: &types.ComponentChangeDiff{
ComponentName: "cluster-api",
NewVersion: "v0.2.0",
OldVersion: "v0.1.0",
},
ControlPlane: &types.ComponentChangeDiff{
ComponentName: "kubeadm",
NewVersion: "v0.2.0",
OldVersion: "v0.1.0",
},
BootstrapProviders: []types.ComponentChangeDiff{
{
ComponentName: "kubeadm",
NewVersion: "v0.2.0",
OldVersion: "v0.1.0",
},
{
ComponentName: "etcdadm-bootstrap",
NewVersion: "v0.2.0",
OldVersion: "v0.1.0",
},
{
ComponentName: "etcdadm-controller",
NewVersion: "v0.2.0",
OldVersion: "v0.1.0",
},
},
InfrastructureProvider: tt.providerChangeDiff,
}
tt.provider.EXPECT().ChangeDiff(tt.currentSpec, tt.newSpec).Return(tt.providerChangeDiff)
tt.capiClient.EXPECT().Upgrade(tt.ctx, tt.cluster, tt.newSpec, changeDiff)

tt.Expect(tt.upgrader.Upgrade(tt.ctx, tt.cluster, tt.provider, tt.currentSpec, tt.newSpec)).To(Succeed())
}

func TestUpgraderUpgradeCAPIClientError(t *testing.T) {
tt := newUpgraderTest(t)
changeDiff := &clusterapi.CAPIChangeDiff{
InfrastructureProvider: tt.providerChangeDiff,
}
tt.provider.EXPECT().ChangeDiff(tt.currentSpec, tt.newSpec).Return(tt.providerChangeDiff)
tt.capiClient.EXPECT().Upgrade(tt.ctx, tt.cluster, tt.newSpec, changeDiff).Return(errors.New("error from client"))

tt.Expect(tt.upgrader.Upgrade(tt.ctx, tt.cluster, tt.provider, tt.currentSpec, tt.newSpec)).NotTo(Succeed())
}

0 comments on commit 90d60f6

Please sign in to comment.