Example #1
0
func TestDeploy_reenableTriggers(t *testing.T) {
	mktrigger := func() deployapi.DeploymentTriggerPolicy {
		t := deploytest.OkImageChangeTrigger()
		t.ImageChangeParams.Automatic = false
		return t
	}

	var updated *deployapi.DeploymentConfig

	osClient := &tc.Fake{}
	osClient.ReactFn = func(action ktc.Action) (runtime.Object, error) {
		switch a := action.(type) {
		case ktc.UpdateActionImpl:
			updated = a.GetObject().(*deployapi.DeploymentConfig)
			return updated, nil
		}
		t.Fatalf("unexpected action: %+v", action)
		return nil, nil
	}

	config := deploytest.OkDeploymentConfig(1)
	config.Triggers = []deployapi.DeploymentTriggerPolicy{}
	count := 3
	for i := 0; i < count; i++ {
		config.Triggers = append(config.Triggers, mktrigger())
	}

	o := &DeployOptions{osClient: osClient}
	err := o.reenableTriggers(config, ioutil.Discard)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

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

	if e, a := count, len(config.Triggers); e != a {
		t.Fatalf("expected %d triggers, got %d", e, a)
	}
	for _, trigger := range config.Triggers {
		if !trigger.ImageChangeParams.Automatic {
			t.Errorf("expected trigger to be enabled: %#v", trigger.ImageChangeParams)
		}
	}
}
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)
	}
}
Example #3
0
func TestDeploy_reenableTriggers(t *testing.T) {
	mktrigger := func() deployapi.DeploymentTriggerPolicy {
		t := deploytest.OkImageChangeTrigger()
		t.ImageChangeParams.Automatic = false
		return t
	}

	var updated *deployapi.DeploymentConfig

	osClient := &tc.Fake{}
	osClient.AddReactor("update", "deploymentconfigs", func(action ktc.Action) (handled bool, ret runtime.Object, err error) {
		updated = action.(ktc.UpdateAction).GetObject().(*deployapi.DeploymentConfig)
		return true, updated, nil
	})

	config := deploytest.OkDeploymentConfig(1)
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{}
	count := 3
	for i := 0; i < count; i++ {
		config.Spec.Triggers = append(config.Spec.Triggers, mktrigger())
	}

	o := &DeployOptions{osClient: osClient, out: ioutil.Discard}
	err := o.reenableTriggers(config)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

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

	if e, a := count, len(config.Spec.Triggers); e != a {
		t.Fatalf("expected %d triggers, got %d", e, a)
	}
	for _, trigger := range config.Spec.Triggers {
		if !trigger.ImageChangeParams.Automatic {
			t.Errorf("expected trigger to be enabled: %#v", trigger.ImageChangeParams)
		}
	}
}
Example #4
0
// TestHandle_imageChangeTrigger ensures that a config with an image change
// trigger will be reconciled.
func TestHandle_imageChangeTrigger(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.OkImageChangeTrigger()}
	if err := controller.Handle(config); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !updated {
		t.Fatalf("expected config to be instantiated")
	}
}
Example #5
0
func TestDeploy_triggerEnable(t *testing.T) {
	var updated *deployapi.DeploymentConfig
	triggerEnabler := &triggerEnabler{
		updateConfig: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) {
			updated = config
			return config, nil
		},
	}

	mktrigger := func() deployapi.DeploymentTriggerPolicy {
		t := deploytest.OkImageChangeTrigger()
		t.ImageChangeParams.Automatic = false
		return t
	}
	count := 3

	config := deploytest.OkDeploymentConfig(1)
	config.Triggers = []deployapi.DeploymentTriggerPolicy{}
	for i := 0; i < count; i++ {
		config.Triggers = append(config.Triggers, mktrigger())
	}

	err := triggerEnabler.enableTriggers(config, ioutil.Discard)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

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

	if e, a := count, len(config.Triggers); e != a {
		t.Fatalf("expected %d triggers, got %d", e, a)
	}
	for _, trigger := range config.Triggers {
		if !trigger.ImageChangeParams.Automatic {
			t.Errorf("expected trigger to be enabled: %#v", trigger.ImageChangeParams)
		}
	}
}
Example #6
0
func TestValidateDeploymentConfigICTMissingImage(t *testing.T) {
	dc := &api.DeploymentConfig{
		ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "bar"},
		Spec: api.DeploymentConfigSpec{
			Replicas: 1,
			Triggers: []api.DeploymentTriggerPolicy{test.OkImageChangeTrigger()},
			Selector: test.OkSelector(),
			Strategy: test.OkStrategy(),
			Template: test.OkPodTemplateMissingImage("container1"),
		},
	}
	errs := ValidateDeploymentConfig(dc)

	if len(errs) > 0 {
		t.Errorf("Unexpected non-empty error list: %+v", errs)
	}

	for _, c := range dc.Spec.Template.Spec.Containers {
		if c.Image == "unset" {
			t.Errorf("%s image field still has validation fake out value of %s", c.Name, c.Image)
		}
	}
}
Example #7
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)
	}
}
// TestTriggers_imageChange ensures that a deployment config with an ImageChange trigger
// will start a new deployment when an image change happens.
func TestTriggers_imageChange(t *testing.T) {
	testutil.RequireEtcd(t)
	_, clusterAdminKubeConfig, err := testserver.StartTestMaster()
	if err != nil {
		t.Fatalf("error starting master: %v", err)
	}
	openshiftClusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig)
	if err != nil {
		t.Fatalf("error getting cluster admin client: %v", err)
	}
	openshiftClusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
	if err != nil {
		t.Fatalf("error getting cluster admin client config: %v", err)
	}
	openshiftProjectAdminClient, err := testserver.CreateNewProject(openshiftClusterAdminClient, *openshiftClusterAdminClientConfig, testutil.Namespace(), "bob")
	if err != nil {
		t.Fatalf("error creating project: %v", err)
	}

	imageStream := &imageapi.ImageStream{ObjectMeta: kapi.ObjectMeta{Name: deploytest.ImageStreamName}}

	config := deploytest.OkDeploymentConfig(0)
	config.Namespace = testutil.Namespace()
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{deploytest.OkImageChangeTrigger()}

	configWatch, err := openshiftProjectAdminClient.DeploymentConfigs(testutil.Namespace()).Watch(kapi.ListOptions{})
	if err != nil {
		t.Fatalf("Couldn't subscribe to deploymentconfigs %v", err)
	}
	defer configWatch.Stop()

	if imageStream, err = openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Create(imageStream); err != nil {
		t.Fatalf("Couldn't create imagestream: %v", err)
	}

	imageWatch, err := openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Watch(kapi.ListOptions{})
	if err != nil {
		t.Fatalf("Couldn't subscribe to imagestreams: %v", err)
	}
	defer imageWatch.Stop()

	updatedImage := fmt.Sprintf("sha256:%s", deploytest.ImageID)
	updatedPullSpec := fmt.Sprintf("registry:8080/%s/%s@%s", testutil.Namespace(), deploytest.ImageStreamName, updatedImage)
	// Make a function which can create a new tag event for the image stream and
	// then wait for the stream status to be asynchronously updated.
	createTagEvent := func() {
		mapping := &imageapi.ImageStreamMapping{
			ObjectMeta: kapi.ObjectMeta{Name: imageStream.Name},
			Tag:        imageapi.DefaultImageTag,
			Image: imageapi.Image{
				ObjectMeta: kapi.ObjectMeta{
					Name: updatedImage,
				},
				DockerImageReference: updatedPullSpec,
			},
		}
		if err := openshiftProjectAdminClient.ImageStreamMappings(testutil.Namespace()).Create(mapping); err != nil {
			t.Fatalf("unexpected error: %v", err)
		}

		t.Log("Waiting for image stream mapping to be reflected in the image stream status...")
	statusLoop:
		for {
			select {
			case event := <-imageWatch.ResultChan():
				stream := event.Object.(*imageapi.ImageStream)
				if _, ok := stream.Status.Tags[imageapi.DefaultImageTag]; ok {
					t.Logf("imagestream %q now has status with tags: %#v", stream.Name, stream.Status.Tags)
					break statusLoop
				}
				t.Logf("Still waiting for latest tag status on imagestream %q", stream.Name)
			}
		}
	}

	if config, err = openshiftProjectAdminClient.DeploymentConfigs(testutil.Namespace()).Create(config); err != nil {
		t.Fatalf("Couldn't create deploymentconfig: %v", err)
	}

	createTagEvent()

	var newConfig *deployapi.DeploymentConfig
	t.Log("Waiting for a new deployment config in response to imagestream update")
