From 6352aa842811f10c0c61fd4c8ebb5a73661c6c6e Mon Sep 17 00:00:00 2001 From: Tanvir Tatla Date: Thu, 15 Feb 2024 17:30:57 -0800 Subject: [PATCH 1/2] Use client factory --- cmd/eksctl-anywhere/cmd/createcluster.go | 2 + pkg/clients/kubernetes/unauth.go | 11 +- pkg/clients/kubernetes/unauth_test.go | 12 +- pkg/clustermanager/cluster_manager.go | 5 - pkg/workflows/create_prep.go | 41 ++++++ pkg/workflows/create_prep_test.go | 123 ++++++++++++++++++ pkg/workflows/interfaces/interfaces.go | 1 - pkg/workflows/interfaces/mocks/clients.go | 14 -- pkg/workflows/management/create.go | 6 +- .../management/create_install_eksa.go | 2 +- pkg/workflows/management/create_test.go | 47 ++++++- pkg/workflows/management/create_workload.go | 2 +- pkg/workflows/workload/create.go | 4 + pkg/workflows/workload/create_test.go | 30 ++++- pkg/workflows/workload/createcluster.go | 2 +- 15 files changed, 264 insertions(+), 38 deletions(-) create mode 100644 pkg/workflows/create_prep.go create mode 100644 pkg/workflows/create_prep_test.go diff --git a/cmd/eksctl-anywhere/cmd/createcluster.go b/cmd/eksctl-anywhere/cmd/createcluster.go index 6828e0d6ea01..8dc42b9f9b17 100644 --- a/cmd/eksctl-anywhere/cmd/createcluster.go +++ b/cmd/eksctl-anywhere/cmd/createcluster.go @@ -258,6 +258,7 @@ func (cc *createClusterOptions) createCluster(cmd *cobra.Command, _ []string) er deps.EksdInstaller, deps.PackageInstaller, deps.ClusterCreator, + deps.UnAuthKubectlClient, ) err = createWorkloadCluster.Run(ctx, clusterSpec, createValidations) @@ -266,6 +267,7 @@ func (cc *createClusterOptions) createCluster(cmd *cobra.Command, _ []string) er createMgmtCluster := management.NewCreate( deps.Bootstrapper, + deps.UnAuthKubeClient, deps.Provider, deps.ClusterManager, deps.GitOpsFlux, diff --git a/pkg/clients/kubernetes/unauth.go b/pkg/clients/kubernetes/unauth.go index eebaaf80da03..d504f047f093 100644 --- a/pkg/clients/kubernetes/unauth.go +++ b/pkg/clients/kubernetes/unauth.go @@ -8,6 +8,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" ) @@ -41,7 +42,15 @@ func (c *UnAuthClient) Get(ctx context.Context, name, namespace, kubeconfig stri return fmt.Errorf("getting kubernetes resource: %v", err) } - return c.kubectl.Get(ctx, resourceType, kubeconfig, obj, &KubectlGetOptions{Name: name, Namespace: namespace}) + var opts KubectlGetOptions + + if namespace == "" { + opts = KubectlGetOptions{Name: name, ClusterScoped: pointer.Bool(true)} + } else { + opts = KubectlGetOptions{Name: name, Namespace: namespace} + } + + return c.kubectl.Get(ctx, resourceType, kubeconfig, obj, &opts) } // KubeconfigClient returns an equivalent authenticated client. diff --git a/pkg/clients/kubernetes/unauth_test.go b/pkg/clients/kubernetes/unauth_test.go index 96b31a77e65a..150e93964b72 100644 --- a/pkg/clients/kubernetes/unauth_test.go +++ b/pkg/clients/kubernetes/unauth_test.go @@ -9,6 +9,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/utils/pointer" clusterapiv1 "sigs.k8s.io/cluster-api/api/v1beta1" controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -24,30 +25,35 @@ func TestUnAuthClientGetSuccess(t *testing.T) { namespace string obj runtime.Object wantResourceType string + options kubernetes.KubectlGetOptions }{ { name: "eksa cluster", namespace: "eksa-system", obj: &anywherev1.Cluster{}, wantResourceType: "Cluster.v1alpha1.anywhere.eks.amazonaws.com", + options: kubernetes.KubectlGetOptions{Name: "eksa cluster", Namespace: "eksa-system"}, }, { name: "capi cluster", namespace: "eksa-system", obj: &clusterapiv1.Cluster{}, wantResourceType: "Cluster.v1beta1.cluster.x-k8s.io", + options: kubernetes.KubectlGetOptions{Name: "capi cluster", Namespace: "eksa-system"}, }, { name: "capi kubeadm controlplane", namespace: "eksa-system", obj: &controlplanev1.KubeadmControlPlane{}, wantResourceType: "KubeadmControlPlane.v1beta1.controlplane.cluster.x-k8s.io", + options: kubernetes.KubectlGetOptions{Name: "capi kubeadm controlplane", Namespace: "eksa-system"}, }, { name: "my-node", namespace: "", obj: &corev1.NodeList{}, wantResourceType: "Node", + options: kubernetes.KubectlGetOptions{Name: "my-node", ClusterScoped: pointer.Bool(true)}, }, } for _, tt := range tests { @@ -58,11 +64,7 @@ func TestUnAuthClientGetSuccess(t *testing.T) { kubectl := mocks.NewMockKubectl(ctrl) kubeconfig := "k.kubeconfig" - o := &kubernetes.KubectlGetOptions{ - Name: tt.name, - Namespace: tt.namespace, - } - kubectl.EXPECT().Get(ctx, tt.wantResourceType, kubeconfig, tt.obj, o) + kubectl.EXPECT().Get(ctx, tt.wantResourceType, kubeconfig, tt.obj, &tt.options) c := kubernetes.NewUnAuthClient(kubectl) g.Expect(c.Init()).To(Succeed()) diff --git a/pkg/clustermanager/cluster_manager.go b/pkg/clustermanager/cluster_manager.go index 15bd462a055c..b5068b76f98d 100644 --- a/pkg/clustermanager/cluster_manager.go +++ b/pkg/clustermanager/cluster_manager.go @@ -1404,11 +1404,6 @@ func (c *ClusterManager) DeletePackageResources(ctx context.Context, managementC return c.clusterClient.DeletePackageResources(ctx, managementCluster, clusterName) } -// CreateNamespace creates a namespace on the target cluster if it does not already exist. -func (c *ClusterManager) CreateNamespace(ctx context.Context, targetCluster *types.Cluster, namespace string) error { - return c.clusterClient.CreateNamespaceIfNotPresent(ctx, targetCluster.KubeconfigFile, namespace) -} - func (c *ClusterManager) getUpgraderImagesFromBundle(ctx context.Context, cluster *types.Cluster, cl *cluster.Spec) (*corev1.ConfigMap, error) { upgraderImages := make(map[string]string) for _, versionBundle := range cl.Bundles.Spec.VersionsBundles { diff --git a/pkg/workflows/create_prep.go b/pkg/workflows/create_prep.go new file mode 100644 index 000000000000..bba782c31513 --- /dev/null +++ b/pkg/workflows/create_prep.go @@ -0,0 +1,41 @@ +package workflows + +import ( + "context" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/aws/eks-anywhere/pkg/workflows/interfaces" +) + +// CreateNamespaceIfNotPresent creates the namespace on the cluster if it does not already exist. +func CreateNamespaceIfNotPresent(ctx context.Context, namespace, kubeconfig string, clientFactory interfaces.ClientFactory) error { + client, err := clientFactory.BuildClientFromKubeconfig(kubeconfig) + if err != nil { + return err + } + + if err := client.Get(ctx, namespace, "", &corev1.Namespace{}); err != nil && !errors.IsNotFound(err) { + return err + } else if err == nil { + return nil + } + + ns := &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Namespace", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + } + + if err = client.Create(ctx, ns); err != nil { + return err + } + + return nil +} diff --git a/pkg/workflows/create_prep_test.go b/pkg/workflows/create_prep_test.go new file mode 100644 index 000000000000..a5df25c1bc92 --- /dev/null +++ b/pkg/workflows/create_prep_test.go @@ -0,0 +1,123 @@ +package workflows_test + +import ( + "context" + "fmt" + "testing" + + "github.com/golang/mock/gomock" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + + clientmocks "github.com/aws/eks-anywhere/pkg/clients/kubernetes/mocks" + "github.com/aws/eks-anywhere/pkg/workflows" + "github.com/aws/eks-anywhere/pkg/workflows/interfaces/mocks" +) + +type createPrepTestSetup struct { + t *testing.T + ctx context.Context + client *clientmocks.MockClient + clientFactory *mocks.MockClientFactory +} + +func newCreatePrepTest(t *testing.T) *createPrepTestSetup { + mockCtrl := gomock.NewController(t) + client := clientmocks.NewMockClient(mockCtrl) + clientFactory := mocks.NewMockClientFactory(mockCtrl) + + return &createPrepTestSetup{ + t: t, + ctx: context.Background(), + client: client, + clientFactory: clientFactory, + } +} + +func newNamespace(name string) *corev1.Namespace { + return &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Namespace", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } +} + +func TestCreateNamespaceNotExistsSuccess(t *testing.T) { + test := newCreatePrepTest(t) + kubeconfig := "testpath" + namespace := "test-ns" + + test.clientFactory.EXPECT().BuildClientFromKubeconfig(kubeconfig).Return(test.client, nil) + test.client.EXPECT().Get(test.ctx, namespace, "", &corev1.Namespace{}).Return(apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: ""}, "")) + test.client.EXPECT().Create(test.ctx, newNamespace(namespace)).Return(nil) + + err := workflows.CreateNamespaceIfNotPresent(test.ctx, namespace, kubeconfig, test.clientFactory) + if err != nil { + t.Fatalf("Expected nil, but got %v", err) + } +} + +func TestCreateNamespaceAlreadyExistsSuccess(t *testing.T) { + test := newCreatePrepTest(t) + kubeconfig := "testpath" + namespace := "default" + + test.clientFactory.EXPECT().BuildClientFromKubeconfig(kubeconfig).Return(test.client, nil) + test.client.EXPECT().Get(test.ctx, namespace, "", &corev1.Namespace{}).Return(nil) + + err := workflows.CreateNamespaceIfNotPresent(test.ctx, namespace, kubeconfig, test.clientFactory) + if err != nil { + t.Fatalf("Expected nil, but got %v", err) + } +} + +func TestCreateNamespaceBuildClientFail(t *testing.T) { + test := newCreatePrepTest(t) + kubeconfig := "testpath" + namespace := "test-ns" + + test.clientFactory.EXPECT().BuildClientFromKubeconfig(kubeconfig).Return(test.client, fmt.Errorf("")) + + err := workflows.CreateNamespaceIfNotPresent(test.ctx, namespace, kubeconfig, test.clientFactory) + + if err == nil { + t.Fatalf("Expected error, but got nil") + } +} + +func TestCreateNamespaceGetNamespaceFail(t *testing.T) { + test := newCreatePrepTest(t) + kubeconfig := "testpath" + namespace := "test-ns" + + test.clientFactory.EXPECT().BuildClientFromKubeconfig(kubeconfig).Return(test.client, nil) + test.client.EXPECT().Get(test.ctx, namespace, "", &corev1.Namespace{}).Return(fmt.Errorf("")) + + err := workflows.CreateNamespaceIfNotPresent(test.ctx, namespace, kubeconfig, test.clientFactory) + + if err == nil { + t.Fatalf("Expected error, but got nil") + } +} + +func TestCreateNamespaceFail(t *testing.T) { + test := newCreatePrepTest(t) + kubeconfig := "testpath" + namespace := "test-ns" + + test.clientFactory.EXPECT().BuildClientFromKubeconfig(kubeconfig).Return(test.client, nil) + test.client.EXPECT().Get(test.ctx, namespace, "", &corev1.Namespace{}).Return(apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: ""}, "")) + test.client.EXPECT().Create(test.ctx, newNamespace(namespace)).Return(fmt.Errorf("")) + + err := workflows.CreateNamespaceIfNotPresent(test.ctx, namespace, kubeconfig, test.clientFactory) + + if err == nil { + t.Fatalf("Expected error, but got nil") + } +} diff --git a/pkg/workflows/interfaces/interfaces.go b/pkg/workflows/interfaces/interfaces.go index 87469494a8ac..7eff799e3c7e 100644 --- a/pkg/workflows/interfaces/interfaces.go +++ b/pkg/workflows/interfaces/interfaces.go @@ -57,7 +57,6 @@ type ClusterManager interface { GenerateAWSIAMKubeconfig(ctx context.Context, cluster *types.Cluster) error DeletePackageResources(ctx context.Context, managementCluster *types.Cluster, clusterName string) error CreateRegistryCredSecret(ctx context.Context, mgmt *types.Cluster) error - CreateNamespace(ctx context.Context, targetCluster *types.Cluster, namespace string) error } type GitOpsManager interface { diff --git a/pkg/workflows/interfaces/mocks/clients.go b/pkg/workflows/interfaces/mocks/clients.go index d9329ef401e9..f9f56646fbb4 100644 --- a/pkg/workflows/interfaces/mocks/clients.go +++ b/pkg/workflows/interfaces/mocks/clients.go @@ -197,20 +197,6 @@ func (mr *MockClusterManagerMockRecorder) CreateEKSAResources(arg0, arg1, arg2, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateEKSAResources", reflect.TypeOf((*MockClusterManager)(nil).CreateEKSAResources), arg0, arg1, arg2, arg3, arg4) } -// CreateNamespace mocks base method. -func (m *MockClusterManager) CreateNamespace(arg0 context.Context, arg1 *types.Cluster, arg2 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateNamespace", arg0, arg1, arg2) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateNamespace indicates an expected call of CreateNamespace. -func (mr *MockClusterManagerMockRecorder) CreateNamespace(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNamespace", reflect.TypeOf((*MockClusterManager)(nil).CreateNamespace), arg0, arg1, arg2) -} - // CreateRegistryCredSecret mocks base method. func (m *MockClusterManager) CreateRegistryCredSecret(arg0 context.Context, arg1 *types.Cluster) error { m.ctrl.T.Helper() diff --git a/pkg/workflows/management/create.go b/pkg/workflows/management/create.go index 9dbc5ecfcc78..9b8e4ab60bb3 100644 --- a/pkg/workflows/management/create.go +++ b/pkg/workflows/management/create.go @@ -13,6 +13,7 @@ import ( // Create is a schema for create cluster. type Create struct { bootstrapper interfaces.Bootstrapper + clientFactory interfaces.ClientFactory provider providers.Provider clusterManager interfaces.ClusterManager gitOpsManager interfaces.GitOpsManager @@ -24,7 +25,8 @@ type Create struct { } // NewCreate builds a new create construct. -func NewCreate(bootstrapper interfaces.Bootstrapper, provider providers.Provider, +func NewCreate(bootstrapper interfaces.Bootstrapper, + clientFactory interfaces.ClientFactory, provider providers.Provider, clusterManager interfaces.ClusterManager, gitOpsManager interfaces.GitOpsManager, writer filewriter.FileWriter, eksdInstaller interfaces.EksdInstaller, packageInstaller interfaces.PackageInstaller, @@ -33,6 +35,7 @@ func NewCreate(bootstrapper interfaces.Bootstrapper, provider providers.Provider ) *Create { return &Create{ bootstrapper: bootstrapper, + clientFactory: clientFactory, provider: provider, clusterManager: clusterManager, gitOpsManager: gitOpsManager, @@ -48,6 +51,7 @@ func NewCreate(bootstrapper interfaces.Bootstrapper, provider providers.Provider func (c *Create) Run(ctx context.Context, clusterSpec *cluster.Spec, validator interfaces.Validator) error { commandContext := &task.CommandContext{ Bootstrapper: c.bootstrapper, + ClientFactory: c.clientFactory, Provider: c.provider, ClusterManager: c.clusterManager, GitOpsManager: c.gitOpsManager, diff --git a/pkg/workflows/management/create_install_eksa.go b/pkg/workflows/management/create_install_eksa.go index d508f57e8897..fc5a91e97fc4 100644 --- a/pkg/workflows/management/create_install_eksa.go +++ b/pkg/workflows/management/create_install_eksa.go @@ -58,7 +58,7 @@ func (s *installEksaComponentsOnWorkloadTask) Run(ctx context.Context, commandCo commandContext.ClusterSpec.Cluster.SetManagementComponentsVersion(commandContext.ClusterSpec.EKSARelease.Spec.Version) if commandContext.ClusterSpec.Cluster.Namespace != "" { - if err := commandContext.ClusterManager.CreateNamespace(ctx, commandContext.WorkloadCluster, commandContext.ClusterSpec.Cluster.Namespace); err != nil { + if err := workflows.CreateNamespaceIfNotPresent(ctx, commandContext.ClusterSpec.Cluster.Namespace, commandContext.WorkloadCluster.KubeconfigFile, commandContext.ClientFactory); err != nil { commandContext.SetError(err) return &workflows.CollectMgmtClusterDiagnosticsTask{} } diff --git a/pkg/workflows/management/create_test.go b/pkg/workflows/management/create_test.go index cd642e32e3b0..61abe9c1817c 100644 --- a/pkg/workflows/management/create_test.go +++ b/pkg/workflows/management/create_test.go @@ -7,6 +7,10 @@ import ( "testing" "github.com/golang/mock/gomock" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "github.com/aws/eks-anywhere/internal/test" "github.com/aws/eks-anywhere/pkg/api/v1alpha1" @@ -44,6 +48,7 @@ type createTestSetup struct { workloadCluster *types.Cluster workflow *management.Create client *clientmocks.MockClient + clientFactory *mocks.MockClientFactory } func newCreateTest(t *testing.T) *createTestSetup { @@ -65,9 +70,11 @@ func newCreateTest(t *testing.T) *createTestSetup { clusterCreator := mocks.NewMockClusterCreator(mockCtrl) validator := mocks.NewMockValidator(mockCtrl) client := clientmocks.NewMockClient(mockCtrl) + clientFactory := mocks.NewMockClientFactory(mockCtrl) workflow := management.NewCreate( bootstrapper, + clientFactory, provider, clusterManager, gitOpsManager, @@ -91,6 +98,7 @@ func newCreateTest(t *testing.T) *createTestSetup { return &createTestSetup{ t: t, bootstrapper: bootstrapper, + clientFactory: clientFactory, clusterManager: clusterManager, gitOpsManager: gitOpsManager, provider: provider, @@ -176,7 +184,7 @@ func (c *createTestSetup) expectInstallEksaComponentsBootstrap(err1, err2, err3, func (c *createTestSetup) expectCreateWorkload(err1, err2, err3, err4, err5, err6 error) { gomock.InOrder( - c.clusterManager.EXPECT().CreateNamespace(c.ctx, c.bootstrapCluster, c.clusterSpec.Cluster.Namespace).Return(err1), + c.clientFactory.EXPECT().BuildClientFromKubeconfig(c.bootstrapCluster.KubeconfigFile).Return(c.client, err1), c.clusterCreator.EXPECT().CreateSync(c.ctx, c.clusterSpec, c.bootstrapCluster).Return(c.workloadCluster, err2), @@ -223,7 +231,7 @@ func (c *createTestSetup) expectInstallEksaComponentsWorkload(err1, err2, err3 e c.eksdInstaller.EXPECT().InstallEksdManifest( c.ctx, c.clusterSpec, c.workloadCluster), - c.clusterManager.EXPECT().CreateNamespace(c.ctx, c.workloadCluster, c.clusterSpec.Cluster.Namespace).Return(err3), + c.clientFactory.EXPECT().BuildClientFromKubeconfig(c.workloadCluster.KubeconfigFile).Return(c.client, err3), c.clusterCreator.EXPECT().Run(c.ctx, c.clusterSpec, *c.workloadCluster).Return(err2), ) @@ -255,6 +263,19 @@ func (c *createTestSetup) expectWriteClusterConfig() { ) } +func (c *createTestSetup) expectCreateNamespace() { + n := c.clusterSpec.Cluster.Namespace + ns := &corev1.Namespace{ + TypeMeta: v1.TypeMeta{ + APIVersion: "v1", + Kind: "Namespace", + }, + ObjectMeta: v1.ObjectMeta{Name: n}, + } + c.client.EXPECT().Get(c.ctx, n, "", &corev1.Namespace{}).Return(apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: ""}, "")).MaxTimes(2) + c.client.EXPECT().Create(c.ctx, ns).MaxTimes(2) +} + func (c *createTestSetup) expectDeleteBootstrap(err error) { c.bootstrapper.EXPECT().DeleteBootstrapCluster(c.ctx, c.bootstrapCluster, gomock.Any(), gomock.Any()).Return(err) } @@ -279,6 +300,7 @@ func TestCreateRunSuccess(t *testing.T) { test.expectWriteClusterConfig() test.expectDeleteBootstrap(nil) test.expectCuratedPackagesInstallation() + test.expectCreateNamespace() err := test.run() if err != nil { @@ -521,7 +543,8 @@ func TestCreateSyncFailure(t *testing.T) { test.expectCAPIInstall(nil, nil, nil) test.expectInstallEksaComponentsBootstrap(nil, nil, nil, nil) - test.clusterManager.EXPECT().CreateNamespace(test.ctx, test.bootstrapCluster, test.clusterSpec.Cluster.Namespace).Return(nil) + test.clientFactory.EXPECT().BuildClientFromKubeconfig(test.bootstrapCluster.KubeconfigFile).Return(test.client, nil) + test.expectCreateNamespace() test.clusterCreator.EXPECT().CreateSync(test.ctx, test.clusterSpec, test.bootstrapCluster).Return(nil, errors.New("test")) test.clusterManager.EXPECT().SaveLogsManagementCluster(test.ctx, test.clusterSpec, test.bootstrapCluster) test.writer.EXPECT().Write(fmt.Sprintf("%s-checkpoint.yaml", test.clusterSpec.Cluster.Name), gomock.Any()) @@ -540,7 +563,8 @@ func TestCreateEKSANamespaceFailure(t *testing.T) { test.expectCAPIInstall(nil, nil, nil) test.expectInstallEksaComponentsBootstrap(nil, nil, nil, nil) - test.clusterManager.EXPECT().CreateNamespace(test.ctx, test.bootstrapCluster, test.clusterSpec.Cluster.Namespace).Return(nil) + test.clientFactory.EXPECT().BuildClientFromKubeconfig(test.bootstrapCluster.KubeconfigFile).Return(test.client, nil) + test.expectCreateNamespace() test.clusterCreator.EXPECT().CreateSync(test.ctx, test.clusterSpec, test.bootstrapCluster).Return(test.workloadCluster, nil) test.clusterManager.EXPECT().CreateEKSANamespace(test.ctx, test.workloadCluster).Return(errors.New("test")) test.clusterManager.EXPECT().SaveLogsManagementCluster(test.ctx, test.clusterSpec, test.bootstrapCluster) @@ -561,7 +585,8 @@ func TestCreateInstallCAPIWorkloadFailure(t *testing.T) { test.expectInstallEksaComponentsBootstrap(nil, nil, nil, nil) test.expectPreflightValidationsToPass() - test.clusterManager.EXPECT().CreateNamespace(test.ctx, test.bootstrapCluster, test.clusterSpec.Cluster.Namespace).Return(nil) + test.clientFactory.EXPECT().BuildClientFromKubeconfig(test.bootstrapCluster.KubeconfigFile).Return(test.client, nil) + test.expectCreateNamespace() test.clusterCreator.EXPECT().CreateSync( test.ctx, test.clusterSpec, test.bootstrapCluster).Return(test.workloadCluster, nil) @@ -590,6 +615,7 @@ func TestCreateUpdateSecretsFailure(t *testing.T) { test.expectInstallEksaComponentsBootstrap(nil, nil, nil, nil) test.expectPreflightValidationsToPass() + test.expectCreateNamespace() test.expectCreateWorkload(nil, nil, nil, nil, nil, errors.New("test")) test.clusterManager.EXPECT().SaveLogsManagementCluster(test.ctx, test.clusterSpec, test.bootstrapCluster) @@ -611,6 +637,7 @@ func TestCreatePostWorkloadInitFailure(t *testing.T) { c.expectCAPIInstall(nil, nil, nil) c.expectInstallEksaComponentsBootstrap(nil, nil, nil, nil) c.expectCreateWorkload(nil, nil, nil, nil, nil, nil) + c.expectCreateNamespace() c.expectInstallResourcesOnManagementTask(fmt.Errorf("test")) @@ -636,6 +663,7 @@ func TestCreateMoveCAPIFailure(t *testing.T) { c.expectInstallResourcesOnManagementTask(nil) c.expectPauseReconcile(nil) c.expectMoveManagement(errors.New("test")) + c.expectCreateNamespace() c.clusterManager.EXPECT().SaveLogsManagementCluster(c.ctx, c.clusterSpec, c.bootstrapCluster) c.clusterManager.EXPECT().SaveLogsWorkloadCluster(c.ctx, c.provider, c.clusterSpec, c.workloadCluster) @@ -658,6 +686,7 @@ func TestPauseReconcilerFailure(t *testing.T) { c.expectCreateWorkload(nil, nil, nil, nil, nil, nil) c.expectInstallResourcesOnManagementTask(nil) c.expectPauseReconcile(errors.New("test")) + c.expectCreateNamespace() c.clusterManager.EXPECT().SaveLogsManagementCluster(c.ctx, c.clusterSpec, c.bootstrapCluster) c.clusterManager.EXPECT().SaveLogsWorkloadCluster(c.ctx, c.provider, c.clusterSpec, c.workloadCluster) @@ -681,6 +710,7 @@ func TestCreateEKSAWorkloadComponentsFailure(t *testing.T) { test.expectInstallResourcesOnManagementTask(nil) test.expectPauseReconcile(nil) test.expectMoveManagement(nil) + test.expectCreateNamespace() test.eksdInstaller.EXPECT().InstallEksdCRDs(test.ctx, test.clusterSpec, test.workloadCluster).Return(fmt.Errorf("test")) @@ -707,6 +737,7 @@ func TestCreateEKSAWorkloadFailure(t *testing.T) { test.expectPauseReconcile(nil) test.expectMoveManagement(nil) test.expectInstallEksaComponentsWorkload(nil, fmt.Errorf("test"), nil) + test.expectCreateNamespace() test.clusterManager.EXPECT().SaveLogsManagementCluster(test.ctx, test.clusterSpec, test.bootstrapCluster) @@ -726,6 +757,7 @@ func TestCreateEKSAWorkloadNamespaceFailure(t *testing.T) { test.expectCAPIInstall(nil, nil, nil) test.expectInstallEksaComponentsBootstrap(nil, nil, nil, nil) test.expectCreateWorkload(nil, nil, nil, nil, nil, nil) + test.expectCreateNamespace() test.expectInstallResourcesOnManagementTask(nil) test.expectPauseReconcile(nil) test.expectMoveManagement(nil) @@ -742,7 +774,7 @@ func TestCreateEKSAWorkloadNamespaceFailure(t *testing.T) { test.eksdInstaller.EXPECT().InstallEksdManifest( test.ctx, test.clusterSpec, test.workloadCluster), - test.clusterManager.EXPECT().CreateNamespace(test.ctx, test.workloadCluster, test.clusterSpec.Cluster.Namespace).Return(fmt.Errorf("")), + test.clientFactory.EXPECT().BuildClientFromKubeconfig(test.workloadCluster.KubeconfigFile).Return(test.client, fmt.Errorf("")), ) test.clusterManager.EXPECT().SaveLogsManagementCluster(test.ctx, test.clusterSpec, test.bootstrapCluster) @@ -767,6 +799,7 @@ func TestCreateGitOPsFailure(t *testing.T) { test.expectPauseReconcile(nil) test.expectMoveManagement(nil) test.expectInstallEksaComponentsWorkload(nil, nil, nil) + test.expectCreateNamespace() gomock.InOrder( test.provider.EXPECT().DatacenterConfig( @@ -802,6 +835,7 @@ func TestCreateWriteConfigFailure(t *testing.T) { test.expectInstallEksaComponentsWorkload(nil, nil, nil) test.expectInstallGitOpsManager() test.expectPreflightValidationsToPass() + test.expectCreateNamespace() gomock.InOrder( test.provider.EXPECT().DatacenterConfig( @@ -877,6 +911,7 @@ func TestCreateRunDeleteBootstrapFailure(t *testing.T) { test.expectWriteClusterConfig() test.expectDeleteBootstrap(fmt.Errorf("test")) test.expectCuratedPackagesInstallation() + test.expectCreateNamespace() test.writer.EXPECT().Write("test-cluster-checkpoint.yaml", gomock.Any(), gomock.Any()) diff --git a/pkg/workflows/management/create_workload.go b/pkg/workflows/management/create_workload.go index 5efc456282db..e3289a297816 100644 --- a/pkg/workflows/management/create_workload.go +++ b/pkg/workflows/management/create_workload.go @@ -19,7 +19,7 @@ func (s *createWorkloadClusterTask) Run(ctx context.Context, commandContext *tas commandContext.ClusterSpec.Cluster.SetManagementComponentsVersion(commandContext.ClusterSpec.EKSARelease.Spec.Version) if commandContext.ClusterSpec.Cluster.Namespace != "" { - if err := commandContext.ClusterManager.CreateNamespace(ctx, commandContext.BootstrapCluster, commandContext.ClusterSpec.Cluster.Namespace); err != nil { + if err := workflows.CreateNamespaceIfNotPresent(ctx, commandContext.ClusterSpec.Cluster.Namespace, commandContext.BootstrapCluster.KubeconfigFile, commandContext.ClientFactory); err != nil { commandContext.SetError(err) return &workflows.CollectMgmtClusterDiagnosticsTask{} } diff --git a/pkg/workflows/workload/create.go b/pkg/workflows/workload/create.go index 73f6c20e4fe5..219a173a3d12 100644 --- a/pkg/workflows/workload/create.go +++ b/pkg/workflows/workload/create.go @@ -12,6 +12,7 @@ import ( // Create is the workflow that creates a workload clusters. type Create struct { + clientFactory interfaces.ClientFactory provider providers.Provider clusterManager interfaces.ClusterManager gitOpsManager interfaces.GitOpsManager @@ -28,6 +29,7 @@ func NewCreate(provider providers.Provider, eksdInstaller interfaces.EksdInstaller, packageInstaller interfaces.PackageInstaller, clusterCreator interfaces.ClusterCreator, + clientFactory interfaces.ClientFactory, ) *Create { return &Create{ provider: provider, @@ -37,12 +39,14 @@ func NewCreate(provider providers.Provider, eksdInstaller: eksdInstaller, clusterCreator: clusterCreator, packageInstaller: packageInstaller, + clientFactory: clientFactory, } } // Run executes the tasks to create a workload cluster. func (c *Create) Run(ctx context.Context, clusterSpec *cluster.Spec, validator interfaces.Validator) error { commandContext := &task.CommandContext{ + ClientFactory: c.clientFactory, Provider: c.provider, ClusterManager: c.clusterManager, GitOpsManager: c.gitOpsManager, diff --git a/pkg/workflows/workload/create_test.go b/pkg/workflows/workload/create_test.go index 29fdee8d7907..d5f667f3a8a1 100644 --- a/pkg/workflows/workload/create_test.go +++ b/pkg/workflows/workload/create_test.go @@ -9,9 +9,14 @@ import ( "testing" "github.com/golang/mock/gomock" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "github.com/aws/eks-anywhere/internal/test" "github.com/aws/eks-anywhere/pkg/api/v1alpha1" + clientmocks "github.com/aws/eks-anywhere/pkg/clients/kubernetes/mocks" "github.com/aws/eks-anywhere/pkg/cluster" "github.com/aws/eks-anywhere/pkg/features" writermocks "github.com/aws/eks-anywhere/pkg/filewriter/mocks" @@ -39,6 +44,8 @@ type createTestSetup struct { workloadCluster *types.Cluster workload *workload.Create managementComponents *cluster.ManagementComponents + client *clientmocks.MockClient + clientFactory *mocks.MockClientFactory } func newCreateTest(t *testing.T) *createTestSetup { @@ -55,6 +62,8 @@ func newCreateTest(t *testing.T) *createTestSetup { datacenterConfig := &v1alpha1.VSphereDatacenterConfig{} machineConfigs := []providers.MachineConfig{&v1alpha1.VSphereMachineConfig{}} clusterUpgrader := mocks.NewMockClusterCreator(mockCtrl) + client := clientmocks.NewMockClient(mockCtrl) + clientFactory := mocks.NewMockClientFactory(mockCtrl) validator := mocks.NewMockValidator(mockCtrl) @@ -71,6 +80,7 @@ func newCreateTest(t *testing.T) *createTestSetup { eksdInstaller, packageInstaller, clusterUpgrader, + clientFactory, ) for _, e := range featureEnvVars { @@ -99,6 +109,8 @@ func newCreateTest(t *testing.T) *createTestSetup { }), workloadCluster: &types.Cluster{Name: "workload"}, managementComponents: managementComponents, + clientFactory: clientFactory, + client: client, } } @@ -108,9 +120,23 @@ func (c *createTestSetup) expectSetup() { c.gitOpsManager.EXPECT().Validations(c.ctx, c.clusterSpec) } +func (c *createTestSetup) expectCreateNamespace() { + n := c.clusterSpec.Cluster.Namespace + ns := &corev1.Namespace{ + TypeMeta: v1.TypeMeta{ + APIVersion: "v1", + Kind: "Namespace", + }, + ObjectMeta: v1.ObjectMeta{Name: n}, + } + c.client.EXPECT().Get(c.ctx, n, "", &corev1.Namespace{}).Return(apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: ""}, "")).MaxTimes(2) + c.client.EXPECT().Create(c.ctx, ns).MaxTimes(2) +} + func (c *createTestSetup) expectCreateWorkloadCluster(err1, err2 error) { - c.clusterManager.EXPECT().CreateNamespace(c.ctx, c.clusterSpec.ManagementCluster, c.clusterSpec.Cluster.Namespace).Return(err1) + c.clientFactory.EXPECT().BuildClientFromKubeconfig(c.clusterSpec.ManagementCluster.KubeconfigFile).Return(c.client, err1) c.clusterCreator.EXPECT().CreateSync(c.ctx, c.clusterSpec, c.clusterSpec.ManagementCluster).Return(c.workloadCluster, err2) + c.expectCreateNamespace() } func (c *createTestSetup) expectWriteWorkloadClusterConfig(err error) { @@ -200,7 +226,7 @@ func TestCreateNamespaceFail(t *testing.T) { test.expectPreflightValidationsToPass() test.expectDatacenterConfig() test.expectMachineConfigs() - test.clusterManager.EXPECT().CreateNamespace(test.ctx, test.clusterSpec.ManagementCluster, test.clusterSpec.Cluster.Namespace).Return(fmt.Errorf("")) + test.clientFactory.EXPECT().BuildClientFromKubeconfig(test.clusterSpec.ManagementCluster.KubeconfigFile).Return(test.client, fmt.Errorf("")) test.expectSaveLogsManagement() err := test.run() diff --git a/pkg/workflows/workload/createcluster.go b/pkg/workflows/workload/createcluster.go index f8028b950c88..32a60b65e3ba 100644 --- a/pkg/workflows/workload/createcluster.go +++ b/pkg/workflows/workload/createcluster.go @@ -15,7 +15,7 @@ func (c *createCluster) Run(ctx context.Context, commandContext *task.CommandCon logger.Info("Creating workload cluster") if commandContext.ClusterSpec.Cluster.Namespace != "" { - if err := commandContext.ClusterManager.CreateNamespace(ctx, commandContext.ManagementCluster, commandContext.ClusterSpec.Cluster.Namespace); err != nil { + if err := workflows.CreateNamespaceIfNotPresent(ctx, commandContext.ClusterSpec.Cluster.Namespace, commandContext.ManagementCluster.KubeconfigFile, commandContext.ClientFactory); err != nil { commandContext.SetError(err) return &workflows.CollectMgmtClusterDiagnosticsTask{} } From d8ceefd41f6cddf22ae22b3f6817b8cb0033beb3 Mon Sep 17 00:00:00 2001 From: Tanvir Tatla Date: Thu, 15 Feb 2024 17:34:30 -0800 Subject: [PATCH 2/2] fix iamauth test --- pkg/workflows/management/create_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/workflows/management/create_test.go b/pkg/workflows/management/create_test.go index 61abe9c1817c..41505fc0d81a 100644 --- a/pkg/workflows/management/create_test.go +++ b/pkg/workflows/management/create_test.go @@ -878,6 +878,7 @@ func TestCreateWriteConfigAWSIAMFailure(t *testing.T) { test.expectPreflightValidationsToPass() test.clusterSpec.AWSIamConfig = &v1alpha1.AWSIamConfig{} test.expectWriteClusterConfig() + test.expectCreateNamespace() test.clusterManager.EXPECT().GenerateAWSIAMKubeconfig(test.ctx, test.workloadCluster).Return(errors.New("test"))