sigs.k8s.io/cluster-api@v1.7.1/exp/addons/internal/webhooks/clusterresourceset_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 webhooks
    18  
    19  import (
    20  	"testing"
    21  
    22  	. "github.com/onsi/gomega"
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	ctrl "sigs.k8s.io/controller-runtime"
    25  
    26  	addonsv1 "sigs.k8s.io/cluster-api/exp/addons/api/v1beta1"
    27  	"sigs.k8s.io/cluster-api/internal/webhooks/util"
    28  )
    29  
    30  var ctx = ctrl.SetupSignalHandler()
    31  
    32  func TestClusterResourcesetDefault(t *testing.T) {
    33  	g := NewWithT(t)
    34  	clusterResourceSet := &addonsv1.ClusterResourceSet{}
    35  	defaultingValidationCRS := clusterResourceSet.DeepCopy()
    36  	defaultingValidationCRS.Spec.ClusterSelector = metav1.LabelSelector{
    37  		MatchLabels: map[string]string{"foo": "bar"},
    38  	}
    39  	webhook := ClusterResourceSet{}
    40  	t.Run("for ClusterResourceSet", util.CustomDefaultValidateTest(ctx, defaultingValidationCRS, &webhook))
    41  	g.Expect(webhook.Default(ctx, clusterResourceSet)).To(Succeed())
    42  
    43  	g.Expect(clusterResourceSet.Spec.Strategy).To(Equal(string(addonsv1.ClusterResourceSetStrategyApplyOnce)))
    44  }
    45  
    46  func TestClusterResourceSetLabelSelectorAsSelectorValidation(t *testing.T) {
    47  	tests := []struct {
    48  		name      string
    49  		selectors map[string]string
    50  		expectErr bool
    51  	}{
    52  		{
    53  			name:      "should not return error for valid selector",
    54  			selectors: map[string]string{"foo": "bar"},
    55  			expectErr: false,
    56  		},
    57  		{
    58  			name:      "should return error for invalid selector",
    59  			selectors: map[string]string{"-123-foo": "bar"},
    60  			expectErr: true,
    61  		},
    62  	}
    63  
    64  	for _, tt := range tests {
    65  		t.Run(tt.name, func(t *testing.T) {
    66  			g := NewWithT(t)
    67  			clusterResourceSet := &addonsv1.ClusterResourceSet{
    68  				Spec: addonsv1.ClusterResourceSetSpec{
    69  					ClusterSelector: metav1.LabelSelector{
    70  						MatchLabels: tt.selectors,
    71  					},
    72  				},
    73  			}
    74  			webhook := ClusterResourceSet{}
    75  			if tt.expectErr {
    76  				warnings, err := webhook.ValidateCreate(ctx, clusterResourceSet)
    77  				g.Expect(err).To(HaveOccurred())
    78  				g.Expect(warnings).To(BeEmpty())
    79  				warnings, err = webhook.ValidateUpdate(ctx, clusterResourceSet, clusterResourceSet)
    80  				g.Expect(err).To(HaveOccurred())
    81  				g.Expect(warnings).To(BeEmpty())
    82  			} else {
    83  				warnings, err := webhook.ValidateCreate(ctx, clusterResourceSet)
    84  				g.Expect(err).ToNot(HaveOccurred())
    85  				g.Expect(warnings).To(BeEmpty())
    86  				warnings, err = webhook.ValidateUpdate(ctx, clusterResourceSet, clusterResourceSet)
    87  				g.Expect(err).ToNot(HaveOccurred())
    88  				g.Expect(warnings).To(BeEmpty())
    89  			}
    90  		})
    91  	}
    92  }
    93  
    94  func TestClusterResourceSetStrategyImmutable(t *testing.T) {
    95  	tests := []struct {
    96  		name        string
    97  		oldStrategy string
    98  		newStrategy string
    99  		expectErr   bool
   100  	}{
   101  		{
   102  			name:        "when the Strategy has not changed",
   103  			oldStrategy: string(addonsv1.ClusterResourceSetStrategyApplyOnce),
   104  			newStrategy: string(addonsv1.ClusterResourceSetStrategyApplyOnce),
   105  			expectErr:   false,
   106  		},
   107  		{
   108  			name:        "when the Strategy has changed",
   109  			oldStrategy: string(addonsv1.ClusterResourceSetStrategyApplyOnce),
   110  			newStrategy: "",
   111  			expectErr:   true,
   112  		},
   113  	}
   114  
   115  	for _, tt := range tests {
   116  		t.Run(tt.name, func(t *testing.T) {
   117  			g := NewWithT(t)
   118  
   119  			newClusterResourceSet := &addonsv1.ClusterResourceSet{
   120  				Spec: addonsv1.ClusterResourceSetSpec{
   121  					ClusterSelector: metav1.LabelSelector{
   122  						MatchLabels: map[string]string{
   123  							"test": "test",
   124  						},
   125  					},
   126  					Strategy: tt.newStrategy,
   127  				},
   128  			}
   129  
   130  			oldClusterResourceSet := &addonsv1.ClusterResourceSet{
   131  				Spec: addonsv1.ClusterResourceSetSpec{
   132  					ClusterSelector: metav1.LabelSelector{
   133  						MatchLabels: map[string]string{
   134  							"test": "test",
   135  						},
   136  					},
   137  					Strategy: tt.oldStrategy,
   138  				},
   139  			}
   140  			webhook := ClusterResourceSet{}
   141  
   142  			warnings, err := webhook.ValidateUpdate(ctx, oldClusterResourceSet, newClusterResourceSet)
   143  			if tt.expectErr {
   144  				g.Expect(err).To(HaveOccurred())
   145  				g.Expect(warnings).To(BeEmpty())
   146  				return
   147  			}
   148  			g.Expect(err).ToNot(HaveOccurred())
   149  			g.Expect(warnings).To(BeEmpty())
   150  		})
   151  	}
   152  }
   153  
   154  func TestClusterResourceSetClusterSelectorImmutable(t *testing.T) {
   155  	tests := []struct {
   156  		name               string
   157  		oldClusterSelector map[string]string
   158  		newClusterSelector map[string]string
   159  		expectErr          bool
   160  	}{
   161  		{
   162  			name:               "when the ClusterSelector has not changed",
   163  			oldClusterSelector: map[string]string{"foo": "bar"},
   164  			newClusterSelector: map[string]string{"foo": "bar"},
   165  			expectErr:          false,
   166  		},
   167  		{
   168  			name:               "when the ClusterSelector has changed",
   169  			oldClusterSelector: map[string]string{"foo": "bar"},
   170  			newClusterSelector: map[string]string{"foo": "different"},
   171  			expectErr:          true,
   172  		},
   173  	}
   174  
   175  	for _, tt := range tests {
   176  		t.Run(tt.name, func(t *testing.T) {
   177  			g := NewWithT(t)
   178  
   179  			newClusterResourceSet := &addonsv1.ClusterResourceSet{
   180  				Spec: addonsv1.ClusterResourceSetSpec{
   181  					ClusterSelector: metav1.LabelSelector{
   182  						MatchLabels: tt.newClusterSelector,
   183  					},
   184  				},
   185  			}
   186  
   187  			oldClusterResourceSet := &addonsv1.ClusterResourceSet{
   188  				Spec: addonsv1.ClusterResourceSetSpec{
   189  					ClusterSelector: metav1.LabelSelector{
   190  						MatchLabels: tt.oldClusterSelector,
   191  					},
   192  				},
   193  			}
   194  			webhook := ClusterResourceSet{}
   195  
   196  			warnings, err := webhook.ValidateUpdate(ctx, oldClusterResourceSet, newClusterResourceSet)
   197  			if tt.expectErr {
   198  				g.Expect(err).To(HaveOccurred())
   199  				g.Expect(warnings).To(BeEmpty())
   200  				return
   201  			}
   202  			g.Expect(err).ToNot(HaveOccurred())
   203  			g.Expect(warnings).To(BeEmpty())
   204  		})
   205  	}
   206  }
   207  
   208  func TestClusterResourceSetSelectorNotEmptyValidation(t *testing.T) {
   209  	g := NewWithT(t)
   210  	clusterResourceSet := &addonsv1.ClusterResourceSet{}
   211  	webhook := ClusterResourceSet{}
   212  	err := webhook.validate(nil, clusterResourceSet)
   213  	g.Expect(err).To(HaveOccurred())
   214  	g.Expect(err.Error()).To(ContainSubstring("selector must not be empty"))
   215  }