Skip to content

Commit

Permalink
WIP adding tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Wollesen committed Mar 1, 2023
1 parent 443efce commit d0f3cf1
Show file tree
Hide file tree
Showing 5 changed files with 458 additions and 9 deletions.
10 changes: 4 additions & 6 deletions controllers/cluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ func (r *ClusterReconciler) postClusterProviderReconcile(ctx context.Context, lo
return controller.Result{}, nil
}

// PackageControllerClient handles packages operations from within the cluster
// controller.
type PackageControllerClient interface {
EnableCuratedPackagesFullLifecycle(context.Context, logr.Logger, string, string, *v1alpha1.Image, *registrymirror.RegistryMirror, ...curatedpackages.PackageControllerClientOpt) error
ReconcileDelete(context.Context, logr.Logger, client.Client, *anywherev1.Cluster) error
Expand All @@ -300,11 +302,7 @@ func (r *ClusterReconciler) postReconcilePackagesForWorkloadCluster(ctx context.
if err != nil {
return err
}

image, ok := verBundle.Charts()["eks-anywhere-packages"]
if !ok {
return fmt.Errorf("no chart image")
}
image := verBundle.PackageController.HelmChart

kubeConfigNN := types.NamespacedName{
Namespace: constants.EksaSystemNamespace,
Expand Down Expand Up @@ -335,7 +333,7 @@ func (r *ClusterReconciler) postReconcilePackagesForWorkloadCluster(ctx context.
err = r.packageControllerClient.EnableCuratedPackagesFullLifecycle(ctx, log,
cluster.Name,
f.Name(),
image,
&image,
rm,
options...,
)
Expand Down
250 changes: 248 additions & 2 deletions controllers/cluster_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package controllers_test
import (
"context"
"fmt"
"strings"
"testing"
"time"

"github.com/go-logr/logr"
"github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
. "github.com/onsi/gomega"
apiv1 "k8s.io/api/core/v1"
Expand All @@ -24,6 +26,7 @@ import (
"github.com/aws/eks-anywhere/controllers/mocks"
"github.com/aws/eks-anywhere/internal/test/envtest"
anywherev1 "github.com/aws/eks-anywhere/pkg/api/v1alpha1"
"github.com/aws/eks-anywhere/pkg/constants"
"github.com/aws/eks-anywhere/pkg/controller/clusters"
"github.com/aws/eks-anywhere/pkg/govmomi"
"github.com/aws/eks-anywhere/pkg/providers/vsphere"
Expand Down Expand Up @@ -98,10 +101,10 @@ func TestClusterReconcilerReconcileSelfManagedCluster(t *testing.T) {
clusterValidator := mocks.NewMockClusterValidator(controller)
registry := newRegistryMock(providerReconciler)
c := fake.NewClientBuilder().WithRuntimeObjects(selfManagedCluster).Build()

mockPCC := mocks.NewMockPackageControllerClient(controller)
providerReconciler.EXPECT().ReconcileWorkerNodes(ctx, gomock.AssignableToTypeOf(logr.Logger{}), sameName(selfManagedCluster))

r := controllers.NewClusterReconciler(c, registry, iam, clusterValidator, nil)
r := controllers.NewClusterReconciler(c, registry, iam, clusterValidator, mockPCC)
result, err := r.Reconcile(ctx, clusterRequest(selfManagedCluster))
g.Expect(err).NotTo(HaveOccurred())
g.Expect(result).To(Equal(ctrl.Result{}))
Expand Down Expand Up @@ -335,6 +338,249 @@ func TestClusterReconcilerDeleteNoCAPIClusterSuccess(t *testing.T) {
}
}

func TestClusterReconcilerDontInstallPackagesOnSelfManaged(t *testing.T) {
ctx := context.Background()
cluster := &anywherev1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "my-cluster",
Namespace: "my-namespace",
},
Spec: anywherev1.ClusterSpec{
KubernetesVersion: "v1.25",
BundlesRef: &anywherev1.BundlesRef{
Name: "my-bundles-ref",
Namespace: "my-namespace",
},
ManagementCluster: anywherev1.ManagementCluster{
Name: "",
},
},
}
objs := []runtime.Object{cluster}
cb := fake.NewClientBuilder()
mockClient := cb.WithRuntimeObjects(objs...).Build()
nullRegistry := newRegistryForDummyProviderReconciler()

ctrl := gomock.NewController(t)
// If any method of the mockPCC is called, this will fail, indicating that
// an installation was attempted.
mockPCC := mocks.NewMockPackageControllerClient(ctrl)
r := controllers.NewClusterReconciler(mockClient, nullRegistry, nil, nil, mockPCC)
_, err := r.Reconcile(ctx, clusterRequest(cluster))
if err != nil {
t.Fatalf("expected err to be nil, got %s", err)
}
}

func TestClusterReconcilerDontDeletePackagesOnSelfManaged(t *testing.T) {
ctx := context.Background()
deleteTime := metav1.NewTime(time.Now().Add(-1 * time.Second))
cluster := &anywherev1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "my-cluster",
Namespace: "my-namespace",
DeletionTimestamp: &deleteTime,
},
Spec: anywherev1.ClusterSpec{
KubernetesVersion: "v1.25",
BundlesRef: &anywherev1.BundlesRef{
Name: "my-bundles-ref",
Namespace: "my-namespace",
},
ManagementCluster: anywherev1.ManagementCluster{
Name: "",
},
},
}
objs := []runtime.Object{cluster}
cb := fake.NewClientBuilder()
mockClient := cb.WithRuntimeObjects(objs...).Build()
nullRegistry := newRegistryForDummyProviderReconciler()

ctrl := gomock.NewController(t)
// At the moment, Reconcile won't get this far, but if the time comes when
// deleting self-managed clusters via full cluster lifecycle happens, we
// need to be aware and adapt appropriately.
mockPCC := mocks.NewMockPackageControllerClient(ctrl)
mockPCC.EXPECT().ReconcileDelete(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(0)
r := controllers.NewClusterReconciler(mockClient, nullRegistry, nil, nil, mockPCC)
_, err := r.Reconcile(ctx, clusterRequest(cluster))
if err == nil || !strings.Contains(err.Error(), "deleting self-managed clusters is not supported") {
t.Fatalf("unexpected error %s", err)
}
}

func TestClusterReconcilerPackagesDeletion(s *testing.T) {
newTestCluster := func() *anywherev1.Cluster {
deleteTime := metav1.NewTime(time.Now().Add(-1 * time.Second))
return &anywherev1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "my-workload-cluster",
Namespace: "my-namespace",
DeletionTimestamp: &deleteTime,
},
Spec: anywherev1.ClusterSpec{
KubernetesVersion: "v1.25",
BundlesRef: &anywherev1.BundlesRef{
Name: "my-bundles-ref",
Namespace: "my-namespace",
},
ManagementCluster: anywherev1.ManagementCluster{
Name: "my-management-cluster",
},
},
}
}

s.Run("errors when package controller client errors", func(t *testing.T) {
ctx := context.Background()
log := testr.New(t)
logCtx := ctrl.LoggerInto(ctx, log)
cluster := newTestCluster()
cluster.Spec.BundlesRef.Name = "non-existent"
ctrl := gomock.NewController(t)
objs := []runtime.Object{cluster}
fakeClient := fake.NewClientBuilder().WithRuntimeObjects(objs...).Build()
nullRegistry := newRegistryForDummyProviderReconciler()
mockPCC := mocks.NewMockPackageControllerClient(ctrl)
mockPCC.EXPECT().ReconcileDelete(logCtx, log, gomock.Any(), gomock.Any()).Return(fmt.Errorf("test error"))
mockIAM := mocks.NewMockAWSIamConfigReconciler(ctrl)
mockValid := mocks.NewMockClusterValidator(ctrl)

r := controllers.NewClusterReconciler(fakeClient, nullRegistry, mockIAM, mockValid, mockPCC)
_, err := r.Reconcile(logCtx, clusterRequest(cluster))
if err == nil || !strings.Contains(err.Error(), "test error") {
t.Errorf("expected package controller client deletion error, got %s", err)
}
})
}

func TestClusterReconcilerPackagesInstall(s *testing.T) {
newTestCluster := func() *anywherev1.Cluster {
return &anywherev1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "my-workload-cluster",
Namespace: "my-namespace",
},
Spec: anywherev1.ClusterSpec{
KubernetesVersion: "v1.25",
BundlesRef: &anywherev1.BundlesRef{
Name: "my-bundles-ref",
Namespace: "my-namespace",
},
ManagementCluster: anywherev1.ManagementCluster{
Name: "my-management-cluster",
},
},
}
}