waitForNewConfig:
	for {
		select {
		case event := <-configWatch.ResultChan():
			if event.Type == watchapi.Modified {
				newConfig = event.Object.(*deployapi.DeploymentConfig)
				// Multiple updates to the config can be expected (e.g. status
				// updates), so wait for a significant update (e.g. version).
				if newConfig.Status.LatestVersion > 0 {
					if e, a := updatedPullSpec, newConfig.Spec.Template.Spec.Containers[0].Image; e != a {
						t.Fatalf("unexpected image for pod template container 0; expected %q, got %q", e, a)
					}
					break waitForNewConfig
				}
				t.Log("Still waiting for a new deployment config in response to imagestream update")
			}
		}
	}
}
Example #9
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)
		}
	}
}
Example #10
0
func TestExport(t *testing.T) {
	exporter := &defaultExporter{}

	baseSA := &kapi.ServiceAccount{}
	baseSA.Name = "my-sa"

	tests := []struct {
		name        string
		object      runtime.Object
		exact       bool
		expectedObj runtime.Object
		expectedErr error
	}{
		{
			name:   "export deploymentConfig",
			object: deploytest.OkDeploymentConfig(1),
			expectedObj: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{
					Name: "config",
				},
				LatestVersion: 0,
				Triggers: []deployapi.DeploymentTriggerPolicy{
					deploytest.OkImageChangeTrigger(),
				},
				Template: deploytest.OkDeploymentTemplate(),
			},
			expectedErr: nil,
		},
		{
			name: "export imageStream",
			object: &imageapi.ImageStream{
				ObjectMeta: kapi.ObjectMeta{
					Name:      "test",
					Namespace: "other",
				},
				Spec: imageapi.ImageStreamSpec{
					Tags: map[string]imageapi.TagReference{
						"v1": {
							Annotations: map[string]string{"an": "annotation"},
						},
					},
				},
				Status: imageapi.ImageStreamStatus{
					DockerImageRepository: "foo/bar",
					Tags: map[string]imageapi.TagEventList{
						"v1": {
							Items: []imageapi.TagEvent{{Image: "the image"}},
						},
					},
				},
			},
			expectedObj: &imageapi.ImageStream{
				ObjectMeta: kapi.ObjectMeta{
					Name:      "test",
					Namespace: "",
				},
				Spec: imageapi.ImageStreamSpec{
					Tags: map[string]imageapi.TagReference{
						"v1": {
							From: &kapi.ObjectReference{
								Kind: "DockerImage",
								Name: "foo/bar:v1",
							},
							Annotations: map[string]string{"an": "annotation"},
						},
					},
				},
				Status: imageapi.ImageStreamStatus{
					Tags: map[string]imageapi.TagEventList{},
				},
			},
			expectedErr: nil,
		},
		{
			name: "remove unexportable SA secrets",
			object: &kapi.ServiceAccount{
				ObjectMeta: kapi.ObjectMeta{
					Name: baseSA.Name,
				},
				ImagePullSecrets: []kapi.LocalObjectReference{
					{Name: osautil.GetDockercfgSecretNamePrefix(baseSA) + "-foo"},
					{Name: "another-pull-secret"},
				},
				Secrets: []kapi.ObjectReference{
					{Name: osautil.GetDockercfgSecretNamePrefix(baseSA) + "-foo"},
					{Name: osautil.GetTokenSecretNamePrefix(baseSA) + "-foo"},
					{Name: "another-mountable-secret"},
				},
			},
			expectedObj: &kapi.ServiceAccount{
				ObjectMeta: kapi.ObjectMeta{
					Name: baseSA.Name,
				},
				ImagePullSecrets: []kapi.LocalObjectReference{
					{Name: "another-pull-secret"},
				},
				Secrets: []kapi.ObjectReference{
					{Name: "another-mountable-secret"},
				},
			},
			expectedErr: nil,
		},
		{
			name: "do not remove unexportable SA secrets with exact",
			object: &kapi.ServiceAccount{
				ObjectMeta: kapi.ObjectMeta{
					Name: baseSA.Name,
				},
				ImagePullSecrets: []kapi.LocalObjectReference{
					{Name: osautil.GetDockercfgSecretNamePrefix(baseSA) + "-foo"},
					{Name: "another-pull-secret"},
				},
				Secrets: []kapi.ObjectReference{
					{Name: osautil.GetDockercfgSecretNamePrefix(baseSA) + "-foo"},
					{Name: osautil.GetTokenSecretNamePrefix(baseSA) + "-foo"},
					{Name: "another-mountable-secret"},
				},
			},
			expectedObj: &kapi.ServiceAccount{
				ObjectMeta: kapi.ObjectMeta{
					Name: baseSA.Name,
				},
				ImagePullSecrets: []kapi.LocalObjectReference{
					{Name: osautil.GetDockercfgSecretNamePrefix(baseSA) + "-foo"},
					{Name: "another-pull-secret"},
				},
				Secrets: []kapi.ObjectReference{
					{Name: osautil.GetDockercfgSecretNamePrefix(baseSA) + "-foo"},
					{Name: osautil.GetTokenSecretNamePrefix(baseSA) + "-foo"},
					{Name: "another-mountable-secret"},
				},
			},
			exact:       true,
			expectedErr: nil,
		},
	}

	for _, test := range tests {
		if err := exporter.Export(test.object, test.exact); err != test.expectedErr {
			t.Errorf("error mismatch: expected %v, got %v", test.expectedErr, err)
		}

		if !reflect.DeepEqual(test.object, test.expectedObj) {
			t.Errorf("object mismatch: expected \n%v\ngot \n%v\n", test.expectedObj, test.object)
		}
	}
}
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)
	}
}
Example #12
0
// TestTriggers_imageChange_nonAutomatic ensures that a deployment config with a non-automatic
// trigger will have its image updated when a deployment is started manually.
func TestTriggers_imageChange_nonAutomatic(t *testing.T) {
	testutil.RequireEtcd(t)
	defer testutil.DumpEtcdOnFailure(t)
	_, clusterAdminKubeConfig, err := testserver.StartTestMaster()
	if err != nil {
		t.Fatalf("error starting master: %v", err)
	}
	openshiftClusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig)
	if err != nil {
		t.Fatalf("error getting cluster admin client: %v", err)
	}
	openshiftClusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
	if err != nil {
		t.Fatalf("error getting cluster admin client config: %v", err)
	}
	oc, err := testserver.CreateNewProject(openshiftClusterAdminClient, *openshiftClusterAdminClientConfig, testutil.Namespace(), "bob")
	if err != nil {
		t.Fatalf("error creating project: %v", err)
	}

	imageStream := &imageapi.ImageStream{ObjectMeta: kapi.ObjectMeta{Name: deploytest.ImageStreamName}}

	if imageStream, err = oc.ImageStreams(testutil.Namespace()).Create(imageStream); err != nil {
		t.Fatalf("Couldn't create imagestream: %v", err)
	}

	imageWatch, err := oc.ImageStreams(testutil.Namespace()).Watch(kapi.ListOptions{})
	if err != nil {
		t.Fatalf("Couldn't subscribe to imagestreams: %v", err)
	}
	defer imageWatch.Stop()

	image := fmt.Sprintf("sha256:%s", deploytest.ImageID)
	pullSpec := fmt.Sprintf("registry:5000/%s/%s@%s", testutil.Namespace(), deploytest.ImageStreamName, image)
	// Make a function which can create a new tag event for the image stream and
	// then wait for the stream status to be asynchronously updated.
	mapping := &imageapi.ImageStreamMapping{
		ObjectMeta: kapi.ObjectMeta{Name: imageStream.Name},
		Tag:        imageapi.DefaultImageTag,
		Image: imageapi.Image{
			ObjectMeta: kapi.ObjectMeta{
				Name: image,
			},
			DockerImageReference: pullSpec,
		},
	}

	createTagEvent := func(mapping *imageapi.ImageStreamMapping) {
		if err := oc.ImageStreamMappings(testutil.Namespace()).Create(mapping); err != nil {
			t.Fatalf("unexpected error: %v", err)
		}

		t.Log("Waiting for image stream mapping to be reflected in the image stream status...")

		timeout := time.After(time.Minute)

		for {
			select {
			case event := <-imageWatch.ResultChan():
				stream := event.Object.(*imageapi.ImageStream)
				tagEventList, ok := stream.Status.Tags[imageapi.DefaultImageTag]
				if ok && len(tagEventList.Items) > 0 && tagEventList.Items[0].DockerImageReference == mapping.Image.DockerImageReference {
					t.Logf("imagestream %q now has status with tags: %#v", stream.Name, stream.Status.Tags)
					return
				}
				if len(tagEventList.Items) > 0 {
					t.Logf("want: %s, got: %s", mapping.Image.DockerImageReference, tagEventList.Items[0].DockerImageReference)
				}
				t.Logf("Still waiting for latest tag status update on imagestream %q with tags: %#v", stream.Name, tagEventList)
			case <-timeout:
				t.Fatalf("timed out waiting for image stream %q to be updated", imageStream.Name)
			}
		}
	}

	configWatch, err := oc.DeploymentConfigs(testutil.Namespace()).Watch(kapi.ListOptions{})
	if err != nil {
		t.Fatalf("Couldn't subscribe to deploymentconfigs: %v", err)
	}
	defer configWatch.Stop()

	config := deploytest.OkDeploymentConfig(0)
	config.Namespace = testutil.Namespace()
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{deploytest.OkImageChangeTrigger()}
	config.Spec.Triggers[0].ImageChangeParams.Automatic = false
	if config, err = oc.DeploymentConfigs(testutil.Namespace()).Create(config); err != nil {
		t.Fatalf("Couldn't create deploymentconfig: %v", err)
	}

	createTagEvent(mapping)

	var newConfig *deployapi.DeploymentConfig
	t.Log("Waiting for the first imagestream update - no deployment should run")

	timeout := time.After(20 * time.Second)

	// Deployment config with automatic=false in its ICT - no deployment should trigger.
	// We don't really care about the initial update since it's not going to be deployed
	// anyway.
