func TestSubstituteImageCustomBaseMatchEnvMissing(t *testing.T) { source := mocks.MockSource() strategy := mockCustomStrategyForImageRepository() output := mocks.MockOutput() bc := mocks.MockBuildConfig(source, strategy, output) generator := mockBuildGenerator() build, err := generator.generateBuildFromConfig(kapi.NewContext(), bc, nil, nil) if err != nil { t.Fatalf("Unexpected error %v", err) } // Custom build with a base Image but no image environment variable. // base image should be replaced, new image environment variable should be added, // existing environment variable should be untouched build.Spec.Strategy.CustomStrategy.Env = make([]kapi.EnvVar, 1) build.Spec.Strategy.CustomStrategy.Env[0] = kapi.EnvVar{Name: "someImage", Value: originalImage} updateCustomImageEnv(build.Spec.Strategy.CustomStrategy, newImage) if build.Spec.Strategy.CustomStrategy.Env[0].Value != originalImage { t.Errorf("Random env variable was improperly substituted in custom strategy") } if build.Spec.Strategy.CustomStrategy.Env[1].Name != buildapi.CustomBuildStrategyBaseImageKey || build.Spec.Strategy.CustomStrategy.Env[1].Value != newImage { t.Errorf("Image env variable was not added in custom strategy %s %s |", build.Spec.Strategy.CustomStrategy.Env[1].Name, build.Spec.Strategy.CustomStrategy.Env[1].Value) } if c := len(build.Spec.Strategy.CustomStrategy.Env); c != 2 { t.Errorf("Expected %d, found %d environment variables", 2, c) } }
func TestSubstituteImageCustomAllMatch(t *testing.T) { source := mocks.MockSource() strategy := mockCustomStrategyForDockerImage(originalImage) output := mocks.MockOutput() bc := mocks.MockBuildConfig(source, strategy, output) generator := mockBuildGenerator() build, err := generator.generateBuildFromConfig(kapi.NewContext(), bc, nil, nil) if err != nil { t.Fatalf("Unexpected error %v", err) } // Full custom build with a Image and a well defined environment variable image value, // both should be replaced. Additional environment variables should not be touched. build.Spec.Strategy.CustomStrategy.Env = make([]kapi.EnvVar, 2) build.Spec.Strategy.CustomStrategy.Env[0] = kapi.EnvVar{Name: "someImage", Value: originalImage} build.Spec.Strategy.CustomStrategy.Env[1] = kapi.EnvVar{Name: buildapi.CustomBuildStrategyBaseImageKey, Value: originalImage} updateCustomImageEnv(build.Spec.Strategy.CustomStrategy, newImage) if build.Spec.Strategy.CustomStrategy.Env[0].Value != originalImage { t.Errorf("Random env variable %s was improperly substituted in custom strategy", build.Spec.Strategy.CustomStrategy.Env[0].Name) } if build.Spec.Strategy.CustomStrategy.Env[1].Value != newImage { t.Errorf("Image env variable was not properly substituted in custom strategy") } if c := len(build.Spec.Strategy.CustomStrategy.Env); c != 2 { t.Errorf("Expected %d, found %d environment variables", 2, c) } if bc.Spec.Strategy.CustomStrategy.From.Name != originalImage { t.Errorf("Custom BuildConfig Image was updated when Build was modified %s!=%s", bc.Spec.Strategy.CustomStrategy.From.Name, originalImage) } if len(bc.Spec.Strategy.CustomStrategy.Env) != 0 { t.Errorf("Custom BuildConfig Env was updated when Build was modified") } }
func TestGenerateBuildFromBuild(t *testing.T) { source := mocks.MockSource() strategy := mockDockerStrategyForImageRepository() output := mocks.MockOutput() build := &buildapi.Build{ ObjectMeta: kapi.ObjectMeta{ Name: "test-build", }, Spec: buildapi.BuildSpec{ Source: source, Revision: &buildapi.SourceRevision{ Git: &buildapi.GitSourceRevision{ Commit: "1234", }, }, Strategy: strategy, Output: output, }, } newBuild := generateBuildFromBuild(build, nil) if !reflect.DeepEqual(build.Spec, newBuild.Spec) { t.Errorf("Build parameters does not match the original Build parameters") } if !reflect.DeepEqual(build.ObjectMeta.Labels, newBuild.ObjectMeta.Labels) { t.Errorf("Build labels does not match the original Build labels") } }
func TestSubstituteImageCustomBaseMatchEnvMismatch(t *testing.T) { source := mocks.MockSource() strategy := mockCustomStrategyForImageRepository() output := mocks.MockOutput() bc := mocks.MockBuildConfig(source, strategy, output) generator := mockBuildGenerator() build, err := generator.generateBuildFromConfig(kapi.NewContext(), bc, nil, nil) if err != nil { t.Fatalf("Unexpected error %v", err) } // Full custom build with a Image and a well defined environment variable image value that does not match the new image // Environment variables should not be updated. build.Spec.Strategy.CustomStrategy.Env = make([]kapi.EnvVar, 2) build.Spec.Strategy.CustomStrategy.Env[0] = kapi.EnvVar{Name: "someEnvVar", Value: originalImage} build.Spec.Strategy.CustomStrategy.Env[1] = kapi.EnvVar{Name: buildapi.CustomBuildStrategyBaseImageKey, Value: "dummy"} updateCustomImageEnv(build.Spec.Strategy.CustomStrategy, newImage) if build.Spec.Strategy.CustomStrategy.Env[0].Value != originalImage { t.Errorf("Random env variable %s was improperly substituted in custom strategy", build.Spec.Strategy.CustomStrategy.Env[0].Name) } if build.Spec.Strategy.CustomStrategy.Env[1].Value != newImage { t.Errorf("Image env variable was not substituted in custom strategy") } if c := len(build.Spec.Strategy.CustomStrategy.Env); c != 2 { t.Errorf("Expected %d, found %d environment variables", 2, c) } }
func TestSubstituteImageCustomAllMismatch(t *testing.T) { source := mocks.MockSource() strategy := mockCustomStrategyForDockerImage(originalImage) output := mocks.MockOutput() bc := mocks.MockBuildConfig(source, strategy, output) generator := mockBuildGenerator() build, err := generator.generateBuildFromConfig(kapi.NewContext(), bc, nil, nil) if err != nil { t.Fatalf("Unexpected error %v", err) } // Full custom build with base image that is not matched // Base image name should be unchanged updateCustomImageEnv(build.Spec.Strategy.CustomStrategy, "dummy") if build.Spec.Strategy.CustomStrategy.From.Name != originalImage { t.Errorf("Base image name was improperly substituted in custom strategy %s %s", build.Spec.Strategy.CustomStrategy.From.Name, originalImage) } }
func TestSubstituteImageCustomBaseMatchEnvNil(t *testing.T) { source := mocks.MockSource() strategy := mockCustomStrategyForImageRepository() output := mocks.MockOutput() bc := mocks.MockBuildConfig(source, strategy, output) generator := mockBuildGenerator() build, err := generator.generateBuildFromConfig(kapi.NewContext(), bc, nil, nil) if err != nil { t.Fatalf("Unexpected error %v", err) } // Custom build with a base Image but no environment variables // base image should be replaced, new image environment variable should be added updateCustomImageEnv(build.Spec.Strategy.CustomStrategy, newImage) if build.Spec.Strategy.CustomStrategy.Env[0].Name != buildapi.CustomBuildStrategyBaseImageKey || build.Spec.Strategy.CustomStrategy.Env[0].Value != newImage { t.Errorf("New image name variable was not added to environment list in custom strategy") } if c := len(build.Spec.Strategy.CustomStrategy.Env); c != 1 { t.Errorf("Expected %d, found %d environment variables", 1, c) } }
func TestCreateInstantiate(t *testing.T) { imageStream := mocks.MockImageStream("testImageStream", "registry.com/namespace/imagename", map[string]string{"test": "newImageID123"}) image := mocks.MockImage("testImage@id", "registry.com/namespace/imagename@id") fakeSecrets := []runtime.Object{} for _, s := range mocks.MockBuilderSecrets() { fakeSecrets = append(fakeSecrets, s) } rest := InstantiateREST{&generator.BuildGenerator{ Secrets: testclient.NewSimpleFake(fakeSecrets...), ServiceAccounts: mocks.MockBuilderServiceAccount(mocks.MockBuilderSecrets()), Client: generator.Client{ GetBuildConfigFunc: func(ctx kapi.Context, name string) (*buildapi.BuildConfig, error) { return mocks.MockBuildConfig(mocks.MockSource(), mocks.MockSourceStrategyForImageRepository(), mocks.MockOutput()), nil }, UpdateBuildConfigFunc: func(ctx kapi.Context, buildConfig *buildapi.BuildConfig) error { return nil }, CreateBuildFunc: func(ctx kapi.Context, build *buildapi.Build) error { return nil }, GetBuildFunc: func(ctx kapi.Context, name string) (*buildapi.Build, error) { return &buildapi.Build{}, nil }, GetImageStreamFunc: func(ctx kapi.Context, name string) (*imageapi.ImageStream, error) { return imageStream, nil }, GetImageStreamTagFunc: func(ctx kapi.Context, name string) (*imageapi.ImageStreamTag, error) { return &imageapi.ImageStreamTag{Image: *image}, nil }, GetImageStreamImageFunc: func(ctx kapi.Context, name string) (*imageapi.ImageStreamImage, error) { return &imageapi.ImageStreamImage{Image: *image}, nil }, }}} _, err := rest.Create(kapi.NewDefaultContext(), &buildapi.BuildRequest{ObjectMeta: kapi.ObjectMeta{Name: "name"}}) if err != nil { t.Errorf("Unexpected error %v", err) } }
func TestGenerateBuildFromBuildWithBuildConfig(t *testing.T) { source := mocks.MockSource() strategy := mockDockerStrategyForImageRepository() output := mocks.MockOutput() annotatedBuild := &buildapi.Build{ ObjectMeta: kapi.ObjectMeta{ Name: "annotatedBuild", Annotations: map[string]string{ buildapi.BuildCloneAnnotation: "sourceOfBuild", }, }, Spec: buildapi.BuildSpec{ Source: source, Revision: &buildapi.SourceRevision{ Git: &buildapi.GitSourceRevision{ Commit: "1234", }, }, Strategy: strategy, Output: output, }, } nonAnnotatedBuild := &buildapi.Build{ ObjectMeta: kapi.ObjectMeta{ Name: "nonAnnotatedBuild", }, Spec: buildapi.BuildSpec{ Source: source, Revision: &buildapi.SourceRevision{ Git: &buildapi.GitSourceRevision{ Commit: "1234", }, }, Strategy: strategy, Output: output, }, } buildConfig := &buildapi.BuildConfig{ ObjectMeta: kapi.ObjectMeta{ Name: "buildConfigName", }, Status: buildapi.BuildConfigStatus{ LastVersion: 5, }, } newBuild := generateBuildFromBuild(annotatedBuild, buildConfig) if !reflect.DeepEqual(annotatedBuild.Spec, newBuild.Spec) { t.Errorf("Build parameters does not match the original Build parameters") } if !reflect.DeepEqual(annotatedBuild.ObjectMeta.Labels, newBuild.ObjectMeta.Labels) { t.Errorf("Build labels does not match the original Build labels") } if newBuild.Annotations[buildapi.BuildNumberAnnotation] != "6" { t.Errorf("Build number annotation is %s expected %s", newBuild.Annotations[buildapi.BuildNumberAnnotation], "6") } if newBuild.Annotations[buildapi.BuildCloneAnnotation] != "annotatedBuild" { t.Errorf("Build number annotation is %s expected %s", newBuild.Annotations[buildapi.BuildCloneAnnotation], "annotatedBuild") } newBuild = generateBuildFromBuild(nonAnnotatedBuild, buildConfig) if !reflect.DeepEqual(nonAnnotatedBuild.Spec, newBuild.Spec) { t.Errorf("Build parameters does not match the original Build parameters") } if !reflect.DeepEqual(nonAnnotatedBuild.ObjectMeta.Labels, newBuild.ObjectMeta.Labels) { t.Errorf("Build labels does not match the original Build labels") } // was incremented by previous test, so expect 7 now. if newBuild.Annotations[buildapi.BuildNumberAnnotation] != "7" { t.Errorf("Build number annotation is %s expected %s", newBuild.Annotations[buildapi.BuildNumberAnnotation], "7") } if newBuild.Annotations[buildapi.BuildCloneAnnotation] != "nonAnnotatedBuild" { t.Errorf("Build number annotation is %s expected %s", newBuild.Annotations[buildapi.BuildCloneAnnotation], "nonAnnotatedBuild") } }
func TestGenerateBuildWithImageTagForCustomStrategyImageRepository(t *testing.T) { source := mocks.MockSource() strategy := mockCustomStrategyForImageRepository() output := mocks.MockOutput() bc := &buildapi.BuildConfig{ ObjectMeta: kapi.ObjectMeta{ Name: "test-build-config", }, Spec: buildapi.BuildConfigSpec{ BuildSpec: buildapi.BuildSpec{ Source: source, Revision: &buildapi.SourceRevision{ Git: &buildapi.GitSourceRevision{ Commit: "1234", }, }, Strategy: strategy, Output: output, }, }, } fakeSecrets := []runtime.Object{} for _, s := range mocks.MockBuilderSecrets() { fakeSecrets = append(fakeSecrets, s) } generator := BuildGenerator{ Secrets: testclient.NewSimpleFake(fakeSecrets...), ServiceAccounts: mocks.MockBuilderServiceAccount(mocks.MockBuilderSecrets()), Client: Client{ GetImageStreamFunc: func(ctx kapi.Context, name string) (*imageapi.ImageStream, error) { return &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: imageRepoName}, Status: imageapi.ImageStreamStatus{ DockerImageRepository: originalImage, Tags: map[string]imageapi.TagEventList{ tagName: { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("%s:%s", originalImage, newTag), Image: newTag, }, }, }, }, }, }, nil }, GetImageStreamTagFunc: func(ctx kapi.Context, name string) (*imageapi.ImageStreamTag, error) { return &imageapi.ImageStreamTag{ Image: imageapi.Image{ ObjectMeta: kapi.ObjectMeta{Name: imageRepoName + ":" + newTag}, DockerImageReference: originalImage + ":" + newTag, }, }, nil }, GetImageStreamImageFunc: func(ctx kapi.Context, name string) (*imageapi.ImageStreamImage, error) { return &imageapi.ImageStreamImage{ Image: imageapi.Image{ ObjectMeta: kapi.ObjectMeta{Name: imageRepoName + ":@id"}, DockerImageReference: originalImage + ":" + newTag, }, }, nil }, UpdateBuildConfigFunc: func(ctx kapi.Context, buildConfig *buildapi.BuildConfig) error { return nil }, }} build, err := generator.generateBuildFromConfig(kapi.NewContext(), bc, nil, nil) if err != nil { t.Fatalf("Unexpected error %v", err) } if build.Spec.Strategy.CustomStrategy.From.Name != newImage { t.Errorf("Custom base image value %s does not match expected value %s", build.Spec.Strategy.CustomStrategy.From.Name, newImage) } }
func TestGenerateBuildFromConfig(t *testing.T) { source := mocks.MockSource() strategy := mockDockerStrategyForDockerImage(originalImage) output := mocks.MockOutput() resources := mockResources() bc := &buildapi.BuildConfig{ ObjectMeta: kapi.ObjectMeta{ Name: "test-build-config", Namespace: "test-namespace", Labels: map[string]string{"testlabel": "testvalue"}, }, Spec: buildapi.BuildConfigSpec{ BuildSpec: buildapi.BuildSpec{ Source: source, Revision: &buildapi.SourceRevision{ Git: &buildapi.GitSourceRevision{ Commit: "1234", }, }, Strategy: strategy, Output: output, Resources: resources, }, }, Status: buildapi.BuildConfigStatus{ LastVersion: 12, }, } revision := &buildapi.SourceRevision{ Git: &buildapi.GitSourceRevision{ Commit: "abcd", }, } generator := mockBuildGenerator() build, err := generator.generateBuildFromConfig(kapi.NewContext(), bc, revision, nil) if err != nil { t.Fatalf("Unexpected error %v", err) } if !reflect.DeepEqual(source, build.Spec.Source) { t.Errorf("Build source does not match BuildConfig source") } // FIXME: This is disabled because the strategies does not match since we plug the // pullSecret into the build strategy. /* if !reflect.DeepEqual(strategy, build.Spec.Strategy) { t.Errorf("Build strategy does not match BuildConfig strategy %+v != %+v", strategy.DockerStrategy, build.Spec.Strategy.DockerStrategy) } */ if !reflect.DeepEqual(output, build.Spec.Output) { t.Errorf("Build output does not match BuildConfig output") } if !reflect.DeepEqual(revision, build.Spec.Revision) { t.Errorf("Build revision does not match passed in revision") } if !reflect.DeepEqual(resources, build.Spec.Resources) { t.Errorf("Build resources does not match passed in resources") } if build.Labels["testlabel"] != bc.Labels["testlabel"] { t.Errorf("Build does not contain labels from BuildConfig") } if build.Labels[buildapi.BuildConfigLabel] != bc.Name { t.Errorf("Build does not contain labels from BuildConfig") } if build.Labels[buildapi.BuildConfigLabelDeprecated] != bc.Name { t.Errorf("Build does not contain labels from BuildConfig") } if build.Status.Config.Name != bc.Name || build.Status.Config.Namespace != bc.Namespace || build.Status.Config.Kind != "BuildConfig" { t.Errorf("Build does not contain correct BuildConfig reference: %v", build.Status.Config) } if build.Annotations[buildapi.BuildNumberAnnotation] != "13" { t.Errorf("Build number annotation value %s does not match expected value 13", build.Annotations[buildapi.BuildNumberAnnotation]) } }
func TestInstantiateWithLastVersion(t *testing.T) { g := mockBuildGenerator() c := g.Client.(Client) c.GetBuildConfigFunc = func(ctx kapi.Context, name string) (*buildapi.BuildConfig, error) { bc := mocks.MockBuildConfig(mocks.MockSource(), mocks.MockSourceStrategyForImageRepository(), mocks.MockOutput()) bc.Status.LastVersion = 1 return bc, nil } g.Client = c // Version not specified _, err := g.Instantiate(kapi.NewDefaultContext(), &buildapi.BuildRequest{}) if err != nil { t.Errorf("Unexpected error %v", err) } // Version specified and it matches lastVersion := 1 _, err = g.Instantiate(kapi.NewDefaultContext(), &buildapi.BuildRequest{LastVersion: &lastVersion}) if err != nil { t.Errorf("Unexpected error %v", err) } // Version specified, but doesn't match lastVersion = 0 _, err = g.Instantiate(kapi.NewDefaultContext(), &buildapi.BuildRequest{LastVersion: &lastVersion}) if err == nil { t.Errorf("Expected an error and did not get one") } }
func mockBuildGenerator() *BuildGenerator { fakeSecrets := []runtime.Object{} for _, s := range mocks.MockBuilderSecrets() { fakeSecrets = append(fakeSecrets, s) } return &BuildGenerator{ Secrets: testclient.NewSimpleFake(fakeSecrets...), ServiceAccounts: mocks.MockBuilderServiceAccount(mocks.MockBuilderSecrets()), Client: Client{ GetBuildConfigFunc: func(ctx kapi.Context, name string) (*buildapi.BuildConfig, error) { return mocks.MockBuildConfig(mocks.MockSource(), mocks.MockSourceStrategyForImageRepository(), mocks.MockOutput()), nil }, UpdateBuildConfigFunc: func(ctx kapi.Context, buildConfig *buildapi.BuildConfig) error { return nil }, CreateBuildFunc: func(ctx kapi.Context, build *buildapi.Build) error { return nil }, GetBuildFunc: func(ctx kapi.Context, name string) (*buildapi.Build, error) { return &buildapi.Build{}, nil }, GetImageStreamFunc: func(ctx kapi.Context, name string) (*imageapi.ImageStream, error) { if name != imageRepoName { return &imageapi.ImageStream{}, nil } return &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Name: imageRepoName, Namespace: imageRepoNamespace, }, Status: imageapi.ImageStreamStatus{ DockerImageRepository: "repo/namespace/image", Tags: map[string]imageapi.TagEventList{ tagName: { Items: []imageapi.TagEvent{ {DockerImageReference: dockerReference}, }, }, imageapi.DefaultImageTag: { Items: []imageapi.TagEvent{ {DockerImageReference: latestDockerReference}, }, }, }, }, }, nil }, GetImageStreamTagFunc: func(ctx kapi.Context, name string) (*imageapi.ImageStreamTag, error) { return &imageapi.ImageStreamTag{ Image: imageapi.Image{ ObjectMeta: kapi.ObjectMeta{Name: imageRepoName + ":" + newTag}, DockerImageReference: latestDockerReference, }, }, nil }, GetImageStreamImageFunc: func(ctx kapi.Context, name string) (*imageapi.ImageStreamImage, error) { return &imageapi.ImageStreamImage{ Image: imageapi.Image{ ObjectMeta: kapi.ObjectMeta{Name: imageRepoName + ":@id"}, DockerImageReference: latestDockerReference, }, }, nil }, }} }
func TestGetNextBuildName(t *testing.T) { bc := mocks.MockBuildConfig(mocks.MockSource(), mocks.MockSourceStrategyForImageRepository(), mocks.MockOutput()) if expected, actual := bc.Name+"-1", getNextBuildName(bc); expected != actual { t.Errorf("Wrong buildName, expected %s, got %s", expected, actual) } if expected, actual := 1, bc.Status.LastVersion; expected != actual { t.Errorf("Wrong version, expected %d, got %d", expected, actual) } }
func TestInstantiateWithLabelsAndAnnotations(t *testing.T) { g := mockBuildGenerator() c := g.Client.(Client) c.GetBuildConfigFunc = func(ctx kapi.Context, name string) (*buildapi.BuildConfig, error) { bc := mocks.MockBuildConfig(mocks.MockSource(), mocks.MockSourceStrategyForImageRepository(), mocks.MockOutput()) bc.Status.LastVersion = 1 return bc, nil } g.Client = c req := &buildapi.BuildRequest{ ObjectMeta: kapi.ObjectMeta{ Annotations: map[string]string{ "a_1": "a_value1", // build number is set as an annotation on the generated build, so we // shouldn't be able to ovewrite it here. buildapi.BuildNumberAnnotation: "bad_annotation", }, Labels: map[string]string{ "l_1": "l_value1", // testbclabel is defined as a label on the mockBuildConfig so we shouldn't // be able to overwrite it here. "testbclabel": "bad_label", }, }, } build, err := g.Instantiate(kapi.NewDefaultContext(), req) if err != nil { t.Errorf("Unexpected error %v", err) } if build.Annotations["a_1"] != "a_value1" || build.Annotations[buildapi.BuildNumberAnnotation] == "bad_annotation" { t.Errorf("Build annotations were merged incorrectly: %v", build.Annotations) } if build.Labels["l_1"] != "l_value1" || build.Labels[buildapi.BuildLabel] == "bad_label" { t.Errorf("Build labels were merged incorrectly: %v", build.Labels) } }