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)
	}
}
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 #3
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 #4
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)
		}
	}
}