Skip to content

Commit

Permalink
oc: add configmaps to build via cli
Browse files Browse the repository at this point in the history
  • Loading branch information
adambkaplan committed May 9, 2018
1 parent 167e110 commit 4b7d9b6
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 11 deletions.
4 changes: 4 additions & 0 deletions pkg/oc/cli/cmd/newbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,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 @@ -112,6 +115,7 @@ func NewCmdNewBuild(name, baseName string, f *clientcmd.Factory, in io.Reader, o
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
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 @@ -96,6 +96,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 @@ -83,7 +83,8 @@ type GenerationInputs struct {
SourceImage string
SourceImagePath string

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

AllowMissingImageStreamTags bool

Expand Down Expand Up @@ -438,11 +439,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 @@ -1355,6 +1355,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 @@ -1395,6 +1396,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 @@ -1826,11 +1828,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 @@ -1843,6 +1846,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 @@ -1859,9 +1863,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 @@ -1875,11 +1880,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 @@ -1898,6 +1905,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

0 comments on commit 4b7d9b6

Please sign in to comment.