Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

oc: ConfigMap build sources #20064

Merged
merged 1 commit into from
Jul 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions contrib/completions/bash/oc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions contrib/completions/zsh/oc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pkg/oc/cli/cmd/newbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ var (
# Create a build config from a remote repository and inject the npmrc into a build
%[1]s %[2]s https://github.com/openshift/ruby-hello-world --build-secret npmrc:.npmrc

# Create a build config from a remote repository and inject environment data into a build
%[1]s %[2]s https://github.com/openshift/ruby-hello-world --build-config-map env:config

# Create a build config that gets its input from a remote repository and another Docker image
%[1]s %[2]s https://github.com/openshift/ruby-hello-world --source-image=openshift/jenkins-1-centos7 --source-image-path=/var/lib/jenkins:tmp`)

Expand Down Expand Up @@ -111,6 +114,7 @@ func NewCmdNewBuild(name, baseName string, f kcmdutil.Factory, in io.Reader, out
cmd.Flags().MarkDeprecated("image", "use --image-stream instead")
cmd.Flags().StringSliceVarP(&config.ImageStreams, "image-stream", "i", config.ImageStreams, "Name of an image stream to to use as a builder.")
cmd.Flags().StringSliceVar(&config.DockerImages, "docker-image", config.DockerImages, "Name of a Docker image to use as a builder.")
cmd.Flags().StringSliceVar(&config.ConfigMaps, "build-config-map", config.ConfigMaps, "ConfigMap and destination to use as an input for the build.")
cmd.Flags().StringSliceVar(&config.Secrets, "build-secret", config.Secrets, "Secret and destination to use as an input for the build.")
cmd.Flags().StringVar(&config.SourceSecret, "source-secret", "", "The name of an existing secret that should be used for cloning a private git repository.")
cmd.Flags().StringVar(&config.PushSecret, "push-secret", "", "The name of an existing secret that should be used for pushing the output image.")
Expand Down
8 changes: 8 additions & 0 deletions pkg/oc/cli/describe/describer.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,14 @@ func describeCommonSpec(p buildapi.CommonSpec, out *tabwriter.Writer) {
}
formatString(out, "Build Secrets", strings.Join(result, ","))
}
if len(p.Source.ConfigMaps) > 0 {
result := []string{}
for _, c := range p.Source.ConfigMaps {
result = append(result, fmt.Sprintf("%s->%s", c.ConfigMap.Name, filepath.Clean(c.DestinationDir)))
}
formatString(out, "Build ConfigMaps", strings.Join(result, ","))
}

if len(p.Source.Images) == 1 && len(p.Source.Images[0].Paths) == 1 {
noneType = false
image := p.Source.Images[0]
Expand Down
2 changes: 2 additions & 0 deletions pkg/oc/generate/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ type SourceRef struct {
Name string
ContextDir string
Secrets []buildapi.SecretBuildSource
ConfigMaps []buildapi.ConfigMapBuildSource

SourceImage *ImageRef
ImageSourcePath string
Expand Down Expand Up @@ -153,6 +154,7 @@ func (r *SourceRef) BuildSource() (*buildapi.BuildSource, []buildapi.BuildTrigge
}
source := &buildapi.BuildSource{}
source.Secrets = r.Secrets
source.ConfigMaps = r.ConfigMaps

if len(r.DockerfileContents) != 0 {
source.Dockerfile = &r.DockerfileContents
Expand Down
20 changes: 20 additions & 0 deletions pkg/oc/generate/app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,26 @@ func TestBuildConfigWithSecrets(t *testing.T) {
}
}

func TestBuildConfigWithConfigMaps(t *testing.T) {
url, err := git.Parse("https://github.com/openshift/origin.git")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
source := &SourceRef{URL: url, ConfigMaps: []buildapi.ConfigMapBuildSource{
{ConfigMap: kapi.LocalObjectReference{Name: "foo"}, DestinationDir: "/var"},
{ConfigMap: kapi.LocalObjectReference{Name: "bar"}},
}}
build := &BuildRef{Source: source}
config, err := build.BuildConfig()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
configMaps := config.Spec.Source.ConfigMaps
if got := len(configMaps); got != 2 {
t.Errorf("expected 2 source configMaps in build config, got %d", got)
}
}

func TestBuildConfigBinaryWithImageSource(t *testing.T) {
source := &SourceRef{
Name: "binarybuild",
Expand Down
46 changes: 45 additions & 1 deletion pkg/oc/generate/app/sourcelookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ type SourceRepository struct {
remoteURL *s2igit.URL
contextDir string
secrets []buildapi.SecretBuildSource
configMaps []buildapi.ConfigMapBuildSource
info *SourceRepositoryInfo
sourceImage ComponentReference
sourceImageFrom string
Expand Down Expand Up @@ -357,7 +358,12 @@ func (r *SourceRepository) ContextDir() string {
return r.contextDir
}

// Secrets returns the secrets
// ConfigMaps returns the configMap build sources
func (r *SourceRepository) ConfigMaps() []buildapi.ConfigMapBuildSource {
return r.configMaps
}

// Secrets returns the secret build sources
func (r *SourceRepository) Secrets() []buildapi.SecretBuildSource {
return r.secrets
}
Expand Down Expand Up @@ -390,6 +396,43 @@ func (r *SourceRepository) AddDockerfile(contents string) error {
return nil
}

// AddBuildConfigMaps adds the defined configMaps into the build. The input format for
// the secrets is "<secretName>:<destinationDir>". The destinationDir is
// optional and when not specified the default is the current working directory.
func (r *SourceRepository) AddBuildConfigMaps(configMaps []string) error {
injections := s2iapi.VolumeList{}
r.configMaps = []buildapi.ConfigMapBuildSource{}
for _, in := range configMaps {
if err := injections.Set(in); err != nil {
return err
}
}
configMapExists := func(name string) bool {
for _, c := range r.configMaps {
if c.ConfigMap.Name == name {
return true
}
}
return false
}
for _, in := range injections {
if r.GetStrategy() == generate.StrategyDocker && filepath.IsAbs(in.Destination) {
return fmt.Errorf("for the docker strategy, the configMap destination directory %q must be a relative path", in.Destination)
}
if len(validation.ValidateConfigMapName(in.Source, false)) != 0 {
return fmt.Errorf("the %q must be a valid configMap name", in.Source)
}
if configMapExists(in.Source) {
return fmt.Errorf("the %q configMap can be used just once", in.Source)
}
r.configMaps = append(r.configMaps, buildapi.ConfigMapBuildSource{
ConfigMap: kapi.LocalObjectReference{Name: in.Source},
DestinationDir: in.Destination,
})
}
return nil
}

// AddBuildSecrets adds the defined secrets into a build. The input format for
// the secrets is "<secretName>:<destinationDir>". The destinationDir is
// optional and when not specified the default is the current working directory.
Expand Down Expand Up @@ -540,6 +583,7 @@ func StrategyAndSourceForRepository(repo *SourceRepository, image *ImageRef) (*B
source := &SourceRef{
Binary: repo.binary,
Secrets: repo.secrets,
ConfigMaps: repo.configMaps,
RequiresAuth: repo.requiresAuth,
}

Expand Down
60 changes: 60 additions & 0 deletions pkg/oc/generate/app/sourcelookup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,63 @@ func TestAddBuildSecrets(t *testing.T) {
}
}
}

func TestAddBuildConfigMaps(t *testing.T) {
type result struct{ name, dest string }
type tc struct {
in []string
expect []result
}
table := []tc{
{
in: []string{"config1"},
expect: []result{{name: "config1", dest: "."}},
},
{
in: []string{"config1", "config1"},
},
{
in: []string{"config1:/var/lib/foo"},
expect: []result{{name: "config1", dest: "/var/lib/foo"}},
},
{
in: []string{"config1", "config2:/foo"},
expect: []result{
{
name: "config1",
dest: ".",
},
{
name: "config2",
dest: "/foo",
},
},
},
}
repo := &SourceRepository{}
repo.strategy = generate.StrategyDocker
if err := repo.AddBuildSecrets([]string{"config1:/absolute/path"}); err == nil {
t.Errorf("expected error for docker strategy when destDir is absolute")
}
for _, item := range table {
repo := &SourceRepository{}
err := repo.AddBuildSecrets(item.in)
if err != nil && len(item.expect) != 0 {
t.Errorf("unexpected error: %v", err)
continue
}
for _, expect := range item.expect {
got := repo.Secrets()
found := false
for _, s := range got {
if s.Secret.Name == expect.name && s.DestinationDir == expect.dest {
found = true
break
}
}
if !found {
t.Errorf("expected %+v secret in %#v not found", expect, got)
}
}
}
}
9 changes: 7 additions & 2 deletions pkg/oc/generate/cmd/newapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ type GenerationInputs struct {
SourceImage string
SourceImagePath string

Secrets []string
Secrets []string
ConfigMaps []string

AllowMissingImageStreamTags bool

Expand Down Expand Up @@ -435,11 +436,15 @@ func (c *AppConfig) buildPipelines(components app.ComponentReferences, environme
switch {
case refInput.ExpectToBuild:
glog.V(4).Infof("will add %q secrets into a build for a source build of %q", strings.Join(c.Secrets, ","), refInput.Uses)

if err := refInput.Uses.AddBuildSecrets(c.Secrets); err != nil {
return nil, fmt.Errorf("unable to add build secrets %q: %v", strings.Join(c.Secrets, ","), err)
}

glog.V(4).Infof("will add %q configMaps into a build for a source build of %q", strings.Join(c.ConfigMaps, ","), refInput.Uses)
if err = refInput.Uses.AddBuildConfigMaps(c.ConfigMaps); err != nil {
return nil, fmt.Errorf("unable to add build configMaps %q: %v", strings.Join(c.Secrets, ","), err)
}

if refInput.Uses.GetStrategy() == generate.StrategyDocker {
numDockerBuilds++
}
Expand Down
37 changes: 29 additions & 8 deletions test/integration/newapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,7 @@ func TestNewAppRunBuilds(t *testing.T) {
ContextDir: "openshift/pipeline",
Git: &buildapi.GitBuildSource{URI: "https://github.com/openshift/nodejs-ex"},
Secrets: []buildapi.SecretBuildSource{},
ConfigMaps: []buildapi.ConfigMapBuildSource{},
}) {
return fmt.Errorf("invalid bc.Spec.Source, got %#v", bc.Spec.Source)
}
Expand Down Expand Up @@ -1386,6 +1387,7 @@ func TestNewAppRunBuilds(t *testing.T) {
ContextDir: "openshift/pipeline",
Git: &buildapi.GitBuildSource{URI: "https://github.com/openshift/nodejs-ex"},
Secrets: []buildapi.SecretBuildSource{},
ConfigMaps: []buildapi.ConfigMapBuildSource{},
}) {
return fmt.Errorf("invalid bc.Spec.Source, got %#v", bc.Spec.Source.Git)
}
Expand Down Expand Up @@ -1817,11 +1819,12 @@ func TestNewAppBuildConfigEnvVarsAndSecrets(t *testing.T) {
okRouteClient := &routefake.Clientset{}

tests := []struct {
name string
config *cmd.AppConfig
expected []kapi.EnvVar
expectedSecrets map[string]string
expectedErr error
name string
config *cmd.AppConfig
expected []kapi.EnvVar
expectedSecrets map[string]string
expectedConfigMaps map[string]string
expectedErr error
}{
{
name: "explicit environment variables for buildConfig and deploymentConfig",
Expand All @@ -1834,6 +1837,7 @@ func TestNewAppBuildConfigEnvVarsAndSecrets(t *testing.T) {
OutputDocker: true,
Environment: []string{"BUILD_ENV_1=env_value_1", "BUILD_ENV_2=env_value_2"},
Secrets: []string{"foo:/var", "bar"},
ConfigMaps: []string{"this:/tmp", "that"},
},

Resolvers: cmd.Resolvers{
Expand All @@ -1850,9 +1854,10 @@ func TestNewAppBuildConfigEnvVarsAndSecrets(t *testing.T) {
RouteClient: okRouteClient.Route(),
OriginNamespace: "default",
},
expected: []kapi.EnvVar{},
expectedSecrets: map[string]string{"foo": "/var", "bar": "."},
expectedErr: nil,
expected: []kapi.EnvVar{},
expectedSecrets: map[string]string{"foo": "/var", "bar": "."},
expectedConfigMaps: map[string]string{"this": "/tmp", "that": "."},
expectedErr: nil,
},
}

Expand All @@ -1866,11 +1871,13 @@ func TestNewAppBuildConfigEnvVarsAndSecrets(t *testing.T) {
}
got := []kapi.EnvVar{}
gotSecrets := []buildapi.SecretBuildSource{}
gotConfigMaps := []buildapi.ConfigMapBuildSource{}
for _, obj := range res.List.Items {
switch tp := obj.(type) {
case *buildapi.BuildConfig:
got = tp.Spec.Strategy.SourceStrategy.Env
gotSecrets = tp.Spec.Source.Secrets
gotConfigMaps = tp.Spec.Source.ConfigMaps
break
}
}
Expand All @@ -1889,6 +1896,20 @@ func TestNewAppBuildConfigEnvVarsAndSecrets(t *testing.T) {
}
}

for configName, destDir := range test.expectedConfigMaps {
found := false
for _, got := range gotConfigMaps {
if got.ConfigMap.Name == configName && got.DestinationDir == destDir {
found = true
continue
}
}
if !found {
t.Errorf("expected configMap %q and destination %q, got %#v", configName, destDir, gotConfigMaps)
continue
}
}

if !reflect.DeepEqual(test.expected, got) {
t.Errorf("%s: unexpected output. Expected: %#v, Got: %#v", test.name, test.expected, got)
continue
Expand Down