diff --git a/Makefile b/Makefile index df6fed1f3fdf1..69dcd15890ba3 100644 --- a/Makefile +++ b/Makefile @@ -543,7 +543,7 @@ mocks: ## Generate mocks ${MOCKGEN} -destination=pkg/bootstrapper/mocks/bootstrapper.go -package=mocks "github.com/aws/eks-anywhere/pkg/bootstrapper" ClusterClient ${MOCKGEN} -destination=pkg/git/providers/github/mocks/github.go -package=mocks "github.com/aws/eks-anywhere/pkg/git/providers/github" GithubClient ${MOCKGEN} -destination=pkg/git/mocks/git.go -package=mocks "github.com/aws/eks-anywhere/pkg/git" Client,ProviderClient - ${MOCKGEN} -destination=pkg/workflows/interfaces/mocks/clients.go -package=mocks "github.com/aws/eks-anywhere/pkg/workflows/interfaces" Bootstrapper,ClusterManager,GitOpsManager,Validator,CAPIManager,EksdInstaller,EksdUpgrader,PackageInstaller,ClusterUpgrader,ClusterCreator + ${MOCKGEN} -destination=pkg/workflows/interfaces/mocks/clients.go -package=mocks "github.com/aws/eks-anywhere/pkg/workflows/interfaces" Bootstrapper,ClusterManager,GitOpsManager,Validator,CAPIManager,EksdInstaller,EksdUpgrader,PackageInstaller,ClusterUpgrader,ClusterCreator,ClientFactory ${MOCKGEN} -destination=pkg/git/gogithub/mocks/client.go -package=mocks "github.com/aws/eks-anywhere/pkg/git/gogithub" Client ${MOCKGEN} -destination=pkg/git/gitclient/mocks/client.go -package=mocks "github.com/aws/eks-anywhere/pkg/git/gitclient" GoGit ${MOCKGEN} -destination=pkg/validations/mocks/docker.go -package=mocks "github.com/aws/eks-anywhere/pkg/validations" DockerExecutable diff --git a/cmd/eksctl-anywhere/cmd/createcluster.go b/cmd/eksctl-anywhere/cmd/createcluster.go index b9bd6afeaffa8..2ed57746dfd0e 100644 --- a/cmd/eksctl-anywhere/cmd/createcluster.go +++ b/cmd/eksctl-anywhere/cmd/createcluster.go @@ -205,14 +205,8 @@ func (cc *createClusterOptions) createCluster(cmd *cobra.Command, _ []string) er return err } - clusterKubeconfig := kubeconfig.FromClusterName(clusterSpec.Cluster.Name) - client, err := deps.UnAuthKubeClient.BuildClientFromKubeconfig(clusterKubeconfig) - if err != nil { - return err - } - createCluster := workflows.NewCreate( - client, + deps.UnAuthKubeClient, deps.Bootstrapper, deps.Provider, deps.ClusterManager, @@ -229,7 +223,7 @@ func (cc *createClusterOptions) createCluster(cmd *cobra.Command, _ []string) er Spec: clusterSpec, WorkloadCluster: &types.Cluster{ Name: clusterSpec.Cluster.Name, - KubeconfigFile: clusterKubeconfig, + KubeconfigFile: kubeconfig.FromClusterName(clusterSpec.Cluster.Name), }, ManagementCluster: mgmt, Provider: deps.Provider, diff --git a/cmd/eksctl-anywhere/cmd/upgradecluster.go b/cmd/eksctl-anywhere/cmd/upgradecluster.go index cfb4280db629c..a7f8f24bd3705 100644 --- a/cmd/eksctl-anywhere/cmd/upgradecluster.go +++ b/cmd/eksctl-anywhere/cmd/upgradecluster.go @@ -201,13 +201,9 @@ func (uc *upgradeClusterOptions) upgradeCluster(cmd *cobra.Command, args []strin upgradeValidations := upgradevalidations.New(validationOpts) - client, err := deps.UnAuthKubeClient.BuildClientFromKubeconfig(workloadCluster.KubeconfigFile) - if err != nil { - return err - } if clusterConfig.IsSelfManaged() { upgrade := management.NewUpgrade( - client, + deps.UnAuthKubeClient, deps.Provider, deps.CAPIManager, deps.ClusterManager, diff --git a/cmd/eksctl-anywhere/cmd/upgrademanagementcomponents.go b/cmd/eksctl-anywhere/cmd/upgrademanagementcomponents.go index e2ff7dc221987..72b29ecdffa60 100644 --- a/cmd/eksctl-anywhere/cmd/upgrademanagementcomponents.go +++ b/cmd/eksctl-anywhere/cmd/upgrademanagementcomponents.go @@ -70,13 +70,8 @@ var upgradeManagementComponentsCmd = &cobra.Command{ } defer close(cmd.Context(), deps) - clusterKubeconfig := kubeconfig.FromClusterName(clusterSpec.Cluster.Name) - client, err := deps.UnAuthKubeClient.BuildClientFromKubeconfig(clusterKubeconfig) - if err != nil { - return err - } runner := management.NewUpgradeManagementComponentsRunner( - client, + deps.UnAuthKubeClient, deps.Provider, deps.CAPIManager, deps.ClusterManager, @@ -88,7 +83,7 @@ var upgradeManagementComponentsCmd = &cobra.Command{ managementCluster := &types.Cluster{ Name: clusterSpec.Cluster.Name, - KubeconfigFile: clusterKubeconfig, + KubeconfigFile: kubeconfig.FromClusterName(clusterSpec.Cluster.Name), } validator := management.NewUMCValidator(managementCluster, deps.Kubectl) diff --git a/pkg/api/v1alpha1/cluster_types.go b/pkg/api/v1alpha1/cluster_types.go index f40da3f43fa9d..a67be6d5a7367 100644 --- a/pkg/api/v1alpha1/cluster_types.go +++ b/pkg/api/v1alpha1/cluster_types.go @@ -1299,8 +1299,8 @@ func (c *Cluster) ControlPlaneAnnotation() string { return controlPlaneAnnotation } -// SetManagmentComponentsVersion sets the `eksa-management-components version` annotation on the Cluster object. -func (c *Cluster) SetManagmentComponentsVersion(version string) { +// SetManagementComponentsVersion sets the `eksa-management-components version` annotation on the Cluster object. +func (c *Cluster) SetManagementComponentsVersion(version string) { if c.IsManaged() { return } diff --git a/pkg/api/v1alpha1/cluster_types_test.go b/pkg/api/v1alpha1/cluster_types_test.go index 86787528abfb4..4788b7f4919d7 100644 --- a/pkg/api/v1alpha1/cluster_types_test.go +++ b/pkg/api/v1alpha1/cluster_types_test.go @@ -3232,34 +3232,33 @@ func TestValidateCluster(t *testing.T) { } func TestCluster_SetManagmentComponentsVersion(t *testing.T) { - managmentClusterName := "mgmt-cluster" - expectedManagmentComponentVersion := "v0.0.0-dev+build.0000" - testCases := []struct { - name string - cluster *v1alpha1.Cluster - wantAnnotations map[string]string + name string + cluster *v1alpha1.Cluster + managementComponentsVersion string + wantManagementComponentsVersion string + wantAnnotations map[string]string }{ { - name: "self-managed cluster", - cluster: baseCluster(func(c *v1alpha1.Cluster) { - c.SetManagmentComponentsVersion(expectedManagmentComponentVersion) - }), - wantAnnotations: map[string]string{"anywhere.eks.amazonaws.com/eksa-management-components-version": expectedManagmentComponentVersion}, + name: "self-managed cluster", + cluster: baseCluster(), + managementComponentsVersion: "v0.0.0-dev+build.0000", + wantAnnotations: map[string]string{"anywhere.eks.amazonaws.com/eksa-management-components-version": "v0.0.0-dev+build.0000"}, }, { name: "managed cluster", cluster: baseCluster(func(c *v1alpha1.Cluster) { - c.SetManagedBy(managmentClusterName) - c.SetManagmentComponentsVersion(expectedManagmentComponentVersion) + c.SetManagedBy("mgmt-cluster") }), - wantAnnotations: map[string]string{"anywhere.eks.amazonaws.com/managed-by": managmentClusterName}, + managementComponentsVersion: "v0.0.0-dev+build.0000", + wantAnnotations: map[string]string{"anywhere.eks.amazonaws.com/managed-by": "mgmt-cluster"}, }, } for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) + tt.cluster.SetManagementComponentsVersion(tt.managementComponentsVersion) g.Expect(tt.cluster.Annotations).To(Equal(tt.wantAnnotations)) }) } diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 605aeff0cfcfc..813cc7bd79734 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -99,3 +99,6 @@ const ( Upgrade Operation = 1 Delete Operation = 2 ) + +// EKSAFieldManager is the owner name for fields applied by the EKS-A CLI. +const EKSAFieldManager = "eks-a-cli" diff --git a/pkg/task/task.go b/pkg/task/task.go index 1805608441fa5..d77f8f09bc43c 100644 --- a/pkg/task/task.go +++ b/pkg/task/task.go @@ -9,7 +9,6 @@ import ( "sigs.k8s.io/yaml" - "github.com/aws/eks-anywhere/pkg/clients/kubernetes" "github.com/aws/eks-anywhere/pkg/cluster" "github.com/aws/eks-anywhere/pkg/filewriter" "github.com/aws/eks-anywhere/pkg/logger" @@ -28,7 +27,7 @@ type Task interface { // Command context maintains the mutable and shared entities. type CommandContext struct { - Client kubernetes.Client + ClientFactory interfaces.ClientFactory Bootstrapper interfaces.Bootstrapper Provider providers.Provider ClusterManager interfaces.ClusterManager diff --git a/pkg/workflows/create.go b/pkg/workflows/create.go index 54f993663a42a..0c84e19c6010c 100644 --- a/pkg/workflows/create.go +++ b/pkg/workflows/create.go @@ -17,12 +17,8 @@ import ( "github.com/aws/eks-anywhere/pkg/workflows/interfaces" ) -const ( - eksaFieldManager = "eks-a-cli" -) - type Create struct { - client kubernetes.Client + clientFactory interfaces.ClientFactory bootstrapper interfaces.Bootstrapper provider providers.Provider clusterManager interfaces.ClusterManager @@ -33,13 +29,13 @@ type Create struct { } // NewCreate returns a Create instance. -func NewCreate(client kubernetes.Client, bootstrapper interfaces.Bootstrapper, provider providers.Provider, +func NewCreate(clientFactory interfaces.ClientFactory, bootstrapper interfaces.Bootstrapper, provider providers.Provider, clusterManager interfaces.ClusterManager, gitOpsManager interfaces.GitOpsManager, writer filewriter.FileWriter, eksdInstaller interfaces.EksdInstaller, packageInstaller interfaces.PackageInstaller, ) *Create { return &Create{ - client: client, + clientFactory: clientFactory, bootstrapper: bootstrapper, provider: provider, clusterManager: clusterManager, @@ -59,7 +55,7 @@ func (c *Create) Run(ctx context.Context, clusterSpec *cluster.Spec, validator i } } commandContext := &task.CommandContext{ - Client: c.client, + ClientFactory: c.clientFactory, Bootstrapper: c.bootstrapper, Provider: c.provider, ClusterManager: c.clusterManager, @@ -382,9 +378,15 @@ func (s *InstallEksaComponentsTask) Run(ctx context.Context, commandContext *tas return &CollectDiagnosticsTask{} } - commandContext.ClusterSpec.Cluster.SetManagmentComponentsVersion(commandContext.ClusterSpec.EKSARelease.Spec.Version) - if err := commandContext.Client.ApplyServerSide(ctx, - eksaFieldManager, + client, err := commandContext.ClientFactory.BuildClientFromKubeconfig(targetCluster.KubeconfigFile) + if err != nil { + commandContext.SetError(err) + return &CollectDiagnosticsTask{} + } + + commandContext.ClusterSpec.Cluster.SetManagementComponentsVersion(commandContext.ClusterSpec.EKSARelease.Spec.Version) + if err := client.ApplyServerSide(ctx, + constants.EKSAFieldManager, commandContext.ClusterSpec.Cluster, kubernetes.ApplyServerSideOptions{ForceOwnership: true}, ); err != nil { diff --git a/pkg/workflows/create_test.go b/pkg/workflows/create_test.go index bc48aa1019ebc..f030a6934713a 100644 --- a/pkg/workflows/create_test.go +++ b/pkg/workflows/create_test.go @@ -14,6 +14,7 @@ import ( "github.com/aws/eks-anywhere/pkg/clients/kubernetes" clientmocks "github.com/aws/eks-anywhere/pkg/clients/kubernetes/mocks" "github.com/aws/eks-anywhere/pkg/cluster" + "github.com/aws/eks-anywhere/pkg/constants" writermocks "github.com/aws/eks-anywhere/pkg/filewriter/mocks" "github.com/aws/eks-anywhere/pkg/providers" providermocks "github.com/aws/eks-anywhere/pkg/providers/mocks" @@ -26,6 +27,7 @@ import ( type createTestSetup struct { t *testing.T client *clientmocks.MockClient + clientFactory *mocks.MockClientFactory packageInstaller *mocks.MockPackageInstaller bootstrapper *mocks.MockBootstrapper clusterManager *mocks.MockClusterManager @@ -47,6 +49,7 @@ type createTestSetup struct { func newCreateTest(t *testing.T) *createTestSetup { mockCtrl := gomock.NewController(t) client := clientmocks.NewMockClient(mockCtrl) + clientFactory := mocks.NewMockClientFactory(mockCtrl) bootstrapper := mocks.NewMockBootstrapper(mockCtrl) clusterManager := mocks.NewMockClusterManager(mockCtrl) gitOpsManager := mocks.NewMockGitOpsManager(mockCtrl) @@ -57,12 +60,13 @@ func newCreateTest(t *testing.T) *createTestSetup { datacenterConfig := &v1alpha1.VSphereDatacenterConfig{} machineConfigs := []providers.MachineConfig{&v1alpha1.VSphereMachineConfig{}} - workflow := workflows.NewCreate(client, bootstrapper, provider, clusterManager, gitOpsManager, writer, eksd, packageInstaller) + workflow := workflows.NewCreate(clientFactory, bootstrapper, provider, clusterManager, gitOpsManager, writer, eksd, packageInstaller) validator := mocks.NewMockValidator(mockCtrl) return &createTestSetup{ t: t, client: client, + clientFactory: clientFactory, bootstrapper: bootstrapper, clusterManager: clusterManager, gitOpsManager: gitOpsManager, @@ -207,9 +211,11 @@ func (c *createTestSetup) expectInstallEksaComponents() { c.eksd.EXPECT().InstallEksdManifest( c.ctx, c.clusterSpec, c.workloadCluster), + c.clientFactory.EXPECT().BuildClientFromKubeconfig(c.workloadCluster.KubeconfigFile).Return(c.client, nil), + c.client.EXPECT().ApplyServerSide( c.ctx, - "eks-a-cli", + constants.EKSAFieldManager, c.clusterSpec.Cluster, kubernetes.ApplyServerSideOptions{ForceOwnership: true}, ), @@ -236,9 +242,11 @@ func (c *createTestSetup) skipInstallEksaComponents() { c.eksd.EXPECT().InstallEksdManifest( c.ctx, c.clusterSpec, c.bootstrapCluster), + c.clientFactory.EXPECT().BuildClientFromKubeconfig(c.bootstrapCluster.KubeconfigFile).Return(c.client, nil), + c.client.EXPECT().ApplyServerSide( c.ctx, - "eks-a-cli", + constants.EKSAFieldManager, c.clusterSpec.Cluster, kubernetes.ApplyServerSideOptions{ForceOwnership: true}, ), @@ -312,7 +320,7 @@ func TestCreateRunSuccess(t *testing.T) { } } -func TestCreateRunInstallEksaComponentsApplyFail(t *testing.T) { +func TestCreateRunInstallEksaComponentsBuildClientFailure(t *testing.T) { wantError := errors.New("test error") test := newCreateTest(t) @@ -339,9 +347,49 @@ func TestCreateRunInstallEksaComponentsApplyFail(t *testing.T) { test.eksd.EXPECT().InstallEksdManifest( test.ctx, test.clusterSpec, test.workloadCluster), + test.clientFactory.EXPECT().BuildClientFromKubeconfig(test.workloadCluster.KubeconfigFile).Return(nil, wantError), + ) + test.clusterManager.EXPECT().SaveLogsManagementCluster(test.ctx, test.clusterSpec, test.bootstrapCluster) + test.clusterManager.EXPECT().SaveLogsWorkloadCluster(test.ctx, test.provider, test.clusterSpec, test.workloadCluster) + test.writer.EXPECT().Write(fmt.Sprintf("%s-checkpoint.yaml", test.clusterSpec.Cluster.Name), gomock.Any()) + + if err := test.run(); err == nil { + t.Fatalf("Create.Run() err = %v, want err = %v", err, wantError) + } +} + +func TestCreateRunInstallEksaComponentsApplyServerSideFailure(t *testing.T) { + wantError := errors.New("test error") + test := newCreateTest(t) + + test.expectSetup() + test.expectPreflightValidationsToPass() + test.expectCreateBootstrap() + test.expectCreateWorkload() + test.expectInstallResourcesOnManagementTask() + test.expectMoveManagement() + gomock.InOrder( + test.clusterManager.EXPECT().InstallCustomComponents( + test.ctx, test.clusterSpec, test.workloadCluster, test.provider), + + test.eksd.EXPECT().InstallEksdCRDs(test.ctx, test.clusterSpec, test.workloadCluster), + + test.provider.EXPECT().DatacenterConfig(test.clusterSpec).Return(test.datacenterConfig), + + test.provider.EXPECT().MachineConfigs(test.clusterSpec).Return(test.machineConfigs), + + test.clusterManager.EXPECT().CreateEKSAResources( + test.ctx, test.workloadCluster, test.clusterSpec, test.datacenterConfig, test.machineConfigs, + ), + + test.eksd.EXPECT().InstallEksdManifest( + test.ctx, test.clusterSpec, test.workloadCluster), + + test.clientFactory.EXPECT().BuildClientFromKubeconfig(test.workloadCluster.KubeconfigFile).Return(test.client, nil), + test.client.EXPECT().ApplyServerSide( test.ctx, - "eks-a-cli", + constants.EKSAFieldManager, test.clusterSpec.Cluster, kubernetes.ApplyServerSideOptions{ForceOwnership: true}, ).Return(wantError), diff --git a/pkg/workflows/interfaces/interfaces.go b/pkg/workflows/interfaces/interfaces.go index 53bf52cb2eea8..82c748d9afd5f 100644 --- a/pkg/workflows/interfaces/interfaces.go +++ b/pkg/workflows/interfaces/interfaces.go @@ -4,6 +4,7 @@ import ( "context" "github.com/aws/eks-anywhere/pkg/bootstrapper" + "github.com/aws/eks-anywhere/pkg/clients/kubernetes" "github.com/aws/eks-anywhere/pkg/cluster" "github.com/aws/eks-anywhere/pkg/constants" "github.com/aws/eks-anywhere/pkg/providers" @@ -11,6 +12,12 @@ import ( "github.com/aws/eks-anywhere/pkg/validations" ) +// ClientFactory builds Kubernetes clients. +type ClientFactory interface { + // BuildClientFromKubeconfig builds a Kubernetes client from a kubeconfig file. + BuildClientFromKubeconfig(kubeconfigPath string) (kubernetes.Client, error) +} + type Bootstrapper interface { CreateBootstrapCluster(ctx context.Context, clusterSpec *cluster.Spec, opts ...bootstrapper.BootstrapClusterOption) (*types.Cluster, error) DeleteBootstrapCluster(context.Context, *types.Cluster, constants.Operation, bool) error diff --git a/pkg/workflows/interfaces/mocks/clients.go b/pkg/workflows/interfaces/mocks/clients.go index 4e09d90db0327..daaf50e0dfd80 100644 --- a/pkg/workflows/interfaces/mocks/clients.go +++ b/pkg/workflows/interfaces/mocks/clients.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/aws/eks-anywhere/pkg/workflows/interfaces (interfaces: Bootstrapper,ClusterManager,GitOpsManager,Validator,CAPIManager,EksdInstaller,EksdUpgrader,PackageInstaller,ClusterUpgrader,ClusterCreator) +// Source: github.com/aws/eks-anywhere/pkg/workflows/interfaces (interfaces: Bootstrapper,ClusterManager,GitOpsManager,Validator,CAPIManager,EksdInstaller,EksdUpgrader,PackageInstaller,ClusterUpgrader,ClusterCreator,ClientFactory) // Package mocks is a generated GoMock package. package mocks @@ -9,6 +9,7 @@ import ( reflect "reflect" bootstrapper "github.com/aws/eks-anywhere/pkg/bootstrapper" + kubernetes "github.com/aws/eks-anywhere/pkg/clients/kubernetes" cluster "github.com/aws/eks-anywhere/pkg/cluster" constants "github.com/aws/eks-anywhere/pkg/constants" providers "github.com/aws/eks-anywhere/pkg/providers" @@ -949,3 +950,41 @@ func (mr *MockClusterCreatorMockRecorder) Run(arg0, arg1, arg2 interface{}) *gom mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockClusterCreator)(nil).Run), arg0, arg1, arg2) } + +// MockClientFactory is a mock of ClientFactory interface. +type MockClientFactory struct { + ctrl *gomock.Controller + recorder *MockClientFactoryMockRecorder +} + +// MockClientFactoryMockRecorder is the mock recorder for MockClientFactory. +type MockClientFactoryMockRecorder struct { + mock *MockClientFactory +} + +// NewMockClientFactory creates a new mock instance. +func NewMockClientFactory(ctrl *gomock.Controller) *MockClientFactory { + mock := &MockClientFactory{ctrl: ctrl} + mock.recorder = &MockClientFactoryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockClientFactory) EXPECT() *MockClientFactoryMockRecorder { + return m.recorder +} + +// BuildClientFromKubeconfig mocks base method. +func (m *MockClientFactory) BuildClientFromKubeconfig(arg0 string) (kubernetes.Client, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BuildClientFromKubeconfig", arg0) + ret0, _ := ret[0].(kubernetes.Client) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// BuildClientFromKubeconfig indicates an expected call of BuildClientFromKubeconfig. +func (mr *MockClientFactoryMockRecorder) BuildClientFromKubeconfig(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildClientFromKubeconfig", reflect.TypeOf((*MockClientFactory)(nil).BuildClientFromKubeconfig), arg0) +} diff --git a/pkg/workflows/management/core_components.go b/pkg/workflows/management/core_components.go index 2c973cf889a1b..bffd33971fb68 100644 --- a/pkg/workflows/management/core_components.go +++ b/pkg/workflows/management/core_components.go @@ -4,16 +4,13 @@ import ( "context" "github.com/aws/eks-anywhere/pkg/clients/kubernetes" + "github.com/aws/eks-anywhere/pkg/constants" "github.com/aws/eks-anywhere/pkg/logger" "github.com/aws/eks-anywhere/pkg/task" "github.com/aws/eks-anywhere/pkg/types" "github.com/aws/eks-anywhere/pkg/workflows" ) -const ( - eksaFieldManager = "eks-a-cli" -) - type ensureEtcdCAPIComponentsExist struct{} // Run ensureEtcdCAPIComponentsExist ensures ETCD CAPI providers on the management cluster. @@ -90,9 +87,14 @@ func runUpgradeCoreComponents(ctx context.Context, commandContext *task.CommandC } commandContext.UpgradeChangeDiff.Append(changeDiff) - commandContext.ClusterSpec.Cluster.SetManagmentComponentsVersion(commandContext.ClusterSpec.EKSARelease.Spec.Version) - if err := commandContext.Client.ApplyServerSide(ctx, - eksaFieldManager, + client, err := commandContext.ClientFactory.BuildClientFromKubeconfig(commandContext.ManagementCluster.KubeconfigFile) + if err != nil { + commandContext.SetError(err) + return err + } + commandContext.ClusterSpec.Cluster.SetManagementComponentsVersion(commandContext.ClusterSpec.EKSARelease.Spec.Version) + if err := client.ApplyServerSide(ctx, + constants.EKSAFieldManager, commandContext.ClusterSpec.Cluster, kubernetes.ApplyServerSideOptions{ForceOwnership: true}, ); err != nil { diff --git a/pkg/workflows/management/upgrade.go b/pkg/workflows/management/upgrade.go index ff40730328b16..738e72dafbd01 100644 --- a/pkg/workflows/management/upgrade.go +++ b/pkg/workflows/management/upgrade.go @@ -3,7 +3,6 @@ package management import ( "context" - "github.com/aws/eks-anywhere/pkg/clients/kubernetes" "github.com/aws/eks-anywhere/pkg/cluster" "github.com/aws/eks-anywhere/pkg/features" "github.com/aws/eks-anywhere/pkg/filewriter" @@ -15,7 +14,7 @@ import ( // Upgrade is a schema for upgrade cluster. type Upgrade struct { - client kubernetes.Client + clientFactory interfaces.ClientFactory provider providers.Provider clusterManager interfaces.ClusterManager gitOpsManager interfaces.GitOpsManager @@ -28,7 +27,7 @@ type Upgrade struct { } // NewUpgrade builds a new upgrade construct. -func NewUpgrade(client kubernetes.Client, provider providers.Provider, +func NewUpgrade(clientFactory interfaces.ClientFactory, provider providers.Provider, capiManager interfaces.CAPIManager, clusterManager interfaces.ClusterManager, gitOpsManager interfaces.GitOpsManager, @@ -39,7 +38,7 @@ func NewUpgrade(client kubernetes.Client, provider providers.Provider, ) *Upgrade { upgradeChangeDiff := types.NewChangeDiff() return &Upgrade{ - client: client, + clientFactory: clientFactory, provider: provider, clusterManager: clusterManager, gitOpsManager: gitOpsManager, @@ -55,7 +54,7 @@ func NewUpgrade(client kubernetes.Client, provider providers.Provider, // Run Upgrade implements upgrade functionality for management cluster's upgrade operation. func (c *Upgrade) Run(ctx context.Context, clusterSpec *cluster.Spec, managementCluster *types.Cluster, validator interfaces.Validator) error { commandContext := &task.CommandContext{ - Client: c.client, + ClientFactory: c.clientFactory, Provider: c.provider, ClusterManager: c.clusterManager, GitOpsManager: c.gitOpsManager, diff --git a/pkg/workflows/management/upgrade_management_components.go b/pkg/workflows/management/upgrade_management_components.go index b0637e178eb78..c99da5644ddfd 100644 --- a/pkg/workflows/management/upgrade_management_components.go +++ b/pkg/workflows/management/upgrade_management_components.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - "github.com/aws/eks-anywhere/pkg/clients/kubernetes" "github.com/aws/eks-anywhere/pkg/cluster" "github.com/aws/eks-anywhere/pkg/executables" "github.com/aws/eks-anywhere/pkg/filewriter" @@ -19,7 +18,7 @@ import ( // UpgradeManagementComponentsWorkflow is a schema for upgrade management components. type UpgradeManagementComponentsWorkflow struct { - client kubernetes.Client + clientFactory interfaces.ClientFactory provider providers.Provider clusterManager interfaces.ClusterManager gitOpsManager interfaces.GitOpsManager @@ -31,7 +30,7 @@ type UpgradeManagementComponentsWorkflow struct { // NewUpgradeManagementComponentsRunner builds a new UpgradeManagementCommponents construct. func NewUpgradeManagementComponentsRunner( - client kubernetes.Client, + clientFactory interfaces.ClientFactory, provider providers.Provider, capiManager interfaces.CAPIManager, clusterManager interfaces.ClusterManager, @@ -41,7 +40,7 @@ func NewUpgradeManagementComponentsRunner( eksdInstaller interfaces.EksdInstaller, ) *UpgradeManagementComponentsWorkflow { return &UpgradeManagementComponentsWorkflow{ - client: client, + clientFactory: clientFactory, provider: provider, clusterManager: clusterManager, gitOpsManager: gitOpsManager, @@ -91,7 +90,7 @@ func (u *UMCValidator) PreflightValidations(ctx context.Context) []validations.V // Run Upgrade implements upgrade functionality for management cluster's upgrade operation. func (umc *UpgradeManagementComponentsWorkflow) Run(ctx context.Context, clusterSpec *cluster.Spec, managementCluster *types.Cluster, validator interfaces.Validator) error { commandContext := &task.CommandContext{ - Client: umc.client, + ClientFactory: umc.clientFactory, Provider: umc.provider, ClusterManager: umc.clusterManager, ManagementCluster: managementCluster, diff --git a/pkg/workflows/management/upgrade_management_components_test.go b/pkg/workflows/management/upgrade_management_components_test.go index 78b27ec8562de..19788625e656b 100644 --- a/pkg/workflows/management/upgrade_management_components_test.go +++ b/pkg/workflows/management/upgrade_management_components_test.go @@ -11,6 +11,7 @@ import ( "github.com/aws/eks-anywhere/internal/test" "github.com/aws/eks-anywhere/pkg/clients/kubernetes" clientmocks "github.com/aws/eks-anywhere/pkg/clients/kubernetes/mocks" + "github.com/aws/eks-anywhere/pkg/constants" writermocks "github.com/aws/eks-anywhere/pkg/filewriter/mocks" "github.com/aws/eks-anywhere/pkg/kubeconfig" providermocks "github.com/aws/eks-anywhere/pkg/providers/mocks" @@ -46,6 +47,7 @@ var eksdChangeDiff = types.NewChangeDiff(&types.ComponentChangeDiff{ type TestMocks struct { mockCtrl *gomock.Controller client *clientmocks.MockClient + clientFactory *mocks.MockClientFactory clusterManager *mocks.MockClusterManager gitOpsManager *mocks.MockGitOpsManager provider *providermocks.MockProvider @@ -61,6 +63,7 @@ func NewTestMocks(t *testing.T) *TestMocks { return &TestMocks{ mockCtrl: mockCtrl, client: clientmocks.NewMockClient(mockCtrl), + clientFactory: mocks.NewMockClientFactory(mockCtrl), clusterManager: mocks.NewMockClusterManager(mockCtrl), gitOpsManager: mocks.NewMockGitOpsManager(mockCtrl), provider: providermocks.NewMockProvider(mockCtrl), @@ -75,7 +78,7 @@ func NewTestMocks(t *testing.T) *TestMocks { func TestRunnerHappyPath(t *testing.T) { mocks := NewTestMocks(t) runner := NewUpgradeManagementComponentsRunner( - mocks.client, + mocks.clientFactory, mocks.provider, mocks.capiManager, mocks.clusterManager, @@ -87,8 +90,8 @@ func TestRunnerHappyPath(t *testing.T) { clusterSpec := test.NewClusterSpec() managementCluster := &types.Cluster{ - Name: clusterSpec.Cluster.Name, - KubeconfigFile: kubeconfig.FromClusterName(clusterSpec.Cluster.Name), + Name: clusterSpec.Cluster.Name, + KubeconfigFile: kubeconfig.FromClusterName(clusterSpec.Cluster.Name), } ctx := context.Background() @@ -106,9 +109,10 @@ func TestRunnerHappyPath(t *testing.T) { mocks.gitOpsManager.EXPECT().Upgrade(ctx, managementCluster, curSpec, newSpec).Return(fluxChangeDiff, nil), mocks.clusterManager.EXPECT().Upgrade(ctx, managementCluster, curSpec, newSpec).Return(eksaChangeDiff, nil), mocks.eksdUpgrader.EXPECT().Upgrade(ctx, managementCluster, curSpec, newSpec).Return(eksdChangeDiff, nil), + mocks.clientFactory.EXPECT().BuildClientFromKubeconfig(managementCluster.KubeconfigFile).Return(mocks.client, nil), mocks.client.EXPECT().ApplyServerSide( ctx, - "eks-a-cli", + constants.EKSAFieldManager, newSpec.Cluster, kubernetes.ApplyServerSideOptions{ForceOwnership: true}, ).Return(nil), @@ -132,7 +136,7 @@ func TestRunnerHappyPath(t *testing.T) { func TestRunnerStopsWhenValidationFailed(t *testing.T) { mocks := NewTestMocks(t) runner := NewUpgradeManagementComponentsRunner( - mocks.client, + mocks.clientFactory, mocks.provider, mocks.capiManager, mocks.clusterManager, @@ -144,8 +148,8 @@ func TestRunnerStopsWhenValidationFailed(t *testing.T) { clusterSpec := test.NewClusterSpec() managementCluster := &types.Cluster{ - Name: clusterSpec.Cluster.Name, - KubeconfigFile: kubeconfig.FromClusterName(clusterSpec.Cluster.Name), + Name: clusterSpec.Cluster.Name, + KubeconfigFile: kubeconfig.FromClusterName(clusterSpec.Cluster.Name), } ctx := context.Background() diff --git a/pkg/workflows/management/upgrade_test.go b/pkg/workflows/management/upgrade_test.go index aa1cefb2788d3..54f112fcbf55b 100644 --- a/pkg/workflows/management/upgrade_test.go +++ b/pkg/workflows/management/upgrade_test.go @@ -15,6 +15,7 @@ import ( "github.com/aws/eks-anywhere/pkg/clients/kubernetes" clientmocks "github.com/aws/eks-anywhere/pkg/clients/kubernetes/mocks" "github.com/aws/eks-anywhere/pkg/cluster" + "github.com/aws/eks-anywhere/pkg/constants" "github.com/aws/eks-anywhere/pkg/features" writermocks "github.com/aws/eks-anywhere/pkg/filewriter/mocks" "github.com/aws/eks-anywhere/pkg/providers" @@ -27,6 +28,7 @@ import ( type upgradeManagementTestSetup struct { t *testing.T client *clientmocks.MockClient + clientFactory *mocks.MockClientFactory clusterManager *mocks.MockClusterManager gitOpsManager *mocks.MockGitOpsManager provider *providermocks.MockProvider @@ -50,6 +52,7 @@ func newUpgradeManagementTest(t *testing.T) *upgradeManagementTestSetup { featureEnvVars := []string{} mockCtrl := gomock.NewController(t) client := clientmocks.NewMockClient(mockCtrl) + clientFactory := mocks.NewMockClientFactory(mockCtrl) clusterManager := mocks.NewMockClusterManager(mockCtrl) gitOpsManager := mocks.NewMockGitOpsManager(mockCtrl) provider := providermocks.NewMockProvider(mockCtrl) @@ -62,7 +65,7 @@ func newUpgradeManagementTest(t *testing.T) *upgradeManagementTestSetup { machineConfigs := []providers.MachineConfig{&v1alpha1.VSphereMachineConfig{}} clusterUpgrader := mocks.NewMockClusterUpgrader(mockCtrl) management := management.NewUpgrade( - client, + clientFactory, provider, capiUpgrader, clusterManager, @@ -80,6 +83,7 @@ func newUpgradeManagementTest(t *testing.T) *upgradeManagementTestSetup { return &upgradeManagementTestSetup{ t: t, client: client, + clientFactory: clientFactory, clusterManager: clusterManager, gitOpsManager: gitOpsManager, provider: provider, @@ -103,7 +107,7 @@ func newUpgradeManagementTest(t *testing.T) *upgradeManagementTestSetup { func newUpgradeManagementClusterTest(t *testing.T) *upgradeManagementTestSetup { tt := newUpgradeManagementTest(t) - tt.managementCluster = &types.Cluster{Name: "management"} + tt.managementCluster = &types.Cluster{Name: "management", KubeconfigFile: "kubeconfig"} return tt } @@ -169,10 +173,14 @@ func (c *upgradeManagementTestSetup) expectUpgradeCoreComponents() { ) } +func (c *upgradeManagementTestSetup) expectBuildClientFromKubeconfig(err error) { + c.clientFactory.EXPECT().BuildClientFromKubeconfig(c.managementCluster.KubeconfigFile).Return(c.client, err) +} + func (c *upgradeManagementTestSetup) expectApplyServerSide(err error) { c.client.EXPECT().ApplyServerSide( c.ctx, - "eks-a-cli", + constants.EKSAFieldManager, c.newClusterSpec.Cluster, kubernetes.ApplyServerSideOptions{ForceOwnership: true}, ).Return(err) @@ -364,6 +372,7 @@ func TestUpgradeManagementRunFailedBackup(t *testing.T) { test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectPauseGitOpsReconcile(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectBackupManagementFromCluster(errors.New("")) test.expectBackupManagementInfrastructureFromCluster(errors.New("")) @@ -386,6 +395,7 @@ func TestUpgradeManagementRunPauseWorkloadCAPIFailed(t *testing.T) { test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectPauseGitOpsReconcile(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectBackupManagementFromCluster(nil) test.expectPauseCAPIWorkloadClusters(errors.New("")) @@ -398,6 +408,28 @@ func TestUpgradeManagementRunPauseWorkloadCAPIFailed(t *testing.T) { } } +func TestUpgradeManagementRunFailedUpgradeBuildClientFromKubeconfig(t *testing.T) { + os.Unsetenv(features.CheckpointEnabledEnvVar) + features.ClearCache() + test := newUpgradeManagementClusterTest(t) + test.expectSetup() + test.expectPreflightValidationsToPass() + test.expectUpdateSecrets(nil) + test.expectEnsureManagementEtcdCAPIComponentsExist(nil) + test.expectPauseGitOpsReconcile(nil) + test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(errors.New("")) + test.expectDatacenterConfig() + test.expectMachineConfigs() + test.expectSaveLogs() + test.expectWriteCheckpointFile() + + err := test.run() + if err == nil { + t.Fatal("UpgradeManagement.Run() err = nil, want err not nil") + } +} + func TestUpgradeManagementRunFailedUpgradeApplyServerSide(t *testing.T) { os.Unsetenv(features.CheckpointEnabledEnvVar) features.ClearCache() @@ -408,6 +440,7 @@ func TestUpgradeManagementRunFailedUpgradeApplyServerSide(t *testing.T) { test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectPauseGitOpsReconcile(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(errors.New("")) test.expectDatacenterConfig() test.expectMachineConfigs() @@ -430,6 +463,7 @@ func TestUpgradeManagementRunFailedUpgradeInstallEksd(t *testing.T) { test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectPauseGitOpsReconcile(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectBackupManagementFromCluster(nil) test.expectPauseCAPIWorkloadClusters(nil) @@ -457,6 +491,7 @@ func TestUpgradeManagementRunFailedUpgradeApplyBundles(t *testing.T) { test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectPauseGitOpsReconcile(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectBackupManagementFromCluster(nil) test.expectPauseCAPIWorkloadClusters(nil) @@ -482,6 +517,7 @@ func TestUpgradeManagementRunFailedUpgradeApplyReleases(t *testing.T) { test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectPauseGitOpsReconcile(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectBackupManagementFromCluster(nil) test.expectPauseCAPIWorkloadClusters(nil) @@ -508,6 +544,7 @@ func TestUpgradeManagementRunFailedUpgrade(t *testing.T) { test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectPauseGitOpsReconcile(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectBackupManagementFromCluster(nil) test.expectPauseCAPIWorkloadClusters(nil) @@ -535,6 +572,7 @@ func TestUpgradeManagementRunResumeCAPIWorkloadFailed(t *testing.T) { test.expectUpdateSecrets(nil) test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectPauseGitOpsReconcile(nil) test.expectBackupManagementFromCluster(nil) @@ -568,6 +606,7 @@ func TestUpgradeManagementRunUpdateGitEksaSpecFailed(t *testing.T) { test.expectUpdateSecrets(nil) test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectPauseGitOpsReconcile(nil) test.expectBackupManagementFromCluster(nil) @@ -597,6 +636,7 @@ func TestUpgradeManagementRunForceReconcileGitRepoFailed(t *testing.T) { test.expectUpdateSecrets(nil) test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectPauseGitOpsReconcile(nil) test.expectBackupManagementFromCluster(nil) @@ -627,6 +667,7 @@ func TestUpgradeManagementRunResumeClusterResourcesReconcileFailed(t *testing.T) test.expectUpdateSecrets(nil) test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectPauseGitOpsReconcile(nil) test.expectBackupManagementFromCluster(nil) @@ -659,6 +700,7 @@ func TestUpgradeManagementRunSuccess(t *testing.T) { test.expectUpdateSecrets(nil) test.expectEnsureManagementEtcdCAPIComponentsExist(nil) test.expectUpgradeCoreComponents() + test.expectBuildClientFromKubeconfig(nil) test.expectApplyServerSide(nil) test.expectPauseGitOpsReconcile(nil) test.expectBackupManagementFromCluster(nil)