Skip to content

Commit 07cc8ec

Browse files
committed
oc: add configmaps to build via cli
RFE/bug 1540978
1 parent 8157540 commit 07cc8ec

File tree

10 files changed

+179
-11
lines changed

10 files changed

+179
-11
lines changed

contrib/completions/bash/oc

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/completions/zsh/oc

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/oc/cli/cmd/newbuild.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ var (
5959
# Create a build config from a remote repository and inject the npmrc into a build
6060
%[1]s %[2]s https://github.com/openshift/ruby-hello-world --build-secret npmrc:.npmrc
6161
62+
# Create a build config from a remote repository and inject environment data into a build
63+
%[1]s %[2]s https://github.com/openshift/ruby-hello-world --build-config-map env:config
64+
6265
# Create a build config that gets its input from a remote repository and another Docker image
6366
%[1]s %[2]s https://github.com/openshift/ruby-hello-world --source-image=openshift/jenkins-1-centos7 --source-image-path=/var/lib/jenkins:tmp`)
6467

@@ -111,6 +114,7 @@ func NewCmdNewBuild(name, baseName string, f kcmdutil.Factory, in io.Reader, out
111114
cmd.Flags().MarkDeprecated("image", "use --image-stream instead")
112115
cmd.Flags().StringSliceVarP(&config.ImageStreams, "image-stream", "i", config.ImageStreams, "Name of an image stream to to use as a builder.")
113116
cmd.Flags().StringSliceVar(&config.DockerImages, "docker-image", config.DockerImages, "Name of a Docker image to use as a builder.")
117+
cmd.Flags().StringSliceVar(&config.ConfigMaps, "build-config-map", config.ConfigMaps, "ConfigMap and destination to use as an input for the build.")
114118
cmd.Flags().StringSliceVar(&config.Secrets, "build-secret", config.Secrets, "Secret and destination to use as an input for the build.")
115119
cmd.Flags().StringVar(&config.SourceSecret, "source-secret", "", "The name of an existing secret that should be used for cloning a private git repository.")
116120
cmd.Flags().StringVar(&config.PushSecret, "push-secret", "", "The name of an existing secret that should be used for pushing the output image.")

pkg/oc/cli/describe/describer.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,14 @@ func describeCommonSpec(p buildapi.CommonSpec, out *tabwriter.Writer) {
328328
}
329329
formatString(out, "Build Secrets", strings.Join(result, ","))
330330
}
331+
if len(p.Source.ConfigMaps) > 0 {
332+
result := []string{}
333+
for _, c := range p.Source.ConfigMaps {
334+
result = append(result, fmt.Sprintf("%s->%s", c.ConfigMap.Name, filepath.Clean(c.DestinationDir)))
335+
}
336+
formatString(out, "Build ConfigMaps", strings.Join(result, ","))
337+
}
338+
331339
if len(p.Source.Images) == 1 && len(p.Source.Images[0].Paths) == 1 {
332340
noneType = false
333341
image := p.Source.Images[0]

pkg/oc/generate/app/app.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ type SourceRef struct {
112112
Name string
113113
ContextDir string
114114
Secrets []buildapi.SecretBuildSource
115+
ConfigMaps []buildapi.ConfigMapBuildSource
115116

116117
SourceImage *ImageRef
117118
ImageSourcePath string
@@ -153,6 +154,7 @@ func (r *SourceRef) BuildSource() (*buildapi.BuildSource, []buildapi.BuildTrigge
153154
}
154155
source := &buildapi.BuildSource{}
155156
source.Secrets = r.Secrets
157+
source.ConfigMaps = r.ConfigMaps
156158

157159
if len(r.DockerfileContents) != 0 {
158160
source.Dockerfile = &r.DockerfileContents

pkg/oc/generate/app/app_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,26 @@ func TestBuildConfigWithSecrets(t *testing.T) {
9797
}
9898
}
9999

100+
func TestBuildConfigWithConfigMaps(t *testing.T) {
101+
url, err := git.Parse("https://github.com/openshift/origin.git")
102+
if err != nil {
103+
t.Fatalf("unexpected error: %v", err)
104+
}
105+
source := &SourceRef{URL: url, ConfigMaps: []buildapi.ConfigMapBuildSource{
106+
{ConfigMap: kapi.LocalObjectReference{Name: "foo"}, DestinationDir: "/var"},
107+
{ConfigMap: kapi.LocalObjectReference{Name: "bar"}},
108+
}}
109+
build := &BuildRef{Source: source}
110+
config, err := build.BuildConfig()
111+
if err != nil {
112+
t.Fatalf("unexpected error: %v", err)
113+
}
114+
configMaps := config.Spec.Source.ConfigMaps
115+
if got := len(configMaps); got != 2 {
116+
t.Errorf("expected 2 source configMaps in build config, got %d", got)
117+
}
118+
}
119+
100120
func TestBuildConfigBinaryWithImageSource(t *testing.T) {
101121
source := &SourceRef{
102122
Name: "binarybuild",

pkg/oc/generate/app/sourcelookup.go

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ type SourceRepository struct {
101101
remoteURL *s2igit.URL
102102
contextDir string
103103
secrets []buildapi.SecretBuildSource
104+
configMaps []buildapi.ConfigMapBuildSource
104105
info *SourceRepositoryInfo
105106
sourceImage ComponentReference
106107
sourceImageFrom string
@@ -357,7 +358,12 @@ func (r *SourceRepository) ContextDir() string {
357358
return r.contextDir
358359
}
359360

360-
// Secrets returns the secrets
361+
// ConfigMaps returns the configMap build sources
362+
func (r *SourceRepository) ConfigMaps() []buildapi.ConfigMapBuildSource {
363+
return r.configMaps
364+
}
365+
366+
// Secrets returns the secret build sources
361367
func (r *SourceRepository) Secrets() []buildapi.SecretBuildSource {
362368
return r.secrets
363369
}
@@ -390,6 +396,43 @@ func (r *SourceRepository) AddDockerfile(contents string) error {
390396
return nil
391397
}
392398

399+
// AddBuildConfigMaps adds the defined configMaps into the build. The input format for
400+
// the secrets is "<secretName>:<destinationDir>". The destinationDir is
401+
// optional and when not specified the default is the current working directory.
402+
func (r *SourceRepository) AddBuildConfigMaps(configMaps []string) error {
403+
injections := s2iapi.VolumeList{}
404+
r.configMaps = []buildapi.ConfigMapBuildSource{}
405+
for _, in := range configMaps {
406+
if err := injections.Set(in); err != nil {
407+
return err
408+
}
409+
}
410+
configMapExists := func(name string) bool {
411+
for _, c := range r.configMaps {
412+
if c.ConfigMap.Name == name {
413+
return true
414+
}
415+
}
416+
return false
417+
}
418+
for _, in := range injections {
419+
if r.GetStrategy() == generate.StrategyDocker && filepath.IsAbs(in.Destination) {
420+
return fmt.Errorf("for the docker strategy, the configMap destination directory %q must be a relative path", in.Destination)
421+
}
422+
if len(validation.ValidateConfigMapName(in.Source, false)) != 0 {
423+
return fmt.Errorf("the %q must be a valid configMap name", in.Source)
424+
}
425+
if configMapExists(in.Source) {
426+
return fmt.Errorf("the %q configMap can be used just once", in.Source)
427+
}
428+
r.configMaps = append(r.configMaps, buildapi.ConfigMapBuildSource{
429+
ConfigMap: kapi.LocalObjectReference{Name: in.Source},
430+
DestinationDir: in.Destination,
431+
})
432+
}
433+
return nil
434+
}
435+
393436
// AddBuildSecrets adds the defined secrets into a build. The input format for
394437
// the secrets is "<secretName>:<destinationDir>". The destinationDir is
395438
// optional and when not specified the default is the current working directory.
@@ -540,6 +583,7 @@ func StrategyAndSourceForRepository(repo *SourceRepository, image *ImageRef) (*B
540583
source := &SourceRef{
541584
Binary: repo.binary,
542585
Secrets: repo.secrets,
586+
ConfigMaps: repo.configMaps,
543587
RequiresAuth: repo.requiresAuth,
544588
}
545589

pkg/oc/generate/app/sourcelookup_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,63 @@ func TestAddBuildSecrets(t *testing.T) {
6565
}
6666
}
6767
}
68+
69+
func TestAddBuildConfigMaps(t *testing.T) {
70+
type result struct{ name, dest string }
71+
type tc struct {
72+
in []string
73+
expect []result
74+
}
75+
table := []tc{
76+
{
77+
in: []string{"config1"},
78+
expect: []result{{name: "config1", dest: "."}},
79+
},
80+
{
81+
in: []string{"config1", "config1"},
82+
},
83+
{
84+
in: []string{"config1:/var/lib/foo"},
85+
expect: []result{{name: "config1", dest: "/var/lib/foo"}},
86+
},
87+
{
88+
in: []string{"config1", "config2:/foo"},
89+
expect: []result{
90+
{
91+
name: "config1",
92+
dest: ".",
93+
},
94+
{
95+
name: "config2",
96+
dest: "/foo",
97+
},
98+
},
99+
},
100+
}
101+
repo := &SourceRepository{}
102+
repo.strategy = generate.StrategyDocker
103+
if err := repo.AddBuildSecrets([]string{"config1:/absolute/path"}); err == nil {
104+
t.Errorf("expected error for docker strategy when destDir is absolute")
105+
}
106+
for _, item := range table {
107+
repo := &SourceRepository{}
108+
err := repo.AddBuildSecrets(item.in)
109+
if err != nil && len(item.expect) != 0 {
110+
t.Errorf("unexpected error: %v", err)
111+
continue
112+
}
113+
for _, expect := range item.expect {
114+
got := repo.Secrets()
115+
found := false
116+
for _, s := range got {
117+
if s.Secret.Name == expect.name && s.DestinationDir == expect.dest {
118+
found = true
119+
break
120+
}
121+
}
122+
if !found {
123+
t.Errorf("expected %+v secret in %#v not found", expect, got)
124+
}
125+
}
126+
}
127+
}

pkg/oc/generate/cmd/newapp.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ type GenerationInputs struct {
8282
SourceImage string
8383
SourceImagePath string
8484

85-
Secrets []string
85+
Secrets []string
86+
ConfigMaps []string
8687

8788
AllowMissingImageStreamTags bool
8889

@@ -435,11 +436,15 @@ func (c *AppConfig) buildPipelines(components app.ComponentReferences, environme
435436
switch {
436437
case refInput.ExpectToBuild:
437438
glog.V(4).Infof("will add %q secrets into a build for a source build of %q", strings.Join(c.Secrets, ","), refInput.Uses)
438-
439439
if err := refInput.Uses.AddBuildSecrets(c.Secrets); err != nil {
440440
return nil, fmt.Errorf("unable to add build secrets %q: %v", strings.Join(c.Secrets, ","), err)
441441
}
442442

443+
glog.V(4).Infof("will add %q configMaps into a build for a source build of %q", strings.Join(c.ConfigMaps, ","), refInput.Uses)
444+
if err = refInput.Uses.AddBuildConfigMaps(c.ConfigMaps); err != nil {
445+
return nil, fmt.Errorf("unable to add build configMaps %q: %v", strings.Join(c.Secrets, ","), err)
446+
}
447+
443448
if refInput.Uses.GetStrategy() == generate.StrategyDocker {
444449
numDockerBuilds++
445450
}

test/integration/newapp_test.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,7 @@ func TestNewAppRunBuilds(t *testing.T) {
13461346
ContextDir: "openshift/pipeline",
13471347
Git: &buildapi.GitBuildSource{URI: "https://github.com/openshift/nodejs-ex"},
13481348
Secrets: []buildapi.SecretBuildSource{},
1349+
ConfigMaps: []buildapi.ConfigMapBuildSource{},
13491350
}) {
13501351
return fmt.Errorf("invalid bc.Spec.Source, got %#v", bc.Spec.Source)
13511352
}
@@ -1386,6 +1387,7 @@ func TestNewAppRunBuilds(t *testing.T) {
13861387
ContextDir: "openshift/pipeline",
13871388
Git: &buildapi.GitBuildSource{URI: "https://github.com/openshift/nodejs-ex"},
13881389
Secrets: []buildapi.SecretBuildSource{},
1390+
ConfigMaps: []buildapi.ConfigMapBuildSource{},
13891391
}) {
13901392
return fmt.Errorf("invalid bc.Spec.Source, got %#v", bc.Spec.Source.Git)
13911393
}
@@ -1817,11 +1819,12 @@ func TestNewAppBuildConfigEnvVarsAndSecrets(t *testing.T) {
18171819
okRouteClient := &routefake.Clientset{}
18181820

18191821
tests := []struct {
1820-
name string
1821-
config *cmd.AppConfig
1822-
expected []kapi.EnvVar
1823-
expectedSecrets map[string]string
1824-
expectedErr error
1822+
name string
1823+
config *cmd.AppConfig
1824+
expected []kapi.EnvVar
1825+
expectedSecrets map[string]string
1826+
expectedConfigMaps map[string]string
1827+
expectedErr error
18251828
}{
18261829
{
18271830
name: "explicit environment variables for buildConfig and deploymentConfig",
@@ -1834,6 +1837,7 @@ func TestNewAppBuildConfigEnvVarsAndSecrets(t *testing.T) {
18341837
OutputDocker: true,
18351838
Environment: []string{"BUILD_ENV_1=env_value_1", "BUILD_ENV_2=env_value_2"},
18361839
Secrets: []string{"foo:/var", "bar"},
1840+
ConfigMaps: []string{"this:/tmp", "that"},
18371841
},
18381842

18391843
Resolvers: cmd.Resolvers{
@@ -1850,9 +1854,10 @@ func TestNewAppBuildConfigEnvVarsAndSecrets(t *testing.T) {
18501854
RouteClient: okRouteClient.Route(),
18511855
OriginNamespace: "default",
18521856
},
1853-
expected: []kapi.EnvVar{},
1854-
expectedSecrets: map[string]string{"foo": "/var", "bar": "."},
1855-
expectedErr: nil,
1857+
expected: []kapi.EnvVar{},
1858+
expectedSecrets: map[string]string{"foo": "/var", "bar": "."},
1859+
expectedConfigMaps: map[string]string{"this": "/tmp", "that": "."},
1860+
expectedErr: nil,
18561861
},
18571862
}
18581863

@@ -1866,11 +1871,13 @@ func TestNewAppBuildConfigEnvVarsAndSecrets(t *testing.T) {
18661871
}
18671872
got := []kapi.EnvVar{}
18681873
gotSecrets := []buildapi.SecretBuildSource{}
1874+
gotConfigMaps := []buildapi.ConfigMapBuildSource{}
18691875
for _, obj := range res.List.Items {
18701876
switch tp := obj.(type) {
18711877
case *buildapi.BuildConfig:
18721878
got = tp.Spec.Strategy.SourceStrategy.Env
18731879
gotSecrets = tp.Spec.Source.Secrets
1880+
gotConfigMaps = tp.Spec.Source.ConfigMaps
18741881
break
18751882
}
18761883
}
@@ -1889,6 +1896,20 @@ func TestNewAppBuildConfigEnvVarsAndSecrets(t *testing.T) {
18891896
}
18901897
}
18911898

1899+
for configName, destDir := range test.expectedConfigMaps {
1900+
found := false
1901+
for _, got := range gotConfigMaps {
1902+
if got.ConfigMap.Name == configName && got.DestinationDir == destDir {
1903+
found = true
1904+
continue
1905+
}
1906+
}
1907+
if !found {
1908+
t.Errorf("expected configMap %q and destination %q, got %#v", configName, destDir, gotConfigMaps)
1909+
continue
1910+
}
1911+
}
1912+
18921913
if !reflect.DeepEqual(test.expected, got) {
18931914
t.Errorf("%s: unexpected output. Expected: %#v, Got: %#v", test.name, test.expected, got)
18941915
continue

0 commit comments

Comments
 (0)