Skip to content
This repository was archived by the owner on Jun 3, 2025. It is now read-only.

Commit de4b734

Browse files
authored
Merge pull request #993 from antechrestos/feature/expand_build_args_with_environment_variable
Expand build argument from environment when no value specified
2 parents 3f73230 + 2f1e54e commit de4b734

4 files changed

Lines changed: 129 additions & 7 deletions

File tree

cmd/executor/cmd/root.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ var RootCmd = &cobra.Command{
5555
Use: "executor",
5656
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
5757
if cmd.Use == "executor" {
58+
resolveEnvironmentBuildArgs(opts.BuildArgs, os.Getenv)
5859
if err := util.ConfigureLogging(logLevel); err != nil {
5960
return err
6061
}
@@ -200,6 +201,17 @@ func resolveDockerfilePath() error {
200201
return errors.New("please provide a valid path to a Dockerfile within the build context with --dockerfile")
201202
}
202203

204+
// resolveEnvironmentBuildArgs replace build args without value by the same named environment variable
205+
func resolveEnvironmentBuildArgs(arguments []string, resolver func(string) string) {
206+
for index, argument := range arguments {
207+
i := strings.Index(argument, "=")
208+
if i < 0 {
209+
value := resolver(argument)
210+
arguments[index] = fmt.Sprintf("%s=%s", argument, value)
211+
}
212+
}
213+
}
214+
203215
// copy Dockerfile to /kaniko/Dockerfile so that if it's specified in the .dockerignore
204216
// it won't be copied into the image
205217
func copyDockerfile() error {

cmd/executor/cmd/root_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,55 @@ func TestIsUrl(t *testing.T) {
9797
})
9898
}
9999
}
100+
101+
func TestResolveEnvironmentBuildArgs(t *testing.T) {
102+
tests := []struct {
103+
description string
104+
input []string
105+
expected []string
106+
mockedEnvironmentResolver func(string) string
107+
}{
108+
{
109+
description: "replace when environment variable is present and value is not specified",
110+
input: []string{"variable1"},
111+
expected: []string{"variable1=value1"},
112+
mockedEnvironmentResolver: func(variable string) string {
113+
if variable == "variable1" {
114+
return "value1"
115+
}
116+
return ""
117+
},
118+
},
119+
{
120+
description: "do not replace when environment variable is present and value is specified",
121+
input: []string{"variable1=value1", "variable2=value2"},
122+
expected: []string{"variable1=value1", "variable2=value2"},
123+
mockedEnvironmentResolver: func(variable string) string {
124+
return "unexpected"
125+
},
126+
},
127+
{
128+
description: "do not replace when environment variable is present and empty value is specified",
129+
input: []string{"variable1="},
130+
expected: []string{"variable1="},
131+
mockedEnvironmentResolver: func(variable string) string {
132+
return "unexpected"
133+
},
134+
},
135+
{
136+
description: "replace with empty value when environment variable is not present or empty and value is not specified",
137+
input: []string{"variable1", "variable2=value2"},
138+
expected: []string{"variable1=", "variable2=value2"},
139+
mockedEnvironmentResolver: func(variable string) string {
140+
return ""
141+
},
142+
},
143+
}
144+
145+
for _, tt := range tests {
146+
t.Run(tt.description, func(t *testing.T) {
147+
resolveEnvironmentBuildArgs(tt.input, tt.mockedEnvironmentResolver)
148+
testutil.CheckDeepEqual(t, tt.expected, tt.input)
149+
})
150+
}
151+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FROM debian:9.11
2+
3+
ARG SSH_PRIVATE_KEY
4+
ARG SSH_PUBLIC_KEY
5+
6+
RUN mkdir .ssh && \
7+
chmod 700 .ssh && \
8+
echo "$SSH_PRIVATE_KEY" > .ssh/id_rsa && \
9+
echo "$SSH_PUBLIC_KEY" > .ssh/id_rsa.pub && \
10+
chmod 600 .ssh/id_rsa .ssh/id_rsa.pub

integration/images.go

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package integration
1818

1919
import (
20+
"bytes"
2021
"fmt"
2122
"io/ioutil"
2223
"os"
@@ -46,10 +47,11 @@ const (
4647

4748
// Arguments to build Dockerfiles with, used for both docker and kaniko builds
4849
var argsMap = map[string][]string{
49-
"Dockerfile_test_run": {"file=/file"},
50-
"Dockerfile_test_workdir": {"workdir=/arg/workdir"},
51-
"Dockerfile_test_add": {"file=context/foo"},
52-
"Dockerfile_test_onbuild": {"file=/tmp/onbuild"},
50+
"Dockerfile_test_run": {"file=/file"},
51+
"Dockerfile_test_workdir": {"workdir=/arg/workdir"},
52+
"Dockerfile_test_add": {"file=context/foo"},
53+
"Dockerfile_test_arg_secret": {"SSH_PRIVATE_KEY", "SSH_PUBLIC_KEY=Pµbl1cK€Y"},
54+
"Dockerfile_test_onbuild": {"file=/tmp/onbuild"},
5355
"Dockerfile_test_scratch": {
5456
"image=scratch",
5557
"hello=hello-value",
@@ -59,6 +61,11 @@ var argsMap = map[string][]string{
5961
"Dockerfile_test_multistage": {"file=/foo2"},
6062
}
6163

64+
// Environment to build Dockerfiles with, used for both docker and kaniko builds
65+
var envsMap = map[string][]string{
66+
"Dockerfile_test_arg_secret": {"SSH_PRIVATE_KEY=ThEPriv4t3Key"},
67+
}
68+
6269
// Arguments to build Dockerfiles with when building with docker
6370
var additionalDockerFlagsMap = map[string][]string{
6471
"Dockerfile_test_target": {"--target=second"},
@@ -71,6 +78,36 @@ var additionalKanikoFlagsMap = map[string][]string{
7178
"Dockerfile_test_target": {"--target=second"},
7279
}
7380

81+
// output check to do when building with kaniko
82+
var outputChecks = map[string]func(string, []byte) error{
83+
"Dockerfile_test_arg_secret": checkArgsNotPrinted,
84+
}
85+
86+
// Checks if argument are not printed in output.
87+
// Argument may be passed through --build-arg key=value manner or --build-arg key with key in environment
88+
func checkArgsNotPrinted(dockerfile string, out []byte) error {
89+
for _, arg := range argsMap[dockerfile] {
90+
argSplitted := strings.Split(arg, "=")
91+
if len(argSplitted) == 2 {
92+
if idx := bytes.Index(out, []byte(argSplitted[1])); idx >= 0 {
93+
return fmt.Errorf("Argument value %s for argument %s displayed in output", argSplitted[1], argSplitted[0])
94+
}
95+
} else if len(argSplitted) == 1 {
96+
if envs, ok := envsMap[dockerfile]; ok {
97+
for _, env := range envs {
98+
envSplitted := strings.Split(env, "=")
99+
if len(envSplitted) == 2 {
100+
if idx := bytes.Index(out, []byte(envSplitted[1])); idx >= 0 {
101+
return fmt.Errorf("Argument value %s for argument %s displayed in output", envSplitted[1], argSplitted[0])
102+
}
103+
}
104+
}
105+
}
106+
}
107+
}
108+
return nil
109+
}
110+
74111
var bucketContextTests = []string{"Dockerfile_test_copy_bucket"}
75112
var reproducibleTests = []string{"Dockerfile_test_reproducible"}
76113

@@ -164,8 +201,7 @@ func (d *DockerFileBuilder) BuildImage(config *gcpConfig, dockerfilesPath, docke
164201
var buildArgs []string
165202
buildArgFlag := "--build-arg"
166203
for _, arg := range argsMap[dockerfile] {
167-
buildArgs = append(buildArgs, buildArgFlag)
168-
buildArgs = append(buildArgs, arg)
204+
buildArgs = append(buildArgs, buildArgFlag, arg)
169205
}
170206
// build docker image
171207
additionalFlags := append(buildArgs, additionalDockerFlagsMap[dockerfile]...)
@@ -177,6 +213,9 @@ func (d *DockerFileBuilder) BuildImage(config *gcpConfig, dockerfilesPath, docke
177213
"."},
178214
additionalFlags...)...,
179215
)
216+
if env, ok := envsMap[dockerfile]; ok {
217+
dockerCmd.Env = append(dockerCmd.Env, env...)
218+
}
180219

181220
timer := timing.Start(dockerfile + "_docker")
182221
out, err := RunCommandWithoutTest(dockerCmd)
@@ -225,7 +264,11 @@ func (d *DockerFileBuilder) BuildImage(config *gcpConfig, dockerfilesPath, docke
225264
"-v", cwd + ":/workspace",
226265
"-v", benchmarkDir + ":/kaniko/benchmarks",
227266
}
228-
267+
if env, ok := envsMap[dockerfile]; ok {
268+
for _, envVariable := range env {
269+
dockerRunFlags = append(dockerRunFlags, "-e", envVariable)
270+
}
271+
}
229272
dockerRunFlags = addServiceAccountFlags(dockerRunFlags, serviceAccount)
230273

231274
dockerRunFlags = append(dockerRunFlags, ExecutorImage,
@@ -242,6 +285,11 @@ func (d *DockerFileBuilder) BuildImage(config *gcpConfig, dockerfilesPath, docke
242285
if err != nil {
243286
return fmt.Errorf("Failed to build image %s with kaniko command \"%s\": %s %s", dockerImage, kanikoCmd.Args, err, string(out))
244287
}
288+
if outputCheck := outputChecks[dockerfile]; outputCheck != nil {
289+
if err := outputCheck(dockerfile, out); err != nil {
290+
return fmt.Errorf("Output check failed for image %s with kaniko command \"%s\": %s %s", dockerImage, kanikoCmd.Args, err, string(out))
291+
}
292+
}
245293

246294
d.FilesBuilt[dockerfile] = true
247295
return nil

0 commit comments

Comments
 (0)