mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 12:18:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			220 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			220 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2017 The Kubernetes Authors.
 | 
						|
 | 
						|
Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
you may not use this file except in compliance with the License.
 | 
						|
You may obtain a copy of the License at
 | 
						|
 | 
						|
    http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 | 
						|
Unless required by applicable law or agreed to in writing, software
 | 
						|
distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
See the License for the specific language governing permissions and
 | 
						|
limitations under the License.
 | 
						|
*/
 | 
						|
 | 
						|
package scale
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"encoding/json"
 | 
						|
	"io/ioutil"
 | 
						|
	"path"
 | 
						|
	"strings"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	clientv3 "go.etcd.io/etcd/client/v3"
 | 
						|
	"google.golang.org/grpc/grpclog"
 | 
						|
 | 
						|
	appsv1 "k8s.io/api/apps/v1"
 | 
						|
	corev1 "k8s.io/api/core/v1"
 | 
						|
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						|
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 | 
						|
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
						|
	"k8s.io/client-go/kubernetes"
 | 
						|
	apitesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
 | 
						|
	"k8s.io/kubernetes/test/integration/framework"
 | 
						|
)
 | 
						|
 | 
						|
func makeGVR(group, version, resource string) schema.GroupVersionResource {
 | 
						|
	return schema.GroupVersionResource{Group: group, Version: version, Resource: resource}
 | 
						|
}
 | 
						|
func makeGVK(group, version, kind string) schema.GroupVersionKind {
 | 
						|
	return schema.GroupVersionKind{Group: group, Version: version, Kind: kind}
 | 
						|
}
 | 
						|
 | 
						|
func TestMain(m *testing.M) {
 | 
						|
	framework.EtcdMain(m.Run)
 | 
						|
}
 | 
						|
 | 
						|