s.Run("errors when bundles aren't found", func(t *testing.T) {
ctx := context.Background()
log := testr.New(t)
logCtx := ctrl.LoggerInto(ctx, log)
cluster := newTestCluster()
cluster.Spec.BundlesRef.Name = "non-existent"
ctrl := gomock.NewController(t)
objs := []runtime.Object{cluster}
fakeClient := fake.NewClientBuilder().WithRuntimeObjects(objs...).Build()
nullRegistry := newRegistryForDummyProviderReconciler()
mockPCC := mocks.NewMockPackageControllerClient(ctrl)
mockIAM := mocks.NewMockAWSIamConfigReconciler(ctrl)

mockValid := mocks.NewMockClusterValidator(ctrl)
mockValid.EXPECT().ValidateManagementClusterName(logCtx, log, gomock.Any()).Return(nil)

r := controllers.NewClusterReconciler(fakeClient, nullRegistry, mockIAM, mockValid, mockPCC)
_, err := r.Reconcile(logCtx, clusterRequest(cluster))
if err == nil || !apierrors.IsNotFound(err) {
t.Errorf("expected not found err getting cluster resource, got %s", err)
}
})

s.Run("errors when a matching k8s bundle version isn't found", func(t *testing.T) {
ctx := context.Background()
log := testr.New(t)
logCtx := ctrl.LoggerInto(ctx, log)
cluster := newTestCluster()
cluster.Spec.KubernetesVersion = "non-existent"
ctrl := gomock.NewController(t)
bundles := createBundle(cluster)
bundles.ObjectMeta.Name = cluster.Spec.BundlesRef.Name
bundles.ObjectMeta.Namespace = cluster.Spec.BundlesRef.Namespace
objs := []runtime.Object{cluster, bundles}
fakeClient := fake.NewClientBuilder().WithRuntimeObjects(objs...).Build()
nullRegistry := newRegistryForDummyProviderReconciler()
mockPCC := mocks.NewMockPackageControllerClient(ctrl)
mockIAM := mocks.NewMockAWSIamConfigReconciler(ctrl)
mockValid := mocks.NewMockClusterValidator(ctrl)
mockValid.EXPECT().ValidateManagementClusterName(logCtx, log, gomock.Any()).Return(nil)

r := controllers.NewClusterReconciler(fakeClient, nullRegistry, mockIAM, mockValid, mockPCC)
_, err := r.Reconcile(logCtx, clusterRequest(cluster))
if err == nil || !strings.Contains(err.Error(), "no bundle for kube version") {
t.Errorf("expected no bundle for kube version error, got %s", err)
}
})

