...

Source file src/k8s.io/kubernetes/test/integration/scale/scale_test.go

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

     1  /*
     2  Copyright 2017 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 scale
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"io"
    23  	"path"
    24  	"strings"
    25  	"testing"
    26  
    27  	"google.golang.org/grpc/grpclog"
    28  
    29  	appsv1 "k8s.io/api/apps/v1"
    30  	corev1 "k8s.io/api/core/v1"
    31  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    32  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    33  	"k8s.io/apimachinery/pkg/runtime/schema"
    34  	"k8s.io/client-go/kubernetes"
    35  	apitesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
    36  	"k8s.io/kubernetes/test/integration/framework"
    37  )
    38  
    39  func makeGVR(group, version, resource string) schema.GroupVersionResource {
    40  	return schema.GroupVersionResource{Group: group, Version: version, Resource: resource}
    41  }
    42  func makeGVK(group, version, kind string) schema.GroupVersionKind {
    43  	return schema.GroupVersionKind{Group: group, Version: version, Kind: kind}
    44  }
    45  
    46  func TestMain(m *testing.M) {
    47  	framework.EtcdMain(m.Run)
    48  }
    49  
    50  func TestScaleSubresources(t *testing.T) {
    51  	clientSet, tearDown := setupWithOptions(t, nil, []string{
    52  		"--runtime-config",
    53  		"api/all=true",
    54  	})
    55  	defer tearDown()
    56  
    57  	_, resourceLists, err := clientSet.Discovery().ServerGroupsAndResources()
    58  	if err != nil {
    59  		t.Fatal(err)
    60  	}
    61  
    62  	expectedScaleSubresources := map[schema.GroupVersionResource]schema.GroupVersionKind{
    63  		makeGVR("", "v1", "replicationcontrollers/scale"): makeGVK("autoscaling", "v1", "Scale"),
    64  
    65  		makeGVR("apps", "v1", "deployments/scale"):  makeGVK("autoscaling", "v1", "Scale"),
    66  		makeGVR("apps", "v1", "replicasets/scale"):  makeGVK("autoscaling", "v1", "Scale"),
    67  		makeGVR("apps", "v1", "statefulsets/scale"): makeGVK("autoscaling", "v1", "Scale"),
    68  	}
    69  
    70  	autoscalingGVK := schema.GroupVersionKind{Group: "autoscaling", Version: "v1", Kind: "Scale"}
    71  
    72  	discoveredScaleSubresources := map[schema.GroupVersionResource]schema.GroupVersionKind{}
    73  	for _, resourceList := range resourceLists {
    74  		containingGV, err := schema.ParseGroupVersion(resourceList.GroupVersion)
    75  		if err != nil {
    76  			t.Fatalf("error getting group version for %#v: %v", resourceList, err)
    77  		}
    78  
    79  		for _, resource := range resourceList.APIResources {
    80  			if !strings.HasSuffix(resource.Name, "/scale") {
    81  				continue
    82  			}
    83  
    84  			gvr := containingGV.WithResource(resource.Name)
    85  			if _, exists := discoveredScaleSubresources[gvr]; exists {
    86  				t.Errorf("scale subresource %#v listed multiple times in discovery", gvr)
    87  				continue
    88  			}
    89  
    90  			gvk := containingGV.WithKind(resource.Kind)
    91  			if resource.Group != "" {
    92  				gvk.Group = resource.Group
    93  			}
    94  			if resource.Version != "" {
    95  				gvk.Version = resource.Version
    96  			}
    97  			discoveredScaleSubresources[gvr] = gvk
    98  		}
    99  	}
   100  
   101  	// Ensure nothing is missing
   102  	for gvr, gvk := range expectedScaleSubresources {
   103  		if _, ok := discoveredScaleSubresources[gvr]; !ok {
   104  			t.Errorf("expected scale subresource %#v of kind %#v was missing from discovery", gvr, gvk)
   105  		}
   106  	}
   107  
   108  	// Ensure discovery lists expected types
   109  	for gvr, gvk := range discoveredScaleSubresources {
   110  		if expectedGVK, expected := expectedScaleSubresources[gvr]; !expected {
   111  			if gvk == autoscalingGVK {
   112  				t.Errorf("unexpected scale subresource %#v of kind %#v. new scale subresource should be added to expectedScaleSubresources", gvr, gvk)
   113  			} else {
   114  				t.Errorf("unexpected scale subresource %#v of kind %#v. new scale resources are expected to use Scale from the autoscaling/v1 API group", gvr, gvk)
   115  			}
   116  			continue
   117  		} else if expectedGVK != gvk {
   118  			t.Errorf("scale subresource %#v should be of kind %#v, but %#v was listed in discovery", gvr, expectedGVK, gvk)
   119  			continue
   120  		}
   121  	}
   122  
   123  	// Create objects required to exercise scale subresources
   124  	if _, err := clientSet.CoreV1().ReplicationControllers("default").Create(context.TODO(), rcStub, metav1.CreateOptions{}); err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	if _, err := clientSet.AppsV1().ReplicaSets("default").Create(context.TODO(), rsStub, metav1.CreateOptions{}); err != nil {
   128  		t.Fatal(err)
   129  	}
   130  	if _, err := clientSet.AppsV1().Deployments("default").Create(context.TODO(), deploymentStub, metav1.CreateOptions{}); err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	if _, err := clientSet.AppsV1().StatefulSets("default").Create(context.TODO(), ssStub, metav1.CreateOptions{}); err != nil {
   134  		t.Fatal(err)
   135  	}
   136  
   137  	// Ensure scale subresources return and accept expected kinds
   138  	for gvr, gvk := range discoveredScaleSubresources {
   139  		prefix := "/apis"
   140  		if gvr.Group == corev1.GroupName {
   141  			prefix = "/api"
   142  		}
   143  
   144  		resourceParts := strings.SplitN(gvr.Resource, "/", 2)
   145  
   146  		urlPath := path.Join(prefix, gvr.Group, gvr.Version, "namespaces", "default", resourceParts[0], "test", resourceParts[1])
   147  		obj := &unstructured.Unstructured{}
   148  
   149  		getData, err := clientSet.CoreV1().RESTClient().Get().AbsPath(urlPath).DoRaw(context.TODO())
   150  		if err != nil {
   151  			t.Errorf("error fetching %s: %v", urlPath, err)
   152  			continue
   153  		}
   154  		if err := json.Unmarshal(getData, obj); err != nil {
   155  			t.Errorf("error decoding %s: %v", urlPath, err)
   156  			t.Log(string(getData))
   157  			continue
   158  		}
   159  
   160  		if obj.GetObjectKind().GroupVersionKind() != gvk {
   161  			t.Errorf("expected %#v, got %#v from %s", gvk, obj.GetObjectKind().GroupVersionKind(), urlPath)
   162  			t.Log(string(getData))
   163  			continue
   164  		}
   165  
   166  		updateData, err := clientSet.CoreV1().RESTClient().Put().AbsPath(urlPath).Body(getData).DoRaw(context.TODO())
   167  		if err != nil {
   168  			t.Errorf("error putting to %s: %v", urlPath, err)
   169  			t.Log(string(getData))
   170  			t.Log(string(updateData))
   171  			continue
   172  		}
   173  	}
   174  }
   175  
   176  var (
   177  	replicas = int32(1)
   178  
   179  	podStub = corev1.PodTemplateSpec{
   180  		ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"foo": "bar"}},
   181  		Spec:       corev1.PodSpec{Containers: []corev1.Container{{Name: "test", Image: "busybox"}}},
   182  	}
   183  
   184  	rcStub = &corev1.ReplicationController{
   185  		ObjectMeta: metav1.ObjectMeta{Name: "test"},
   186  		Spec:       corev1.ReplicationControllerSpec{Selector: podStub.Labels, Replicas: &replicas, Template: &podStub},
   187  	}
   188  
   189  	rsStub = &appsv1.ReplicaSet{
   190  		ObjectMeta: metav1.ObjectMeta{Name: "test"},
   191  		Spec:       appsv1.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: podStub.Labels}, Replicas: &replicas, Template: podStub},
   192  	}
   193  
   194  	deploymentStub = &appsv1.Deployment{
   195  		ObjectMeta: metav1.ObjectMeta{Name: "test"},
   196  		Spec:       appsv1.DeploymentSpec{Selector: &metav1.LabelSelector{MatchLabels: podStub.Labels}, Replicas: &replicas, Template: podStub},
   197  	}
   198  
   199  	ssStub = &appsv1.StatefulSet{
   200  		ObjectMeta: metav1.ObjectMeta{Name: "test"},
   201  		Spec:       appsv1.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: podStub.Labels}, Replicas: &replicas, Template: podStub},
   202  	}
   203  )
   204  
   205  func setupWithOptions(t *testing.T, instanceOptions *apitesting.TestServerInstanceOptions, flags []string) (client kubernetes.Interface, tearDown func()) {
   206  	grpclog.SetLoggerV2(grpclog.NewLoggerV2(io.Discard, io.Discard, io.Discard))
   207  
   208  	result := apitesting.StartTestServerOrDie(t, instanceOptions, flags, framework.SharedEtcd())
   209  	result.ClientConfig.AcceptContentTypes = ""
   210  	result.ClientConfig.ContentType = ""
   211  	result.ClientConfig.NegotiatedSerializer = nil
   212  	clientSet, err := kubernetes.NewForConfig(result.ClientConfig)
   213  	if err != nil {
   214  		t.Fatalf("error creating clientset: %v", err)
   215  	}
   216  
   217  	return clientSet, result.TearDownFn
   218  }
   219  

View as plain text