github.com/oam-dev/kubevela@v1.9.11/pkg/utils/k8s_test.go (about)

     1  /*
     2  Copyright 2021 The KubeVela 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 utils
    18  
    19  import (
    20  	"context"
    21  
    22  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    23  	"k8s.io/apimachinery/pkg/fields"
    24  	"k8s.io/apimachinery/pkg/runtime"
    25  
    26  	"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
    27  	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
    28  
    29  	. "github.com/onsi/ginkgo/v2"
    30  	. "github.com/onsi/gomega"
    31  	v1 "k8s.io/api/core/v1"
    32  	rbacv1 "k8s.io/api/rbac/v1"
    33  	apierror "k8s.io/apimachinery/pkg/api/errors"
    34  	"sigs.k8s.io/controller-runtime/pkg/client"
    35  
    36  	"github.com/oam-dev/kubevela/pkg/utils/errors"
    37  )
    38  
    39  var _ = Describe("Test Create Or Update Namespace functions", func() {
    40  
    41  	BeforeEach(func() {
    42  	})
    43  
    44  	It("Test Create namespace function", func() {
    45  
    46  		By("test a normal namespace create case that should be created")
    47  		namespaceName := "my-test-test1"
    48  		err := CreateNamespace(context.Background(), k8sClient, namespaceName)
    49  		Expect(err).Should(BeNil())
    50  		var gotNS v1.Namespace
    51  		err = k8sClient.Get(context.Background(), client.ObjectKey{Name: namespaceName}, &gotNS)
    52  		Expect(err).Should(BeNil())
    53  
    54  		By("test a namespace create with no annotations case that should be created")
    55  		namespaceName = "my-test-test2"
    56  		var overrideAnn map[string]string
    57  		var overrideLabels map[string]string
    58  		err = CreateNamespace(context.Background(), k8sClient, namespaceName, MergeOverrideAnnotations(overrideAnn), MergeOverrideLabels(overrideLabels))
    59  		Expect(err).Should(BeNil())
    60  		err = k8sClient.Get(context.Background(), client.ObjectKey{Name: namespaceName}, &gotNS)
    61  		Expect(err).Should(BeNil())
    62  		Expect(gotNS.Annotations).Should(BeNil())
    63  
    64  		By("test a namespace create with annotations case that should be created")
    65  		namespaceName = "my-test-test3"
    66  		overrideAnn = map[string]string{"abc": "xyz", "haha": "123"}
    67  		overrideLabels = map[string]string{"l1": "v1", "l2": "v2"}
    68  		err = CreateNamespace(context.Background(), k8sClient, namespaceName, MergeOverrideAnnotations(overrideAnn), MergeOverrideLabels(overrideLabels))
    69  		Expect(err).Should(BeNil())
    70  		err = k8sClient.Get(context.Background(), client.ObjectKey{Name: namespaceName}, &gotNS)
    71  		Expect(err).Should(BeNil())
    72  		Expect(gotNS.Annotations).Should(BeEquivalentTo(overrideAnn))
    73  		for k, v := range overrideLabels {
    74  			Expect(gotNS.Labels).Should(HaveKeyWithValue(k, v))
    75  		}
    76  
    77  	})
    78  
    79  	It("Test Update namespace function", func() {
    80  
    81  		By("test a normal namespace update with no not found error")
    82  		namespaceName := "updatetest-test1"
    83  		err := UpdateNamespace(context.Background(), k8sClient, namespaceName)
    84  		Expect(apierror.IsNotFound(err)).Should(BeTrue())
    85  
    86  		overrideAnn := map[string]string{"abc": "xyz", "haha": "123"}
    87  		overrideLabels := map[string]string{"l1": "v1", "l2": "v2"}
    88  		err = CreateNamespace(context.Background(), k8sClient, namespaceName, MergeOverrideAnnotations(overrideAnn), MergeOverrideLabels(overrideLabels))
    89  		Expect(err).Should(BeNil())
    90  
    91  		By("test a namespace update with merge labels and annotations case that should be updated")
    92  		overrideAnn = map[string]string{"haha": "456", "newkey": "newvalue"}
    93  		overrideLabels = map[string]string{"l2": "v4", "l3": "v3"}
    94  		err = UpdateNamespace(context.Background(), k8sClient, namespaceName, MergeOverrideAnnotations(overrideAnn), MergeOverrideLabels(overrideLabels))
    95  		Expect(err).Should(BeNil())
    96  		var gotNS v1.Namespace
    97  		err = k8sClient.Get(context.Background(), client.ObjectKey{Name: namespaceName}, &gotNS)
    98  		Expect(err).Should(BeNil())
    99  		Expect(gotNS.Annotations).Should(BeEquivalentTo(map[string]string{"abc": "xyz", "haha": "456", "newkey": "newvalue"}))
   100  		for k, v := range overrideLabels {
   101  			Expect(gotNS.Labels).Should(HaveKeyWithValue(k, v))
   102  		}
   103  
   104  		By("test a namespace update with no conflict label key-value case that should be updated")
   105  		overrideLabels = map[string]string{"l2": "v5"}
   106  		noconflictLabels := map[string]string{"nc1": "v5"}
   107  		err = UpdateNamespace(context.Background(), k8sClient, namespaceName, MergeNoConflictLabels(noconflictLabels), MergeOverrideLabels(overrideLabels))
   108  		Expect(err).Should(BeNil())
   109  		err = k8sClient.Get(context.Background(), client.ObjectKey{Name: namespaceName}, &gotNS)
   110  		Expect(err).Should(BeNil())
   111  		for k, v := range noconflictLabels {
   112  			Expect(gotNS.Labels).Should(HaveKeyWithValue(k, v))
   113  		}
   114  		for k, v := range overrideLabels {
   115  			Expect(gotNS.Labels).Should(HaveKeyWithValue(k, v))
   116  		}
   117  
   118  		By("test a namespace update with conflict label that should return error")
   119  		noconflictLabels = map[string]string{"l2": "v6"}
   120  		err = UpdateNamespace(context.Background(), k8sClient, namespaceName, MergeNoConflictLabels(noconflictLabels))
   121  		Expect(err).ShouldNot(BeNil())
   122  		Expect(errors.IsLabelConflict(err)).Should(BeTrue())
   123  
   124  		By("test a namespace update with conflict key but same key should not return error")
   125  		noconflictLabels = map[string]string{"l2": "v5"}
   126  		err = UpdateNamespace(context.Background(), k8sClient, namespaceName, MergeNoConflictLabels(noconflictLabels))
   127  		Expect(err).Should(BeNil())
   128  
   129  		By("test a namespace update with reset key to be empty")
   130  		overrideLabels = map[string]string{"l1": "", "l2": ""}
   131  		err = UpdateNamespace(context.Background(), k8sClient, namespaceName, MergeOverrideLabels(overrideLabels))
   132  		Expect(err).Should(BeNil())
   133  		err = k8sClient.Get(context.Background(), client.ObjectKey{Name: namespaceName}, &gotNS)
   134  		Expect(err).Should(BeNil())
   135  		for k, v := range overrideLabels {
   136  			Expect(gotNS.Labels).Should(HaveKeyWithValue(k, v))
   137  		}
   138  
   139  		By("test a namespace update with conflict label key but the exist value is empty should be able to change")
   140  		noconflictLabels = map[string]string{"l1": "vx", "l2": "vy"}
   141  		err = UpdateNamespace(context.Background(), k8sClient, namespaceName, MergeNoConflictLabels(noconflictLabels))
   142  		Expect(err).Should(BeNil())
   143  		err = k8sClient.Get(context.Background(), client.ObjectKey{Name: namespaceName}, &gotNS)
   144  		Expect(err).Should(BeNil())
   145  		for k, v := range noconflictLabels {
   146  			Expect(gotNS.Labels).Should(HaveKeyWithValue(k, v))
   147  		}
   148  	})
   149  
   150  	It("Test CreateOrUpdate namespace function", func() {
   151  		By("test a normal namespace update with no namespace exist")
   152  		namespaceName := "create-or-update-test1"
   153  		err := CreateOrUpdateNamespace(context.Background(), k8sClient, namespaceName)
   154  		Expect(err).Should(BeNil())
   155  
   156  		By("test update namespace with functions")
   157  		overrideAnn := map[string]string{"abc": "xyz", "haha": "123"}
   158  		overrideLabels := map[string]string{"l1": "v1", "l2": "v2"}
   159  		noconflictLabels := map[string]string{"c1": "v1", "c2": "v2"}
   160  		err = CreateOrUpdateNamespace(context.Background(), k8sClient, namespaceName, MergeOverrideAnnotations(overrideAnn), MergeOverrideLabels(overrideLabels), MergeNoConflictLabels(noconflictLabels))
   161  		Expect(err).Should(BeNil())
   162  		var gotNS v1.Namespace
   163  		err = k8sClient.Get(context.Background(), client.ObjectKey{Name: namespaceName}, &gotNS)
   164  		Expect(err).Should(BeNil())
   165  		Expect(gotNS.Annotations).Should(BeEquivalentTo(overrideAnn))
   166  		for k, v := range overrideLabels {
   167  			Expect(gotNS.Labels).Should(HaveKeyWithValue(k, v))
   168  		}
   169  		for k, v := range noconflictLabels {
   170  			Expect(gotNS.Labels).Should(HaveKeyWithValue(k, v))
   171  		}
   172  	})
   173  
   174  	It("Test IsClusterScope", func() {
   175  		ok, err := IsClusterScope(v1.SchemeGroupVersion.WithKind("ConfigMap"), k8sClient.RESTMapper())
   176  		Expect(err).Should(Succeed())
   177  		Expect(ok).Should(BeFalse())
   178  		ok, err = IsClusterScope(rbacv1.SchemeGroupVersion.WithKind("ClusterRole"), k8sClient.RESTMapper())
   179  		Expect(err).Should(Succeed())
   180  		Expect(ok).Should(BeTrue())
   181  	})
   182  
   183  	It("Test FilterObjectsByFieldSelector function", func() {
   184  		var componentSpec = v1beta1.ApplicationSpec{
   185  			Components: []common.ApplicationComponent{
   186  				{
   187  					Name:       "test1-component",
   188  					Type:       "worker",
   189  					Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
   190  				},
   191  			},
   192  		}
   193  		var componentStatus = common.AppStatus{
   194  			Services: []common.ApplicationComponentStatus{
   195  				{
   196  					Name:    "test1-component",
   197  					Message: "test1-component applied",
   198  					Healthy: true,
   199  				},
   200  			},
   201  			Phase: common.ApplicationRunning,
   202  		}
   203  		apps := []*v1beta1.Application{
   204  			{
   205  				ObjectMeta: metav1.ObjectMeta{
   206  					Name:      "app1",
   207  					Namespace: "test2",
   208  				},
   209  				Spec:   componentSpec,
   210  				Status: componentStatus,
   211  			},
   212  			{
   213  				ObjectMeta: metav1.ObjectMeta{
   214  					Name:      "app2",
   215  					Namespace: "test2",
   216  				},
   217  				Spec:   componentSpec,
   218  				Status: componentStatus,
   219  			},
   220  		}
   221  
   222  		var objects []runtime.Object
   223  		for i := range apps {
   224  			objects = append(objects, apps[i])
   225  		}
   226  		fieldSelector, err := fields.ParseSelector("metadata.name=app2,metadata.namespace=test2")
   227  		Expect(err).Should(BeNil())
   228  		filteredObjects := FilterObjectsByFieldSelector(objects, fieldSelector)
   229  		Expect(filteredObjects).Should(ContainElements(objects[1]))
   230  	})
   231  })