...

Source file src/k8s.io/kubernetes/test/integration/namespace/ns_conditions_test.go

Documentation: k8s.io/kubernetes/test/integration/namespace

     1  /*
     2  Copyright 2019 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 namespace
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"testing"
    24  	"time"
    25  
    26  	appsv1 "k8s.io/api/apps/v1"
    27  	corev1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    30  	"k8s.io/apimachinery/pkg/util/dump"
    31  	"k8s.io/apimachinery/pkg/util/wait"
    32  	"k8s.io/client-go/dynamic"
    33  	"k8s.io/client-go/informers"
    34  	clientset "k8s.io/client-go/kubernetes"
    35  	"k8s.io/client-go/metadata"
    36  	restclient "k8s.io/client-go/rest"
    37  	"k8s.io/klog/v2/ktesting"
    38  	kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
    39  	"k8s.io/kubernetes/pkg/controller/namespace"
    40  	"k8s.io/kubernetes/test/integration/etcd"
    41  	"k8s.io/kubernetes/test/integration/framework"
    42  )
    43  
    44  func TestNamespaceCondition(t *testing.T) {
    45  	closeFn, nsController, informers, kubeClient, dynamicClient := namespaceLifecycleSetup(t)
    46  	defer closeFn()
    47  	nsName := "test-namespace-conditions"
    48  	_, err := kubeClient.CoreV1().Namespaces().Create(context.TODO(), &corev1.Namespace{
    49  		ObjectMeta: metav1.ObjectMeta{
    50  			Name: nsName,
    51  		},
    52  	}, metav1.CreateOptions{})
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  
    57  	// Start informer and controllers
    58  	_, ctx := ktesting.NewTestContext(t)
    59  	ctx, cancel := context.WithCancel(ctx)
    60  	defer cancel()
    61  
    62  	informers.Start(ctx.Done())
    63  	go nsController.Run(ctx, 5)
    64  
    65  	data := etcd.GetEtcdStorageDataForNamespace(nsName)
    66  	podJSON, err := jsonToUnstructured(data[corev1.SchemeGroupVersion.WithResource("pods")].Stub, "v1", "Pod")
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	_, err = dynamicClient.Resource(corev1.SchemeGroupVersion.WithResource("pods")).Namespace(nsName).Create(context.TODO(), podJSON, metav1.CreateOptions{})
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  
    75  	deploymentJSON, err := jsonToUnstructured(data[appsv1.SchemeGroupVersion.WithResource("deployments")].Stub, "apps/v1", "Deployment")
    76  	if err != nil {
    77  		t.Fatal(err)
    78  	}
    79  	deploymentJSON.SetFinalizers([]string{"custom.io/finalizer"})
    80  	_, err = dynamicClient.Resource(appsv1.SchemeGroupVersion.WithResource("deployments")).Namespace(nsName).Create(context.TODO(), deploymentJSON, metav1.CreateOptions{})
    81  	if err != nil {
    82  		t.Fatal(err)
    83  	}
    84  
    85  	if err = kubeClient.CoreV1().Namespaces().Delete(context.TODO(), nsName, metav1.DeleteOptions{}); err != nil {
    86  		t.Fatal(err)
    87  	}
    88  
    89  	err = wait.PollImmediate(1*time.Second, 60*time.Second, func() (bool, error) {
    90  		curr, err := kubeClient.CoreV1().Namespaces().Get(context.TODO(), nsName, metav1.GetOptions{})
    91  		if err != nil {
    92  			return false, err
    93  		}
    94  
    95  		conditionsFound := 0
    96  		for _, condition := range curr.Status.Conditions {
    97  			if condition.Type == corev1.NamespaceDeletionGVParsingFailure && condition.Message == `All legacy kube types successfully parsed` {
    98  				conditionsFound++
    99  			}
   100  			if condition.Type == corev1.NamespaceDeletionDiscoveryFailure && condition.Message == `All resources successfully discovered` {
   101  				conditionsFound++
   102  			}
   103  			if condition.Type == corev1.NamespaceDeletionContentFailure && condition.Message == `All content successfully deleted, may be waiting on finalization` {
   104  				conditionsFound++
   105  			}
   106  			if condition.Type == corev1.NamespaceContentRemaining && condition.Message == `Some resources are remaining: deployments.apps has 1 resource instances` {
   107  				conditionsFound++
   108  			}
   109  			if condition.Type == corev1.NamespaceFinalizersRemaining && condition.Message == `Some content in the namespace has finalizers remaining: custom.io/finalizer in 1 resource instances` {
   110  				conditionsFound++
   111  			}
   112  		}
   113  
   114  		t.Log(dump.Pretty(curr))
   115  		return conditionsFound == 5, nil
   116  	})
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  }
   121  
   122  // TestNamespaceLabels tests for default labels added in https://github.com/kubernetes/kubernetes/pull/96968
   123  func TestNamespaceLabels(t *testing.T) {
   124  	closeFn, nsController, _, kubeClient, _ := namespaceLifecycleSetup(t)
   125  	defer closeFn()
   126  
   127  	// Even though nscontroller isn't used in this test, its creation is already
   128  	// spawning some goroutines. So we need to run it to ensure they won't leak.
   129  	_, ctx := ktesting.NewTestContext(t)
   130  	ctx, cancel := context.WithCancel(ctx)
   131  	defer cancel()
   132  	go nsController.Run(ctx, 5)
   133  
   134  	nsName := "test-namespace-labels-generated"
   135  	// Create a new namespace w/ no name
   136  	ns, err := kubeClient.CoreV1().Namespaces().Create(context.TODO(), &corev1.Namespace{
   137  		ObjectMeta: metav1.ObjectMeta{
   138  			GenerateName: nsName,
   139  		},
   140  	}, metav1.CreateOptions{})
   141  
   142  	if err != nil {
   143  		t.Fatal(err)
   144  	}
   145  
   146  	if ns.Name != ns.Labels[corev1.LabelMetadataName] {
   147  		t.Fatal(fmt.Errorf("expected %q, got %q", ns.Name, ns.Labels[corev1.LabelMetadataName]))
   148  	}
   149  
   150  	nsList, err := kubeClient.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
   151  
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	for _, ns := range nsList.Items {
   157  		if ns.Name != ns.Labels[corev1.LabelMetadataName] {
   158  			t.Fatal(fmt.Errorf("expected %q, got %q", ns.Name, ns.Labels[corev1.LabelMetadataName]))
   159  		}
   160  	}
   161  }
   162  
   163  // JSONToUnstructured converts a JSON stub to unstructured.Unstructured and
   164  // returns a dynamic resource client that can be used to interact with it
   165  func jsonToUnstructured(stub, version, kind string) (*unstructured.Unstructured, error) {
   166  	typeMetaAdder := map[string]interface{}{}
   167  	if err := json.Unmarshal([]byte(stub), &typeMetaAdder); err != nil {
   168  		return nil, err
   169  	}
   170  
   171  	// we don't require GVK on the data we provide, so we fill it in here.  We could, but that seems extraneous.
   172  	typeMetaAdder["apiVersion"] = version
   173  	typeMetaAdder["kind"] = kind
   174  
   175  	return &unstructured.Unstructured{Object: typeMetaAdder}, nil
   176  }
   177  
   178  func namespaceLifecycleSetup(t *testing.T) (kubeapiservertesting.TearDownFunc, *namespace.NamespaceController, informers.SharedInformerFactory, clientset.Interface, dynamic.Interface) {
   179  	// Disable ServiceAccount admission plugin as we don't have serviceaccount controller running.
   180  	server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd())
   181  
   182  	config := restclient.CopyConfig(server.ClientConfig)
   183  	config.QPS = 10000
   184  	config.Burst = 10000
   185  	clientSet, err := clientset.NewForConfig(config)
   186  	if err != nil {
   187  		t.Fatalf("error in create clientset: %v", err)
   188  	}
   189  	resyncPeriod := 12 * time.Hour
   190  	informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(config, "deployment-informers")), resyncPeriod)
   191  
   192  	metadataClient, err := metadata.NewForConfig(config)
   193  	if err != nil {
   194  		panic(err)
   195  	}
   196  
   197  	discoverResourcesFn := clientSet.Discovery().ServerPreferredNamespacedResources
   198  	_, ctx := ktesting.NewTestContext(t)
   199  	controller := namespace.NewNamespaceController(
   200  		ctx,
   201  		clientSet,
   202  		metadataClient,
   203  		discoverResourcesFn,
   204  		informers.Core().V1().Namespaces(),
   205  		10*time.Hour,
   206  		corev1.FinalizerKubernetes)
   207  
   208  	return server.TearDownFn, controller, informers, clientSet, dynamic.NewForConfigOrDie(config)
   209  }
   210  

View as plain text