sigs.k8s.io/cluster-api@v1.7.1/exp/addons/internal/controllers/clusterresourceset_helpers_test.go (about)

     1  /*
     2  Copyright 2020 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 controllers
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  	"time"
    23  
    24  	. "github.com/onsi/gomega"
    25  	corev1 "k8s.io/api/core/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/runtime"
    28  	"k8s.io/apimachinery/pkg/types"
    29  	"sigs.k8s.io/controller-runtime/pkg/client"
    30  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    31  
    32  	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
    33  	addonsv1 "sigs.k8s.io/cluster-api/exp/addons/api/v1beta1"
    34  )
    35  
    36  const (
    37  	notDefaultNamespace = "not-default"
    38  )
    39  
    40  func TestGetorCreateClusterResourceSetBinding(t *testing.T) {
    41  	testClusterWithBinding := &clusterv1.Cluster{
    42  		ObjectMeta: metav1.ObjectMeta{
    43  			Name:      "test-cluster-with-binding",
    44  			Namespace: metav1.NamespaceDefault,
    45  		},
    46  	}
    47  
    48  	testClusterResourceSetBinding := &addonsv1.ClusterResourceSetBinding{
    49  		ObjectMeta: metav1.ObjectMeta{
    50  			Namespace: testClusterWithBinding.Namespace,
    51  			Name:      testClusterWithBinding.Name,
    52  		},
    53  		Spec: addonsv1.ClusterResourceSetBindingSpec{
    54  			Bindings: []*addonsv1.ResourceSetBinding{
    55  				{
    56  					ClusterResourceSetName: "test-clusterResourceSet",
    57  					Resources: []addonsv1.ResourceBinding{
    58  						{
    59  							ResourceRef: addonsv1.ResourceRef{
    60  								Name: "mySecret",
    61  								Kind: "Secret",
    62  							},
    63  							Applied:         true,
    64  							Hash:            "xyz",
    65  							LastAppliedTime: &metav1.Time{Time: time.Now().UTC()},
    66  						},
    67  					},
    68  				},
    69  			},
    70  		},
    71  	}
    72  
    73  	testClusterNoBinding := &clusterv1.Cluster{
    74  		ObjectMeta: metav1.ObjectMeta{
    75  			Name:      "test-cluster-no-binding",
    76  			Namespace: metav1.NamespaceDefault,
    77  		},
    78  	}
    79  
    80  	c := fake.NewClientBuilder().
    81  		WithObjects(testClusterResourceSetBinding).
    82  		Build()
    83  	r := &ClusterResourceSetReconciler{
    84  		Client: c,
    85  	}
    86  
    87  	tests := []struct {
    88  		name                     string
    89  		cluster                  *clusterv1.Cluster
    90  		numOfClusterResourceSets int
    91  	}{
    92  		{
    93  			name:                     "should return existing ClusterResourceSetBinding ",
    94  			cluster:                  testClusterWithBinding,
    95  			numOfClusterResourceSets: 1,
    96  		},
    97  		{
    98  			name:                     "should return a new ClusterResourceSetBinding",
    99  			cluster:                  testClusterNoBinding,
   100  			numOfClusterResourceSets: 0,
   101  		},
   102  	}
   103  
   104  	for _, tt := range tests {
   105  		t.Run(tt.name, func(t *testing.T) {
   106  			gs := NewWithT(t)
   107  
   108  			clusterResourceSetBinding, err := r.getOrCreateClusterResourceSetBinding(context.TODO(), tt.cluster, &addonsv1.ClusterResourceSet{})
   109  			gs.Expect(err).ToNot(HaveOccurred())
   110  
   111  			gs.Expect(clusterResourceSetBinding.Spec.Bindings).To(HaveLen(tt.numOfClusterResourceSets))
   112  		})
   113  	}
   114  }
   115  
   116  func TestGetSecretFromNamespacedName(t *testing.T) {
   117  	existingSecretName := types.NamespacedName{Name: "my-secret", Namespace: metav1.NamespaceDefault}
   118  	existingSecret := &corev1.Secret{
   119  		TypeMeta: metav1.TypeMeta{Kind: "Secret", APIVersion: "v1"},
   120  		ObjectMeta: metav1.ObjectMeta{
   121  			Name:      existingSecretName.Name,
   122  			Namespace: existingSecretName.Namespace,
   123  		},
   124  	}
   125  
   126  	tests := []struct {
   127  		name       string
   128  		secretName types.NamespacedName
   129  		want       *corev1.Secret
   130  		wantErr    bool
   131  	}{
   132  		{
   133  			name:       "should return secret when secret exists",
   134  			secretName: types.NamespacedName{Name: "my-secret", Namespace: metav1.NamespaceDefault},
   135  			want:       existingSecret,
   136  			wantErr:    false,
   137  		},
   138  		{
   139  			name:       "should return error when secret does not exist",
   140  			secretName: types.NamespacedName{Name: "my-secret", Namespace: notDefaultNamespace},
   141  			want:       nil,
   142  			wantErr:    true,
   143  		},
   144  	}
   145  
   146  	for _, tt := range tests {
   147  		t.Run(tt.name, func(t *testing.T) {
   148  			gs := NewWithT(t)
   149  
   150  			c := fake.NewClientBuilder().
   151  				WithObjects(existingSecret).
   152  				Build()
   153  
   154  			got, err := getSecret(context.TODO(), c, tt.secretName)
   155  
   156  			if tt.wantErr {
   157  				gs.Expect(err).To(HaveOccurred())
   158  				return
   159  			}
   160  			gs.Expect(err).ToNot(HaveOccurred())
   161  
   162  			gs.Expect(*got).To(BeComparableTo(*tt.want))
   163  		})
   164  	}
   165  }
   166  
   167  func TestGetConfigMapFromNamespacedName(t *testing.T) {
   168  	g := NewWithT(t)
   169  
   170  	scheme := runtime.NewScheme()
   171  	g.Expect(corev1.AddToScheme(scheme)).To(Succeed())
   172  
   173  	existingConfigMapName := types.NamespacedName{Name: "my-configmap", Namespace: metav1.NamespaceDefault}
   174  	existingConfigMap := &corev1.ConfigMap{
   175  		TypeMeta: metav1.TypeMeta{Kind: "ConfigMap", APIVersion: "v1"},
   176  		ObjectMeta: metav1.ObjectMeta{
   177  			Name:      existingConfigMapName.Name,
   178  			Namespace: existingConfigMapName.Namespace,
   179  		},
   180  	}
   181  
   182  	tests := []struct {
   183  		name          string
   184  		configMapName types.NamespacedName
   185  		want          *corev1.ConfigMap
   186  		wantErr       bool
   187  	}{
   188  		{
   189  			name:          "should return configmap when configmap exists",
   190  			configMapName: types.NamespacedName{Name: "my-configmap", Namespace: metav1.NamespaceDefault},
   191  			want:          existingConfigMap,
   192  			wantErr:       false,
   193  		},
   194  		{
   195  			name:          "should return error when configmap does not exist",
   196  			configMapName: types.NamespacedName{Name: "my-configmap", Namespace: notDefaultNamespace},
   197  			want:          nil,
   198  			wantErr:       true,
   199  		},
   200  	}
   201  
   202  	for _, tt := range tests {
   203  		t.Run(tt.name, func(t *testing.T) {
   204  			gs := NewWithT(t)
   205  
   206  			c := fake.NewClientBuilder().
   207  				WithScheme(scheme).
   208  				WithObjects(existingConfigMap).
   209  				Build()
   210  
   211  			got, err := getConfigMap(context.TODO(), c, tt.configMapName)
   212  
   213  			if tt.wantErr {
   214  				gs.Expect(err).To(HaveOccurred())
   215  				return
   216  			}
   217  			gs.Expect(err).ToNot(HaveOccurred())
   218  
   219  			gs.Expect(*got).To(BeComparableTo(*tt.want))
   220  		})
   221  	}
   222  }
   223  
   224  func TestEnsureKubernetesServiceCreated(t *testing.T) {
   225  	g := NewWithT(t)
   226  
   227  	scheme := runtime.NewScheme()
   228  	g.Expect(corev1.AddToScheme(scheme)).To(Succeed())
   229  
   230  	kubernetesAPIServerService := &corev1.Service{
   231  		TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: "v1"},
   232  		ObjectMeta: metav1.ObjectMeta{
   233  			Name:      "kubernetes",
   234  			Namespace: metav1.NamespaceDefault,
   235  		},
   236  	}
   237  
   238  	tests := []struct {
   239  		name         string
   240  		existingObjs []client.Object
   241  		wantErr      bool
   242  	}{
   243  		{
   244  			name:         "should return nil when Kubernetes API Server Service exists",
   245  			existingObjs: []client.Object{kubernetesAPIServerService},
   246  			wantErr:      false,
   247  		},
   248  		{
   249  			name:         "should return error when Kubernetes API Server Service does not exist",
   250  			existingObjs: []client.Object{},
   251  			wantErr:      true,
   252  		},
   253  	}
   254  
   255  	for _, tt := range tests {
   256  		t.Run(tt.name, func(t *testing.T) {
   257  			gs := NewWithT(t)
   258  
   259  			c := fake.NewClientBuilder().
   260  				WithScheme(scheme).
   261  				WithObjects(tt.existingObjs...).
   262  				Build()
   263  
   264  			err := ensureKubernetesServiceCreated(context.TODO(), c)
   265  
   266  			if tt.wantErr {
   267  				gs.Expect(err).To(HaveOccurred())
   268  				return
   269  			}
   270  			gs.Expect(err).ToNot(HaveOccurred())
   271  		})
   272  	}
   273  }