Support BuildArgs for arg command
This commit is contained in:
parent
3aafb843e2
commit
26d8501489
|
|
@ -36,7 +36,6 @@ After each command, we append a layer of changed files to the base image (if the
|
||||||
The majority of Dockerfile commands can be executed with kaniko, but we're still working on supporting the following commands:
|
The majority of Dockerfile commands can be executed with kaniko, but we're still working on supporting the following commands:
|
||||||
|
|
||||||
* HEALTHCHECK
|
* HEALTHCHECK
|
||||||
* ARG
|
|
||||||
|
|
||||||
Multi-Stage Dockerfiles are also unsupported currently, but will be ready soon.
|
Multi-Stage Dockerfiles are also unsupported currently, but will be ready soon.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,9 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/genuinetools/amicontained/container"
|
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/executor"
|
"github.com/GoogleContainerTools/kaniko/pkg/executor"
|
||||||
|
"github.com/genuinetools/amicontained/container"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/constants"
|
"github.com/GoogleContainerTools/kaniko/pkg/constants"
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
|
@ -40,6 +40,7 @@ var (
|
||||||
dockerInsecureSkipTLSVerify bool
|
dockerInsecureSkipTLSVerify bool
|
||||||
logLevel string
|
logLevel string
|
||||||
force bool
|
force bool
|
||||||
|
buildArgs buildArg
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
@ -49,6 +50,7 @@ func init() {
|
||||||
RootCmd.PersistentFlags().StringVarP(&destination, "destination", "d", "", "Registry the final image should be pushed to (ex: gcr.io/test/example:latest)")
|
RootCmd.PersistentFlags().StringVarP(&destination, "destination", "d", "", "Registry the final image should be pushed to (ex: gcr.io/test/example:latest)")
|
||||||
RootCmd.MarkPersistentFlagRequired("destination")
|
RootCmd.MarkPersistentFlagRequired("destination")
|
||||||
RootCmd.PersistentFlags().StringVarP(&snapshotMode, "snapshotMode", "", "full", "Set this flag to change the file attributes inspected during snapshotting")
|
RootCmd.PersistentFlags().StringVarP(&snapshotMode, "snapshotMode", "", "full", "Set this flag to change the file attributes inspected during snapshotting")
|
||||||
|
RootCmd.PersistentFlags().VarP(&buildArgs, "build-arg", "", "This flag allows you to pass in ARG values at build time. Set it repeatedly for multiple values.")
|
||||||
RootCmd.PersistentFlags().BoolVarP(&dockerInsecureSkipTLSVerify, "insecure-skip-tls-verify", "", false, "Push to insecure registry ignoring TLS verify")
|
RootCmd.PersistentFlags().BoolVarP(&dockerInsecureSkipTLSVerify, "insecure-skip-tls-verify", "", false, "Push to insecure registry ignoring TLS verify")
|
||||||
RootCmd.PersistentFlags().StringVarP(&logLevel, "verbosity", "v", constants.DefaultLogLevel, "Log level (debug, info, warn, error, fatal, panic")
|
RootCmd.PersistentFlags().StringVarP(&logLevel, "verbosity", "v", constants.DefaultLogLevel, "Log level (debug, info, warn, error, fatal, panic")
|
||||||
RootCmd.PersistentFlags().BoolVarP(&force, "force", "", false, "Force building outside of a container")
|
RootCmd.PersistentFlags().BoolVarP(&force, "force", "", false, "Force building outside of a container")
|
||||||
|
|
@ -77,13 +79,33 @@ var RootCmd = &cobra.Command{
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if err := executor.DoBuild(dockerfilePath, srcContext, destination, snapshotMode, dockerInsecureSkipTLSVerify); err != nil {
|
if err := executor.DoBuild(dockerfilePath, srcContext, destination, snapshotMode, dockerInsecureSkipTLSVerify, buildArgs); err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type buildArg []string
|
||||||
|
|
||||||
|
// Now, for our new type, implement the two methods of
|
||||||
|
// the flag.Value interface...
|
||||||
|
// The first method is String() string
|
||||||
|
func (b *buildArg) String() string {
|
||||||
|
return strings.Join(*b, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The second method is Set(value string) error
|
||||||
|
func (b *buildArg) Set(value string) error {
|
||||||
|
logrus.Infof("appending to build args %s", value)
|
||||||
|
*b = append(*b, value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *buildArg) Type() string {
|
||||||
|
return "Build ARG Type"
|
||||||
|
}
|
||||||
|
|
||||||
func checkContained() bool {
|
func checkContained() bool {
|
||||||
_, err := container.DetectRuntime()
|
_, err := container.DetectRuntime()
|
||||||
return err == nil
|
return err == nil
|
||||||
|
|
|
||||||
|
|
@ -14,5 +14,9 @@ ADD $contextenv/* /tmp/${contextenv}/
|
||||||
ADD context/tars/fil* /tars/
|
ADD context/tars/fil* /tars/
|
||||||
ADD context/tars/file.tar /tars_again
|
ADD context/tars/file.tar /tars_again
|
||||||
|
|
||||||
|
# Test with ARG
|
||||||
|
ARG file
|
||||||
|
COPY $file /arg
|
||||||
|
|
||||||
# Finally, test adding a remote URL, concurrently with a normal file
|
# Finally, test adding a remote URL, concurrently with a normal file
|
||||||
ADD https://github.com/GoogleCloudPlatform/docker-credential-gcr/releases/download/v1.4.3/docker-credential-gcr_linux_386-1.4.3.tar.gz context/foo /test/all/
|
ADD https://github.com/GoogleCloudPlatform/docker-credential-gcr/releases/download/v1.4.3/docker-credential-gcr_linux_386-1.4.3.tar.gz context/foo /test/all/
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
FROM gcr.io/kaniko-test/onbuild-base:latest
|
FROM gcr.io/kaniko-test/onbuild-base:latest
|
||||||
COPY context/foo foo
|
COPY context/foo foo
|
||||||
ENV dir /new/workdir/
|
ENV dir /new/workdir/
|
||||||
ONBUILD RUN echo "onbuild" > /tmp/onbuild
|
ARG file
|
||||||
|
ONBUILD RUN echo "onbuild" > $file
|
||||||
ONBUILD RUN echo "onbuild 2" > ${dir}
|
ONBUILD RUN echo "onbuild 2" > ${dir}
|
||||||
ONBUILD WORKDIR /new/workdir
|
ONBUILD WORKDIR /new/workdir
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,7 @@ RUN echo "hey" > /etc/foo
|
||||||
RUN echo "baz" > /etc/baz
|
RUN echo "baz" > /etc/baz
|
||||||
RUN cp /etc/baz /etc/bar
|
RUN cp /etc/baz /etc/bar
|
||||||
RUN rm /etc/baz
|
RUN rm /etc/baz
|
||||||
|
|
||||||
|
# Test with ARG
|
||||||
|
ARG file
|
||||||
|
RUN echo "run" > $file
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,14 @@
|
||||||
FROM scratch
|
FROM scratch
|
||||||
ADD context/foo /foo
|
# First, make sure simple arg replacement works
|
||||||
ENV hello hello
|
ARG file
|
||||||
ADD context/foo /$hello
|
COPY $file /foo
|
||||||
|
# Check that setting a default value works
|
||||||
|
ARG file2=context/bar/bat
|
||||||
|
COPY $file2 /bat
|
||||||
|
# Check that overriding a default value works
|
||||||
|
ARG file3=context/bar/baz
|
||||||
|
COPY $file3 /baz
|
||||||
|
# Check that setting an ENV will override the ARG
|
||||||
|
ENV file context/bar/bam/bat
|
||||||
|
COPY $file /env
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,7 @@ ENV dir /another/new/dir
|
||||||
WORKDIR $dir/newdir
|
WORKDIR $dir/newdir
|
||||||
WORKDIR $dir/$doesntexist
|
WORKDIR $dir/$doesntexist
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
|
# Test with ARG
|
||||||
|
ARG workdir
|
||||||
|
WORKDIR $workdir
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ var fileTests = []struct {
|
||||||
kanikoContextBucket bool
|
kanikoContextBucket bool
|
||||||
repo string
|
repo string
|
||||||
snapshotMode string
|
snapshotMode string
|
||||||
|
args []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
description: "test extract filesystem",
|
description: "test extract filesystem",
|
||||||
|
|
@ -64,6 +65,9 @@ var fileTests = []struct {
|
||||||
dockerContext: dockerfilesPath,
|
dockerContext: dockerfilesPath,
|
||||||
kanikoContext: dockerfilesPath,
|
kanikoContext: dockerfilesPath,
|
||||||
repo: "test-run",
|
repo: "test-run",
|
||||||
|
args: []string{
|
||||||
|
"file=/file",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "test run no files changed",
|
description: "test run no files changed",
|
||||||
|
|
@ -99,6 +103,9 @@ var fileTests = []struct {
|
||||||
dockerContext: buildcontextPath,
|
dockerContext: buildcontextPath,
|
||||||
kanikoContext: buildcontextPath,
|
kanikoContext: buildcontextPath,
|
||||||
repo: "test-workdir",
|
repo: "test-workdir",
|
||||||
|
args: []string{
|
||||||
|
"workdir=/arg/workdir",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "test volume",
|
description: "test volume",
|
||||||
|
|
@ -115,6 +122,9 @@ var fileTests = []struct {
|
||||||
dockerContext: buildcontextPath,
|
dockerContext: buildcontextPath,
|
||||||
kanikoContext: buildcontextPath,
|
kanikoContext: buildcontextPath,
|
||||||
repo: "test-add",
|
repo: "test-add",
|
||||||
|
args: []string{
|
||||||
|
"file=context/foo",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "test mv add",
|
description: "test mv add",
|
||||||
|
|
@ -139,6 +149,9 @@ var fileTests = []struct {
|
||||||
dockerContext: buildcontextPath,
|
dockerContext: buildcontextPath,
|
||||||
kanikoContext: buildcontextPath,
|
kanikoContext: buildcontextPath,
|
||||||
repo: "test-onbuild",
|
repo: "test-onbuild",
|
||||||
|
args: []string{
|
||||||
|
"file=/tmp/onbuild",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "test scratch",
|
description: "test scratch",
|
||||||
|
|
@ -147,6 +160,11 @@ var fileTests = []struct {
|
||||||
dockerContext: buildcontextPath,
|
dockerContext: buildcontextPath,
|
||||||
kanikoContext: buildcontextPath,
|
kanikoContext: buildcontextPath,
|
||||||
repo: "test-scratch",
|
repo: "test-scratch",
|
||||||
|
args: []string{
|
||||||
|
"hello=hello-value",
|
||||||
|
"file=context/foo",
|
||||||
|
"file3=context/b*",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,18 +249,23 @@ func main() {
|
||||||
Args: []string{"push", onbuildBaseImage},
|
Args: []string{"push", onbuildBaseImage},
|
||||||
}
|
}
|
||||||
y := testyaml{
|
y := testyaml{
|
||||||
Steps: []step{containerDiffStep, containerDiffPermissions, GCSBucketTarBuildContext, uploadTarBuildContext, buildExecutorImage,
|
Steps: []step{containerDiffStep, containerDiffPermissions, GCSBucketTarBuildContext,
|
||||||
buildOnbuildImage, pushOnbuildBase},
|
uploadTarBuildContext, buildExecutorImage, buildOnbuildImage, pushOnbuildBase},
|
||||||
Timeout: "1200s",
|
Timeout: "1200s",
|
||||||
}
|
}
|
||||||
for _, test := range fileTests {
|
for _, test := range fileTests {
|
||||||
// First, build the image with docker
|
// First, build the image with docker
|
||||||
dockerImageTag := testRepo + dockerPrefix + test.repo
|
dockerImageTag := testRepo + dockerPrefix + test.repo
|
||||||
|
var buildArgs []string
|
||||||
|
buildArgFlag := "--build-arg"
|
||||||
|
for _, arg := range test.args {
|
||||||
|
buildArgs = append(buildArgs, buildArgFlag)
|
||||||
|
buildArgs = append(buildArgs, arg)
|
||||||
|
}
|
||||||
dockerBuild := step{
|
dockerBuild := step{
|
||||||
Name: dockerImage,
|
Name: dockerImage,
|
||||||
Args: []string{"build", "-t", dockerImageTag, "-f", test.dockerfilePath, test.dockerContext},
|
Args: append([]string{"build", "-t", dockerImageTag, "-f", test.dockerfilePath, test.dockerContext}, buildArgs...),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, buld the image with kaniko
|
// Then, buld the image with kaniko
|
||||||
kanikoImage := testRepo + kanikoPrefix + test.repo
|
kanikoImage := testRepo + kanikoPrefix + test.repo
|
||||||
snapshotMode := ""
|
snapshotMode := ""
|
||||||
|
|
@ -255,7 +278,7 @@ func main() {
|
||||||
}
|
}
|
||||||
kaniko := step{
|
kaniko := step{
|
||||||
Name: executorImage,
|
Name: executorImage,
|
||||||
Args: []string{"--destination", kanikoImage, "--dockerfile", test.dockerfilePath, contextFlag, test.kanikoContext, snapshotMode},
|
Args: append([]string{"--destination", kanikoImage, "--dockerfile", test.dockerfilePath, contextFlag, test.kanikoContext, snapshotMode}, buildArgs...),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pull the kaniko image
|
// Pull the kaniko image
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -41,7 +42,7 @@ type AddCommand struct {
|
||||||
// - If dest doesn't end with a slash, the filepath is inferred to be <dest>/<filename>
|
// - If dest doesn't end with a slash, the filepath is inferred to be <dest>/<filename>
|
||||||
// 2. If <src> is a local tar archive:
|
// 2. If <src> is a local tar archive:
|
||||||
// -If <src> is a local tar archive, it is unpacked at the dest, as 'tar -x' would
|
// -If <src> is a local tar archive, it is unpacked at the dest, as 'tar -x' would
|
||||||
func (a *AddCommand) ExecuteCommand(config *v1.Config) error {
|
func (a *AddCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
srcs := a.cmd.SourcesAndDest[:len(a.cmd.SourcesAndDest)-1]
|
srcs := a.cmd.SourcesAndDest[:len(a.cmd.SourcesAndDest)-1]
|
||||||
dest := a.cmd.SourcesAndDest[len(a.cmd.SourcesAndDest)-1]
|
dest := a.cmd.SourcesAndDest[len(a.cmd.SourcesAndDest)-1]
|
||||||
|
|
||||||
|
|
@ -49,7 +50,8 @@ func (a *AddCommand) ExecuteCommand(config *v1.Config) error {
|
||||||
logrus.Infof("dest: %s", dest)
|
logrus.Infof("dest: %s", dest)
|
||||||
|
|
||||||
// First, resolve any environment replacement
|
// First, resolve any environment replacement
|
||||||
resolvedEnvs, err := util.ResolveEnvironmentReplacementList(a.cmd.SourcesAndDest, config.Env, true)
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
|
resolvedEnvs, err := util.ResolveEnvironmentReplacementList(a.cmd.SourcesAndDest, replacementEnvs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +103,7 @@ func (a *AddCommand) ExecuteCommand(config *v1.Config) error {
|
||||||
},
|
},
|
||||||
buildcontext: a.buildcontext,
|
buildcontext: a.buildcontext,
|
||||||
}
|
}
|
||||||
if err := copyCmd.ExecuteCommand(config); err != nil {
|
if err := copyCmd.ExecuteCommand(config, buildArgs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
a.snapshotFiles = append(a.snapshotFiles, copyCmd.snapshotFiles...)
|
a.snapshotFiles = append(a.snapshotFiles, copyCmd.snapshotFiles...)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Google LLC
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
|
"github.com/google/go-containerregistry/v1"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ArgCommand struct {
|
||||||
|
cmd *instructions.ArgCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecuteCommand only needs to add this ARG key/value as seen
|
||||||
|
func (r *ArgCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
|
logrus.Info("ARG")
|
||||||
|
buildArgs.AddArg(r.cmd.Key, r.cmd.Value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilesToSnapshot returns an empty array since this command only touches metadata.
|
||||||
|
func (r *ArgCommand) FilesToSnapshot() []string {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatedBy returns some information about the command for the image config history
|
||||||
|
func (r *ArgCommand) CreatedBy() string {
|
||||||
|
return strings.Join([]string{r.cmd.Name(), r.cmd.Key}, " ")
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
|
|
@ -30,7 +31,7 @@ type CmdCommand struct {
|
||||||
|
|
||||||
// ExecuteCommand executes the CMD command
|
// ExecuteCommand executes the CMD command
|
||||||
// Argument handling is the same as RUN.
|
// Argument handling is the same as RUN.
|
||||||
func (c *CmdCommand) ExecuteCommand(config *v1.Config) error {
|
func (c *CmdCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: CMD")
|
logrus.Info("cmd: CMD")
|
||||||
var newCommand []string
|
var newCommand []string
|
||||||
if c.cmd.PrependShell {
|
if c.cmd.PrependShell {
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,10 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/go-containerregistry/v1"
|
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/testutil"
|
"github.com/GoogleContainerTools/kaniko/testutil"
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
|
"github.com/google/go-containerregistry/v1"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdTests = []struct {
|
var cmdTests = []struct {
|
||||||
|
|
@ -56,7 +54,7 @@ func TestExecuteCmd(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := cmd.ExecuteCommand(cfg)
|
err := cmd.ExecuteCommand(cfg, nil)
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedCmd, cfg.Cmd)
|
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedCmd, cfg.Cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
"github.com/google/go-containerregistry/v1"
|
"github.com/google/go-containerregistry/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
@ -28,7 +29,7 @@ type DockerCommand interface {
|
||||||
// 1. Making required changes to the filesystem (ex. copying files for ADD/COPY or setting ENV variables)
|
// 1. Making required changes to the filesystem (ex. copying files for ADD/COPY or setting ENV variables)
|
||||||
// 2. Updating metadata fields in the config
|
// 2. Updating metadata fields in the config
|
||||||
// It should not change the config history.
|
// It should not change the config history.
|
||||||
ExecuteCommand(*v1.Config) error
|
ExecuteCommand(*v1.Config, *dockerfile.BuildArgs) error
|
||||||
// The config history has a "created by" field, should return information about the command
|
// The config history has a "created by" field, should return information about the command
|
||||||
CreatedBy() string
|
CreatedBy() string
|
||||||
// A list of files to snapshot, empty for metadata commands or nil if we don't know
|
// A list of files to snapshot, empty for metadata commands or nil if we don't know
|
||||||
|
|
@ -63,6 +64,8 @@ func GetCommand(cmd instructions.Command, buildcontext string) (DockerCommand, e
|
||||||
return &VolumeCommand{cmd: c}, nil
|
return &VolumeCommand{cmd: c}, nil
|
||||||
case *instructions.StopSignalCommand:
|
case *instructions.StopSignalCommand:
|
||||||
return &StopSignalCommand{cmd: c}, nil
|
return &StopSignalCommand{cmd: c}, nil
|
||||||
|
case *instructions.ArgCommand:
|
||||||
|
return &ArgCommand{cmd: c}, nil
|
||||||
case *instructions.MaintainerCommand:
|
case *instructions.MaintainerCommand:
|
||||||
logrus.Warnf("%s is deprecated, skipping", cmd.Name())
|
logrus.Warnf("%s is deprecated, skipping", cmd.Name())
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,15 @@ package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/constants"
|
"github.com/GoogleContainerTools/kaniko/pkg/constants"
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
|
||||||
"github.com/google/go-containerregistry/v1"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
|
"github.com/google/go-containerregistry/v1"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CopyCommand struct {
|
type CopyCommand struct {
|
||||||
|
|
@ -33,15 +35,16 @@ type CopyCommand struct {
|
||||||
snapshotFiles []string
|
snapshotFiles []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CopyCommand) ExecuteCommand(config *v1.Config) error {
|
func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
srcs := c.cmd.SourcesAndDest[:len(c.cmd.SourcesAndDest)-1]
|
srcs := c.cmd.SourcesAndDest[:len(c.cmd.SourcesAndDest)-1]
|
||||||
dest := c.cmd.SourcesAndDest[len(c.cmd.SourcesAndDest)-1]
|
dest := c.cmd.SourcesAndDest[len(c.cmd.SourcesAndDest)-1]
|
||||||
|
|
||||||
logrus.Infof("cmd: copy %s", srcs)
|
logrus.Infof("cmd: copy %s", srcs)
|
||||||
logrus.Infof("dest: %s", dest)
|
logrus.Infof("dest: %s", dest)
|
||||||
|
|
||||||
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
// First, resolve any environment replacement
|
// First, resolve any environment replacement
|
||||||
resolvedEnvs, err := util.ResolveEnvironmentReplacementList(c.cmd.SourcesAndDest, config.Env, true)
|
resolvedEnvs, err := util.ResolveEnvironmentReplacementList(c.cmd.SourcesAndDest, replacementEnvs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
|
|
@ -29,7 +30,7 @@ type EntrypointCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteCommand handles command processing similar to CMD and RUN,
|
// ExecuteCommand handles command processing similar to CMD and RUN,
|
||||||
func (e *EntrypointCommand) ExecuteCommand(config *v1.Config) error {
|
func (e *EntrypointCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: ENTRYPOINT")
|
logrus.Info("cmd: ENTRYPOINT")
|
||||||
var newCommand []string
|
var newCommand []string
|
||||||
if e.cmd.PrependShell {
|
if e.cmd.PrependShell {
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ func TestEntrypointExecuteCmd(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := cmd.ExecuteCommand(cfg)
|
err := cmd.ExecuteCommand(cfg, nil)
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedCmd, cfg.Entrypoint)
|
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedCmd, cfg.Entrypoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
|
@ -29,15 +30,16 @@ type EnvCommand struct {
|
||||||
cmd *instructions.EnvCommand
|
cmd *instructions.EnvCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EnvCommand) ExecuteCommand(config *v1.Config) error {
|
func (e *EnvCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: ENV")
|
logrus.Info("cmd: ENV")
|
||||||
newEnvs := e.cmd.Env
|
newEnvs := e.cmd.Env
|
||||||
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
for index, pair := range newEnvs {
|
for index, pair := range newEnvs {
|
||||||
expandedKey, err := util.ResolveEnvironmentReplacement(pair.Key, config.Env, false)
|
expandedKey, err := util.ResolveEnvironmentReplacement(pair.Key, replacementEnvs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
expandedValue, err := util.ResolveEnvironmentReplacement(pair.Value, config.Env, false)
|
expandedValue, err := util.ResolveEnvironmentReplacement(pair.Value, replacementEnvs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,12 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/testutil"
|
"github.com/GoogleContainerTools/kaniko/testutil"
|
||||||
|
docker "github.com/docker/docker/builder/dockerfile"
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
"github.com/google/go-containerregistry/v1"
|
"github.com/google/go-containerregistry/v1"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUpdateEnvConfig(t *testing.T) {
|
func TestUpdateEnvConfig(t *testing.T) {
|
||||||
|
|
@ -77,6 +78,10 @@ func Test_EnvExecute(t *testing.T) {
|
||||||
Key: "$path",
|
Key: "$path",
|
||||||
Value: "$home/",
|
Value: "$home/",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Key: "$buildArg1",
|
||||||
|
Value: "$buildArg2",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -86,7 +91,20 @@ func Test_EnvExecute(t *testing.T) {
|
||||||
"home=/root",
|
"home=/root",
|
||||||
"HOME=/root",
|
"HOME=/root",
|
||||||
"/usr/=/root/",
|
"/usr/=/root/",
|
||||||
|
"foo=foo2",
|
||||||
}
|
}
|
||||||
err := envCmd.ExecuteCommand(cfg)
|
buildArgs := setUpBuildArgs()
|
||||||
|
err := envCmd.ExecuteCommand(cfg, buildArgs)
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, err, expectedEnvs, cfg.Env)
|
testutil.CheckErrorAndDeepEqual(t, false, err, expectedEnvs, cfg.Env)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setUpBuildArgs() *docker.BuildArgs {
|
||||||
|
buildArgs := dockerfile.NewBuildArgs([]string{
|
||||||
|
"buildArg1=foo",
|
||||||
|
"buildArg2=foo2",
|
||||||
|
})
|
||||||
|
buildArgs.AddArg("buildArg1", nil)
|
||||||
|
d := "default"
|
||||||
|
buildArgs.AddArg("buildArg2", &d)
|
||||||
|
return buildArgs
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
|
@ -30,17 +31,18 @@ type ExposeCommand struct {
|
||||||
cmd *instructions.ExposeCommand
|
cmd *instructions.ExposeCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ExposeCommand) ExecuteCommand(config *v1.Config) error {
|
func (r *ExposeCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: EXPOSE")
|
logrus.Info("cmd: EXPOSE")
|
||||||
// Grab the currently exposed ports
|
// Grab the currently exposed ports
|
||||||
existingPorts := config.ExposedPorts
|
existingPorts := config.ExposedPorts
|
||||||
if existingPorts == nil {
|
if existingPorts == nil {
|
||||||
existingPorts = make(map[string]struct{})
|
existingPorts = make(map[string]struct{})
|
||||||
}
|
}
|
||||||
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
// Add any new ones in
|
// Add any new ones in
|
||||||
for _, p := range r.cmd.Ports {
|
for _, p := range r.cmd.Ports {
|
||||||
// Resolve any environment variables
|
// Resolve any environment variables
|
||||||
p, err := util.ResolveEnvironmentReplacement(p, config.Env, false)
|
p, err := util.ResolveEnvironmentReplacement(p, replacementEnvs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/testutil"
|
"github.com/GoogleContainerTools/kaniko/testutil"
|
||||||
|
|
@ -60,8 +61,8 @@ func TestUpdateExposedPorts(t *testing.T) {
|
||||||
"8085/tcp": {},
|
"8085/tcp": {},
|
||||||
"8085/udp": {},
|
"8085/udp": {},
|
||||||
}
|
}
|
||||||
|
buildArgs := dockerfile.NewBuildArgs([]string{})
|
||||||
err := exposeCmd.ExecuteCommand(cfg)
|
err := exposeCmd.ExecuteCommand(cfg, buildArgs)
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, err, expectedPorts, cfg.ExposedPorts)
|
testutil.CheckErrorAndDeepEqual(t, false, err, expectedPorts, cfg.ExposedPorts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,7 +80,7 @@ func TestInvalidProtocol(t *testing.T) {
|
||||||
Ports: ports,
|
Ports: ports,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
buildArgs := dockerfile.NewBuildArgs([]string{})
|
||||||
err := exposeCmd.ExecuteCommand(cfg)
|
err := exposeCmd.ExecuteCommand(cfg, buildArgs)
|
||||||
testutil.CheckErrorAndDeepEqual(t, true, err, nil, nil)
|
testutil.CheckErrorAndDeepEqual(t, true, err, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
|
@ -29,24 +30,29 @@ type LabelCommand struct {
|
||||||
cmd *instructions.LabelCommand
|
cmd *instructions.LabelCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *LabelCommand) ExecuteCommand(config *v1.Config) error {
|
func (r *LabelCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: LABEL")
|
logrus.Info("cmd: LABEL")
|
||||||
return updateLabels(r.cmd.Labels, config)
|
return updateLabels(r.cmd.Labels, config, buildArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateLabels(labels []instructions.KeyValuePair, config *v1.Config) error {
|
func updateLabels(labels []instructions.KeyValuePair, config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
existingLabels := config.Labels
|
existingLabels := config.Labels
|
||||||
if existingLabels == nil {
|
if existingLabels == nil {
|
||||||
existingLabels = make(map[string]string)
|
existingLabels = make(map[string]string)
|
||||||
}
|
}
|
||||||
// Let's unescape values before setting the label
|
// Let's unescape values before setting the label
|
||||||
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
for index, kvp := range labels {
|
for index, kvp := range labels {
|
||||||
unescaped, err := util.ResolveEnvironmentReplacement(kvp.Value, []string{}, false)
|
key, err := util.ResolveEnvironmentReplacement(kvp.Key, replacementEnvs, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
unescaped, err := util.ResolveEnvironmentReplacement(kvp.Value, replacementEnvs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
labels[index] = instructions.KeyValuePair{
|
labels[index] = instructions.KeyValuePair{
|
||||||
Key: kvp.Key,
|
Key: key,
|
||||||
Value: unescaped,
|
Value: unescaped,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/testutil"
|
"github.com/GoogleContainerTools/kaniko/testutil"
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
"github.com/google/go-containerregistry/v1"
|
"github.com/google/go-containerregistry/v1"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUpdateLabels(t *testing.T) {
|
func TestUpdateLabels(t *testing.T) {
|
||||||
|
|
@ -48,14 +48,25 @@ func TestUpdateLabels(t *testing.T) {
|
||||||
Key: "backslashes",
|
Key: "backslashes",
|
||||||
Value: "lots\\\\ of\\\\ words",
|
Value: "lots\\\\ of\\\\ words",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Key: "$label",
|
||||||
|
Value: "foo",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedLabels := map[string]string{
|
arguments := []string{
|
||||||
"foo": "override",
|
"label=build_arg_label",
|
||||||
"bar": "baz",
|
|
||||||
"multiword": "lots of words",
|
|
||||||
"backslashes": "lots\\ of\\ words",
|
|
||||||
}
|
}
|
||||||
updateLabels(labels, cfg)
|
|
||||||
|
buildArgs := dockerfile.NewBuildArgs(arguments)
|
||||||
|
buildArgs.AddArg("label", nil)
|
||||||
|
expectedLabels := map[string]string{
|
||||||
|
"foo": "override",
|
||||||
|
"bar": "baz",
|
||||||
|
"multiword": "lots of words",
|
||||||
|
"backslashes": "lots\\ of\\ words",
|
||||||
|
"build_arg_label": "foo",
|
||||||
|
}
|
||||||
|
updateLabels(labels, cfg, buildArgs)
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, nil, expectedLabels, cfg.Labels)
|
testutil.CheckErrorAndDeepEqual(t, false, nil, expectedLabels, cfg.Labels)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
"github.com/google/go-containerregistry/v1"
|
"github.com/google/go-containerregistry/v1"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
@ -28,10 +29,11 @@ type OnBuildCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
//ExecuteCommand adds the specified expression in Onbuild to the config
|
//ExecuteCommand adds the specified expression in Onbuild to the config
|
||||||
func (o *OnBuildCommand) ExecuteCommand(config *v1.Config) error {
|
func (o *OnBuildCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: ONBUILD")
|
logrus.Info("cmd: ONBUILD")
|
||||||
logrus.Infof("args: %s", o.cmd.Expression)
|
logrus.Infof("args: %s", o.cmd.Expression)
|
||||||
resolvedExpression, err := util.ResolveEnvironmentReplacement(o.cmd.Expression, config.Env, false)
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
|
resolvedExpression, err := util.ResolveEnvironmentReplacement(o.cmd.Expression, replacementEnvs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/testutil"
|
"github.com/GoogleContainerTools/kaniko/testutil"
|
||||||
|
|
@ -62,8 +63,8 @@ func TestExecuteOnbuild(t *testing.T) {
|
||||||
Expression: test.expression,
|
Expression: test.expression,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
buildArgs := dockerfile.NewBuildArgs([]string{})
|
||||||
err := onbuildCmd.ExecuteCommand(cfg)
|
err := onbuildCmd.ExecuteCommand(cfg, buildArgs)
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedArray, cfg.OnBuild)
|
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedArray, cfg.OnBuild)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,22 +17,23 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
|
"github.com/google/go-containerregistry/v1"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
|
||||||
"github.com/google/go-containerregistry/v1"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RunCommand struct {
|
type RunCommand struct {
|
||||||
cmd *instructions.RunCommand
|
cmd *instructions.RunCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RunCommand) ExecuteCommand(config *v1.Config) error {
|
func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
var newCommand []string
|
var newCommand []string
|
||||||
if r.cmd.PrependShell {
|
if r.cmd.PrependShell {
|
||||||
// This is the default shell on Linux
|
// This is the default shell on Linux
|
||||||
|
|
@ -54,7 +55,8 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config) error {
|
||||||
cmd := exec.Command(newCommand[0], newCommand[1:]...)
|
cmd := exec.Command(newCommand[0], newCommand[1:]...)
|
||||||
cmd.Dir = config.WorkingDir
|
cmd.Dir = config.WorkingDir
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Env = config.Env
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
|
cmd.Env = replacementEnvs
|
||||||
|
|
||||||
// If specified, run the command as a specific user
|
// If specified, run the command as a specific user
|
||||||
if config.User != "" {
|
if config.User != "" {
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
|
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
"github.com/google/go-containerregistry/v1"
|
"github.com/google/go-containerregistry/v1"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ShellCommand struct {
|
type ShellCommand struct {
|
||||||
|
|
@ -29,7 +29,7 @@ type ShellCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteCommand handles command processing similar to CMD and RUN,
|
// ExecuteCommand handles command processing similar to CMD and RUN,
|
||||||
func (s *ShellCommand) ExecuteCommand(config *v1.Config) error {
|
func (s *ShellCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: SHELL")
|
logrus.Info("cmd: SHELL")
|
||||||
var newShell []string
|
var newShell []string
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ func TestShellExecuteCmd(t *testing.T) {
|
||||||
Shell: test.cmdLine,
|
Shell: test.cmdLine,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := cmd.ExecuteCommand(cfg)
|
err := cmd.ExecuteCommand(cfg, nil)
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedShell, cfg.Shell)
|
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedShell, cfg.Shell)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,13 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
"github.com/docker/docker/pkg/signal"
|
"github.com/docker/docker/pkg/signal"
|
||||||
"github.com/google/go-containerregistry/v1"
|
"github.com/google/go-containerregistry/v1"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StopSignalCommand struct {
|
type StopSignalCommand struct {
|
||||||
|
|
@ -31,11 +31,12 @@ type StopSignalCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteCommand handles command processing similar to CMD and RUN,
|
// ExecuteCommand handles command processing similar to CMD and RUN,
|
||||||
func (s *StopSignalCommand) ExecuteCommand(config *v1.Config) error {
|
func (s *StopSignalCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: STOPSIGNAL")
|
logrus.Info("cmd: STOPSIGNAL")
|
||||||
|
|
||||||
// resolve possible environment variables
|
// resolve possible environment variables
|
||||||
resolvedEnvs, err := util.ResolveEnvironmentReplacementList([]string{s.cmd.Signal}, config.Env, false)
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
|
resolvedEnvs, err := util.ResolveEnvironmentReplacementList([]string{s.cmd.Signal}, replacementEnvs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/testutil"
|
"github.com/GoogleContainerTools/kaniko/testutil"
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
"github.com/google/go-containerregistry/v1"
|
"github.com/google/go-containerregistry/v1"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var stopsignalTests = []struct {
|
var stopsignalTests = []struct {
|
||||||
|
|
@ -54,7 +54,8 @@ func TestStopsignalExecuteCmd(t *testing.T) {
|
||||||
Signal: test.signal,
|
Signal: test.signal,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := cmd.ExecuteCommand(cfg)
|
b := dockerfile.NewBuildArgs([]string{})
|
||||||
|
err := cmd.ExecuteCommand(cfg, b)
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedSignal, cfg.StopSignal)
|
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedSignal, cfg.StopSignal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,30 +17,31 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os/user"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
"github.com/google/go-containerregistry/v1"
|
"github.com/google/go-containerregistry/v1"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"os/user"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserCommand struct {
|
type UserCommand struct {
|
||||||
cmd *instructions.UserCommand
|
cmd *instructions.UserCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *UserCommand) ExecuteCommand(config *v1.Config) error {
|
func (r *UserCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: USER")
|
logrus.Info("cmd: USER")
|
||||||
u := r.cmd.User
|
u := r.cmd.User
|
||||||
userAndGroup := strings.Split(u, ":")
|
userAndGroup := strings.Split(u, ":")
|
||||||
userStr, err := util.ResolveEnvironmentReplacement(userAndGroup[0], config.Env, false)
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
|
userStr, err := util.ResolveEnvironmentReplacement(userAndGroup[0], replacementEnvs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var groupStr string
|
var groupStr string
|
||||||
if len(userAndGroup) > 1 {
|
if len(userAndGroup) > 1 {
|
||||||
groupStr, err = util.ResolveEnvironmentReplacement(userAndGroup[1], config.Env, false)
|
groupStr, err = util.ResolveEnvironmentReplacement(userAndGroup[1], replacementEnvs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/testutil"
|
"github.com/GoogleContainerTools/kaniko/testutil"
|
||||||
|
|
@ -93,7 +94,8 @@ func TestUpdateUser(t *testing.T) {
|
||||||
User: test.user,
|
User: test.user,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := cmd.ExecuteCommand(cfg)
|
buildArgs := dockerfile.NewBuildArgs([]string{})
|
||||||
|
err := cmd.ExecuteCommand(cfg, buildArgs)
|
||||||
testutil.CheckErrorAndDeepEqual(t, test.shouldError, err, test.expectedUid, cfg.User)
|
testutil.CheckErrorAndDeepEqual(t, test.shouldError, err, test.expectedUid, cfg.User)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -31,10 +32,11 @@ type VolumeCommand struct {
|
||||||
snapshotFiles []string
|
snapshotFiles []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VolumeCommand) ExecuteCommand(config *v1.Config) error {
|
func (v *VolumeCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: VOLUME")
|
logrus.Info("cmd: VOLUME")
|
||||||
volumes := v.cmd.Volumes
|
volumes := v.cmd.Volumes
|
||||||
resolvedVolumes, err := util.ResolveEnvironmentReplacementList(volumes, config.Env, true)
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
|
resolvedVolumes, err := util.ResolveEnvironmentReplacementList(volumes, replacementEnvs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/testutil"
|
"github.com/GoogleContainerTools/kaniko/testutil"
|
||||||
|
|
@ -49,7 +50,7 @@ func TestUpdateVolume(t *testing.T) {
|
||||||
"/var/lib": {},
|
"/var/lib": {},
|
||||||
"/etc": {},
|
"/etc": {},
|
||||||
}
|
}
|
||||||
|
buildArgs := dockerfile.NewBuildArgs([]string{})
|
||||||
err := volumeCmd.ExecuteCommand(cfg)
|
err := volumeCmd.ExecuteCommand(cfg, buildArgs)
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, err, expectedVolumes, cfg.Volumes)
|
testutil.CheckErrorAndDeepEqual(t, false, err, expectedVolumes, cfg.Volumes)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
|
@ -31,10 +32,11 @@ type WorkdirCommand struct {
|
||||||
snapshotFiles []string
|
snapshotFiles []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WorkdirCommand) ExecuteCommand(config *v1.Config) error {
|
func (w *WorkdirCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
logrus.Info("cmd: workdir")
|
logrus.Info("cmd: workdir")
|
||||||
workdirPath := w.cmd.Path
|
workdirPath := w.cmd.Path
|
||||||
resolvedWorkingDir, err := util.ResolveEnvironmentReplacement(workdirPath, config.Env, true)
|
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
|
||||||
|
resolvedWorkingDir, err := util.ResolveEnvironmentReplacement(workdirPath, replacementEnvs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/testutil"
|
"github.com/GoogleContainerTools/kaniko/testutil"
|
||||||
|
|
@ -78,7 +79,8 @@ func TestWorkdirCommand(t *testing.T) {
|
||||||
},
|
},
|
||||||
snapshotFiles: []string{},
|
snapshotFiles: []string{},
|
||||||
}
|
}
|
||||||
cmd.ExecuteCommand(cfg)
|
buildArgs := dockerfile.NewBuildArgs([]string{})
|
||||||
|
cmd.ExecuteCommand(cfg, buildArgs)
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, nil, test.expectedPath, cfg.WorkingDir)
|
testutil.CheckErrorAndDeepEqual(t, false, nil, test.expectedPath, cfg.WorkingDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Google LLC
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dockerfile
|
||||||
|
|
||||||
|
import (
|
||||||
|
d "github.com/docker/docker/builder/dockerfile"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewBuildArgs(args []string) *d.BuildArgs {
|
||||||
|
argsFromOptions := make(map[string]*string)
|
||||||
|
for _, a := range args {
|
||||||
|
s := strings.Split(a, "=")
|
||||||
|
if len(s) == 1 {
|
||||||
|
argsFromOptions[s[0]] = nil
|
||||||
|
} else {
|
||||||
|
argsFromOptions[s[0]] = &s[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d.NewBuildArgs(argsFromOptions)
|
||||||
|
}
|
||||||
|
|
@ -44,7 +44,7 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, dockerInsecureSkipTLSVerify bool) error {
|
func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, dockerInsecureSkipTLSVerify bool, args []string) error {
|
||||||
// Parse dockerfile and unpack base image to root
|
// Parse dockerfile and unpack base image to root
|
||||||
d, err := ioutil.ReadFile(dockerfilePath)
|
d, err := ioutil.ReadFile(dockerfilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -108,6 +108,7 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
buildArgs := dockerfile.NewBuildArgs(args)
|
||||||
// Currently only supports single stage builds
|
// Currently only supports single stage builds
|
||||||
for _, stage := range stages {
|
for _, stage := range stages {
|
||||||
if err := resolveOnBuild(&stage, &imageConfig.Config); err != nil {
|
if err := resolveOnBuild(&stage, &imageConfig.Config); err != nil {
|
||||||
|
|
@ -121,7 +122,7 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke
|
||||||
if dockerCommand == nil {
|
if dockerCommand == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := dockerCommand.ExecuteCommand(&imageConfig.Config); err != nil {
|
if err := dockerCommand.ExecuteCommand(&imageConfig.Config, buildArgs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Now, we get the files to snapshot from this command and take the snapshot
|
// Now, we get the files to snapshot from this command and take the snapshot
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,11 @@ limitations under the License.
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile"
|
||||||
"github.com/docker/docker/builder/dockerfile/instructions"
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
"github.com/docker/docker/builder/dockerfile/parser"
|
"github.com/docker/docker/builder/dockerfile/parser"
|
||||||
"github.com/docker/docker/builder/dockerfile/shell"
|
"github.com/docker/docker/builder/dockerfile/shell"
|
||||||
|
"github.com/google/go-containerregistry/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -222,3 +224,10 @@ func IsSrcRemoteFileURL(rawurl string) bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReplacementEnvs returns a list of all variables that can be used for
|
||||||
|
// environment replacement
|
||||||
|
func ReplacementEnvs(config *v1.Config, buildArgs *dockerfile.BuildArgs) []string {
|
||||||
|
filtered := buildArgs.FilterAllowed(config.Env)
|
||||||
|
return append(config.Env, filtered...)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue