sigs.k8s.io/cluster-api-provider-aws@v1.5.5/api/v1beta1/awsclusterstaticidentity_webhook_test.go (about) 1 /* 2 Copyright 2021 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 v1beta1 18 19 import ( 20 "context" 21 "testing" 22 23 . "github.com/onsi/gomega" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 26 clusterv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" 27 ) 28 29 func TestCreateAWSClusterStaticIdentityValidation(t *testing.T) { 30 tests := []struct { 31 name string 32 selectors map[string]string 33 wantError bool 34 }{ 35 { 36 name: "should not return error for valid selector", 37 selectors: map[string]string{"foo": "bar"}, 38 wantError: false, 39 }, 40 { 41 name: "should return error for invalid selector", 42 selectors: map[string]string{"-123-foo": "bar"}, 43 wantError: true, 44 }, 45 } 46 for _, tt := range tests { 47 t.Run(tt.name, func(t *testing.T) { 48 identity := &AWSClusterStaticIdentity{ 49 TypeMeta: metav1.TypeMeta{ 50 APIVersion: GroupVersion.String(), 51 Kind: string(ClusterStaticIdentityKind), 52 }, 53 ObjectMeta: metav1.ObjectMeta{ 54 Name: "static", 55 }, 56 Spec: AWSClusterStaticIdentitySpec{ 57 AWSClusterIdentitySpec: AWSClusterIdentitySpec{ 58 AllowedNamespaces: &AllowedNamespaces{ 59 Selector: metav1.LabelSelector{ 60 MatchLabels: tt.selectors, 61 }, 62 }, 63 }, 64 SecretRef: "test-secret", 65 }, 66 } 67 68 ctx := context.TODO() 69 if err := testEnv.Create(ctx, identity); (err != nil) != tt.wantError { 70 t.Errorf("ValidateCreate() error = %v, wantErr %v", err, tt.wantError) 71 } 72 testEnv.Delete(ctx, identity) 73 }) 74 } 75 } 76 77 func TestAWSClusterStaticValidateUpdate(t *testing.T) { 78 staticIdentity := &AWSClusterStaticIdentity{ 79 TypeMeta: metav1.TypeMeta{ 80 APIVersion: GroupVersion.String(), 81 Kind: string(ClusterStaticIdentityKind), 82 }, 83 ObjectMeta: metav1.ObjectMeta{ 84 Name: "static", 85 }, 86 Spec: AWSClusterStaticIdentitySpec{ 87 SecretRef: "test-secret", 88 }, 89 } 90 91 ctx := context.TODO() 92 defer testEnv.Delete(ctx, staticIdentity) 93 94 if err := testEnv.Create(ctx, staticIdentity); err != nil { 95 t.Errorf("staticIdentity creation failed %v", err) 96 } 97 98 tests := []struct { 99 name string 100 identity *AWSClusterStaticIdentity 101 wantError bool 102 }{ 103 { 104 name: "do not allow any spec changes", 105 identity: &AWSClusterStaticIdentity{ 106 Spec: AWSClusterStaticIdentitySpec{ 107 SecretRef: "test", 108 }, 109 }, 110 wantError: true, 111 }, 112 { 113 name: "no error when updating the same object", 114 identity: staticIdentity, 115 wantError: false, 116 }, 117 } 118 119 for _, tt := range tests { 120 t.Run(tt.name, func(t *testing.T) { 121 identity := tt.identity.DeepCopy() 122 identity.TypeMeta = metav1.TypeMeta{ 123 APIVersion: GroupVersion.String(), 124 Kind: string(ClusterStaticIdentityKind), 125 } 126 ctx := context.TODO() 127 if err := testEnv.Update(ctx, identity); (err != nil) != tt.wantError { 128 t.Errorf("ValidateUpdate() error = %v, wantErr %v", err, tt.wantError) 129 } 130 }) 131 } 132 } 133 134 func TestAWSClusterStaticIdentityUpdateLabelSelectorValidation(t *testing.T) { 135 staticIdentity := &AWSClusterStaticIdentity{ 136 TypeMeta: metav1.TypeMeta{ 137 APIVersion: GroupVersion.String(), 138 Kind: string(ClusterStaticIdentityKind), 139 }, 140 ObjectMeta: metav1.ObjectMeta{ 141 Name: "static", 142 }, 143 Spec: AWSClusterStaticIdentitySpec{ 144 AWSClusterIdentitySpec: AWSClusterIdentitySpec{ 145 AllowedNamespaces: &AllowedNamespaces{ 146 Selector: metav1.LabelSelector{ 147 MatchLabels: map[string]string{"foo": "bar"}, 148 }, 149 }, 150 }, 151 SecretRef: "test-secret", 152 }, 153 } 154 155 ctx := context.TODO() 156 defer testEnv.Delete(ctx, staticIdentity) 157 158 if err := testEnv.Create(ctx, staticIdentity); err != nil { 159 t.Errorf("staticIdentity creation failed %v", err) 160 } 161 162 tests := []struct { 163 name string 164 identity *AWSClusterStaticIdentity 165 wantError bool 166 }{ 167 { 168 name: "should not return error for valid selector", 169 identity: staticIdentity, 170 wantError: false, 171 }, 172 { 173 name: "should return error for invalid selector", 174 identity: &AWSClusterStaticIdentity{ 175 ObjectMeta: metav1.ObjectMeta{ 176 Name: "static", 177 }, 178 Spec: AWSClusterStaticIdentitySpec{ 179 AWSClusterIdentitySpec: AWSClusterIdentitySpec{ 180 AllowedNamespaces: &AllowedNamespaces{ 181 Selector: metav1.LabelSelector{ 182 MatchLabels: map[string]string{"-foo-123": "bar"}, 183 }, 184 }, 185 }, 186 }, 187 }, 188 wantError: true, 189 }, 190 } 191 for _, tt := range tests { 192 t.Run(tt.name, func(t *testing.T) { 193 identity := tt.identity.DeepCopy() 194 ctx := context.TODO() 195 if err := testEnv.Update(ctx, identity); (err != nil) != tt.wantError { 196 t.Errorf("ValidateUpdate() error = %v, wantErr %v", err, tt.wantError) 197 } 198 }) 199 } 200 } 201 202 func TestAWSClusterStaticIdentity_Default(t *testing.T) { 203 g := NewWithT(t) 204 tests := []struct { 205 name string 206 beforeAWSClusterStaticIdentity *AWSClusterStaticIdentity 207 afterAWSClusterStaticIdentity *AWSClusterStaticIdentity 208 }{ 209 { 210 name: "Set label while creating AWSClusterStaticIdentity if labels are undefined", 211 beforeAWSClusterStaticIdentity: &AWSClusterStaticIdentity{ 212 ObjectMeta: metav1.ObjectMeta{ 213 Name: "default", 214 }, 215 Spec: AWSClusterStaticIdentitySpec{ 216 AWSClusterIdentitySpec: AWSClusterIdentitySpec{ 217 AllowedNamespaces: &AllowedNamespaces{}, 218 }, 219 }, 220 }, 221 afterAWSClusterStaticIdentity: &AWSClusterStaticIdentity{ 222 ObjectMeta: metav1.ObjectMeta{ 223 Name: "default", 224 Labels: map[string]string{ 225 clusterv1.ClusterctlMoveHierarchyLabelName: "", 226 }, 227 }, 228 Spec: AWSClusterStaticIdentitySpec{ 229 AWSClusterIdentitySpec: AWSClusterIdentitySpec{ 230 AllowedNamespaces: &AllowedNamespaces{}, 231 }, 232 }, 233 }, 234 }, 235 { 236 name: "Not update any label while creating AWSClusterStaticIdentity if labels are already defined", 237 beforeAWSClusterStaticIdentity: &AWSClusterStaticIdentity{ 238 ObjectMeta: metav1.ObjectMeta{ 239 Name: "default", 240 Labels: map[string]string{ 241 clusterv1.ClusterctlMoveHierarchyLabelName: "abc", 242 }, 243 }, 244 Spec: AWSClusterStaticIdentitySpec{ 245 AWSClusterIdentitySpec: AWSClusterIdentitySpec{ 246 AllowedNamespaces: &AllowedNamespaces{}, 247 }, 248 }, 249 }, 250 afterAWSClusterStaticIdentity: &AWSClusterStaticIdentity{ 251 ObjectMeta: metav1.ObjectMeta{ 252 Name: "default", 253 Labels: map[string]string{ 254 clusterv1.ClusterctlMoveHierarchyLabelName: "abc", 255 }, 256 }, 257 Spec: AWSClusterStaticIdentitySpec{ 258 AWSClusterIdentitySpec: AWSClusterIdentitySpec{ 259 AllowedNamespaces: &AllowedNamespaces{}, 260 }, 261 }, 262 }, 263 }, 264 } 265 266 for _, tt := range tests { 267 t.Run(tt.name, func(t *testing.T) { 268 ctx := context.TODO() 269 awsClusterStaticIdentity := tt.beforeAWSClusterStaticIdentity.DeepCopy() 270 g.Expect(testEnv.Create(ctx, awsClusterStaticIdentity)).To(Succeed()) 271 g.Expect(len(awsClusterStaticIdentity.ObjectMeta.Labels)).To(Not(Equal(0))) 272 g.Expect(awsClusterStaticIdentity.ObjectMeta.Labels[clusterv1.ClusterctlMoveHierarchyLabelName]).To(Equal(tt.afterAWSClusterStaticIdentity.ObjectMeta.Labels[clusterv1.ClusterctlMoveHierarchyLabelName])) 273 g.Expect(testEnv.Delete(ctx, awsClusterStaticIdentity)).To(Succeed()) 274 }) 275 } 276 }