Beispiel #1
0
// TestHandle_newConfigTriggers ensures that the creation of a new config
// (with version 0) with a config change trigger results in a version bump and
// cause update for initial deployment.
func TestHandle_newConfigTriggers(t *testing.T) {
	var updated *deployapi.DeploymentConfig

	fake := &testclient.Fake{}
	fake.AddReactor("update", "deploymentconfigs/status", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
		updated = action.(ktestclient.UpdateAction).GetObject().(*deployapi.DeploymentConfig)
		return true, updated, nil
	})
	kFake := &ktestclient.Fake{}

	controller := NewDeploymentTriggerController(fake, kFake, codec)

	config := testapi.OkDeploymentConfig(0)
	config.Namespace = kapi.NamespaceDefault
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{testapi.OkConfigChangeTrigger()}
	if err := controller.Handle(config); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if updated == nil {
		t.Fatalf("expected config to be updated")
	}
	if e, a := int64(1), updated.Status.LatestVersion; e != a {
		t.Fatalf("expected update to latestversion=%d, got %d", e, a)
	}
	if updated.Status.Details == nil {
		t.Fatalf("expected config change details to be set")
	} else if updated.Status.Details.Causes == nil {
		t.Fatalf("expected config change causes to be set")
	} else if updated.Status.Details.Causes[0].Type != deployapi.DeploymentTriggerOnConfigChange {
		t.Fatalf("expected config change cause to be set to config change trigger, got %s", updated.Status.Details.Causes[0].Type)
	}
}
Beispiel #2
0
// TestHandle_waitForImageController tests an initial deployment with unresolved image. The config
// change controller should never increment latestVersion, thus trigger a deployment for this config.
func TestHandle_waitForImageController(t *testing.T) {
	fake := &testclient.Fake{}
	kFake := &ktestclient.Fake{}

	fake.PrependReactor("update", "deploymentconfigs/status", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
		t.Fatalf("an update should never run before the template image is resolved")
		return true, nil, nil
	})

	controller := &DeploymentConfigChangeController{
		client:  fake,
		kClient: kFake,
		decodeConfig: func(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, error) {
			return deployutil.DecodeDeploymentConfig(deployment, kapi.Codecs.LegacyCodec(deployapi.SchemeGroupVersion))
		},
	}

	config := testapi.OkDeploymentConfig(0)
	config.Namespace = kapi.NamespaceDefault
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{testapi.OkConfigChangeTrigger(), testapi.OkImageChangeTrigger()}

	if err := controller.Handle(config); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
}
Beispiel #3
0
// TestHandle_changeWithTemplateDiff ensures that a pod template change to a
// config with a config change trigger results in a version bump and cause
// update.
func TestHandle_changeWithTemplateDiff(t *testing.T) {
	var updated *deployapi.DeploymentConfig

	controller := &DeploymentConfigChangeController{
		decodeConfig: func(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, error) {
			return deployutil.DecodeDeploymentConfig(deployment, api.Codec)
		},
		changeStrategy: &changeStrategyImpl{
			generateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) {
				return deployapitest.OkDeploymentConfig(2), nil
			},
			updateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) {
				updated = config
				return config, nil
			},
			getDeploymentFunc: func(namespace, name string) (*kapi.ReplicationController, error) {
				deployment, _ := deployutil.MakeDeployment(deployapitest.OkDeploymentConfig(1), kapi.Codec)
				return deployment, nil
			},
		},
	}

	config := deployapitest.OkDeploymentConfig(1)
	config.Triggers = []deployapi.DeploymentTriggerPolicy{deployapitest.OkConfigChangeTrigger()}
	config.Template.ControllerTemplate.Template.Spec.Containers[1].Name = "modified"
	err := controller.Handle(config)

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	if updated == nil {
		t.Fatalf("expected config to be updated")
	}

	if e, a := 2, updated.LatestVersion; e != a {
		t.Fatalf("expected update to latestversion=%d, got %d", e, a)
	}

	if updated.Details == nil {
		t.Fatalf("expected config change details to be set")
	} else if updated.Details.Causes == nil {
		t.Fatalf("expected config change causes to be set")
	} else if updated.Details.Causes[0].Type != deployapi.DeploymentTriggerOnConfigChange {
		t.Fatalf("expected config change cause to be set to config change trigger, got %s", updated.Details.Causes[0].Type)
	}
}
func TestHandle_nonAutomaticImageUpdates(t *testing.T) {
	var updated *deployapi.DeploymentConfig

	controller := &DeploymentConfigChangeController{
		decodeConfig: func(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, error) {
			return deployutil.DecodeDeploymentConfig(deployment, kapi.Codecs.LegacyCodec(deployapi.SchemeGroupVersion))
		},
		changeStrategy: &changeStrategyImpl{
			generateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) {
				generated := deployapitest.OkDeploymentConfig(1)
				// The generator doesn't change automatic so it's ok to fake it here.
				generated.Spec.Triggers[0].ImageChangeParams.Automatic = false
				generated.Status.Details = deployapitest.OkImageChangeDetails()
				updated = generated
				return generated, nil
			},
			updateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) {
				updated.Status.Details = deployapitest.OkConfigChangeDetails()
				return updated, nil
			},
		},
	}

	config := deployapitest.OkDeploymentConfig(0)
	ict := deployapitest.OkImageChangeTrigger()
	ict.ImageChangeParams.Automatic = false
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{deployapitest.OkConfigChangeTrigger(), ict}

	if err := controller.Handle(config); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	if e, a := 1, updated.Status.LatestVersion; e != a {
		t.Fatalf("expected update to latestversion=%d, got %d", e, a)
	}

	if updated.Status.Details == nil {
		t.Fatalf("expected config change details to be set")
	} else if updated.Status.Details.Causes == nil {
		t.Fatalf("expected config change causes to be set")
	} else if updated.Status.Details.Causes[0].Type != deployapi.DeploymentTriggerOnConfigChange {
		t.Fatalf("expected config change cause to be set to config change trigger, got %s", updated.Status.Details.Causes[0].Type)
	}
}
Beispiel #5
0
// TestHandle_waitForImageController tests an initial deployment with unresolved image. The config
// change controller should never increment latestVersion, thus trigger a deployment for this config.
func TestHandle_waitForImageController(t *testing.T) {
	fake := &testclient.Fake{}
	kFake := &ktestclient.Fake{}

	fake.PrependReactor("update", "deploymentconfigs/status", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
		t.Fatalf("an update should never run before the template image is resolved")
		return true, nil, nil
	})

	controller := NewDeploymentTriggerController(fake, kFake, codec)

	config := testapi.OkDeploymentConfig(0)
	config.Namespace = kapi.NamespaceDefault
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{testapi.OkConfigChangeTrigger(), testapi.OkImageChangeTrigger()}

	if err := controller.Handle(config); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
}
// TestHandle_newConfigTriggers ensures that the creation of a new config
// (with version 0) with a config change trigger results in a version bump and
// cause update for initial deployment.
func TestHandle_newConfigTriggers(t *testing.T) {
	var updated *deployapi.DeploymentConfig

	controller := &DeploymentConfigChangeController{
		decodeConfig: func(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, error) {
			return deployutil.DecodeDeploymentConfig(deployment, kapi.Codecs.LegacyCodec(deployapi.SchemeGroupVersion))
		},
		changeStrategy: &changeStrategyImpl{
			generateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) {
				return deployapitest.OkDeploymentConfig(1), nil
			},
			updateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) {
				updated = config
				return config, nil
			},
		},
	}

	config := deployapitest.OkDeploymentConfig(0)
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{deployapitest.OkConfigChangeTrigger()}
	err := controller.Handle(config)

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	if updated == nil {
		t.Fatalf("expected config to be updated")
	}

	if e, a := 1, updated.Status.LatestVersion; e != a {
		t.Fatalf("expected update to latestversion=%d, got %d", e, a)
	}

	if updated.Status.Details == nil {
		t.Fatalf("expected config change details to be set")
	} else if updated.Status.Details.Causes == nil {
		t.Fatalf("expected config change causes to be set")
	} else if updated.Status.Details.Causes[0].Type != deployapi.DeploymentTriggerOnConfigChange {
		t.Fatalf("expected config change cause to be set to config change trigger, got %s", updated.Status.Details.Causes[0].Type)
	}
}
func TestHandle_raceWithTheImageController(t *testing.T) {
	var updated *deployapi.DeploymentConfig

	controller := &DeploymentConfigChangeController{
		decodeConfig: func(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, error) {
			return deployutil.DecodeDeploymentConfig(deployment, kapi.Codecs.LegacyCodec(deployapi.SchemeGroupVersion))
		},
		changeStrategy: &changeStrategyImpl{
			generateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) {
				generated := deployapitest.OkDeploymentConfig(1)
				generated.Status.Details = deployapitest.OkImageChangeDetails()
				updated = generated
				return generated, nil
			},
			updateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) {
				t.Errorf("an update should never run in the presence of races")
				updated.Status.Details = deployapitest.OkConfigChangeDetails()
				return updated, nil
			},
		},
	}

	config := deployapitest.OkDeploymentConfig(0)
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{deployapitest.OkConfigChangeTrigger(), deployapitest.OkImageChangeTrigger()}

	if err := controller.Handle(config); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	if e, a := 1, updated.Status.LatestVersion; e != a {
		t.Fatalf("expected update to latestversion=%d, got %d", e, a)
	}

	if updated.Status.Details == nil {
		t.Fatalf("expected config change details to be set")
	} else if updated.Status.Details.Causes == nil {
		t.Fatalf("expected config change causes to be set")
	} else if updated.Status.Details.Causes[0].Type != deployapi.DeploymentTriggerOnImageChange {
		t.Fatalf("expected config change cause to be set to image change trigger, got %s", updated.Status.Details.Causes[0].Type)
	}
}
Beispiel #8
0
// TestHandle_changeWithoutTemplateDiff ensures that an updated config with no
// pod template diff results in the config version remaining the same.
func TestHandle_changeWithoutTemplateDiff(t *testing.T) {
	config := deployapitest.OkDeploymentConfig(1)
	config.Triggers = []deployapi.DeploymentTriggerPolicy{deployapitest.OkConfigChangeTrigger()}

	generated := false
	updated := false

	controller := &DeploymentConfigChangeController{
		decodeConfig: func(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, error) {
			return deployutil.DecodeDeploymentConfig(deployment, api.Codec)
		},
		changeStrategy: &changeStrategyImpl{
			generateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) {
				generated = true
				return config, nil
			},
			updateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) {
				updated = true
				return config, nil
			},
			getDeploymentFunc: func(namespace, name string) (*kapi.ReplicationController, error) {
				deployment, _ := deployutil.MakeDeployment(deployapitest.OkDeploymentConfig(1), kapi.Codec)
				return deployment, nil
			},
		},
	}

	err := controller.Handle(config)

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	if generated {
		t.Error("Unexpected generation of deploymentConfig")
	}

	if updated {
		t.Error("Unexpected update of deploymentConfig")
	}
}
Beispiel #9
0
// TestHandle_configChangeTrigger ensures that a config with a config change
// trigger will be reconciled.
func TestHandle_configChangeTrigger(t *testing.T) {
	updated := false

	fake := &testclient.Fake{}
	fake.AddReactor("update", "deploymentconfigs/instantiate", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
		updated = true
		return true, nil, nil
	})

	controller := NewDeploymentTriggerController(dcInformer, streamInformer, fake, codec)

	config := testapi.OkDeploymentConfig(0)
	config.Namespace = kapi.NamespaceDefault
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{testapi.OkConfigChangeTrigger()}
	if err := controller.Handle(config); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !updated {
		t.Fatalf("expected config to be instantiated")
	}
}
Beispiel #10
0
// TestHandle_changeWithTemplateDiff ensures that a pod template change to a
// config with a config change trigger results in a version bump and cause
// update.
func TestHandle_changeWithTemplateDiff(t *testing.T) {
	scenarios := []struct {
		name           string
		modify         func(*deployapi.DeploymentConfig)
		changeExpected bool
	}{
		{
			name:           "container name change",
			changeExpected: true,
			modify: func(config *deployapi.DeploymentConfig) {
				config.Spec.Template.Spec.Containers[1].Name = "modified"
			},
		},
		{
			name:           "template label change",
			changeExpected: true,
			modify: func(config *deployapi.DeploymentConfig) {
				config.Spec.Template.Labels["newkey"] = "value"
			},
		},
		{
			name:           "no diff",
			changeExpected: false,
			modify:         func(config *deployapi.DeploymentConfig) {},
		},
	}

	for _, s := range scenarios {
		t.Logf("running scenario: %s", s.name)

		config := deployapitest.OkDeploymentConfig(1)
		config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{deployapitest.OkConfigChangeTrigger()}
		deployment, _ := deployutil.MakeDeployment(config, kapi.Codec)
		var updated *deployapi.DeploymentConfig

		controller := &DeploymentConfigChangeController{
			decodeConfig: func(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, error) {
				return deployutil.DecodeDeploymentConfig(deployment, api.Codec)
			},
			changeStrategy: &changeStrategyImpl{
				generateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) {
					return deployapitest.OkDeploymentConfig(2), nil
				},
				updateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) {
					updated = config
					return config, nil
				},
				getDeploymentFunc: func(namespace, name string) (*kapi.ReplicationController, error) {
					return deployment, nil
				},
			},
		}

		s.modify(config)
		err := controller.Handle(config)
		if err != nil {
			t.Errorf("unexpected error: %v", err)
		}

		if s.changeExpected {
			if updated == nil {
				t.Errorf("expected config to be updated")
				continue
			}
			if e, a := 2, updated.Status.LatestVersion; e != a {
				t.Errorf("expected update to latestversion=%d, got %d", e, a)
			}

			if updated.Status.Details == nil {
				t.Errorf("expected config change details to be set")
			} else if updated.Status.Details.Causes == nil {
				t.Errorf("expected config change causes to be set")
			} else if updated.Status.Details.Causes[0].Type != deployapi.DeploymentTriggerOnConfigChange {
				t.Errorf("expected config change cause to be set to config change trigger, got %s", updated.Status.Details.Causes[0].Type)
			}
		} else {
			if updated != nil {
				t.Errorf("unexpected update to version %d", updated.Status.LatestVersion)
			}
		}
	}
}
func TestTriggers_configChange(t *testing.T) {
	const namespace = "test-triggers-configchange"

	_, clusterAdminKubeConfig, err := testserver.StartTestMaster()
	checkErr(t, err)
	clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
	checkErr(t, err)
	clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig)
	checkErr(t, err)
	_, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, namespace, "my-test-user")
	checkErr(t, err)
	osClient, kubeClient, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "my-test-user")
	checkErr(t, err)

	config := deploytest.OkDeploymentConfig(0)
	config.Namespace = namespace
	config.Spec.Triggers[0] = deploytest.OkConfigChangeTrigger()

	rcWatch, err := kubeClient.ReplicationControllers(namespace).Watch(labels.Everything(), fields.Everything(), "0")
	if err != nil {
		t.Fatalf("Couldn't subscribe to Deployments %v", err)
	}
	defer rcWatch.Stop()

	// submit the initial deployment config
	if _, err := osClient.DeploymentConfigs(namespace).Create(config); err != nil {
		t.Fatalf("Couldn't create DeploymentConfig: %v", err)
	}

	// verify the initial deployment exists
	event := <-rcWatch.ResultChan()
	if e, a := watchapi.Added, event.Type; e != a {
		t.Fatalf("expected watch event type %s, got %s", e, a)
	}

	deployment := event.Object.(*kapi.ReplicationController)

	if e, a := config.Name, deployutil.DeploymentConfigNameFor(deployment); e != a {
		t.Fatalf("Expected deployment annotated with deploymentConfig '%s', got '%s'", e, a)
	}

	assertEnvVarEquals("ENV1", "VAL1", deployment, t)

	retryErr := kclient.RetryOnConflict(wait.Backoff{Steps: maxUpdateRetries}, func() error {
		// submit a new config with an updated environment variable
		config, err := osClient.DeploymentConfigs(namespace).Generate(config.Name)
		if err != nil {
			return err
		}

		config.Spec.Template.Spec.Containers[0].Env[0].Value = "UPDATED"

		// before we update the config, we need to update the state of the existing deployment
		// this is required to be done manually since the deployment and deployer pod controllers are not run in this test
		// get this live or conflicts will never end up resolved
		liveDeployment, err := kubeClient.ReplicationControllers(deployment.Namespace).Get(deployment.Name)
		if err != nil {
			return err
		}
		liveDeployment.Annotations[deployapi.DeploymentStatusAnnotation] = string(deployapi.DeploymentStatusComplete)
		// update the deployment
		if _, err := kubeClient.ReplicationControllers(namespace).Update(liveDeployment); err != nil {
			return err
		}

		event = <-rcWatch.ResultChan()
		if e, a := watchapi.Modified, event.Type; e != a {
			t.Fatalf("expected watch event type %s, got %s", e, a)
		}

		if _, err := osClient.DeploymentConfigs(namespace).Update(config); err != nil {
			return err
		}
		return nil
	})
	if retryErr != nil {
		t.Fatal(retryErr)
	}

	var newDeployment *kapi.ReplicationController
	for {
		event = <-rcWatch.ResultChan()
		if event.Type != watchapi.Added {
			// Discard modifications which could be applied to the original RC, etc.
			continue
		}
		newDeployment = event.Object.(*kapi.ReplicationController)
		break
	}

	assertEnvVarEquals("ENV1", "UPDATED", newDeployment, t)

	if newDeployment.Name == deployment.Name {
		t.Fatalf("expected new deployment; old=%s, new=%s", deployment.Name, newDeployment.Name)
	}
}
Beispiel #12
0
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()
}
Beispiel #13
0
func TestCanTrigger(t *testing.T) {
	tests := []struct {
		name string

		config  *deployapi.DeploymentConfig
		decoded *deployapi.DeploymentConfig
		force   bool

		expected       bool
		expectedCauses []deployapi.DeploymentCause
		expectedErr    bool
	}{
		{
			name: "no trigger [w/ podtemplate change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Triggers: []deployapi.DeploymentTriggerPolicy{},
					Template: deploytest.OkPodTemplateChanged(),
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Triggers: []deployapi.DeploymentTriggerPolicy{},
					Template: deploytest.OkPodTemplate(),
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			force: false,

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "forced updated",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(),
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			force: true,

			expected:       true,
			expectedCauses: []deployapi.DeploymentCause{{Type: deployapi.DeploymentTriggerManual}},
		},
		{
			name: "config change trigger only [w/ podtemplate change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			force: false,

			expected:       true,
			expectedCauses: deploytest.OkConfigChangeDetails().Causes,
		},
		{
			name: "config change trigger only [no change][initial]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(0),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(0),
			},
			force: false,

			expected:       true,
			expectedCauses: deploytest.OkConfigChangeDetails().Causes,
		},
		{
			name: "config change trigger only [no change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			force: false,

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "image change trigger only [automatic=false][w/ podtemplate change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(), // Irrelevant change
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkNonAutomaticICT(), // Image still to be resolved but it's false anyway
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkNonAutomaticICT(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			force: false,

			expected:       false,
			expectedCauses: nil,
			expectedErr:    true,
		},
		{
			name: "image change trigger only [automatic=false][w/ image change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(), // Image has been updated in the template but automatic=false
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkTriggeredNonAutomatic(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkNonAutomaticICT(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			force: false,

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "image change trigger only [automatic=true][w/ image change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkTriggeredImageChange(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkImageChangeTrigger(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			force: false,

			expected:       true,
			expectedCauses: deploytest.OkImageChangeDetails().Causes,
		},
		{
			name: "image change trigger only [automatic=true][no change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkTriggeredImageChange(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkTriggeredImageChange(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			force: false,

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "config change and image change trigger [automatic=false][initial][w/ image change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
						deploytest.OkTriggeredNonAutomatic(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(0),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
						deploytest.OkNonAutomaticICT(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(0),
			},
			force: false,

			expected:       true,
			expectedCauses: deploytest.OkConfigChangeDetails().Causes,
		},
		{
			name: "config change and image change trigger [automatic=false][initial][no change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
						deploytest.OkNonAutomaticICT(), // Image is not resolved yet
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(0),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
						deploytest.OkNonAutomaticICT(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(0),
			},
			force: false,

			expected:       false,
			expectedCauses: nil,
			expectedErr:    true,
		},
		{
			name: "config change and image change trigger [automatic=true][initial][w/ podtemplate change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(), // Pod template has changed but the image in the template is yet to be updated
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
						deploytest.OkImageChangeTrigger(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(0),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
						deploytest.OkImageChangeTrigger(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(0),
			},
			force: false,

			expected:       false,
			expectedCauses: nil,
			expectedErr:    true,
		},
		{
			name: "config change and image change trigger [automatic=true][initial][w/ image change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
						deploytest.OkTriggeredImageChange(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(0),
			},
			decoded: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
						deploytest.OkImageChangeTrigger(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(0),
			},
			force: false,

			expected:       true,
			expectedCauses: deploytest.OkImageChangeDetails().Causes,
		},
		{
			name: "config change and image change trigger [automatic=true][no change]",

			config: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "config"},
				Spec: deployapi.DeploymentConfigSpec{
					Template: deploytest.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						deploytest.OkConfigChangeTrigger(),
						deploytest.OkTriggeredImageChange(),
					},
				},
				Status: deploytest.OkDeploymentConfigStatus(1),
			},
			force: false,

			expected:       false,
			expectedCauses: nil,
		},
	}

	for _, test := range tests {
		t.Logf("running scenario %q", test.name)

		fake := &ktestclient.Fake{}
		fake.AddReactor("get", "replicationcontrollers", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
			config := test.decoded
			if config == nil {
				config = test.config
			}
			config = deploytest.RoundTripConfig(t, config)
			deployment, _ := deployutil.MakeDeployment(config, codec)
			return true, deployment, nil
		})

		test.config = deploytest.RoundTripConfig(t, test.config)

		got, gotCauses, err := canTrigger(test.config, fake, codec, test.force)
		if err != nil && !test.expectedErr {
			t.Errorf("unexpected error: %v", err)
			continue
		}
		if err == nil && test.expectedErr {
			t.Errorf("expected an error")
			continue
		}
		if test.expected != got {
			t.Errorf("expected to trigger: %t, got: %t", test.expected, got)
		}
		if !kapi.Semantic.DeepEqual(test.expectedCauses, gotCauses) {
			t.Errorf("expected causes:\n%#v\ngot:\n%#v", test.expectedCauses, gotCauses)
		}
	}
}
Beispiel #14
0
// TestHandle_changeWithTemplateDiff ensures that a pod template change to a
// config with a config change trigger results in a version bump and cause
// update.
func TestHandle_changeWithTemplateDiff(t *testing.T) {
	scenarios := []struct {
		name           string
		modify         func(*deployapi.DeploymentConfig)
		changeExpected bool
	}{
		{
			name:           "container name change",
			changeExpected: true,
			modify: func(config *deployapi.DeploymentConfig) {
				config.Spec.Template.Spec.Containers[1].Name = "modified"
			},
		},
		{
			name:           "template label change",
			changeExpected: true,
			modify: func(config *deployapi.DeploymentConfig) {
				config.Spec.Template.Labels["newkey"] = "value"
			},
		},
		{
			name:           "no diff",
			changeExpected: false,
			modify:         func(config *deployapi.DeploymentConfig) {},
		},
	}

	for _, s := range scenarios {
		t.Logf("running scenario: %s", s.name)
		fake := &testclient.Fake{}
		kFake := &ktestclient.Fake{}

		config := testapi.OkDeploymentConfig(1)
		config.Namespace = kapi.NamespaceDefault
		config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{testapi.OkConfigChangeTrigger()}
		deployment, _ := deployutil.MakeDeployment(config, kapi.Codecs.LegacyCodec(deployapi.SchemeGroupVersion))
		var updated *deployapi.DeploymentConfig

		fake.PrependReactor("update", "deploymentconfigs/status", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
			updated = action.(ktestclient.UpdateAction).GetObject().(*deployapi.DeploymentConfig)
			return true, updated, nil
		})
		kFake.PrependReactor("get", "replicationcontrollers", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
			return true, deployment, nil
		})

		controller := NewDeploymentTriggerController(fake, kFake, codec)

		s.modify(config)
		if err := controller.Handle(config); err != nil {
			t.Errorf("unexpected error: %v", err)
			continue
		}

		if !s.changeExpected {
			if updated != nil {
				t.Errorf("unexpected update to version %d", updated.Status.LatestVersion)
			}
			continue
		}

		// changeExpected == true
		if updated == nil {
			t.Errorf("expected config to be updated")
			continue
		}
		if e, a := int64(2), updated.Status.LatestVersion; e != a {
			t.Errorf("expected update to latestversion=%d, got %d", e, a)
			continue
		}

		if updated.Status.Details == nil {
			t.Errorf("expected config change details to be set")
		} else if updated.Status.Details.Causes == nil {
			t.Errorf("expected config change causes to be set")
		} else if updated.Status.Details.Causes[0].Type != deployapi.DeploymentTriggerOnConfigChange {
			t.Errorf("expected config change cause to be set to config change trigger, got %s", updated.Status.Details.Causes[0].Type)
		}
	}
}
Beispiel #15
0
func TestCanTrigger(t *testing.T) {
	tests := []struct {
		name string

		config  *deployapi.DeploymentConfig
		decoded *deployapi.DeploymentConfig

		expected       bool
		expectedCauses []deployapi.DeploymentCause
	}{
		{
			name: "nil decoded config",

			config:  testapi.OkDeploymentConfig(1),
			decoded: nil,

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "no trigger",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplateChanged(),
				},
				Status: testapi.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
				},
				Status: testapi.OkDeploymentConfigStatus(1),
			},

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "config change trigger only",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(1),
			},

			expected:       true,
			expectedCauses: testapi.OkConfigChangeDetails().Causes,
		},
		{
			name: "config change trigger only [no change][initial]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(0),
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(0),
			},

			expected:       true,
			expectedCauses: testapi.OkConfigChangeDetails().Causes,
		},
		{
			name: "config change trigger only [no change]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(1),
			},

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "image change trigger only [automatic=false]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplateChanged(), // Irrelevant change
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkNonAutomaticICT(), // Image still to be resolved but it's false anyway
					},
				},
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkNonAutomaticICT(),
					},
				},
			},

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "image change trigger only [automatic=false][image triggered]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplateChanged(), // Image has been updated in the template but automatic=false
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkTriggeredNonAutomatic(),
					},
				},
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkNonAutomaticICT(),
					},
				},
			},

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "image change trigger only [automatic=true]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkTriggeredImageChange(),
					},
				},
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkImageChangeTrigger(),
					},
				},
			},

			expected:       true,
			expectedCauses: testapi.OkImageChangeDetails().Causes,
		},
		{
			name: "image change trigger only [automatic=true][no change]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkImageChangeTrigger(),
					},
				},
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkImageChangeTrigger(),
					},
				},
			},

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "config change and image change trigger [automatic=false][initial][image resolved]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
						testapi.OkTriggeredNonAutomatic(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(0),
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
						testapi.OkNonAutomaticICT(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(0),
			},

			expected:       true,
			expectedCauses: testapi.OkConfigChangeDetails().Causes,
		},
		{
			name: "config change and image change trigger [automatic=false][initial]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
						testapi.OkNonAutomaticICT(), // Image is not resolved yet
					},
				},
				Status: testapi.OkDeploymentConfigStatus(0),
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
						testapi.OkNonAutomaticICT(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(0),
			},

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "config change and image change trigger [automatic=true][initial]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplateChanged(), // Pod template has changed but the image in the template is yet to be updated
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
						testapi.OkImageChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(0),
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
						testapi.OkImageChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(0),
			},

			expected:       false,
			expectedCauses: nil,
		},
		{
			name: "config change and image change trigger [automatic=true][initial][image triggered]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplateChanged(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
						testapi.OkTriggeredImageChange(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(0),
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
						testapi.OkImageChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(0),
			},

			expected:       true,
			expectedCauses: testapi.OkImageChangeDetails().Causes,
		},
		{
			name: "config change and image change trigger [automatic=true][no change]",

			config: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
						testapi.OkImageChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(1),
			},
			decoded: &deployapi.DeploymentConfig{
				Spec: deployapi.DeploymentConfigSpec{
					Template: testapi.OkPodTemplate(),
					Triggers: []deployapi.DeploymentTriggerPolicy{
						testapi.OkConfigChangeTrigger(),
						testapi.OkImageChangeTrigger(),
					},
				},
				Status: testapi.OkDeploymentConfigStatus(1),
			},

			expected:       false,
			expectedCauses: nil,
		},
	}

	for _, test := range tests {
		got, gotCauses := canTrigger(test.config, test.decoded)
		if test.expected != got {
			t.Errorf("%s: expected to trigger: %t, got: %t", test.name, test.expected, got)
			continue
		}
		if !kapi.Semantic.DeepEqual(test.expectedCauses, gotCauses) {
			t.Errorf("%s: expected causes:\n%#v\ngot:\n%#v", test.name, test.expectedCauses, gotCauses)
		}
	}
}
Beispiel #16
0
func TestValidateDeploymentConfigMissingFields(t *testing.T) {
	errorCases := map[string]struct {
		DeploymentConfig api.DeploymentConfig
		ErrorType        field.ErrorType
		Field            string
	}{
		"empty container field": {
			api.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"},
				Spec: api.DeploymentConfigSpec{
					Replicas: 1,
					Triggers: []api.DeploymentTriggerPolicy{test.OkConfigChangeTrigger()},
					Selector: test.OkSelector(),
					Strategy: test.OkStrategy(),
					Template: test.OkPodTemplateMissingImage("container1"),
				},
			},
			field.ErrorTypeRequired,
			"spec.template.spec.containers[0].image",
		},
		"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",
		},
		"invalid spec.strategy.customParams.environment": {
			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{
							Environment: []kapi.EnvVar{
								{Name: "A=B"},
							},
						},
					},
					Template: test.OkPodTemplate(),
				},
			},
			field.ErrorTypeInvalid,
			"spec.strategy.customParams.environment[0].name",
		},
		"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.ErrorTypeInvalid,
			"spec.strategy.recreateParams.pre",
		},
		"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]",
		},
		"missing spec.strategy.recreateParams.mid.execNewPod": {
			api.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"},
				Spec: api.DeploymentConfigSpec{
					Replicas: 1,
					Strategy: api.DeploymentStrategy{
						Type: api.DeploymentStrategyTypeRecreate,
						RecreateParams: &api.RecreateDeploymentStrategyParams{
							Mid: &api.LifecycleHook{
								FailurePolicy: api.LifecycleHookFailurePolicyRetry,
							},
						},
					},
					Template: test.OkPodTemplate(),
					Selector: test.OkSelector(),
				},
			},
			field.ErrorTypeInvalid,
			"spec.strategy.recreateParams.mid",
		},
		"missing spec.strategy.recreateParams.post.execNewPod": {
			api.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"},
				Spec: api.DeploymentConfigSpec{
					Replicas: 1,
					Strategy: api.DeploymentStrategy{
						Type: api.DeploymentStrategyTypeRecreate,
						RecreateParams: &api.RecreateDeploymentStrategyParams{
							Post: &api.LifecycleHook{
								FailurePolicy: api.LifecycleHookFailurePolicyRetry,
							},
						},
					},
					Template: test.OkPodTemplate(),
					Selector: test.OkSelector(),
				},
			},
			field.ErrorTypeInvalid,
			"spec.strategy.recreateParams.post",
		},
		"missing spec.strategy.after.tagImages": {
			api.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"},
				Spec: api.DeploymentConfigSpec{
					Replicas: 1,
					Strategy: api.DeploymentStrategy{
						Type: api.DeploymentStrategyTypeRecreate,
						RecreateParams: &api.RecreateDeploymentStrategyParams{
							Post: &api.LifecycleHook{
								FailurePolicy: api.LifecycleHookFailurePolicyRetry,
								TagImages: []api.TagImageHook{
									{
										ContainerName: "missing",
										To:            kapi.ObjectReference{Kind: "ImageStreamTag", Name: "stream:tag"},
									},
								},
							},
						},
					},
					Template: test.OkPodTemplate(),
					Selector: test.OkSelector(),
				},
			},
			field.ErrorTypeInvalid,
			"spec.strategy.recreateParams.post.tagImages[0].containerName",
		},
		"missing spec.strategy.after.tagImages.to.kind": {
			api.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"},
				Spec: api.DeploymentConfigSpec{
					Replicas: 1,
					Strategy: api.DeploymentStrategy{
						Type: api.DeploymentStrategyTypeRecreate,
						RecreateParams: &api.RecreateDeploymentStrategyParams{
							Post: &api.LifecycleHook{
								FailurePolicy: api.LifecycleHookFailurePolicyRetry,
								TagImages: []api.TagImageHook{
									{
										ContainerName: "container1",
										To:            kapi.ObjectReference{Name: "stream:tag"},
									},
								},
							},
						},
					},
					Template: test.OkPodTemplate(),
					Selector: test.OkSelector(),
				},
			},
			field.ErrorTypeInvalid,
			"spec.strategy.recreateParams.post.tagImages[0].to.kind",
		},
		"missing spec.strategy.after.tagImages.to.name": {
			api.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"},
				Spec: api.DeploymentConfigSpec{
					Replicas: 1,
					Strategy: api.DeploymentStrategy{
						Type: api.DeploymentStrategyTypeRecreate,
						RecreateParams: &api.RecreateDeploymentStrategyParams{
							Post: &api.LifecycleHook{
								FailurePolicy: api.LifecycleHookFailurePolicyRetry,
								TagImages: []api.TagImageHook{
									{
										ContainerName: "container1",
										To:            kapi.ObjectReference{Kind: "ImageStreamTag"},
									},
								},
							},
						},
					},
					Template: test.OkPodTemplate(),
					Selector: test.OkSelector(),
				},
			},
			field.ErrorTypeRequired,
			"spec.strategy.recreateParams.post.tagImages[0].to.name",
		},
		"can't have both tag and execNewPod": {
			api.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"},
				Spec: api.DeploymentConfigSpec{
					Replicas: 1,
					Strategy: api.DeploymentStrategy{
						Type: api.DeploymentStrategyTypeRecreate,
						RecreateParams: &api.RecreateDeploymentStrategyParams{
							Post: &api.LifecycleHook{
								FailurePolicy: api.LifecycleHookFailurePolicyRetry,
								ExecNewPod:    &api.ExecNewPodHook{},
								TagImages:     []api.TagImageHook{{}},
							},
						},
					},
					Template: test.OkPodTemplate(),
					Selector: test.OkSelector(),
				},
			},
			field.ErrorTypeInvalid,
			"spec.strategy.recreateParams.post",
		},
		"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 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 TestTriggers_configChange(t *testing.T) {
	testutil.DeleteAllEtcdKeys()
	openshift := NewTestDeployOpenshift(t)
	defer openshift.Close()

	config := deploytest.OkDeploymentConfig(0)
	config.Namespace = testutil.Namespace()
	config.Triggers[0] = deploytest.OkConfigChangeTrigger()
	var err error

	watch, err := openshift.KubeClient.ReplicationControllers(testutil.Namespace()).Watch(labels.Everything(), fields.Everything(), "0")
	if err != nil {
		t.Fatalf("Couldn't subscribe to Deployments %v", err)
	}
	defer watch.Stop()

	// submit the initial deployment config
	if _, err := openshift.Client.DeploymentConfigs(testutil.Namespace()).Create(config); err != nil {
		t.Fatalf("Couldn't create DeploymentConfig: %v", err)
	}

	// verify the initial deployment exists
	event := <-watch.ResultChan()
	if e, a := watchapi.Added, event.Type; e != a {
		t.Fatalf("expected watch event type %s, got %s", e, a)
	}

	deployment := event.Object.(*kapi.ReplicationController)

	if e, a := config.Name, deployutil.DeploymentConfigNameFor(deployment); e != a {
		t.Fatalf("Expected deployment annotated with deploymentConfig '%s', got '%s'", e, a)
	}

	assertEnvVarEquals("ENV1", "VAL1", deployment, t)

	// submit a new config with an updated environment variable
	if config, err = openshift.Client.DeploymentConfigs(testutil.Namespace()).Generate(config.Name); err != nil {
		t.Fatalf("Error generating config: %v", err)
	}

	config.Template.ControllerTemplate.Template.Spec.Containers[0].Env[0].Value = "UPDATED"

	// before we update the config, we need to update the state of the existing deployment
	// this is required to be done manually since the deployment and deployer pod controllers are not run in this test
	deployment.Annotations[deployapi.DeploymentStatusAnnotation] = string(deployapi.DeploymentStatusComplete)
	// update the deployment
	if _, err = openshift.KubeClient.ReplicationControllers(testutil.Namespace()).Update(deployment); err != nil {
		t.Fatalf("Error updating existing deployment: %v", err)
	}

	event = <-watch.ResultChan()
	if e, a := watchapi.Modified, event.Type; e != a {
		t.Fatalf("expected watch event type %s, got %s", e, a)
	}

	if _, err := openshift.Client.DeploymentConfigs(testutil.Namespace()).Update(config); err != nil {
		t.Fatalf("Couldn't create updated DeploymentConfig: %v", err)
	}

	event = <-watch.ResultChan()
	if e, a := watchapi.Added, event.Type; e != a {
		t.Fatalf("expected watch event type %s, got %s", e, a)
	}
	newDeployment := event.Object.(*kapi.ReplicationController)

	assertEnvVarEquals("ENV1", "UPDATED", newDeployment, t)

	if newDeployment.Name == deployment.Name {
		t.Fatalf("expected new deployment; old=%s, new=%s", deployment.Name, newDeployment.Name)
	}
}
Beispiel #19
0
// TestHandle_automaticImageUpdates tests automatic and non-automatic updates
// from image change triggers.
func TestHandle_automaticImageUpdates(t *testing.T) {
	tests := []struct {
		name           string
		auto           bool
		canTrigger     bool
		version        int64
		expectedUpdate bool
	}{
		{
			name:           "initial deployment with unresolved image (auto: true)",
			auto:           true,
			canTrigger:     false,
			version:        0,
			expectedUpdate: false,
		},
		{
			name:           "initial deployment with unresolved image (auto: false)",
			auto:           false,
			canTrigger:     false,
			version:        0,
			expectedUpdate: false,
		},
		{
			name:           "initial deployment with resolved image (auto: true)",
			auto:           true,
			canTrigger:     true,
			version:        0,
			expectedUpdate: true,
		},
		{
			name:           "initial deployment with resolved image (auto: false)",
			auto:           false,
			canTrigger:     true,
			version:        0,
			expectedUpdate: true,
		},
	}

	for _, test := range tests {
		updated := false

		fake := &testclient.Fake{}
		kFake := &ktestclient.Fake{}
		fake.PrependReactor("update", "deploymentconfigs/status", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
			updated = true
			return true, nil, nil
		})
		kFake.PrependReactor("get", "replicationcontrollers", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
			// This will always return no template difference. We test template differences in TestHandle_changeWithTemplateDiff
			config := testapi.OkDeploymentConfig(0)
			deployment, _ := deployutil.MakeDeployment(config, kapi.Codecs.LegacyCodec(deployapi.SchemeGroupVersion))
			return true, deployment, nil
		})

		controller := NewDeploymentTriggerController(fake, kFake, codec)

		config := testapi.OkDeploymentConfig(test.version)
		config.Namespace = kapi.NamespaceDefault
		ict := testapi.OkImageChangeTrigger()
		ict.ImageChangeParams.Automatic = test.auto
		if test.canTrigger {
			ict.ImageChangeParams.LastTriggeredImage = testapi.DockerImageReference
		}
		config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{testapi.OkConfigChangeTrigger(), ict}

		if err := controller.Handle(config); err != nil {
			t.Errorf("%s: unexpected error: %v", test.name, err)
			continue
		}

		if test.expectedUpdate != updated {
			t.Errorf("%s: expected update: %t, got update: %t", test.name, test.expectedUpdate, updated)
		}
	}
}