func TestScaleSubresources(t *testing.T) {
 | 
						|
	clientSet, tearDown := setupWithOptions(t, nil, []string{
 | 
						|
		"--runtime-config",
 | 
						|
		"api/all=true",
 | 
						|
	})
 | 
						|
	defer tearDown()
 | 
						|
 | 
						|
	_, resourceLists, err := clientSet.Discovery().ServerGroupsAndResources()
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	expectedScaleSubresources := map[schema.GroupVersionResource]schema.GroupVersionKind{
 | 
						|
		makeGVR("", "v1", "replicationcontrollers/scale"): makeGVK("autoscaling", "v1", "Scale"),
 | 
						|
 | 
						|
		makeGVR("apps", "v1", "deployments/scale"):  makeGVK("autoscaling", "v1", "Scale"),
 | 
						|
		makeGVR("apps", "v1", "replicasets/scale"):  makeGVK("autoscaling", "v1", "Scale"),
 | 
						|
		makeGVR("apps", "v1", "statefulsets/scale"): makeGVK("autoscaling", "v1", "Scale"),
 | 
						|
	}
 | 
						|
 | 
						|
	autoscalingGVK := schema.GroupVersionKind{Group: "autoscaling", Version: "v1", Kind: "Scale"}
 | 
						|
 | 
						|
	discoveredScaleSubresources := map[schema.GroupVersionResource]schema.GroupVersionKind{}
 | 
						|
	for _, resourceList := range resourceLists {
 | 
						|
		containingGV, err := schema.ParseGroupVersion(resourceList.GroupVersion)
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("error getting group version for %#v: %v", resourceList, err)
 | 
						|
		}
 | 
						|
 | 
						|
		for _, resource := range resourceList.APIResources {
 | 
						|
			if !strings.HasSuffix(resource.Name, "/scale") {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			gvr := containingGV.WithResource(resource.Name)
 | 
						|
			if _, exists := discoveredScaleSubresources[gvr]; exists {
 | 
						|
				t.Errorf("scale subresource %#v listed multiple times in discovery", gvr)
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			gvk := containingGV.WithKind(resource.Kind)
 | 
						|
			if resource.Group != "" {
 | 
						|
				gvk.Group = resource.Group
 | 
						|
			}
 | 
						|
			if resource.Version != "" {
 | 
						|
				gvk.Version = resource.Version
 | 
						|
			}
 | 
						|
			discoveredScaleSubresources[gvr] = gvk
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Ensure nothing is missing
 | 
						|
	for gvr, gvk := range expectedScaleSubresources {
 | 
						|
		if _, ok := discoveredScaleSubresources[gvr]; !ok {
 | 
						|
			t.Errorf("expected scale subresource %#v of kind %#v was missing from discovery", gvr, gvk)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Ensure discovery lists expected types
 | 
						|
	for gvr, gvk := range discoveredScaleSubresources {
 | 
						|
		if expectedGVK, expected := expectedScaleSubresources[gvr]; !expected {
 | 
						|
			if gvk == autoscalingGVK {
 | 
						|
				t.Errorf("unexpected scale subresource %#v of kind %#v. new scale subresource should be added to expectedScaleSubresources", gvr, gvk)
 | 
						|
			} else {
 | 
						|
				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)
 | 
						|
			}
 | 
						|
			continue
 | 
						|
		} else if expectedGVK != gvk {
 | 
						|
			t.Errorf("scale subresource %#v should be of kind %#v, but %#v was listed in discovery", gvr, expectedGVK, gvk)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Create objects required to exercise scale subresources
 | 
						|
	if _, err := clientSet.CoreV1().ReplicationControllers("default").Create(context.TODO(), rcStub, metav1.CreateOptions{}); err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if _, err := clientSet.AppsV1().ReplicaSets("default").Create(context.TODO(), rsStub, metav1.CreateOptions{}); err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if _, err := clientSet.AppsV1().Deployments("default").Create(context.TODO(), deploymentStub, metav1.CreateOptions{}); err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if _, err := clientSet.AppsV1().StatefulSets("default").Create(context.TODO(), ssStub, metav1.CreateOptions{}); err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	// Ensure scale subresources return and accept expected kinds
 | 
						|
	for gvr, gvk := range discoveredScaleSubresources {
 | 
						|
		prefix := "/apis"
 | 
						|
		if gvr.Group == corev1.GroupName {
 | 
						|
			prefix = "/api"
 | 
						|
		}
 | 
						|
 | 
						|
		resourceParts := strings.SplitN(gvr.Resource, "/", 2)
 | 
						|
 | 
						|
		urlPath := path.Join(prefix, gvr.Group, gvr.Version, "namespaces", "default", resourceParts[0], "test", resourceParts[1])
 | 
						|
		obj := &unstructured.Unstructured{}
 | 
						|
 | 
						|
		getData, err := clientSet.CoreV1().RESTClient().Get().AbsPath(urlPath).DoRaw(context.TODO())
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("error fetching %s: %v", urlPath, err)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if err := json.Unmarshal(getData, obj); err != nil {
 | 
						|
			t.Errorf("error decoding %s: %v", urlPath, err)
 | 
						|
			t.Log(string(getData))
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		if obj.GetObjectKind().GroupVersionKind() != gvk {
 | 
						|
			t.Errorf("expected %#v, got %#v from %s", gvk, obj.GetObjectKind().GroupVersionKind(), urlPath)
 | 
						|
			t.Log(string(getData))
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		updateData, err := clientSet.CoreV1().RESTClient().Put().AbsPath(urlPath).Body(getData).DoRaw(context.TODO())
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("error putting to %s: %v", urlPath, err)
 | 
						|
			t.Log(string(getData))
 | 
						|
			t.Log(string(updateData))
 | 
						|
			continue
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
var (
 | 
						|
	replicas = int32(1)
 | 
						|
 | 
						|
	podStub = corev1.PodTemplateSpec{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"foo": "bar"}},
 | 
						|
		Spec:       corev1.PodSpec{Containers: []corev1.Container{{Name: "test", Image: "busybox"}}},
 | 
						|
	}
 | 
						|
 | 
						|
	rcStub = &corev1.ReplicationController{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: "test"},
 | 
						|
		Spec:       corev1.ReplicationControllerSpec{Selector: podStub.Labels, Replicas: &replicas, Template: &podStub},
 | 
						|
	}
 | 
						|
 | 
						|
	rsStub = &appsv1.ReplicaSet{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: "test"},
 | 
						|
		Spec:       appsv1.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: podStub.Labels}, Replicas: &replicas, Template: podStub},
 | 
						|
	}
 | 
						|
 | 
						|
	deploymentStub = &appsv1.Deployment{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: "test"},
 | 
						|
		Spec:       appsv1.DeploymentSpec{Selector: &metav1.LabelSelector{MatchLabels: podStub.Labels}, Replicas: &replicas, Template: podStub},
 | 
						|
	}
 | 
						|
 | 
						|
	ssStub = &appsv1.StatefulSet{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: "test"},
 | 
						|
		Spec:       appsv1.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: podStub.Labels}, Replicas: &replicas, Template: podStub},
 | 
						|
	}
 | 
						|
)
 | 
						|
 | 
						|
func setupWithOptions(t *testing.T, instanceOptions *apitesting.TestServerInstanceOptions, flags []string) (client kubernetes.Interface, tearDown func()) {
 | 
						|
	clientv3.SetLogger(grpclog.NewLoggerV2(ioutil.Discard, ioutil.Discard, ioutil.Discard))
 | 
						|
 | 
						|
	result := apitesting.StartTestServerOrDie(t, instanceOptions, flags, framework.SharedEtcd())
 | 
						|
	result.ClientConfig.AcceptContentTypes = ""
 | 
						|
	result.ClientConfig.ContentType = ""
 | 
						|
	result.ClientConfig.NegotiatedSerializer = nil
 | 
						|
	clientSet, err := kubernetes.NewForConfig(result.ClientConfig)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error creating clientset: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	return clientSet, result.TearDownFn
 | 
						|
}
 |