package controller import ( "testing" kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" deployapi "github.com/openshift/origin/pkg/deploy/api" deployapitest "github.com/openshift/origin/pkg/deploy/api/test" deploytest "github.com/openshift/origin/pkg/deploy/controller/test" imageapi "github.com/openshift/origin/pkg/image/api" ) type testIcDeploymentConfigInterface struct { UpdateDeploymentConfigFunc func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) GenerateDeploymentConfigFunc func(namespace, name string) (*deployapi.DeploymentConfig, error) } func (i *testIcDeploymentConfigInterface) UpdateDeploymentConfig(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) { return i.UpdateDeploymentConfigFunc(namespace, config) } func (i *testIcDeploymentConfigInterface) GenerateDeploymentConfig(namespace, name string) (*deployapi.DeploymentConfig, error) { return i.GenerateDeploymentConfigFunc(namespace, name) } const ( nonDefaultNamespace = "nondefaultnamespace" ) func TestUnregisteredContainer(t *testing.T) { config := deployapitest.OkDeploymentConfig(1) config.Triggers[0].ImageChangeParams.ContainerNames = []string{"container-3"} controller := &ImageChangeController{ DeploymentConfigInterface: &testIcDeploymentConfigInterface{ UpdateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) { t.Fatalf("unexpected deployment config update") return nil, nil }, GenerateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) { t.Fatalf("unexpected generator call") return nil, nil }, }, NextImageRepository: func() *imageapi.ImageRepository { return tagUpdate() }, DeploymentConfigStore: deploytest.NewFakeDeploymentConfigStore(config), } // verify no-op controller.HandleImageRepo() } func TestImageChangeForNonAutomaticTag(t *testing.T) { config := deployapitest.OkDeploymentConfig(1) config.Triggers[0].ImageChangeParams.Automatic = false controller := &ImageChangeController{ DeploymentConfigInterface: &testIcDeploymentConfigInterface{ UpdateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) { t.Fatalf("unexpected deployment config update") return nil, nil }, GenerateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) { t.Fatalf("unexpected generator call") return nil, nil }, }, NextImageRepository: func() *imageapi.ImageRepository { return tagUpdate() }, DeploymentConfigStore: deploytest.NewFakeDeploymentConfigStore(config), } // verify no-op controller.HandleImageRepo() } func TestImageChangeForUnregisteredTag(t *testing.T) { config := imageChangeDeploymentConfig() controller := &ImageChangeController{ DeploymentConfigInterface: &testIcDeploymentConfigInterface{ UpdateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) { t.Fatalf("unexpected deployment config update") return nil, nil }, GenerateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) { t.Fatalf("unexpected generator call") return nil, nil }, }, NextImageRepository: func() *imageapi.ImageRepository { imageRepo := tagUpdate() imageRepo.Tags = map[string]string{ "unknown-tag": "ref-1", } return imageRepo }, DeploymentConfigStore: deploytest.NewFakeDeploymentConfigStore(config), } // verify no-op controller.HandleImageRepo() } func TestImageChange(t *testing.T) { var ( generatedConfig *deployapi.DeploymentConfig updatedConfig *deployapi.DeploymentConfig generatedConfigNamespace string updatedConfigNamespace string ) controller := &ImageChangeController{ DeploymentConfigInterface: &testIcDeploymentConfigInterface{ UpdateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) { updatedConfigNamespace = namespace updatedConfig = config return updatedConfig, nil }, GenerateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) { generatedConfigNamespace = namespace generatedConfig = regeneratedConfig(namespace) return generatedConfig, nil }, }, NextImageRepository: func() *imageapi.ImageRepository { return tagUpdate() }, DeploymentConfigStore: deploytest.NewFakeDeploymentConfigStore(imageChangeDeploymentConfig()), } controller.HandleImageRepo() if generatedConfig == nil { t.Fatalf("expected config generation to occur") } if updatedConfig == nil { t.Fatalf("expected an updated deployment config") } else if updatedConfig.Details == nil { t.Fatalf("expected config change details to be set") } else if updatedConfig.Details.Causes == nil { t.Fatalf("expected config change causes to be set") } else if updatedConfig.Details.Causes[0].Type != deployapi.DeploymentTriggerOnImageChange { t.Fatalf("expected ChangeLog details to be set to image change trigger, got %s", updatedConfig.Details.Causes[0].Type) } if generatedConfigNamespace != nonDefaultNamespace { t.Errorf("Expected generatedConfigNamespace %v, got %v", nonDefaultNamespace, generatedConfigNamespace) } if updatedConfigNamespace != nonDefaultNamespace { t.Errorf("Expected updatedConfigNamespace %v, got %v", nonDefaultNamespace, updatedConfigNamespace) } if e, a := updatedConfig.Name, generatedConfig.Name; e != a { t.Fatalf("expected updated config with id %s, got %s", e, a) } if e, a := updatedConfig.Name, generatedConfig.Name; e != a { t.Fatalf("expected updated config with id %s, got %s", e, a) } } // Utilities and convenience methods func originalImageRepo() *imageapi.ImageRepository { return &imageapi.ImageRepository{ ObjectMeta: kapi.ObjectMeta{Name: "test-image-repo", Namespace: nonDefaultNamespace}, DockerImageRepository: "registry:8080/openshift/test-image", Tags: map[string]string{ "test-tag": "ref-1", }, } } func unregisteredTagUpdate() *imageapi.ImageRepository { return &imageapi.ImageRepository{ ObjectMeta: kapi.ObjectMeta{Name: "test-image-repo", Namespace: nonDefaultNamespace}, DockerImageRepository: "registry:8080/openshift/test-image", Tags: map[string]string{ "test-tag": "ref-1", "other-test-tag": "ref-x", }, } } func tagUpdate() *imageapi.ImageRepository { return &imageapi.ImageRepository{ ObjectMeta: kapi.ObjectMeta{Name: "test-image-repo", Namespace: nonDefaultNamespace}, DockerImageRepository: "registry:8080/openshift/test-image", Tags: map[string]string{ "test-tag": "ref-2", }, } } func imageChangeDeploymentConfig() *deployapi.DeploymentConfig { return &deployapi.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "image-change-deploy-config"}, Triggers: []deployapi.DeploymentTriggerPolicy{ { Type: deployapi.DeploymentTriggerOnImageChange, ImageChangeParams: &deployapi.DeploymentTriggerImageChangeParams{ Automatic: true, ContainerNames: []string{"container-1"}, RepositoryName: "registry:8080/openshift/test-image", Tag: "test-tag", }, }, }, Template: deployapi.DeploymentTemplate{ Strategy: deployapi.DeploymentStrategy{ Type: deployapi.DeploymentStrategyTypeRecreate, }, ControllerTemplate: kapi.ReplicationControllerSpec{ Replicas: 1, Selector: map[string]string{ "name": "test-pod", }, Template: &kapi.PodTemplateSpec{ ObjectMeta: kapi.ObjectMeta{ Labels: map[string]string{ "name": "test-pod", }, }, Spec: kapi.PodSpec{ Containers: []kapi.Container{ { Name: "container-1", Image: "registry:8080/openshift/test-image:ref-1", }, }, }, }, }, }, } } func regeneratedConfig(namespace string) *deployapi.DeploymentConfig { return &deployapi.DeploymentConfig{ ObjectMeta: kapi.ObjectMeta{Name: "image-change-deploy-config", Namespace: namespace}, Triggers: []deployapi.DeploymentTriggerPolicy{ { Type: deployapi.DeploymentTriggerOnImageChange, ImageChangeParams: &deployapi.DeploymentTriggerImageChangeParams{ Automatic: true, ContainerNames: []string{"container-1"}, RepositoryName: "registry:8080/openshift/test-image", Tag: "test-tag", }, }, }, Template: deployapi.DeploymentTemplate{ Strategy: deployapi.DeploymentStrategy{ Type: deployapi.DeploymentStrategyTypeRecreate, }, ControllerTemplate: kapi.ReplicationControllerSpec{ Replicas: 1, Selector: map[string]string{ "name": "test-pod", }, Template: &kapi.PodTemplateSpec{ ObjectMeta: kapi.ObjectMeta{ Labels: map[string]string{ "name": "test-pod", }, }, Spec: kapi.PodSpec{ Containers: []kapi.Container{ { Name: "container-1", Image: "registry:8080/openshift/test-image:ref-2", }, }, }, }, }, }, } } func unregisteredConfig() *deployapi.DeploymentConfig { d := imageChangeDeploymentConfig() d.Triggers[0].ImageChangeParams.ContainerNames = []string{"container-3"} return d }