func TestSetDefaulServiceTargetPort(t *testing.T) { in := &versioned.Service{Spec: versioned.ServiceSpec{Ports: []versioned.ServicePort{{Port: 1234}}}} obj := roundTrip(t, runtime.Object(in)) out := obj.(*versioned.Service) if out.Spec.Ports[0].TargetPort != intstr.FromInt(1234) { t.Errorf("Expected TargetPort to be defaulted, got %v", out.Spec.Ports[0].TargetPort) } in = &versioned.Service{Spec: versioned.ServiceSpec{Ports: []versioned.ServicePort{{Port: 1234, TargetPort: intstr.FromInt(5678)}}}} obj = roundTrip(t, runtime.Object(in)) out = obj.(*versioned.Service) if out.Spec.Ports[0].TargetPort != intstr.FromInt(5678) { t.Errorf("Expected TargetPort to be unchanged, got %v", out.Spec.Ports[0].TargetPort) } }
func TestDoRequestNewWayFile(t *testing.T) { reqObj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} reqBodyExpected, err := runtime.Encode(testapi.Default.Codec(), reqObj) if err != nil { t.Errorf("unexpected error: %v", err) } file, err := ioutil.TempFile("", "foo") if err != nil { t.Errorf("unexpected error: %v", err) } defer file.Close() _, err = file.Write(reqBodyExpected) if err != nil { t.Errorf("unexpected error: %v", err) } expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) // TODO: Uncomment when fix #19254 // defer testServer.Close() c := testRESTClient(t, testServer) wasCreated := true obj, err := c.Verb("POST"). Prefix("foo/bar", "baz"). Timeout(time.Second). Body(file.Name()). Do().WasCreated(&wasCreated).Get() if err != nil { t.Errorf("Unexpected error: %v %#v", err, err) return } if obj == nil { t.Error("nil obj") } else if !api.Semantic.DeepDerivative(expectedObj, obj) { t.Errorf("Expected: %#v, got %#v", expectedObj, obj) } if wasCreated { t.Errorf("expected object was not created") } tmpStr := string(reqBodyExpected) requestURL := testapi.Default.ResourcePathWithPrefix("foo/bar/baz", "", "", "") requestURL += "?timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) }
func TestSetDefaultServicePort(t *testing.T) { // Unchanged if set. in := &versioned.Service{Spec: versioned.ServiceSpec{ Ports: []versioned.ServicePort{ {Protocol: "UDP", Port: 9376, TargetPort: intstr.FromString("p")}, {Protocol: "UDP", Port: 8675, TargetPort: intstr.FromInt(309)}, }, }} out := roundTrip(t, runtime.Object(in)).(*versioned.Service) if out.Spec.Ports[0].Protocol != versioned.ProtocolUDP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolUDP, out.Spec.Ports[0].Protocol) } if out.Spec.Ports[0].TargetPort != intstr.FromString("p") { t.Errorf("Expected port %v, got %v", in.Spec.Ports[0].Port, out.Spec.Ports[0].TargetPort) } if out.Spec.Ports[1].Protocol != versioned.ProtocolUDP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolUDP, out.Spec.Ports[1].Protocol) } if out.Spec.Ports[1].TargetPort != intstr.FromInt(309) { t.Errorf("Expected port %v, got %v", in.Spec.Ports[1].Port, out.Spec.Ports[1].TargetPort) } // Defaulted. in = &versioned.Service{Spec: versioned.ServiceSpec{ Ports: []versioned.ServicePort{ {Protocol: "", Port: 9376, TargetPort: intstr.FromString("")}, {Protocol: "", Port: 8675, TargetPort: intstr.FromInt(0)}, }, }} out = roundTrip(t, runtime.Object(in)).(*versioned.Service) if out.Spec.Ports[0].Protocol != versioned.ProtocolTCP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Spec.Ports[0].Protocol) } if out.Spec.Ports[0].TargetPort != intstr.FromInt(int(in.Spec.Ports[0].Port)) { t.Errorf("Expected port %v, got %v", in.Spec.Ports[0].Port, out.Spec.Ports[0].TargetPort) } if out.Spec.Ports[1].Protocol != versioned.ProtocolTCP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Spec.Ports[1].Protocol) } if out.Spec.Ports[1].TargetPort != intstr.FromInt(int(in.Spec.Ports[1].Port)) { t.Errorf("Expected port %v, got %v", in.Spec.Ports[1].Port, out.Spec.Ports[1].TargetPort) } }
func TestDoRequestNewWayObj(t *testing.T) { reqObj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} reqBodyExpected, _ := runtime.Encode(testapi.Default.Codec(), reqObj) expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) // TODO: Uncomment when fix #19254 // defer testServer.Close() c := testRESTClient(t, testServer) obj, err := c.Verb("POST"). Suffix("baz"). Name("bar"). Resource("foo"). LabelsSelectorParam(labels.Set{"name": "foo"}.AsSelector()). Timeout(time.Second). Body(reqObj). Do().Get() if err != nil { t.Errorf("Unexpected error: %v %#v", err, err) return } if obj == nil { t.Error("nil obj") } else if !api.Semantic.DeepDerivative(expectedObj, obj) { t.Errorf("Expected: %#v, got %#v", expectedObj, obj) } tmpStr := string(reqBodyExpected) requestURL := testapi.Default.ResourcePath("foo", "", "bar/baz") requestURL += "?" + unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()) + "=name%3Dfoo&timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) }
func TestDoRequestNewWay(t *testing.T) { reqBody := "request body" expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) // TODO: Uncomment when fix #19254 // defer testServer.Close() c := testRESTClient(t, testServer) obj, err := c.Verb("POST"). Prefix("foo", "bar"). Suffix("baz"). Timeout(time.Second). Body([]byte(reqBody)). Do().Get() if err != nil { t.Errorf("Unexpected error: %v %#v", err, err) return } if obj == nil { t.Error("nil obj") } else if !api.Semantic.DeepDerivative(expectedObj, obj) { t.Errorf("Expected: %#v, got %#v", expectedObj, obj) } requestURL := testapi.Default.ResourcePathWithPrefix("foo/bar", "", "", "baz") requestURL += "?timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &reqBody) }
func addDefaultingFuncs(scheme *runtime.Scheme) { scheme.AddDefaultingFuncs( func(obj *PodExecOptions) { obj.Stdout = true obj.Stderr = true }, func(obj *PodAttachOptions) { obj.Stdout = true obj.Stderr = true }, func(obj *ReplicationController) { var labels map[string]string if obj.Spec.Template != nil { labels = obj.Spec.Template.Labels } // TODO: support templates defined elsewhere when we support them in the API if labels != nil { if len(obj.Spec.Selector) == 0 { obj.Spec.Selector = labels } if len(obj.Labels) == 0 { obj.Labels = labels } } if obj.Spec.Replicas == nil { obj.Spec.Replicas = new(int32) *obj.Spec.Replicas = 1 } }, func(obj *Volume) { if util.AllPtrFieldsNil(&obj.VolumeSource) { obj.VolumeSource = VolumeSource{ EmptyDir: &EmptyDirVolumeSource{}, } } }, func(obj *ContainerPort) { if obj.Protocol == "" { obj.Protocol = ProtocolTCP } }, func(obj *Container) { if obj.ImagePullPolicy == "" { _, tag := parsers.ParseImageName(obj.Image) // Check image tag if tag == "latest" { obj.ImagePullPolicy = PullAlways } else { obj.ImagePullPolicy = PullIfNotPresent } } if obj.TerminationMessagePath == "" { obj.TerminationMessagePath = TerminationMessagePathDefault } }, func(obj *ServiceSpec) { if obj.SessionAffinity == "" { obj.SessionAffinity = ServiceAffinityNone } if obj.Type == "" { obj.Type = ServiceTypeClusterIP } for i := range obj.Ports { sp := &obj.Ports[i] if sp.Protocol == "" { sp.Protocol = ProtocolTCP } if sp.TargetPort == intstr.FromInt(0) || sp.TargetPort == intstr.FromString("") { sp.TargetPort = intstr.FromInt(int(sp.Port)) } } }, func(obj *Pod) { // If limits are specified, but requests are not, default requests to limits // This is done here rather than a more specific defaulting pass on ResourceRequirements // because we only want this defaulting semantic to take place on a Pod and not a PodTemplate for i := range obj.Spec.Containers { // set requests to limits if requests are not specified, but limits are if obj.Spec.Containers[i].Resources.Limits != nil { if obj.Spec.Containers[i].Resources.Requests == nil { obj.Spec.Containers[i].Resources.Requests = make(ResourceList) } for key, value := range obj.Spec.Containers[i].Resources.Limits { if _, exists := obj.Spec.Containers[i].Resources.Requests[key]; !exists { obj.Spec.Containers[i].Resources.Requests[key] = *(value.Copy()) } } } } }, func(obj *PodSpec) { if obj.DNSPolicy == "" { obj.DNSPolicy = DNSClusterFirst } if obj.RestartPolicy == "" { obj.RestartPolicy = RestartPolicyAlways } if obj.HostNetwork { defaultHostNetworkPorts(&obj.Containers) } if obj.SecurityContext == nil { obj.SecurityContext = &PodSecurityContext{} } if obj.TerminationGracePeriodSeconds == nil { period := int64(DefaultTerminationGracePeriodSeconds) obj.TerminationGracePeriodSeconds = &period } }, func(obj *Probe) { if obj.TimeoutSeconds == 0 { obj.TimeoutSeconds = 1 } if obj.PeriodSeconds == 0 { obj.PeriodSeconds = 10 } if obj.SuccessThreshold == 0 { obj.SuccessThreshold = 1 } if obj.FailureThreshold == 0 { obj.FailureThreshold = 3 } }, func(obj *Secret) { if obj.Type == "" { obj.Type = SecretTypeOpaque } }, func(obj *PersistentVolume) { if obj.Status.Phase == "" { obj.Status.Phase = VolumePending } if obj.Spec.PersistentVolumeReclaimPolicy == "" { obj.Spec.PersistentVolumeReclaimPolicy = PersistentVolumeReclaimRetain } }, func(obj *PersistentVolumeClaim) { if obj.Status.Phase == "" { obj.Status.Phase = ClaimPending } }, func(obj *ISCSIVolumeSource) { if obj.ISCSIInterface == "" { obj.ISCSIInterface = "default" } }, func(obj *Endpoints) { for i := range obj.Subsets { ss := &obj.Subsets[i] for i := range ss.Ports { ep := &ss.Ports[i] if ep.Protocol == "" { ep.Protocol = ProtocolTCP } } } }, func(obj *HTTPGetAction) { if obj.Path == "" { obj.Path = "/" } if obj.Scheme == "" { obj.Scheme = URISchemeHTTP } }, func(obj *NamespaceStatus) { if obj.Phase == "" { obj.Phase = NamespaceActive } }, func(obj *Node) { if obj.Spec.ExternalID == "" { obj.Spec.ExternalID = obj.Name } }, func(obj *NodeStatus) { if obj.Allocatable == nil && obj.Capacity != nil { obj.Allocatable = make(ResourceList, len(obj.Capacity)) for key, value := range obj.Capacity { obj.Allocatable[key] = *(value.Copy()) } obj.Allocatable = obj.Capacity } }, func(obj *ObjectFieldSelector) { if obj.APIVersion == "" { obj.APIVersion = "v1" } }, func(obj *LimitRangeItem) { // for container limits, we apply default values if obj.Type == LimitTypeContainer { if obj.Default == nil { obj.Default = make(ResourceList) } if obj.DefaultRequest == nil { obj.DefaultRequest = make(ResourceList) } // If a default limit is unspecified, but the max is specified, default the limit to the max for key, value := range obj.Max { if _, exists := obj.Default[key]; !exists { obj.Default[key] = *(value.Copy()) } } // If a default limit is specified, but the default request is not, default request to limit for key, value := range obj.Default { if _, exists := obj.DefaultRequest[key]; !exists { obj.DefaultRequest[key] = *(value.Copy()) } } // If a default request is not specified, but the min is provided, default request to the min for key, value := range obj.Min { if _, exists := obj.DefaultRequest[key]; !exists { obj.DefaultRequest[key] = *(value.Copy()) } } } }, func(obj *ConfigMap) { if obj.Data == nil { obj.Data = make(map[string]string) } }, ) }
func TestSetDefaultDaemonSet(t *testing.T) { defaultIntOrString := intstr.FromInt(1) defaultLabels := map[string]string{"foo": "bar"} period := int64(v1.DefaultTerminationGracePeriodSeconds) defaultTemplate := v1.PodTemplateSpec{ Spec: v1.PodSpec{ DNSPolicy: v1.DNSClusterFirst, RestartPolicy: v1.RestartPolicyAlways, SecurityContext: &v1.PodSecurityContext{}, TerminationGracePeriodSeconds: &period, }, ObjectMeta: v1.ObjectMeta{ Labels: defaultLabels, }, } templateNoLabel := v1.PodTemplateSpec{ Spec: v1.PodSpec{ DNSPolicy: v1.DNSClusterFirst, RestartPolicy: v1.RestartPolicyAlways, SecurityContext: &v1.PodSecurityContext{}, TerminationGracePeriodSeconds: &period, }, } tests := []struct { original *DaemonSet expected *DaemonSet }{ { // Labels change/defaulting test. original: &DaemonSet{ Spec: DaemonSetSpec{ Template: defaultTemplate, }, }, expected: &DaemonSet{ ObjectMeta: v1.ObjectMeta{ Labels: defaultLabels, }, Spec: DaemonSetSpec{ Selector: &LabelSelector{ MatchLabels: defaultLabels, }, Template: defaultTemplate, UpdateStrategy: DaemonSetUpdateStrategy{ Type: RollingUpdateDaemonSetStrategyType, RollingUpdate: &RollingUpdateDaemonSet{ MaxUnavailable: &defaultIntOrString, }, }, UniqueLabelKey: newString(DefaultDaemonSetUniqueLabelKey), }, }, }, { // Labels change/defaulting test. original: &DaemonSet{ ObjectMeta: v1.ObjectMeta{ Labels: map[string]string{ "bar": "foo", }, }, Spec: DaemonSetSpec{ Template: defaultTemplate, UpdateStrategy: DaemonSetUpdateStrategy{ Type: RollingUpdateDaemonSetStrategyType, RollingUpdate: &RollingUpdateDaemonSet{ MaxUnavailable: &defaultIntOrString, }, }, }, }, expected: &DaemonSet{ ObjectMeta: v1.ObjectMeta{ Labels: map[string]string{ "bar": "foo", }, }, Spec: DaemonSetSpec{ Selector: &LabelSelector{ MatchLabels: defaultLabels, }, Template: defaultTemplate, UpdateStrategy: DaemonSetUpdateStrategy{ Type: RollingUpdateDaemonSetStrategyType, RollingUpdate: &RollingUpdateDaemonSet{ MaxUnavailable: &defaultIntOrString, }, }, UniqueLabelKey: newString(DefaultDaemonSetUniqueLabelKey), }, }, }, { // Update strategy. original: &DaemonSet{}, expected: &DaemonSet{ Spec: DaemonSetSpec{ Template: templateNoLabel, UpdateStrategy: DaemonSetUpdateStrategy{ Type: RollingUpdateDaemonSetStrategyType, RollingUpdate: &RollingUpdateDaemonSet{ MaxUnavailable: &defaultIntOrString, }, }, UniqueLabelKey: newString(DefaultDaemonSetUniqueLabelKey), }, }, }, { // Update strategy. original: &DaemonSet{ Spec: DaemonSetSpec{ UpdateStrategy: DaemonSetUpdateStrategy{ RollingUpdate: &RollingUpdateDaemonSet{}, }, }, }, expected: &DaemonSet{ Spec: DaemonSetSpec{ Template: templateNoLabel, UpdateStrategy: DaemonSetUpdateStrategy{ Type: RollingUpdateDaemonSetStrategyType, RollingUpdate: &RollingUpdateDaemonSet{ MaxUnavailable: &defaultIntOrString, }, }, UniqueLabelKey: newString(DefaultDaemonSetUniqueLabelKey), }, }, }, { // Custom unique label key. original: &DaemonSet{ Spec: DaemonSetSpec{ UpdateStrategy: DaemonSetUpdateStrategy{ RollingUpdate: &RollingUpdateDaemonSet{}, }, UniqueLabelKey: newString("customDaemonSetKey"), }, }, expected: &DaemonSet{ Spec: DaemonSetSpec{ Template: templateNoLabel, UpdateStrategy: DaemonSetUpdateStrategy{ Type: RollingUpdateDaemonSetStrategyType, RollingUpdate: &RollingUpdateDaemonSet{ MaxUnavailable: &defaultIntOrString, }, }, UniqueLabelKey: newString("customDaemonSetKey"), }, }, }, } for i, test := range tests { original := test.original expected := test.expected obj2 := roundTrip(t, runtime.Object(original)) got, ok := obj2.(*DaemonSet) if !ok { t.Errorf("(%d) unexpected object: %v", i, got) t.FailNow() } if !reflect.DeepEqual(got.Spec, expected.Spec) { t.Errorf("(%d) got different than expected\ngot:\n\t%+v\nexpected:\n\t%+v", i, got.Spec, expected.Spec) } } }
func TestSetDefaultDeployment(t *testing.T) { defaultIntOrString := intstr.FromInt(1) differentIntOrString := intstr.FromInt(5) deploymentLabelKey := DefaultDeploymentUniqueLabelKey period := int64(v1.DefaultTerminationGracePeriodSeconds) defaultTemplate := v1.PodTemplateSpec{ Spec: v1.PodSpec{ DNSPolicy: v1.DNSClusterFirst, RestartPolicy: v1.RestartPolicyAlways, SecurityContext: &v1.PodSecurityContext{}, TerminationGracePeriodSeconds: &period, }, } tests := []struct { original *Deployment expected *Deployment }{ { original: &Deployment{}, expected: &Deployment{ Spec: DeploymentSpec{ Replicas: newInt32(1), Strategy: DeploymentStrategy{ Type: RollingUpdateDeploymentStrategyType, RollingUpdate: &RollingUpdateDeployment{ MaxSurge: &defaultIntOrString, MaxUnavailable: &defaultIntOrString, }, }, Template: defaultTemplate, UniqueLabelKey: newString(deploymentLabelKey), }, }, }, { original: &Deployment{ Spec: DeploymentSpec{ Replicas: newInt32(5), Strategy: DeploymentStrategy{ RollingUpdate: &RollingUpdateDeployment{ MaxSurge: &differentIntOrString, }, }, }, }, expected: &Deployment{ Spec: DeploymentSpec{ Replicas: newInt32(5), Strategy: DeploymentStrategy{ Type: RollingUpdateDeploymentStrategyType, RollingUpdate: &RollingUpdateDeployment{ MaxSurge: &differentIntOrString, MaxUnavailable: &defaultIntOrString, }, }, Template: defaultTemplate, UniqueLabelKey: newString(deploymentLabelKey), }, }, }, { original: &Deployment{ Spec: DeploymentSpec{ Replicas: newInt32(5), Strategy: DeploymentStrategy{ Type: RecreateDeploymentStrategyType, }, }, }, expected: &Deployment{ Spec: DeploymentSpec{ Replicas: newInt32(5), Strategy: DeploymentStrategy{ Type: RecreateDeploymentStrategyType, }, Template: defaultTemplate, UniqueLabelKey: newString(deploymentLabelKey), }, }, }, { original: &Deployment{ Spec: DeploymentSpec{ Replicas: newInt32(5), Strategy: DeploymentStrategy{ Type: RecreateDeploymentStrategyType, }, UniqueLabelKey: newString("customDeploymentKey"), }, }, expected: &Deployment{ Spec: DeploymentSpec{ Replicas: newInt32(5), Strategy: DeploymentStrategy{ Type: RecreateDeploymentStrategyType, }, Template: defaultTemplate, UniqueLabelKey: newString("customDeploymentKey"), }, }, }, } for _, test := range tests { original := test.original expected := test.expected obj2 := roundTrip(t, runtime.Object(original)) got, ok := obj2.(*Deployment) if !ok { t.Errorf("unexpected object: %v", got) t.FailNow() } if !reflect.DeepEqual(got.Spec, expected.Spec) { t.Errorf("got different than expected:\n\t%+v\ngot:\n\t%+v", got.Spec, expected.Spec) } } }
func TestFindPort(t *testing.T) { testCases := []struct { name string containers []api.Container port intstr.IntOrString expected int pass bool }{{ name: "valid int, no ports", containers: []api.Container{{}}, port: intstr.FromInt(93), expected: 93, pass: true, }, { name: "valid int, with ports", containers: []api.Container{{Ports: []api.ContainerPort{{ Name: "", ContainerPort: 11, Protocol: "TCP", }, { Name: "p", ContainerPort: 22, Protocol: "TCP", }}}}, port: intstr.FromInt(93), expected: 93, pass: true, }, { name: "valid str, no ports", containers: []api.Container{{}}, port: intstr.FromString("p"), expected: 0, pass: false, }, { name: "valid str, one ctr with ports", containers: []api.Container{{Ports: []api.ContainerPort{{ Name: "", ContainerPort: 11, Protocol: "UDP", }, { Name: "p", ContainerPort: 22, Protocol: "TCP", }, { Name: "q", ContainerPort: 33, Protocol: "TCP", }}}}, port: intstr.FromString("q"), expected: 33, pass: true, }, { name: "valid str, two ctr with ports", containers: []api.Container{{}, {Ports: []api.ContainerPort{{ Name: "", ContainerPort: 11, Protocol: "UDP", }, { Name: "p", ContainerPort: 22, Protocol: "TCP", }, { Name: "q", ContainerPort: 33, Protocol: "TCP", }}}}, port: intstr.FromString("q"), expected: 33, pass: true, }} for _, tc := range testCases { port, err := FindPort(&api.Pod{Spec: api.PodSpec{Containers: tc.containers}}, &api.ServicePort{Protocol: "TCP", TargetPort: tc.port}) if err != nil && tc.pass { t.Errorf("unexpected error for %s: %v", tc.name, err) } if err == nil && !tc.pass { t.Errorf("unexpected non-error for %s: %d", tc.name, port) } if port != tc.expected { t.Errorf("wrong result for %s: expected %d, got %d", tc.name, tc.expected, port) } } }
func addDefaultingFuncs(scheme *runtime.Scheme) { scheme.AddDefaultingFuncs( func(obj *APIVersion) { if len(obj.APIGroup) == 0 { obj.APIGroup = GroupName } }, func(obj *DaemonSet) { labels := obj.Spec.Template.Labels // TODO: support templates defined elsewhere when we support them in the API if labels != nil { if obj.Spec.Selector == nil { obj.Spec.Selector = &LabelSelector{ MatchLabels: labels, } } if len(obj.Labels) == 0 { obj.Labels = labels } } updateStrategy := &obj.Spec.UpdateStrategy if updateStrategy.Type == "" { updateStrategy.Type = RollingUpdateDaemonSetStrategyType } if updateStrategy.Type == RollingUpdateDaemonSetStrategyType { if updateStrategy.RollingUpdate == nil { rollingUpdate := RollingUpdateDaemonSet{} updateStrategy.RollingUpdate = &rollingUpdate } if updateStrategy.RollingUpdate.MaxUnavailable == nil { // Set default MaxUnavailable as 1 by default. maxUnavailable := intstr.FromInt(1) updateStrategy.RollingUpdate.MaxUnavailable = &maxUnavailable } } if obj.Spec.UniqueLabelKey == nil { obj.Spec.UniqueLabelKey = new(string) *obj.Spec.UniqueLabelKey = DefaultDaemonSetUniqueLabelKey } }, func(obj *Deployment) { // Default labels and selector to labels from pod template spec. labels := obj.Spec.Template.Labels if labels != nil { if len(obj.Spec.Selector) == 0 { obj.Spec.Selector = labels } if len(obj.Labels) == 0 { obj.Labels = labels } } // Set DeploymentSpec.Replicas to 1 if it is not set. if obj.Spec.Replicas == nil { obj.Spec.Replicas = new(int32) *obj.Spec.Replicas = 1 } strategy := &obj.Spec.Strategy // Set default DeploymentStrategyType as RollingUpdate. if strategy.Type == "" { strategy.Type = RollingUpdateDeploymentStrategyType } if strategy.Type == RollingUpdateDeploymentStrategyType { if strategy.RollingUpdate == nil { rollingUpdate := RollingUpdateDeployment{} strategy.RollingUpdate = &rollingUpdate } if strategy.RollingUpdate.MaxUnavailable == nil { // Set default MaxUnavailable as 1 by default. maxUnavailable := intstr.FromInt(1) strategy.RollingUpdate.MaxUnavailable = &maxUnavailable } if strategy.RollingUpdate.MaxSurge == nil { // Set default MaxSurge as 1 by default. maxSurge := intstr.FromInt(1) strategy.RollingUpdate.MaxSurge = &maxSurge } } if obj.Spec.UniqueLabelKey == nil { obj.Spec.UniqueLabelKey = new(string) *obj.Spec.UniqueLabelKey = DefaultDeploymentUniqueLabelKey } }, func(obj *Job) { labels := obj.Spec.Template.Labels // TODO: support templates defined elsewhere when we support them in the API if labels != nil { if obj.Spec.Selector == nil { obj.Spec.Selector = &LabelSelector{ MatchLabels: labels, } } if len(obj.Labels) == 0 { obj.Labels = labels } } // For a non-parallel job, you can leave both `.spec.completions` and // `.spec.parallelism` unset. When both are unset, both are defaulted to 1. if obj.Spec.Completions == nil && obj.Spec.Parallelism == nil { obj.Spec.Completions = new(int32) *obj.Spec.Completions = 1 obj.Spec.Parallelism = new(int32) *obj.Spec.Parallelism = 1 } if obj.Spec.Parallelism == nil { obj.Spec.Parallelism = new(int32) *obj.Spec.Parallelism = 1 } }, func(obj *HorizontalPodAutoscaler) { if obj.Spec.MinReplicas == nil { minReplicas := int32(1) obj.Spec.MinReplicas = &minReplicas } if obj.Spec.CPUUtilization == nil { obj.Spec.CPUUtilization = &CPUTargetUtilization{TargetPercentage: 80} } }, func(obj *ReplicaSet) { var labels map[string]string if obj.Spec.Template != nil { labels = obj.Spec.Template.Labels } // TODO: support templates defined elsewhere when we support them in the API if labels != nil { if obj.Spec.Selector == nil { obj.Spec.Selector = &LabelSelector{ MatchLabels: labels, } } if len(obj.Labels) == 0 { obj.Labels = labels } } if obj.Spec.Replicas == nil { obj.Spec.Replicas = new(int32) *obj.Spec.Replicas = 1 } }, ) }