out:
	for {
		select {
		case event := <-configWatch.ResultChan():
			if event.Type != watchapi.Modified {
				continue
			}

			newConfig = event.Object.(*deployapi.DeploymentConfig)

			if newConfig.Status.LatestVersion > 0 {
				t.Fatalf("unexpected latestVersion update - the config has no config change trigger")
			}

		case <-timeout:
			break out
		}
	}

	t.Log("Waiting for the second imagestream update - no deployment should run")

	// Subsequent updates to the image shouldn't update the pod template image
	mapping.Image.Name = "sha256:thisupdatedimageshouldneverlandinthepodtemplate"
	mapping.Image.DockerImageReference = fmt.Sprintf("registry:8080/%s/%s@%s", testutil.Namespace(), deploytest.ImageStreamName, mapping.Image.Name)
	createTagEvent(mapping)

	timeout = time.After(20 * time.Second)

loop:
	for {
		select {
		case event := <-configWatch.ResultChan():
			if event.Type != watchapi.Modified {
				continue
			}

			newConfig = event.Object.(*deployapi.DeploymentConfig)

			if newConfig.Status.LatestVersion > 0 {
				t.Fatalf("unexpected latestVersion update - the config has no config change trigger")
			}

		case <-timeout:
			break loop
		}
	}

	t.Log("Instantiate the deployment config - the latest image should be picked up and a new deployment should run")
	request := &deployapi.DeploymentRequest{
		Name:   config.Name,
		Latest: true,
		Force:  true,
	}
	if _, err = oc.DeploymentConfigs(config.Namespace).Instantiate(request); err != nil {
		t.Fatalf("Couldn't instantiate deployment config %q: %v", config.Name, err)
	}
	config, err = oc.DeploymentConfigs(config.Namespace).Get(config.Name)
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}
	if exp, got := mapping.Image.DockerImageReference, config.Spec.Template.Spec.Containers[0].Image; exp != got {
		t.Fatalf("Expected image %q instead of %q to be updated in deployment config %q", exp, got, config.Name)
	}
	if exp, got := int64(1), config.Status.LatestVersion; exp != got {
		t.Fatalf("Expected latestVersion for deployment config %q to be %d, got %d", config.Name, exp, got)
	}
	if config.Status.Details == nil || len(config.Status.Details.Causes) == 0 {
		t.Fatalf("Expected a cause of deployment for deployment config %q", config.Name)
	}
	if gotType, expectedType := config.Status.Details.Causes[0].Type, deployapi.DeploymentTriggerManual; gotType != expectedType {
		t.Fatalf("Instantiated deployment config should have a %q cause of deployment instead of %q", expectedType, gotType)
	}
}
Example #13
0
func TestExport(t *testing.T) {
	exporter := &defaultExporter{}

	tests := []struct {
		name        string
		object      runtime.Object
		exact       bool
		expectedObj runtime.Object
		expectedErr error
	}{
		{
			name:   "export deploymentConfig",
			object: deploytest.OkDeploymentConfig(1),
			expectedObj: &deployapi.DeploymentConfig{
				ObjectMeta: kapi.ObjectMeta{
					Name: "config",
				},
				LatestVersion: 0,
				Triggers: []deployapi.DeploymentTriggerPolicy{
					deploytest.OkImageChangeTrigger(),
				},
				Template: deploytest.OkDeploymentTemplate(),
			},
			expectedErr: nil,
		},
		{
			name: "export imageStream",
			object: &imageapi.ImageStream{
				ObjectMeta: kapi.ObjectMeta{
					Name:      "test",
					Namespace: "other",
				},
				Spec: imageapi.ImageStreamSpec{
					Tags: map[string]imageapi.TagReference{
						"v1": {
							Annotations: map[string]string{"an": "annotation"},
						},
					},
				},
				Status: imageapi.ImageStreamStatus{
					DockerImageRepository: "foo/bar",
					Tags: map[string]imageapi.TagEventList{
						"v1": {
							Items: []imageapi.TagEvent{{Image: "the image"}},
						},
					},
				},
			},
			expectedObj: &imageapi.ImageStream{
				ObjectMeta: kapi.ObjectMeta{
					Name:      "test",
					Namespace: "",
				},
				Spec: imageapi.ImageStreamSpec{
					Tags: map[string]imageapi.TagReference{
						"v1": {
							From: &kapi.ObjectReference{
								Kind: "DockerImage",
								Name: "foo/bar:v1",
							},
							Annotations: map[string]string{"an": "annotation"},
						},
					},
				},
				Status: imageapi.ImageStreamStatus{
					Tags: map[string]imageapi.TagEventList{},
				},
			},
			expectedErr: nil,
		},
	}

	for _, test := range tests {
		if err := exporter.Export(test.object, test.exact); err != test.expectedErr {
			t.Errorf("error mismatch: expected %v, got %v", test.expectedErr, err)
		}

		if !reflect.DeepEqual(test.object, test.expectedObj) {
			t.Errorf("object mismatch: expected \n%v\ngot \n%v\n", test.expectedObj, test.object)
		}
	}
}
Example #14
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)
		}
	}
}
Example #15
0
// TestTriggers_MultipleICTs ensures that a deployment config with more than one ImageChange trigger
// will start a new deployment iff all images are resolved.
func TestTriggers_MultipleICTs(t *testing.T) {
	testutil.RequireEtcd(t)
	defer testutil.DumpEtcdOnFailure(t)
	_, clusterAdminKubeConfig, err := testserver.StartTestMaster()
	if err != nil {
		t.Fatalf("error starting master: %v", err)
	}
	openshiftClusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig)
	if err != nil {
		t.Fatalf("error getting cluster admin client: %v", err)
	}
	openshiftClusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
	if err != nil {
		t.Fatalf("error getting cluster admin client config: %v", err)
	}
	openshiftProjectAdminClient, err := testserver.CreateNewProject(openshiftClusterAdminClient, *openshiftClusterAdminClientConfig, testutil.Namespace(), "bob")
	if err != nil {
		t.Fatalf("error creating project: %v", err)
	}

	imageStream := &imageapi.ImageStream{ObjectMeta: kapi.ObjectMeta{Name: deploytest.ImageStreamName}}
	secondImageStream := &imageapi.ImageStream{ObjectMeta: kapi.ObjectMeta{Name: "sample"}}

	config := deploytest.OkDeploymentConfig(0)
	config.Namespace = testutil.Namespace()
	firstTrigger := deploytest.OkImageChangeTrigger()
	secondTrigger := deploytest.OkImageChangeTrigger()
	secondTrigger.ImageChangeParams.ContainerNames = []string{"container2"}
	secondTrigger.ImageChangeParams.From.Name = imageapi.JoinImageStreamTag("sample", imageapi.DefaultImageTag)
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{firstTrigger, secondTrigger}

	configWatch, err := openshiftProjectAdminClient.DeploymentConfigs(testutil.Namespace()).Watch(kapi.ListOptions{})
	if err != nil {
		t.Fatalf("Couldn't subscribe to deploymentconfigs %v", err)
	}
	defer configWatch.Stop()

	if imageStream, err = openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Create(imageStream); err != nil {
		t.Fatalf("Couldn't create imagestream %q: %v", imageStream.Name, err)
	}
	if secondImageStream, err = openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Create(secondImageStream); err != nil {
		t.Fatalf("Couldn't create imagestream %q: %v", secondImageStream.Name, err)
	}

	imageWatch, err := openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Watch(kapi.ListOptions{})
	if err != nil {
		t.Fatalf("Couldn't subscribe to imagestreams: %v", err)
	}
	defer imageWatch.Stop()

	updatedImage := fmt.Sprintf("sha256:%s", deploytest.ImageID)
	updatedPullSpec := fmt.Sprintf("registry:8080/%s/%s@%s", testutil.Namespace(), deploytest.ImageStreamName, updatedImage)

	// Make a function which can create a new tag event for the image stream and
	// then wait for the stream status to be asynchronously updated.
	createTagEvent := func(name, tag, image, pullSpec string) {
		mapping := &imageapi.ImageStreamMapping{
			ObjectMeta: kapi.ObjectMeta{Name: name},
			Tag:        tag,
			Image: imageapi.Image{
				ObjectMeta: kapi.ObjectMeta{
					Name: image,
				},
				DockerImageReference: pullSpec,
			},
		}
		if err := openshiftProjectAdminClient.ImageStreamMappings(testutil.Namespace()).Create(mapping); err != nil {
			t.Fatalf("unexpected error: %v", err)
		}

		t.Log("Waiting for image stream mapping to be reflected in the image stream status...")
	statusLoop:
		for {
			select {
			case event := <-imageWatch.ResultChan():
				stream := event.Object.(*imageapi.ImageStream)
				if stream.Name != name {
					continue
				}
				if _, ok := stream.Status.Tags[tag]; ok {
					t.Logf("imagestream %q now has status with tags: %#v", stream.Name, stream.Status.Tags)
					break statusLoop
				}
				t.Logf("Still waiting for latest tag status on imagestream %q", stream.Name)
			}
		}
	}

	if config, err = openshiftProjectAdminClient.DeploymentConfigs(testutil.Namespace()).Create(config); err != nil {
		t.Fatalf("Couldn't create deploymentconfig: %v", err)
	}

	timeout := time.After(30 * time.Second)

	t.Log("Should not trigger a new deployment in response to the first imagestream update")
	createTagEvent(imageStream.Name, imageapi.DefaultImageTag, updatedImage, updatedPullSpec)