s.Run("errors when the kube config secret isn't found", func(t *testing.T) {
ctx := context.Background()
log := testr.New(t)
logCtx := ctrl.LoggerInto(ctx, log)
cluster := newTestCluster()
ctrl := gomock.NewController(t)
bundles := createBundle(cluster)
bundles.Spec.VersionsBundles[0].KubeVersion = string(cluster.Spec.KubernetesVersion)
bundles.ObjectMeta.Name = cluster.Spec.BundlesRef.Name
bundles.ObjectMeta.Namespace = cluster.Spec.BundlesRef.Namespace
objs := []runtime.Object{cluster, bundles}
fakeClient := fake.NewClientBuilder().WithRuntimeObjects(objs...).Build()
nullRegistry := newRegistryForDummyProviderReconciler()
mockPCC := mocks.NewMockPackageControllerClient(ctrl)
mockIAM := mocks.NewMockAWSIamConfigReconciler(ctrl)
mockValid := mocks.NewMockClusterValidator(ctrl)
mockValid.EXPECT().ValidateManagementClusterName(logCtx, log, gomock.Any()).Return(nil)

r := controllers.NewClusterReconciler(fakeClient, nullRegistry, mockIAM, mockValid, mockPCC)
_, err := r.Reconcile(logCtx, clusterRequest(cluster))
if err == nil || !apierrors.IsNotFound(err) {
t.Errorf("expected no kubeconfig secret error, got %s", err)
}
})

