sigs.k8s.io/cluster-api-provider-aws@v1.5.5/cmd/clusterawsadm/gc/gc_test.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package gc
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	. "github.com/onsi/gomega"
    24  	corev1 "k8s.io/api/core/v1"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/runtime"
    27  	"sigs.k8s.io/controller-runtime/pkg/client"
    28  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    29  
    30  	infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1beta1"
    31  	ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/controlplane/eks/api/v1beta1"
    32  	expinfrav1 "sigs.k8s.io/cluster-api-provider-aws/exp/api/v1beta1"
    33  	"sigs.k8s.io/cluster-api-provider-aws/pkg/annotations"
    34  	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
    35  	"sigs.k8s.io/cluster-api/controllers/external"
    36  )
    37  
    38  func TestEnableGC(t *testing.T) {
    39  	RegisterTestingT(t)
    40  
    41  	testClusterName := "test-cluster"
    42  
    43  	testCases := []struct {
    44  		name         string
    45  		clusterName  string
    46  		existingObjs []client.Object
    47  		expectError  bool
    48  	}{
    49  		{
    50  			name:         "no capi cluster",
    51  			clusterName:  testClusterName,
    52  			existingObjs: []client.Object{},
    53  			expectError:  true,
    54  		},
    55  		{
    56  			name:         "no infra cluster",
    57  			clusterName:  testClusterName,
    58  			existingObjs: newManagedCluster(testClusterName, true),
    59  			expectError:  true,
    60  		},
    61  		{
    62  			name:         "with managed control plane and no annotation",
    63  			clusterName:  testClusterName,
    64  			existingObjs: newManagedClusterWithAnnotations(testClusterName, nil),
    65  			expectError:  false,
    66  		},
    67  		{
    68  			name:         "with awscluster and no annotation",
    69  			clusterName:  testClusterName,
    70  			existingObjs: newUnManagedClusterWithAnnotations(testClusterName, nil),
    71  			expectError:  false,
    72  		},
    73  		{
    74  			name:         "with managed control plane and existing annotation",
    75  			clusterName:  testClusterName,
    76  			existingObjs: newManagedClusterWithAnnotations(testClusterName, map[string]string{expinfrav1.ExternalResourceGCAnnotation: "false"}),
    77  			expectError:  false,
    78  		},
    79  	}
    80  
    81  	for _, tc := range testCases {
    82  		t.Run(tc.name, func(t *testing.T) {
    83  			g := NewWithT(t)
    84  
    85  			input := GCInput{
    86  				ClusterName: tc.clusterName,
    87  				Namespace:   "default",
    88  			}
    89  
    90  			fake := newFakeClient(scheme, tc.existingObjs...)
    91  			ctx := context.TODO()
    92  
    93  			proc, err := New(input, WithClient(fake))
    94  			g.Expect(err).NotTo(HaveOccurred())
    95  
    96  			resErr := proc.Enable(ctx)
    97  			if tc.expectError {
    98  				g.Expect(resErr).To(HaveOccurred())
    99  				return
   100  			}
   101  			g.Expect(resErr).NotTo(HaveOccurred())
   102  
   103  			cluster := tc.existingObjs[0].(*clusterv1.Cluster)
   104  			ref := cluster.Spec.InfrastructureRef
   105  
   106  			obj, err := external.Get(ctx, fake, ref, "default")
   107  			g.Expect(err).NotTo(HaveOccurred())
   108  			g.Expect(obj).NotTo(BeNil())
   109  
   110  			annotationVal, hasAnnotation := annotations.Get(obj, expinfrav1.ExternalResourceGCAnnotation)
   111  			g.Expect(hasAnnotation).To(BeTrue())
   112  			g.Expect(annotationVal).To(Equal("true"))
   113  		})
   114  	}
   115  }
   116  
   117  func TestDisableGC(t *testing.T) {
   118  	RegisterTestingT(t)
   119  
   120  	testClusterName := "test-cluster"
   121  
   122  	testCases := []struct {
   123  		name         string
   124  		clusterName  string
   125  		existingObjs []client.Object
   126  		expectError  bool
   127  	}{
   128  		{
   129  			name:         "no capi cluster",
   130  			clusterName:  testClusterName,
   131  			existingObjs: []client.Object{},
   132  			expectError:  true,
   133  		},
   134  		{
   135  			name:         "no infra cluster",
   136  			clusterName:  testClusterName,
   137  			existingObjs: newManagedCluster(testClusterName, true),
   138  			expectError:  true,
   139  		},
   140  		{
   141  			name:         "with managed control plane and with annotation",
   142  			clusterName:  testClusterName,
   143  			existingObjs: newManagedClusterWithAnnotations(testClusterName, map[string]string{expinfrav1.ExternalResourceGCAnnotation: "true"}),
   144  			expectError:  false,
   145  		},
   146  		{
   147  			name:         "with awscluster and with annotation",
   148  			clusterName:  testClusterName,
   149  			existingObjs: newUnManagedClusterWithAnnotations(testClusterName, map[string]string{expinfrav1.ExternalResourceGCAnnotation: "true"}),
   150  			expectError:  false,
   151  		},
   152  	}
   153  
   154  	for _, tc := range testCases {
   155  		t.Run(tc.name, func(t *testing.T) {
   156  			g := NewWithT(t)
   157  
   158  			input := GCInput{
   159  				ClusterName: tc.clusterName,
   160  				Namespace:   "default",
   161  			}
   162  
   163  			fake := newFakeClient(scheme, tc.existingObjs...)
   164  			ctx := context.TODO()
   165  
   166  			proc, err := New(input, WithClient(fake))
   167  			g.Expect(err).NotTo(HaveOccurred())
   168  
   169  			resErr := proc.Disable(ctx)
   170  			if tc.expectError {
   171  				g.Expect(resErr).To(HaveOccurred())
   172  				return
   173  			}
   174  			g.Expect(resErr).NotTo(HaveOccurred())
   175  
   176  			cluster := tc.existingObjs[0].(*clusterv1.Cluster)
   177  			ref := cluster.Spec.InfrastructureRef
   178  
   179  			obj, err := external.Get(ctx, fake, ref, "default")
   180  			g.Expect(err).NotTo(HaveOccurred())
   181  			g.Expect(obj).NotTo(BeNil())
   182  
   183  			annotationVal, hasAnnotation := annotations.Get(obj, expinfrav1.ExternalResourceGCAnnotation)
   184  			g.Expect(hasAnnotation).To(BeTrue())
   185  			g.Expect(annotationVal).To(Equal("false"))
   186  		})
   187  	}
   188  }
   189  
   190  func newFakeClient(scheme *runtime.Scheme, objs ...client.Object) client.Client {
   191  	return fake.NewClientBuilder().WithScheme(scheme).WithObjects(objs...).Build()
   192  }
   193  
   194  func newManagedCluster(name string, excludeInfra bool) []client.Object {
   195  	objs := []client.Object{
   196  		&clusterv1.Cluster{
   197  			TypeMeta: metav1.TypeMeta{
   198  				Kind:       "Cluster",
   199  				APIVersion: clusterv1.GroupVersion.String(),
   200  			},
   201  			ObjectMeta: metav1.ObjectMeta{
   202  				Name:      name,
   203  				Namespace: "default",
   204  			},
   205  			Spec: clusterv1.ClusterSpec{
   206  				InfrastructureRef: &corev1.ObjectReference{
   207  					Name:       name,
   208  					Namespace:  "default",
   209  					Kind:       "AWSManagedControlPlane",
   210  					APIVersion: ekscontrolplanev1.GroupVersion.String(),
   211  				},
   212  			},
   213  		},
   214  	}
   215  
   216  	if !excludeInfra {
   217  		objs = append(objs, &ekscontrolplanev1.AWSManagedControlPlane{
   218  			TypeMeta: metav1.TypeMeta{
   219  				Kind:       "AWSManagedControlPlane",
   220  				APIVersion: ekscontrolplanev1.GroupVersion.String(),
   221  			},
   222  			ObjectMeta: metav1.ObjectMeta{
   223  				Name:      name,
   224  				Namespace: "default",
   225  			},
   226  		})
   227  	}
   228  
   229  	return objs
   230  }
   231  
   232  func newManagedClusterWithAnnotations(name string, annotations map[string]string) []client.Object {
   233  	objs := newManagedCluster(name, false)
   234  
   235  	mcp := objs[1].(*ekscontrolplanev1.AWSManagedControlPlane)
   236  	mcp.ObjectMeta.Annotations = annotations
   237  
   238  	return objs
   239  }
   240  
   241  func newUnManagedCluster(name string, excludeInfra bool) []client.Object {
   242  	objs := []client.Object{
   243  		&clusterv1.Cluster{
   244  			TypeMeta: metav1.TypeMeta{
   245  				Kind:       "Cluster",
   246  				APIVersion: clusterv1.GroupVersion.String(),
   247  			},
   248  			ObjectMeta: metav1.ObjectMeta{
   249  				Name:      name,
   250  				Namespace: "default",
   251  			},
   252  			Spec: clusterv1.ClusterSpec{
   253  				InfrastructureRef: &corev1.ObjectReference{
   254  					Name:       name,
   255  					Namespace:  "default",
   256  					Kind:       "AWSCluster",
   257  					APIVersion: infrav1.GroupVersion.String(),
   258  				},
   259  			},
   260  		},
   261  	}
   262  
   263  	if !excludeInfra {
   264  		objs = append(objs, &infrav1.AWSCluster{
   265  			TypeMeta: metav1.TypeMeta{
   266  				Kind:       "AWSCluster",
   267  				APIVersion: infrav1.GroupVersion.String(),
   268  			},
   269  			ObjectMeta: metav1.ObjectMeta{
   270  				Name:      name,
   271  				Namespace: "default",
   272  			},
   273  		})
   274  	}
   275  
   276  	return objs
   277  }
   278  
   279  func newUnManagedClusterWithAnnotations(name string, annotations map[string]string) []client.Object {
   280  	objs := newUnManagedCluster(name, false)
   281  
   282  	awsc := objs[1].(*infrav1.AWSCluster)
   283  	awsc.ObjectMeta.Annotations = annotations
   284  
   285  	return objs
   286  }