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  }