out:
	for {
		select {
		case event := <-configWatch.ResultChan():
			if event.Type != watchapi.Modified {
				continue
			}

			newConfig := event.Object.(*deployapi.DeploymentConfig)
			if newConfig.Status.LatestVersion > 0 {
				t.Fatalf("unexpected latestVersion update: %#v", newConfig)
			}
			container := newConfig.Spec.Template.Spec.Containers[0]
			if e, a := updatedPullSpec, container.Image; e == a {
				break out
			}

		case <-timeout:
			t.Fatalf("timed out waiting for the first image update to happen")
		}
	}

	t.Log("Should trigger a new deployment in response to the second imagestream update")
	updatedImage = "sampleImage"
	updatedPullSpec = "samplePullSpec"
	createTagEvent(secondImageStream.Name, imageapi.DefaultImageTag, updatedImage, updatedPullSpec)
	for {
	inner:
		select {
		case event := <-configWatch.ResultChan():
			if event.Type != watchapi.Modified {
				continue
			}

			newConfig := event.Object.(*deployapi.DeploymentConfig)
			switch {
			case newConfig.Status.LatestVersion == 0:
				t.Logf("Wating for latestVersion to update to 1")
				break inner
			case newConfig.Status.LatestVersion > 1:
				t.Fatalf("unexpected latestVersion %d for %#v", newConfig.Status.LatestVersion, newConfig)
			}

			container := newConfig.Spec.Template.Spec.Containers[1]
			if e, a := updatedPullSpec, container.Image; e != a {
				t.Fatalf("unexpected image for pod template container %q; expected %q, got %q", container.Name, e, a)
			}

			return

		case <-timeout:
			t.Fatalf("timed out waiting for the second image update to happen")
		}
	}
}
Example #16
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)
		}
	}
}
Example #17
0
// TestTriggers_imageChange_nonAutomatic ensures that a deployment config with a non-automatic
// trigger will have its image updated without starting a new deployment.
func TestTriggers_imageChange_nonAutomatic(t *testing.T) {
	testutil.RequireEtcd(t)
	_, clusterAdminKubeConfig, err := testserver.StartTestMaster()
	if err != nil {
		t.Fatalf("error starting master: %v", err)
	}
	openshiftClusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig)
	if err != nil {
		t.Fatalf("error getting cluster admin client: %v", err)
	}
	openshiftClusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
	if err != nil {
		t.Fatalf("error getting cluster admin client config: %v", err)
	}
	openshiftProjectAdminClient, err := testserver.CreateNewProject(openshiftClusterAdminClient, *openshiftClusterAdminClientConfig, testutil.Namespace(), "bob")
	if err != nil {
		t.Fatalf("error creating project: %v", err)
	}

	imageStream := &imageapi.ImageStream{ObjectMeta: kapi.ObjectMeta{Name: deploytest.ImageStreamName}}

	if imageStream, err = openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Create(imageStream); err != nil {
		t.Fatalf("Couldn't create imagestream: %v", err)
	}

	imageWatch, err := openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Watch(kapi.ListOptions{})
	if err != nil {
		t.Fatalf("Couldn't subscribe to imagestreams: %v", err)
	}
	defer imageWatch.Stop()

	image := fmt.Sprintf("sha256:%s", deploytest.ImageID)
	pullSpec := fmt.Sprintf("registry:5000/%s/%s@%s", testutil.Namespace(), deploytest.ImageStreamName, image)
	// Make a function which can create a new tag event for the image stream and
	// then wait for the stream status to be asynchronously updated.
	mapping := &imageapi.ImageStreamMapping{
		ObjectMeta: kapi.ObjectMeta{Name: imageStream.Name},
		Tag:        imageapi.DefaultImageTag,
		Image: imageapi.Image{
			ObjectMeta: kapi.ObjectMeta{
				Name: image,
			},
			DockerImageReference: pullSpec,
		},
	}
	updated := ""

	createTagEvent := func(mapping *imageapi.ImageStreamMapping) {
		if err := openshiftProjectAdminClient.ImageStreamMappings(testutil.Namespace()).Create(mapping); err != nil {
			t.Fatalf("unexpected error: %v", err)
		}

		t.Log("Waiting for image stream mapping to be reflected in the image stream status...")

		for {
			select {
			case event := <-imageWatch.ResultChan():
				stream := event.Object.(*imageapi.ImageStream)
				tagEventList, ok := stream.Status.Tags[imageapi.DefaultImageTag]
				if ok {
					if updated != tagEventList.Items[0].DockerImageReference {
						updated = tagEventList.Items[0].DockerImageReference
						return
					}
				}
				t.Logf("Still waiting for latest tag status update on imagestream %q", stream.Name)
			}
		}
	}

	configWatch, err := openshiftProjectAdminClient.DeploymentConfigs(testutil.Namespace()).Watch(kapi.ListOptions{})
	if err != nil {
		t.Fatalf("Couldn't subscribe to deploymentconfigs: %v", err)
	}
	defer configWatch.Stop()

	config := deploytest.OkDeploymentConfig(0)
	config.Namespace = testutil.Namespace()
	config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{deploytest.OkImageChangeTrigger()}
	config.Spec.Triggers[0].ImageChangeParams.Automatic = false
	if config, err = openshiftProjectAdminClient.DeploymentConfigs(testutil.Namespace()).Create(config); err != nil {
		t.Fatalf("Couldn't create deploymentconfig: %v", err)
	}

	createTagEvent(mapping)

	var newConfig *deployapi.DeploymentConfig
	t.Log("Waiting for the initial deploymentconfig update in response to the imagestream update")

	timeout := time.After(30 * time.Second)

	// This is the initial deployment with automatic=false in its ICT - it should be updated to pullSpec
