func TestDeployerCustomLabelsAndAnnotations(t *testing.T) { controller := &DeploymentController{ decodeConfig: func(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, error) { return deployutil.DecodeDeploymentConfig(deployment, api.Codec) }, podClient: &podClientImpl{ createPodFunc: func(namespace string, pod *kapi.Pod) (*kapi.Pod, error) { return pod, nil }, }, makeContainer: func(strategy *deployapi.DeploymentStrategy) (*kapi.Container, error) { return okContainer(), nil }, } testCases := []struct { name string strategy deployapi.DeploymentStrategy labels map[string]string annotations map[string]string verifyLabels bool }{ {name: "labels and annotations", strategy: deploytest.OkStrategy(), labels: map[string]string{"label1": "value1"}, annotations: map[string]string{"annotation1": "value1"}, verifyLabels: true}, {name: "custom strategy, no annotations", strategy: deploytest.OkCustomStrategy(), labels: map[string]string{"label2": "value2", "label3": "value3"}, verifyLabels: true}, {name: "custom strategy, no labels", strategy: deploytest.OkCustomStrategy(), annotations: map[string]string{"annotation3": "value3"}, verifyLabels: true}, {name: "no overrride", strategy: deploytest.OkStrategy(), labels: map[string]string{deployapi.DeployerPodForDeploymentLabel: "ignored"}, verifyLabels: false}, } for _, test := range testCases { t.Logf("evaluating test case %s", test.name) config := deploytest.OkDeploymentConfig(1) config.Spec.Strategy = test.strategy config.Spec.Strategy.Labels = test.labels config.Spec.Strategy.Annotations = test.annotations deployment, _ := deployutil.MakeDeployment(config, kapi.Codec) podTemplate, err := controller.makeDeployerPod(deployment) if err != nil { t.Fatal(err) } nameLabel, ok := podTemplate.Labels[deployapi.DeployerPodForDeploymentLabel] if ok && nameLabel != deployment.Name { t.Errorf("label %s expected %s, got %s", deployapi.DeployerPodForDeploymentLabel, deployment.Name, nameLabel) } else if !ok { t.Errorf("label %s not present", deployapi.DeployerPodForDeploymentLabel) } if test.verifyLabels { expectMapContains(t, podTemplate.Labels, test.labels, "labels") } expectMapContains(t, podTemplate.Annotations, test.annotations, "annotations") } }
func TestValidateSelectorMatchesPodTemplateLabels(t *testing.T) { tests := map[string]struct { spec api.DeploymentConfigSpec expectedErr bool errorType field.ErrorType field string }{ "valid template labels": { spec: api.DeploymentConfigSpec{ Selector: test.OkSelector(), Strategy: test.OkStrategy(), Template: test.OkPodTemplate(), }, }, "invalid template labels": { spec: api.DeploymentConfigSpec{ Selector: test.OkSelector(), Strategy: test.OkStrategy(), Template: test.OkPodTemplate(), }, expectedErr: true, errorType: field.ErrorTypeInvalid, field: "spec.template.metadata.labels", }, } for name, test := range tests { if test.expectedErr { test.spec.Template.Labels["a"] = "c" } errs := ValidateDeploymentConfigSpec(test.spec) if len(errs) == 0 && test.expectedErr { t.Errorf("%s: expected failure", name) continue } if !test.expectedErr { continue } if len(errs) != 1 { t.Errorf("%s: expected one error, got %d", name, len(errs)) continue } err := errs[0] if err.Type != test.errorType { t.Errorf("%s: expected error to have type %q, got %q", name, test.errorType, err.Type) } if err.Field != test.field { t.Errorf("%s: expected error to have field %q, got %q", name, test.field, err.Field) } } }
func TestValidateDeploymentConfigDefaultImageStreamKind(t *testing.T) { config := &api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: []api.DeploymentTriggerPolicy{ { Type: api.DeploymentTriggerOnImageChange, ImageChangeParams: &api.DeploymentTriggerImageChangeParams{ From: kapi.ObjectReference{ Kind: "ImageStreamTag", Name: "name:v1", }, ContainerNames: []string{"foo"}, }, }, }, Selector: test.OkSelector(), Template: test.OkPodTemplate(), Strategy: test.OkStrategy(), }, } if errs := ValidateDeploymentConfig(config); len(errs) > 0 { t.Errorf("Unxpected non-empty error list: %v", errs) } }
func TestDeployerCustomLabelsAndAnnotations(t *testing.T) { testCases := []struct { name string strategy deployapi.DeploymentStrategy labels map[string]string annotations map[string]string verifyLabels bool }{ {name: "labels and annotations", strategy: deploytest.OkStrategy(), labels: map[string]string{"label1": "value1"}, annotations: map[string]string{"annotation1": "value1"}, verifyLabels: true}, {name: "custom strategy, no annotations", strategy: deploytest.OkCustomStrategy(), labels: map[string]string{"label2": "value2", "label3": "value3"}, verifyLabels: true}, {name: "custom strategy, no labels", strategy: deploytest.OkCustomStrategy(), annotations: map[string]string{"annotation3": "value3"}, verifyLabels: true}, {name: "no overrride", strategy: deploytest.OkStrategy(), labels: map[string]string{deployapi.DeployerPodForDeploymentLabel: "ignored"}, verifyLabels: false}, } for _, test := range testCases { t.Logf("evaluating test case %s", test.name) config := deploytest.OkDeploymentConfig(1) config.Spec.Strategy = test.strategy config.Spec.Strategy.Labels = test.labels config.Spec.Strategy.Annotations = test.annotations deployment, _ := deployutil.MakeDeployment(config, codec) fake := &ktestclient.Fake{} fake.AddReactor("create", "pods", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { return true, deployerPod(deployment, "", true), nil }) controller := okDeploymentController(fake, nil, nil, true) podTemplate, err := controller.makeDeployerPod(deployment) if err != nil { t.Fatal(err) } nameLabel, ok := podTemplate.Labels[deployapi.DeployerPodForDeploymentLabel] if ok && nameLabel != deployment.Name { t.Errorf("label %s expected %s, got %s", deployapi.DeployerPodForDeploymentLabel, deployment.Name, nameLabel) } else if !ok { t.Errorf("label %s not present", deployapi.DeployerPodForDeploymentLabel) } if test.verifyLabels { expectMapContains(t, podTemplate.Labels, test.labels, "labels") } expectMapContains(t, podTemplate.Annotations, test.annotations, "annotations") } }
func TestDeploymentConfigStrategy(t *testing.T) { ctx := kapi.NewDefaultContext() if !Strategy.NamespaceScoped() { t.Errorf("DeploymentConfig is namespace scoped") } if Strategy.AllowCreateOnUpdate() { t.Errorf("DeploymentConfig should not allow create on update") } deploymentConfig := &deployapi.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "default"}, Template: deployapi.DeploymentTemplate{ Strategy: deploytest.OkStrategy(), ControllerTemplate: deploytest.OkControllerTemplate(), }, } Strategy.PrepareForCreate(deploymentConfig) errs := Strategy.Validate(ctx, deploymentConfig) if len(errs) != 0 { t.Errorf("Unexpected error validating %v", errs) } updatedDeploymentConfig := &deployapi.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "bar", Namespace: "default"}, Template: deployapi.DeploymentTemplate{ Strategy: deploytest.OkStrategy(), ControllerTemplate: deploytest.OkControllerTemplate(), }, } errs = Strategy.ValidateUpdate(ctx, updatedDeploymentConfig, deploymentConfig) if len(errs) == 0 { t.Errorf("Expected error validating") } // name must match, and resource version must be provided updatedDeploymentConfig.Name = "foo" updatedDeploymentConfig.ResourceVersion = "1" errs = Strategy.ValidateUpdate(ctx, updatedDeploymentConfig, deploymentConfig) if len(errs) != 0 { t.Errorf("Unexpected error validating %v", errs) } invalidDeploymentConfig := &deployapi.DeploymentConfig{} errs = Strategy.Validate(ctx, invalidDeploymentConfig) if len(errs) == 0 { t.Errorf("Expected error validating") } }
func TestValidateDeploymentConfigOK(t *testing.T) { errs := ValidateDeploymentConfig(&api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: manualTrigger(), Selector: test.OkSelector(), Strategy: test.OkStrategy(), Template: test.OkPodTemplate(), }, }) if len(errs) > 0 { t.Errorf("Unxpected non-empty error list: %#v", errs) } }
func TestValidateDeploymentConfigICTMissingImage(t *testing.T) { dc := &api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: []api.DeploymentTriggerPolicy{test.OkImageChangeTrigger()}, Selector: test.OkSelector(), Strategy: test.OkStrategy(), Template: test.OkPodTemplateMissingImage("container1"), }, } errs := ValidateDeploymentConfig(dc) if len(errs) > 0 { t.Errorf("Unexpected non-empty error list: %+v", errs) } for _, c := range dc.Spec.Template.Spec.Containers { if c.Image == "unset" { t.Errorf("%s image field still has validation fake out value of %s", c.Name, c.Image) } } }
func TestDeploymentConfigDescriber(t *testing.T) { config := deployapitest.OkDeploymentConfig(1) deployment, _ := deployutil.MakeDeployment(config, kapi.Codec) podList := &kapi.PodList{} eventList := &kapi.EventList{} deploymentList := &kapi.ReplicationControllerList{} d := &DeploymentConfigDescriber{ client: &genericDeploymentDescriberClient{ getDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) { return config, nil }, getDeploymentFunc: func(namespace, name string) (*kapi.ReplicationController, error) { return deployment, nil }, listDeploymentsFunc: func(namespace string, selector labels.Selector) (*kapi.ReplicationControllerList, error) { return deploymentList, nil }, listPodsFunc: func(namespace string, selector labels.Selector) (*kapi.PodList, error) { return podList, nil }, listEventsFunc: func(deploymentConfig *deployapi.DeploymentConfig) (*kapi.EventList, error) { return eventList, nil }, }, } describe := func() { if output, err := d.Describe("test", "deployment"); err != nil { t.Fatalf("unexpected error: %v", err) } else { t.Logf("describer output:\n%s\n", output) } } podList.Items = []kapi.Pod{*mkPod(kapi.PodRunning, 0)} describe() config.Triggers = append(config.Triggers, deployapitest.OkConfigChangeTrigger()) describe() config.Template.Strategy = deployapitest.OkCustomStrategy() describe() config.Triggers[0].ImageChangeParams.RepositoryName = "" config.Triggers[0].ImageChangeParams.From = kapi.ObjectReference{Name: "imageRepo"} describe() config.Template.Strategy = deployapitest.OkStrategy() config.Template.Strategy.RecreateParams = &deployapi.RecreateDeploymentStrategyParams{ Pre: &deployapi.LifecycleHook{ FailurePolicy: deployapi.LifecycleHookFailurePolicyAbort, ExecNewPod: &deployapi.ExecNewPodHook{ ContainerName: "container", Command: []string{"/command1", "args"}, Env: []kapi.EnvVar{ { Name: "KEY1", Value: "value1", }, }, }, }, Post: &deployapi.LifecycleHook{ FailurePolicy: deployapi.LifecycleHookFailurePolicyIgnore, ExecNewPod: &deployapi.ExecNewPodHook{ ContainerName: "container", Command: []string{"/command2", "args"}, Env: []kapi.EnvVar{ { Name: "KEY2", Value: "value2", }, }, }, }, } describe() }
func TestDeploymentConfigDescriber(t *testing.T) { config := deployapitest.OkDeploymentConfig(1) deployment, _ := deployutil.MakeDeployment(config, kapi.Codecs.LegacyCodec(deployapi.SchemeGroupVersion)) podList := &kapi.PodList{} fake := &testclient.Fake{} fake.PrependReactor("get", "deploymentconfigs", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { return true, config, nil }) kFake := &ktestclient.Fake{} kFake.PrependReactor("list", "horizontalpodautoscalers", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { return true, &extensions.HorizontalPodAutoscalerList{ Items: []extensions.HorizontalPodAutoscaler{ *deployapitest.OkHPAForDeploymentConfig(config, 1, 3), }}, nil }) kFake.PrependReactor("get", "replicationcontrollers", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { return true, deployment, nil }) kFake.PrependReactor("list", "replicationcontrollers", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { return true, &kapi.ReplicationControllerList{}, nil }) kFake.PrependReactor("list", "pods", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { return true, podList, nil }) kFake.PrependReactor("list", "events", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { return true, &kapi.EventList{}, nil }) d := &DeploymentConfigDescriber{ osClient: fake, kubeClient: kFake, } describe := func() string { output, err := d.Describe("test", "deployment", kubectl.DescriberSettings{}) if err != nil { t.Fatalf("unexpected error: %v", err) return "" } t.Logf("describer output:\n%s\n", output) return output } podList.Items = []kapi.Pod{*mkPod(kapi.PodRunning, 0)} out := describe() substr := "Autoscaling:\tbetween 1 and 3 replicas" if !strings.Contains(out, substr) { t.Fatalf("expected %q in output:\n%s", substr, out) } config.Spec.Triggers = append(config.Spec.Triggers, deployapitest.OkConfigChangeTrigger()) describe() config.Spec.Strategy = deployapitest.OkCustomStrategy() describe() config.Spec.Triggers[0].ImageChangeParams.From = kapi.ObjectReference{Name: "imagestream"} describe() config.Spec.Strategy = deployapitest.OkStrategy() config.Spec.Strategy.RecreateParams = &deployapi.RecreateDeploymentStrategyParams{ Pre: &deployapi.LifecycleHook{ FailurePolicy: deployapi.LifecycleHookFailurePolicyAbort, ExecNewPod: &deployapi.ExecNewPodHook{ ContainerName: "container", Command: []string{"/command1", "args"}, Env: []kapi.EnvVar{ { Name: "KEY1", Value: "value1", }, }, }, }, Post: &deployapi.LifecycleHook{ FailurePolicy: deployapi.LifecycleHookFailurePolicyIgnore, ExecNewPod: &deployapi.ExecNewPodHook{ ContainerName: "container", Command: []string{"/command2", "args"}, Env: []kapi.EnvVar{ { Name: "KEY2", Value: "value2", }, }, }, }, } describe() }
func TestValidateDeploymentConfigMissingFields(t *testing.T) { errorCases := map[string]struct { DeploymentConfig api.DeploymentConfig ErrorType field.ErrorType Field string }{ "missing name": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "", Namespace: "bar"}, Spec: test.OkDeploymentConfigSpec(), }, field.ErrorTypeRequired, "metadata.name", }, "missing namespace": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: ""}, Spec: test.OkDeploymentConfigSpec(), }, field.ErrorTypeRequired, "metadata.namespace", }, "invalid name": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "-foo", Namespace: "bar"}, Spec: test.OkDeploymentConfigSpec(), }, field.ErrorTypeInvalid, "metadata.name", }, "invalid namespace": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "-bar"}, Spec: test.OkDeploymentConfigSpec(), }, field.ErrorTypeInvalid, "metadata.namespace", }, "missing trigger.type": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: []api.DeploymentTriggerPolicy{ { ImageChangeParams: &api.DeploymentTriggerImageChangeParams{ ContainerNames: []string{"foo"}, }, }, }, Selector: test.OkSelector(), Strategy: test.OkStrategy(), Template: test.OkPodTemplate(), }, }, field.ErrorTypeRequired, "spec.triggers[0].type", }, "missing Trigger imageChangeParams.from": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: []api.DeploymentTriggerPolicy{ { Type: api.DeploymentTriggerOnImageChange, ImageChangeParams: &api.DeploymentTriggerImageChangeParams{ ContainerNames: []string{"foo"}, }, }, }, Selector: test.OkSelector(), Strategy: test.OkStrategy(), Template: test.OkPodTemplate(), }, }, field.ErrorTypeRequired, "spec.triggers[0].imageChangeParams.from", }, "invalid Trigger imageChangeParams.from.kind": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: []api.DeploymentTriggerPolicy{ { Type: api.DeploymentTriggerOnImageChange, ImageChangeParams: &api.DeploymentTriggerImageChangeParams{ From: kapi.ObjectReference{ Kind: "Invalid", Name: "name:tag", }, ContainerNames: []string{"foo"}, }, }, }, Selector: test.OkSelector(), Strategy: test.OkStrategy(), Template: test.OkPodTemplate(), }, }, field.ErrorTypeInvalid, "spec.triggers[0].imageChangeParams.from.kind", }, "missing Trigger imageChangeParams.containerNames": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: []api.DeploymentTriggerPolicy{ { Type: api.DeploymentTriggerOnImageChange, ImageChangeParams: &api.DeploymentTriggerImageChangeParams{ From: kapi.ObjectReference{ Kind: "ImageStreamTag", Name: "foo:v1", }, }, }, }, Selector: test.OkSelector(), Strategy: test.OkStrategy(), Template: test.OkPodTemplate(), }, }, field.ErrorTypeRequired, "spec.triggers[0].imageChangeParams.containerNames", }, "missing strategy.type": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: manualTrigger(), Selector: test.OkSelector(), Strategy: api.DeploymentStrategy{ CustomParams: test.OkCustomParams(), }, Template: test.OkPodTemplate(), }, }, field.ErrorTypeRequired, "spec.strategy.type", }, "missing strategy.customParams": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: manualTrigger(), Selector: test.OkSelector(), Strategy: api.DeploymentStrategy{ Type: api.DeploymentStrategyTypeCustom, }, Template: test.OkPodTemplate(), }, }, field.ErrorTypeRequired, "spec.strategy.customParams", }, "missing spec.strategy.customParams.image": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: manualTrigger(), Selector: test.OkSelector(), Strategy: api.DeploymentStrategy{ Type: api.DeploymentStrategyTypeCustom, CustomParams: &api.CustomDeploymentStrategyParams{}, }, Template: test.OkPodTemplate(), }, }, field.ErrorTypeRequired, "spec.strategy.customParams.image", }, "missing spec.strategy.recreateParams.pre.failurePolicy": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Strategy: api.DeploymentStrategy{ Type: api.DeploymentStrategyTypeRecreate, RecreateParams: &api.RecreateDeploymentStrategyParams{ Pre: &api.LifecycleHook{ ExecNewPod: &api.ExecNewPodHook{ Command: []string{"cmd"}, ContainerName: "container", }, }, }, }, Template: test.OkPodTemplate(), Selector: test.OkSelector(), }, }, field.ErrorTypeRequired, "spec.strategy.recreateParams.pre.failurePolicy", }, "missing spec.strategy.recreateParams.pre.execNewPod": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Strategy: api.DeploymentStrategy{ Type: api.DeploymentStrategyTypeRecreate, RecreateParams: &api.RecreateDeploymentStrategyParams{ Pre: &api.LifecycleHook{ FailurePolicy: api.LifecycleHookFailurePolicyRetry, }, }, }, Template: test.OkPodTemplate(), Selector: test.OkSelector(), }, }, field.ErrorTypeRequired, "spec.strategy.recreateParams.pre.execNewPod", }, "missing spec.strategy.recreateParams.pre.execNewPod.command": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Strategy: api.DeploymentStrategy{ Type: api.DeploymentStrategyTypeRecreate, RecreateParams: &api.RecreateDeploymentStrategyParams{ Pre: &api.LifecycleHook{ FailurePolicy: api.LifecycleHookFailurePolicyRetry, ExecNewPod: &api.ExecNewPodHook{ ContainerName: "container", }, }, }, }, Template: test.OkPodTemplate(), Selector: test.OkSelector(), }, }, field.ErrorTypeRequired, "spec.strategy.recreateParams.pre.execNewPod.command", }, "missing spec.strategy.recreateParams.pre.execNewPod.containerName": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Strategy: api.DeploymentStrategy{ Type: api.DeploymentStrategyTypeRecreate, RecreateParams: &api.RecreateDeploymentStrategyParams{ Pre: &api.LifecycleHook{ FailurePolicy: api.LifecycleHookFailurePolicyRetry, ExecNewPod: &api.ExecNewPodHook{ Command: []string{"cmd"}, }, }, }, }, Template: test.OkPodTemplate(), Selector: test.OkSelector(), }, }, field.ErrorTypeRequired, "spec.strategy.recreateParams.pre.execNewPod.containerName", }, "invalid spec.strategy.recreateParams.pre.execNewPod.volumes": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Strategy: api.DeploymentStrategy{ Type: api.DeploymentStrategyTypeRecreate, RecreateParams: &api.RecreateDeploymentStrategyParams{ Pre: &api.LifecycleHook{ FailurePolicy: api.LifecycleHookFailurePolicyRetry, ExecNewPod: &api.ExecNewPodHook{ ContainerName: "container", Command: []string{"cmd"}, Volumes: []string{"good", ""}, }, }, }, }, Template: test.OkPodTemplate(), Selector: test.OkSelector(), }, }, field.ErrorTypeInvalid, "spec.strategy.recreateParams.pre.execNewPod.volumes[1]", }, "invalid spec.strategy.rollingParams.intervalSeconds": { rollingConfig(-20, 1, 1), field.ErrorTypeInvalid, "spec.strategy.rollingParams.intervalSeconds", }, "invalid spec.strategy.rollingParams.updatePeriodSeconds": { rollingConfig(1, -20, 1), field.ErrorTypeInvalid, "spec.strategy.rollingParams.updatePeriodSeconds", }, "invalid spec.strategy.rollingParams.timeoutSeconds": { rollingConfig(1, 1, -20), field.ErrorTypeInvalid, "spec.strategy.rollingParams.timeoutSeconds", }, "missing spec.strategy.rollingParams.pre.failurePolicy": { api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Strategy: api.DeploymentStrategy{ Type: api.DeploymentStrategyTypeRolling, RollingParams: &api.RollingDeploymentStrategyParams{ IntervalSeconds: mkint64p(1), UpdatePeriodSeconds: mkint64p(1), TimeoutSeconds: mkint64p(20), MaxSurge: intstr.FromInt(1), Pre: &api.LifecycleHook{ ExecNewPod: &api.ExecNewPodHook{ Command: []string{"cmd"}, ContainerName: "container", }, }, }, }, Template: test.OkPodTemplate(), Selector: test.OkSelector(), }, }, field.ErrorTypeRequired, "spec.strategy.rollingParams.pre.failurePolicy", }, "both maxSurge and maxUnavailable 0 spec.strategy.rollingParams.maxUnavailable": { rollingConfigMax(intstr.FromInt(0), intstr.FromInt(0)), field.ErrorTypeInvalid, "spec.strategy.rollingParams.maxUnavailable", }, "invalid lower bound spec.strategy.rollingParams.maxUnavailable": { rollingConfigMax(intstr.FromInt(0), intstr.FromInt(-100)), field.ErrorTypeInvalid, "spec.strategy.rollingParams.maxUnavailable", }, "invalid lower bound spec.strategy.rollingParams.maxSurge": { rollingConfigMax(intstr.FromInt(-1), intstr.FromInt(0)), field.ErrorTypeInvalid, "spec.strategy.rollingParams.maxSurge", }, "both maxSurge and maxUnavailable 0 percent spec.strategy.rollingParams.maxUnavailable": { rollingConfigMax(intstr.FromString("0%"), intstr.FromString("0%")), field.ErrorTypeInvalid, "spec.strategy.rollingParams.maxUnavailable", }, "invalid lower bound percent spec.strategy.rollingParams.maxUnavailable": { rollingConfigMax(intstr.FromInt(0), intstr.FromString("-1%")), field.ErrorTypeInvalid, "spec.strategy.rollingParams.maxUnavailable", }, "invalid upper bound percent spec.strategy.rollingParams.maxUnavailable": { rollingConfigMax(intstr.FromInt(0), intstr.FromString("101%")), field.ErrorTypeInvalid, "spec.strategy.rollingParams.maxUnavailable", }, "invalid percent spec.strategy.rollingParams.maxUnavailable": { rollingConfigMax(intstr.FromInt(0), intstr.FromString("foo")), field.ErrorTypeInvalid, "spec.strategy.rollingParams.maxUnavailable", }, "invalid percent spec.strategy.rollingParams.maxSurge": { rollingConfigMax(intstr.FromString("foo"), intstr.FromString("100%")), field.ErrorTypeInvalid, "spec.strategy.rollingParams.maxSurge", }, } for testName, v := range errorCases { errs := ValidateDeploymentConfig(&v.DeploymentConfig) if len(v.ErrorType) == 0 { if len(errs) > 0 { for _, e := range errs { t.Errorf("%s: unexpected error: %s", testName, e) } } continue } if len(errs) == 0 { t.Errorf("%s: expected test failure, got success", testName) } for i := range errs { if got, exp := errs[i].Type, v.ErrorType; got != exp { t.Errorf("%s: expected error \"%v\" to have type %q, but got %q", testName, errs[i], exp, got) } if got, exp := errs[i].Field, v.Field; got != exp { t.Errorf("%s: expected error \"%v\" to have field %q, but got %q", testName, errs[i], exp, got) } } } }
func TestValidateDeploymentConfigUpdate(t *testing.T) { oldConfig := &api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar", ResourceVersion: "1"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: manualTrigger(), Selector: test.OkSelector(), Strategy: test.OkStrategy(), Template: test.OkPodTemplate(), }, Status: api.DeploymentConfigStatus{ LatestVersion: 5, }, } newConfig := &api.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar", ResourceVersion: "1"}, Spec: api.DeploymentConfigSpec{ Replicas: 1, Triggers: manualTrigger(), Selector: test.OkSelector(), Strategy: test.OkStrategy(), Template: test.OkPodTemplate(), }, Status: api.DeploymentConfigStatus{ LatestVersion: 3, }, } scenarios := []struct { oldLatestVersion int newLatestVersion int }{ {5, 3}, {5, 7}, {0, -1}, } for _, values := range scenarios { oldConfig.Status.LatestVersion = values.oldLatestVersion newConfig.Status.LatestVersion = values.newLatestVersion errs := ValidateDeploymentConfigUpdate(newConfig, oldConfig) if len(errs) == 0 { t.Errorf("Expected update failure") } for i := range errs { if errs[i].Type != field.ErrorTypeInvalid { t.Errorf("expected update error to have type %s: %v", field.ErrorTypeInvalid, errs[i]) } if errs[i].Field != "status.latestVersion" { t.Errorf("expected update error to have field %s: %v", "latestVersion", errs[i]) } } } // testing for a successful update oldConfig.Status.LatestVersion = 5 newConfig.Status.LatestVersion = 6 errs := ValidateDeploymentConfigUpdate(newConfig, oldConfig) if len(errs) > 0 { t.Errorf("Unexpected update failure") } }