package imagechange import ( "flag" "testing" kapi "k8s.io/kubernetes/pkg/api" deployapi "github.com/openshift/origin/pkg/deploy/api" deployapitest "github.com/openshift/origin/pkg/deploy/api/test" imageapi "github.com/openshift/origin/pkg/image/api" ) func init() { flag.Set("v", "5") } // TestHandle_changeForNonAutomaticTag ensures that an image update for which // there is a matching trigger results in a no-op due to the trigger's // automatic flag being set to false. func TestHandle_changeForNonAutomaticTag(t *testing.T) { controller := &ImageChangeController{ deploymentConfigClient: &deploymentConfigClientImpl{ updateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) { t.Fatalf("unexpected DeploymentConfig update") return nil, nil }, generateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) { t.Fatalf("unexpected generator call") return nil, nil }, listDeploymentConfigsFunc: func() ([]*deployapi.DeploymentConfig, error) { config := deployapitest.OkDeploymentConfig(1) config.Spec.Triggers[0].ImageChangeParams.Automatic = false return []*deployapi.DeploymentConfig{config}, nil }, }, } // verify no-op tagUpdate := makeRepo( "test-image-repo", imageapi.DefaultImageTag, "registry:8080/openshift/test-image@sha256:00000000000000000000000000000001", "00000000000000000000000000000001", ) err := controller.Handle(tagUpdate) if err != nil { t.Fatalf("unexpected err: %v", err) } } // TestHandle_changeForUnregisteredTag ensures that an image update for which // there is a matching trigger results in a no-op due to the tag specified on // the trigger not matching the tags defined on the image repo. func TestHandle_changeForUnregisteredTag(t *testing.T) { controller := &ImageChangeController{ deploymentConfigClient: &deploymentConfigClientImpl{ updateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) { t.Fatalf("unexpected DeploymentConfig update") return nil, nil }, generateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) { t.Fatalf("unexpected generator call") return nil, nil }, listDeploymentConfigsFunc: func() ([]*deployapi.DeploymentConfig, error) { return []*deployapi.DeploymentConfig{deployapitest.OkDeploymentConfig(0)}, nil }, }, } // verify no-op imageRepo := makeRepo( "test-image-repo", "unrecognized", "registry:8080/openshift/test-image@sha256:00000000000000000000000000000001", "00000000000000000000000000000001", ) err := controller.Handle(imageRepo) if err != nil { t.Fatalf("unexpected err: %v", err) } } // TestHandle_matchScenarios comprehensively tests trigger definitions against // image repo updates to ensure that the image change triggers match (or don't // match) properly. func TestHandle_matchScenarios(t *testing.T) { params := map[string]*deployapi.DeploymentTriggerImageChangeParams{ "params.1": { Automatic: true, ContainerNames: []string{"container-1"}, From: kapi.ObjectReference{Namespace: kapi.NamespaceDefault, Name: imageapi.JoinImageStreamTag("repoA", imageapi.DefaultImageTag)}, LastTriggeredImage: "", }, "params.2": { Automatic: true, ContainerNames: []string{"container-1"}, From: kapi.ObjectReference{Name: imageapi.JoinImageStreamTag("repoA", imageapi.DefaultImageTag)}, LastTriggeredImage: "", }, "params.3": { Automatic: false, ContainerNames: []string{"container-1"}, From: kapi.ObjectReference{Namespace: kapi.NamespaceDefault, Name: imageapi.JoinImageStreamTag("repoA", imageapi.DefaultImageTag)}, LastTriggeredImage: "", }, "params.4": { Automatic: true, ContainerNames: []string{"container-1"}, From: kapi.ObjectReference{Name: imageapi.JoinImageStreamTag("repoA", imageapi.DefaultImageTag)}, LastTriggeredImage: "registry:8080/openshift/test-image@sha256:00000000000000000000000000000001", }, "params.5": { Automatic: true, ContainerNames: []string{"container-1"}, From: kapi.ObjectReference{Namespace: kapi.NamespaceDefault, Name: imageapi.JoinImageStreamTag("repoC", imageapi.DefaultImageTag)}, LastTriggeredImage: "", }, } tagHistoryFor := func(tag, dir, image string) map[string]imageapi.TagEventList { return map[string]imageapi.TagEventList{ tag: { Items: []imageapi.TagEvent{ { DockerImageReference: dir, Image: image, }, }, }, } } updates := map[string]*imageapi.ImageStream{ "update.1": { ObjectMeta: kapi.ObjectMeta{Name: "repoA", Namespace: kapi.NamespaceDefault}, Status: imageapi.ImageStreamStatus{ Tags: tagHistoryFor( imageapi.DefaultImageTag, "registry:8080/openshift/test-image@sha256:00000000000000000000000000000001", "00000000000000000000000000000001", ), }, }, } scenarios := []struct { param string repo string matches bool }{ // Update from empty last image ID to a new one with explicit namespaces {"params.1", "update.1", true}, // Update from empty last image ID to a new one with implicit namespaces {"params.2", "update.1", true}, // Update from empty last image ID to a new one, but not marked automatic {"params.3", "update.1", false}, // Updated image ID is equal to the last triggered ID {"params.4", "update.1", false}, // Trigger repo reference doesn't match {"params.5", "update.1", false}, } for _, s := range scenarios { config := deployapitest.OkDeploymentConfig(0) config.Namespace = kapi.NamespaceDefault config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{ { Type: deployapi.DeploymentTriggerOnImageChange, ImageChangeParams: params[s.param], }, } updated := false generated := false controller := &ImageChangeController{ deploymentConfigClient: &deploymentConfigClientImpl{ updateDeploymentConfigFunc: func(namespace string, config *deployapi.DeploymentConfig) (*deployapi.DeploymentConfig, error) { if !s.matches { t.Fatalf("unexpected DeploymentConfig update for scenario: %v", s) } updated = true return config, nil }, generateDeploymentConfigFunc: func(namespace, name string) (*deployapi.DeploymentConfig, error) { if !s.matches { t.Fatalf("unexpected generator call for scenario: %v", s) } generated = true // simulate a generation newConfig := deployapitest.OkDeploymentConfig(config.Status.LatestVersion + 1) newConfig.Namespace = config.Namespace newConfig.Spec.Triggers = config.Spec.Triggers return newConfig, nil }, listDeploymentConfigsFunc: func() ([]*deployapi.DeploymentConfig, error) { return []*deployapi.DeploymentConfig{config}, nil }, }, } t.Logf("running scenario: %v", s) err := controller.Handle(updates[s.repo]) if err != nil { t.Fatalf("unexpected error for scenario %v: %v", s, err) } // assert updates/generations occurred if s.matches && !updated { t.Fatalf("expected update for scenario: %v", s) } if s.matches && !generated { t.Fatalf("expected generation for scenario: %v", s) } } } func makeRepo(name, tag, dir, image string) *imageapi.ImageStream { return &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: name}, Status: imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ tag: { Items: []imageapi.TagEvent{ { DockerImageReference: dir, Image: image, }, }, }, }, }, } }