out:
	for {
		select {
		case event := <-configWatch.ResultChan():
			if event.Type != watchapi.Modified {
				continue
			}

			newConfig = event.Object.(*deployapi.DeploymentConfig)

			if newConfig.Status.LatestVersion > 0 {
				t.Fatalf("unexpected latestVersion update - the config has no config change trigger")
			}

			if e, a := updated, newConfig.Spec.Template.Spec.Containers[0].Image; e == a {
				break out
			}
		case <-timeout:
			t.Fatalf("timed out waiting for the image update to happen")
		}
	}

	t.Log("Waiting for the second imagestream update - it shouldn't update the deploymentconfig")

	// Subsequent updates to the image shouldn't update the pod template image
	mapping.Image.Name = "sha256:thisupdatedimageshouldneverlandinthepodtemplate"
	mapping.Image.DockerImageReference = fmt.Sprintf("registry:8080/%s/%s@%s", testutil.Namespace(), deploytest.ImageStreamName, mapping.Image.Name)
	createTagEvent(mapping)

	for {
		select {
		case event := <-configWatch.ResultChan():
			if event.Type != watchapi.Modified {
				continue
			}

			newConfig = event.Object.(*deployapi.DeploymentConfig)

			if newConfig.Status.LatestVersion > 0 {
				t.Fatalf("unexpected latestVersion update - the config has no config change trigger")
			}

			if e, a := updated, newConfig.Spec.Template.Spec.Containers[0].Image; e == a {
				t.Fatalf("unexpected image update, expected initial image to be the same")
			}
		case <-timeout:
			return
		}
	}
}
func TestGeneration(t *testing.T) {
	from := deploytest.OkDeploymentConfig(2)
	from.Spec.Strategy = deployapi.DeploymentStrategy{
		Type: deployapi.DeploymentStrategyTypeCustom,
	}
	from.Spec.Triggers = append(from.Spec.Triggers, deployapi.DeploymentTriggerPolicy{Type: deployapi.DeploymentTriggerOnConfigChange})
	from.Spec.Triggers = append(from.Spec.Triggers, deploytest.OkImageChangeTrigger())
	from.Spec.Template.Spec.Containers[0].Name = "changed"
	from.Spec.Replicas = 5
	from.Spec.Selector = map[string]string{
		"new1": "new2",
		"new2": "new2",
	}

	to := deploytest.OkDeploymentConfig(1)

	// Generate a rollback for every combination of flag (using 1 bit per flag).
	rollbackSpecs := []*deployapi.DeploymentConfigRollbackSpec{}
	for i := 0; i < 15; i++ {
		spec := &deployapi.DeploymentConfigRollbackSpec{
			From: kapi.ObjectReference{
				Name:      "deployment",
				Namespace: kapi.NamespaceDefault,
			},
			IncludeTriggers:        i&(1<<0) > 0,
			IncludeTemplate:        i&(1<<1) > 0,
			IncludeReplicationMeta: i&(1<<2) > 0,
			IncludeStrategy:        i&(1<<3) > 0,
		}
		rollbackSpecs = append(rollbackSpecs, spec)
	}

	generator := &RollbackGenerator{}

	// Test every combination.
	for _, spec := range rollbackSpecs {
		t.Logf("testing spec %#v", spec)

		if rollback, err := generator.GenerateRollback(from, to, spec); err != nil {
			t.Fatalf("Unexpected error: %v", err)
		} else {
			if hasStrategyDiff(from, rollback) && !spec.IncludeStrategy {
				t.Fatalf("unexpected strategy diff: from=%v, rollback=%v", from, rollback)
			}

			if hasTriggerDiff(from, rollback) && !spec.IncludeTriggers {
				t.Fatalf("unexpected trigger diff: from=%v, rollback=%v", from, rollback)
			}

			if hasPodTemplateDiff(from, rollback) && !spec.IncludeTemplate {
				t.Fatalf("unexpected template diff: from=%v, rollback=%v", from, rollback)
			}

			if hasReplicationMetaDiff(from, rollback) && !spec.IncludeReplicationMeta {
				t.Fatalf("unexpected replication meta diff: from=%v, rollback=%v", from, rollback)
			}

			for i, trigger := range rollback.Spec.Triggers {
				if trigger.Type == deployapi.DeploymentTriggerOnImageChange && trigger.ImageChangeParams.Automatic {
					t.Errorf("image change trigger %d should be disabled", i)
				}
			}
		}
	}
}
Example #19
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)
	}
}