s.Run("errors when enable fails", func(t *testing.T) {
ctx := context.Background()
log := testr.New(t)
logCtx := ctrl.LoggerInto(ctx, log)
cluster := newTestCluster()
ctrl := gomock.NewController(t)
bundles := createBundle(cluster)
bundles.Spec.VersionsBundles[0].KubeVersion = string(cluster.Spec.KubernetesVersion)
bundles.ObjectMeta.Name = cluster.Spec.BundlesRef.Name
bundles.ObjectMeta.Namespace = cluster.Spec.BundlesRef.Namespace
secret := &apiv1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: constants.EksaSystemNamespace,
Name: cluster.Name + "-kubeconfig",
},
}
objs := []runtime.Object{cluster, bundles, secret}
fakeClient := fake.NewClientBuilder().WithRuntimeObjects(objs...).Build()
nullRegistry := newRegistryForDummyProviderReconciler()
mockIAM := mocks.NewMockAWSIamConfigReconciler(ctrl)
mockValid := mocks.NewMockClusterValidator(ctrl)
mockValid.EXPECT().ValidateManagementClusterName(logCtx, log, gomock.Any()).Return(nil)
mockPCC := mocks.NewMockPackageControllerClient(ctrl)
mockPCC.EXPECT().EnableCuratedPackagesFullLifecycle(logCtx, log, cluster.Name, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("test error"))

r := controllers.NewClusterReconciler(fakeClient, nullRegistry, mockIAM, mockValid, mockPCC)
_, err := r.Reconcile(logCtx, clusterRequest(cluster))
if err == nil || !strings.Contains(err.Error(), "package controller client error: test error") {
t.Errorf("expected package controller client error, got %s", err)
}
})
}

func createWNMachineConfig() *anywherev1.VSphereMachineConfig {
return &anywherev1.VSphereMachineConfig{
TypeMeta: metav1.TypeMeta{
Expand Down
6 changes: 5 additions & 1 deletion pkg/curatedpackages/packagecontrollerclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,10 @@ func (pc *PackageControllerClient) GetCuratedPackagesRegistries() (sourceRegistr
defaultImageRegistry = gatedOCINamespace
}
} else {
defaultImageRegistry = strings.ReplaceAll(defaultImageRegistry, eksaDefaultRegion, pc.eksaRegion)
// The eksaRegion field is optional, hence its presence can't be assumed.
if pc.eksaRegion != "" {
defaultImageRegistry = strings.ReplaceAll(defaultImageRegistry, eksaDefaultRegion, pc.eksaRegion)
}
}
return sourceRegistry, defaultRegistry, defaultImageRegistry
}
Expand Down Expand Up @@ -428,6 +431,7 @@ func (pc *PackageControllerClient) ReconcileDelete(ctx context.Context, logger l
}

name := "eks-anywhere-packages-" + pc.clusterName
// TODO this namespace should no longer be empty, following PR 5081
if err := pc.deleter.Delete(ctx, pc.kubeConfig, name, ""); err != nil {
return err
}
Expand Down
Loading

0 comments on commit d0f3cf1

Please sign in to comment.