mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			204 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2016 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 api_test
 | 
						|
 | 
						|
import (
 | 
						|
	"math/rand"
 | 
						|
	"reflect"
 | 
						|
	"sort"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/google/gofuzz"
 | 
						|
 | 
						|
	"k8s.io/kubernetes/pkg/api"
 | 
						|
	apiv1 "k8s.io/kubernetes/pkg/api/v1"
 | 
						|
	batchv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1"
 | 
						|
	extensionsv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
 | 
						|
	metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
 | 
						|
	"k8s.io/kubernetes/pkg/runtime"
 | 
						|
	"k8s.io/kubernetes/pkg/runtime/schema"
 | 
						|
	"k8s.io/kubernetes/pkg/util/diff"
 | 
						|
)
 | 
						|
 | 
						|
type orderedGroupVersionKinds []schema.GroupVersionKind
 | 
						|
 | 
						|
func (o orderedGroupVersionKinds) Len() int      { return len(o) }
 | 
						|
func (o orderedGroupVersionKinds) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
 | 
						|
func (o orderedGroupVersionKinds) Less(i, j int) bool {
 | 
						|
	return o[i].String() < o[j].String()
 | 
						|
}
 | 
						|
 | 
						|
func TestVerifyDefaulting(t *testing.T) {
 | 
						|
	job := &batchv2alpha1.JobTemplate{}
 | 
						|
	batchv2alpha1.SetObjectDefaults_JobTemplate(job)
 | 
						|
	if job.Template.Spec.Template.Spec.DNSPolicy != apiv1.DNSClusterFirst {
 | 
						|
		t.Errorf("unexpected defaulting: %#v", job)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// TODO: add a reflexive test that verifies that all SetDefaults functions are registered
 | 
						|
func TestDefaulting(t *testing.T) {
 | 
						|
	// these are the known types with defaulters - you must add to this list if you add a top level defaulter
 | 
						|
	typesWithDefaulting := map[schema.GroupVersionKind]struct{}{
 | 
						|
		{Group: "", Version: "v1", Kind: "ConfigMap"}:                                       {},
 | 
						|
		{Group: "", Version: "v1", Kind: "ConfigMapList"}:                                   {},
 | 
						|
		{Group: "", Version: "v1", Kind: "Endpoints"}:                                       {},
 | 
						|
		{Group: "", Version: "v1", Kind: "EndpointsList"}:                                   {},
 | 
						|
		{Group: "", Version: "v1", Kind: "Namespace"}:                                       {},
 | 
						|
		{Group: "", Version: "v1", Kind: "NamespaceList"}:                                   {},
 | 
						|
		{Group: "", Version: "v1", Kind: "Node"}:                                            {},
 | 
						|
		{Group: "", Version: "v1", Kind: "NodeList"}:                                        {},
 | 
						|
		{Group: "", Version: "v1", Kind: "PersistentVolume"}:                                {},
 | 
						|
		{Group: "", Version: "v1", Kind: "PersistentVolumeList"}:                            {},
 | 
						|
		{Group: "", Version: "v1", Kind: "PersistentVolumeClaim"}:                           {},
 | 
						|
		{Group: "", Version: "v1", Kind: "PersistentVolumeClaimList"}:                       {},
 | 
						|
		{Group: "", Version: "v1", Kind: "PodAttachOptions"}:                                {},
 | 
						|
		{Group: "", Version: "v1", Kind: "PodExecOptions"}:                                  {},
 | 
						|
		{Group: "", Version: "v1", Kind: "Pod"}:                                             {},
 | 
						|
		{Group: "", Version: "v1", Kind: "PodList"}:                                         {},
 | 
						|
		{Group: "", Version: "v1", Kind: "PodTemplate"}:                                     {},
 | 
						|
		{Group: "", Version: "v1", Kind: "PodTemplateList"}:                                 {},
 | 
						|
		{Group: "", Version: "v1", Kind: "ReplicationController"}:                           {},
 | 
						|
		{Group: "", Version: "v1", Kind: "ReplicationControllerList"}:                       {},
 | 
						|
		{Group: "", Version: "v1", Kind: "Secret"}:                                          {},
 | 
						|
		{Group: "", Version: "v1", Kind: "SecretList"}:                                      {},
 | 
						|
		{Group: "", Version: "v1", Kind: "Service"}:                                         {},
 | 
						|
		{Group: "", Version: "v1", Kind: "ServiceList"}:                                     {},
 | 
						|
		{Group: "apps", Version: "v1beta1", Kind: "StatefulSet"}:                            {},
 | 
						|
		{Group: "apps", Version: "v1beta1", Kind: "StatefulSetList"}:                        {},
 | 
						|
		{Group: "autoscaling", Version: "v1", Kind: "HorizontalPodAutoscaler"}:              {},
 | 
						|
		{Group: "autoscaling", Version: "v1", Kind: "HorizontalPodAutoscalerList"}:          {},
 | 
						|
		{Group: "batch", Version: "v1", Kind: "Job"}:                                        {},
 | 
						|
		{Group: "batch", Version: "v1", Kind: "JobList"}:                                    {},
 | 
						|
		{Group: "batch", Version: "v2alpha1", Kind: "CronJob"}:                              {},
 | 
						|
		{Group: "batch", Version: "v2alpha1", Kind: "CronJobList"}:                          {},
 | 
						|
		{Group: "batch", Version: "v2alpha1", Kind: "Job"}:                                  {},
 | 
						|
		{Group: "batch", Version: "v2alpha1", Kind: "JobList"}:                              {},
 | 
						|
		{Group: "batch", Version: "v2alpha1", Kind: "JobTemplate"}:                          {},
 | 
						|
		{Group: "batch", Version: "v2alpha1", Kind: "ScheduledJob"}:                         {},
 | 
						|
		{Group: "batch", Version: "v2alpha1", Kind: "ScheduledJobList"}:                     {},
 | 
						|
		{Group: "componentconfig", Version: "v1alpha1", Kind: "KubeProxyConfiguration"}:     {},
 | 
						|
		{Group: "componentconfig", Version: "v1alpha1", Kind: "KubeSchedulerConfiguration"}: {},
 | 
						|
		{Group: "componentconfig", Version: "v1alpha1", Kind: "KubeletConfiguration"}:       {},
 | 
						|
		{Group: "kubeadm.k8s.io", Version: "v1alpha1", Kind: "MasterConfiguration"}:         {},
 | 
						|
		// This object contains only int fields which currently breaks the defaulting test because
 | 
						|
		// it's pretty stupid. Once we add non integer fields, we should uncomment this.
 | 
						|
		// {Group: "kubeadm.k8s.io", Version: "v1alpha1", Kind: "NodeConfiguration"}:                 {},
 | 
						|
		{Group: "extensions", Version: "v1beta1", Kind: "DaemonSet"}:                              {},
 | 
						|
		{Group: "extensions", Version: "v1beta1", Kind: "DaemonSetList"}:                          {},
 | 
						|
		{Group: "extensions", Version: "v1beta1", Kind: "Deployment"}:                             {},
 | 
						|
		{Group: "extensions", Version: "v1beta1", Kind: "DeploymentList"}:                         {},
 | 
						|
		{Group: "extensions", Version: "v1beta1", Kind: "HorizontalPodAutoscaler"}:                {},
 | 
						|
		{Group: "extensions", Version: "v1beta1", Kind: "HorizontalPodAutoscalerList"}:            {},
 | 
						|
		{Group: "extensions", Version: "v1beta1", Kind: "ReplicaSet"}:                             {},
 | 
						|
		{Group: "extensions", Version: "v1beta1", Kind: "ReplicaSetList"}:                         {},
 | 
						|
		{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "ClusterRoleBinding"}:     {},
 | 
						|
		{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "ClusterRoleBindingList"}: {},
 | 
						|
		{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "RoleBinding"}:            {},
 | 
						|
		{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "RoleBindingList"}:        {},
 | 
						|
	}
 | 
						|
 | 
						|
	f := fuzz.New().NilChance(.5).NumElements(1, 1).RandSource(rand.NewSource(1))
 | 
						|
	f.Funcs(
 | 
						|
		func(s *runtime.RawExtension, c fuzz.Continue) {},
 | 
						|
		func(s *metav1.LabelSelector, c fuzz.Continue) {
 | 
						|
			c.FuzzNoCustom(s)
 | 
						|
			s.MatchExpressions = nil // need to fuzz this specially
 | 
						|
		},
 | 
						|
		func(s *apiv1.ListOptions, c fuzz.Continue) {
 | 
						|
			c.FuzzNoCustom(s)
 | 
						|
			s.LabelSelector = "" // need to fuzz requirement strings specially
 | 
						|
			s.FieldSelector = "" // need to fuzz requirement strings specially
 | 
						|
		},
 | 
						|
		func(s *extensionsv1beta1.ScaleStatus, c fuzz.Continue) {
 | 
						|
			c.FuzzNoCustom(s)
 | 
						|
			s.TargetSelector = "" // need to fuzz requirement strings specially
 | 
						|
		},
 | 
						|
	)
 | 
						|
 | 
						|
	scheme := api.Scheme
 | 
						|
	var testTypes orderedGroupVersionKinds
 | 
						|
	for gvk := range scheme.AllKnownTypes() {
 | 
						|
		if gvk.Version == runtime.APIVersionInternal {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		testTypes = append(testTypes, gvk)
 | 
						|
	}
 | 
						|
	sort.Sort(testTypes)
 | 
						|
 | 
						|
	for _, gvk := range testTypes {
 | 
						|
		_, expectedChanged := typesWithDefaulting[gvk]
 | 
						|
		iter := 0
 | 
						|
		changedOnce := false
 | 
						|
		for {
 | 
						|
			if iter > *fuzzIters {
 | 
						|
				if !expectedChanged || changedOnce {
 | 
						|
					break
 | 
						|
				}
 | 
						|
				if iter > 300 {
 | 
						|
					t.Errorf("expected %s to trigger defaulting due to fuzzing", gvk)
 | 
						|
					break
 | 
						|
				}
 | 
						|
				// if we expected defaulting, continue looping until the fuzzer gives us one
 | 
						|
				// at worst, we will timeout
 | 
						|
			}
 | 
						|
			iter++
 | 
						|
 | 
						|
			src, err := scheme.New(gvk)
 | 
						|
			if err != nil {
 | 
						|
				t.Fatal(err)
 | 
						|
			}
 | 
						|
			f.Fuzz(src)
 | 
						|
 | 
						|
			src.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{})
 | 
						|
 | 
						|
			original, err := scheme.DeepCopy(src)
 | 
						|
			if err != nil {
 | 
						|
				t.Fatal(err)
 | 
						|
			}
 | 
						|
 | 
						|
			// get internal
 | 
						|
			withDefaults, _ := scheme.DeepCopy(src)
 | 
						|
			scheme.Default(withDefaults.(runtime.Object))
 | 
						|
 | 
						|
			if !reflect.DeepEqual(original, withDefaults) {
 | 
						|
				changedOnce = true
 | 
						|
				if !expectedChanged {
 | 
						|
					t.Errorf("{Group: \"%s\", Version: \"%s\", Kind: \"%s\"} did not expect defaults to be set - update expected or check defaulter registering: %s", gvk.Group, gvk.Version, gvk.Kind, diff.ObjectReflectDiff(original, withDefaults))
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func BenchmarkPodDefaulting(b *testing.B) {
 | 
						|
	f := fuzz.New().NilChance(.5).NumElements(1, 1).RandSource(rand.NewSource(1))
 | 
						|
	items := make([]apiv1.Pod, 100)
 | 
						|
	for i := range items {
 | 
						|
		f.Fuzz(&items[i])
 | 
						|
	}
 | 
						|
 | 
						|
	scheme := api.Scheme
 | 
						|
	b.ResetTimer()
 | 
						|
	for i := 0; i < b.N; i++ {
 | 
						|
		pod := &items[i%len(items)]
 | 
						|
 | 
						|
		scheme.Default(pod)
 | 
						|
	}
 | 
						|
	b.StopTimer()
 | 
						|
}
 |