From 5e6b60f46ed139e6a1ebe284f02f62fc3136da46 Mon Sep 17 00:00:00 2001 From: Sharif Elgamal Date: Thu, 24 May 2018 11:28:32 -0700 Subject: [PATCH] adding metadata tests back to integration tests (#185) * adding metadata tests back to integration tests and fixing resulting bugs * fix onbuild and default env * removing old test files * adding the ArgsEscaped boolean on CMD commands * fix onbuild test * ignore failing test until container-diff is fixed * code comments * adding todo to remove uncomment failing test --- .../dockerfiles/Dockerfile_test_expose | 8 + integration/dockerfiles/Dockerfile_test_label | 7 + .../dockerfiles/Dockerfile_test_multistage | 0 .../dockerfiles/Dockerfile_test_user_run | 2 + integration/integration_test.go | 28 +- .../dockerfiles/config_test_multistage.json | 12 - integration_tests/integration_test_yaml.go | 357 ------------------ pkg/commands/cmd.go | 1 + pkg/commands/onbuild.go | 10 +- pkg/commands/onbuild_test.go | 2 +- pkg/commands/run.go | 18 +- pkg/commands/user.go | 37 +- pkg/commands/user_test.go | 12 +- pkg/constants/constants.go | 3 + pkg/executor/executor.go | 6 + pkg/util/command_util.go | 41 ++ 16 files changed, 119 insertions(+), 425 deletions(-) create mode 100644 integration/dockerfiles/Dockerfile_test_expose create mode 100644 integration/dockerfiles/Dockerfile_test_label rename {integration_tests => integration}/dockerfiles/Dockerfile_test_multistage (100%) delete mode 100644 integration_tests/dockerfiles/config_test_multistage.json delete mode 100644 integration_tests/integration_test_yaml.go diff --git a/integration/dockerfiles/Dockerfile_test_expose b/integration/dockerfiles/Dockerfile_test_expose new file mode 100644 index 000000000..aad7c9fea --- /dev/null +++ b/integration/dockerfiles/Dockerfile_test_expose @@ -0,0 +1,8 @@ +FROM gcr.io/google-appengine/debian9 +EXPOSE 80 +EXPOSE 81/udp +ENV protocol tcp +EXPOSE 82/$protocol +ENV port 83 +EXPOSE $port/udp +EXPOSE $port/$protocol diff --git a/integration/dockerfiles/Dockerfile_test_label b/integration/dockerfiles/Dockerfile_test_label new file mode 100644 index 000000000..a52222599 --- /dev/null +++ b/integration/dockerfiles/Dockerfile_test_label @@ -0,0 +1,7 @@ +FROM gcr.io/google-appengine/debian9 +LABEL foo=bar +LABEL "baz"="bat" +ENV label1 "mylabel" +LABEL label1=$label1 +LABEL multilabel1=multilabel1 multilabel2=multilabel2 multilabel3=multilabel3 + diff --git a/integration_tests/dockerfiles/Dockerfile_test_multistage b/integration/dockerfiles/Dockerfile_test_multistage similarity index 100% rename from integration_tests/dockerfiles/Dockerfile_test_multistage rename to integration/dockerfiles/Dockerfile_test_multistage diff --git a/integration/dockerfiles/Dockerfile_test_user_run b/integration/dockerfiles/Dockerfile_test_user_run index a71fb535e..511043c5a 100644 --- a/integration/dockerfiles/Dockerfile_test_user_run +++ b/integration/dockerfiles/Dockerfile_test_user_run @@ -17,3 +17,5 @@ RUN useradd testuser RUN groupadd testgroup USER testuser:testgroup RUN echo "hey" > /tmp/foo +USER testuser:1001 +RUN echo "hey2" >> /tmp/foo \ No newline at end of file diff --git a/integration/integration_test.go b/integration/integration_test.go index 4f31f3c20..37bb4552e 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -44,14 +44,23 @@ const ( buildContextPath = "/workspace" emptyContainerDiff = `[ { - "Image1": "%s:latest", - "Image2": "%s:latest", + "Image1": "%s", + "Image2": "%s", "DiffType": "File", "Diff": { "Adds": null, "Dels": null, "Mods": null } + }, + { + "Image1": "%s", + "Image2": "%s", + "DiffType": "Metadata", + "Diff": { + "Adds": [], + "Dels": [] + } } ]` ) @@ -76,7 +85,7 @@ func TestMain(m *testing.M) { } func TestRun(t *testing.T) { - dockerfiles, err := filepath.Glob(path.Join(dockerfilesPath, "Dockerfile*")) + dockerfiles, err := filepath.Glob(path.Join(dockerfilesPath, "Dockerfile_test*")) if err != nil { t.Error(err) t.FailNow() @@ -93,16 +102,25 @@ func TestRun(t *testing.T) { "file=context/foo", "file3=context/b*", }, + "Dockerfile_test_multistage": {"file=/foo2"}, } bucketContextTests := []string{"Dockerfile_test_copy_bucket"} + // TODO: remove test_user_run from this when https://github.com/GoogleContainerTools/container-diff/issues/237 is fixed + testsToIgnore := []string{"Dockerfile_test_user_run"} + _, ex, _, _ := runtime.Caller(0) cwd := filepath.Dir(ex) for _, dockerfile := range dockerfiles { t.Run("test_"+dockerfile, func(t *testing.T) { dockerfile = dockerfile[len("dockerfile/")+1:] + for _, d := range testsToIgnore { + if dockerfile == d { + t.SkipNow() + } + } t.Logf("%s\n", dockerfile) var buildArgs []string @@ -151,11 +169,11 @@ func TestRun(t *testing.T) { daemonDockerImage := daemonPrefix + dockerImage containerdiffCmd := exec.Command("container-diff", "diff", daemonDockerImage, kanikoImage, - "-q", "--type=file", "--json") + "-q", "--type=file", "--type=metadata", "--json") diff := RunCommand(containerdiffCmd, t) t.Logf("diff = %s", string(diff)) - expected := fmt.Sprintf(emptyContainerDiff, dockerImage, kanikoImage) + expected := fmt.Sprintf(emptyContainerDiff, dockerImage, kanikoImage, dockerImage, kanikoImage) // Let's compare the json objects themselves instead of strings to avoid // issues with spaces and indents diff --git a/integration_tests/dockerfiles/config_test_multistage.json b/integration_tests/dockerfiles/config_test_multistage.json deleted file mode 100644 index 9aa0494cb..000000000 --- a/integration_tests/dockerfiles/config_test_multistage.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "Image1": "gcr.io/kaniko-test/docker-test-multistage:latest", - "Image2": "gcr.io/kaniko-test/kaniko-test-multistage:latest", - "DiffType": "File", - "Diff": { - "Adds": null, - "Dels": null, - "Mods": null - } - } -] \ No newline at end of file diff --git a/integration_tests/integration_test_yaml.go b/integration_tests/integration_test_yaml.go deleted file mode 100644 index 110a374fe..000000000 --- a/integration_tests/integration_test_yaml.go +++ /dev/null @@ -1,357 +0,0 @@ -/* -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 main - -import ( - "fmt" - - "gopkg.in/yaml.v2" -) - -const ( - executorImage = "executor-image" - dockerImage = "gcr.io/cloud-builders/docker" - ubuntuImage = "ubuntu" - structureTestImage = "gcr.io/gcp-runtimes/container-structure-test" - testRepo = "gcr.io/kaniko-test/" - dockerPrefix = "docker-" - kanikoPrefix = "kaniko-" - daemonPrefix = "daemon://" - containerDiffOutputFile = "container-diff.json" - kanikoTestBucket = "kaniko-test-bucket" - buildcontextPath = "/workspace/integration_tests" - dockerfilesPath = "/workspace/integration_tests/dockerfiles" - onbuildBaseImage = testRepo + "onbuild-base:latest" -) - -var fileTests = []struct { - description string - dockerfilePath string - configPath string - dockerContext string - kanikoContext string - kanikoContextBucket bool - repo string - snapshotMode string - args []string -}{ - { - description: "test extract filesystem", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_extract_fs", - configPath: "/workspace/integration_tests/dockerfiles/config_test_extract_fs.json", - dockerContext: dockerfilesPath, - kanikoContext: dockerfilesPath, - repo: "extract-filesystem", - snapshotMode: "time", - }, - { - description: "test run", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_run", - configPath: "/workspace/integration_tests/dockerfiles/config_test_run.json", - dockerContext: dockerfilesPath, - kanikoContext: dockerfilesPath, - repo: "test-run", - args: []string{ - "file=/file", - }, - }, - { - description: "test run no files changed", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_run_2", - configPath: "/workspace/integration_tests/dockerfiles/config_test_run_2.json", - dockerContext: dockerfilesPath, - kanikoContext: dockerfilesPath, - repo: "test-run-2", - snapshotMode: "time", - }, - { - description: "test copy", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_copy", - configPath: "/workspace/integration_tests/dockerfiles/config_test_copy.json", - dockerContext: buildcontextPath, - kanikoContext: buildcontextPath, - repo: "test-copy", - snapshotMode: "time", - }, - { - description: "test bucket build context", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_copy", - configPath: "/workspace/integration_tests/dockerfiles/config_test_bucket_buildcontext.json", - dockerContext: buildcontextPath, - kanikoContext: kanikoTestBucket, - kanikoContextBucket: true, - repo: "test-bucket-buildcontext", - }, - { - description: "test workdir", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_workdir", - configPath: "/workspace/integration_tests/dockerfiles/config_test_workdir.json", - dockerContext: buildcontextPath, - kanikoContext: buildcontextPath, - repo: "test-workdir", - args: []string{ - "workdir=/arg/workdir", - }, - }, - { - description: "test volume", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_volume", - configPath: "/workspace/integration_tests/dockerfiles/config_test_volume.json", - dockerContext: buildcontextPath, - kanikoContext: buildcontextPath, - repo: "test-volume", - }, - { - description: "test add", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_add", - configPath: "/workspace/integration_tests/dockerfiles/config_test_add.json", - dockerContext: buildcontextPath, - kanikoContext: buildcontextPath, - repo: "test-add", - args: []string{ - "file=context/foo", - }, - }, - { - description: "test mv add", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_mv_add", - configPath: "/workspace/integration_tests/dockerfiles/config_test_mv_add.json", - dockerContext: buildcontextPath, - kanikoContext: buildcontextPath, - repo: "test-mv-add", - }, - { - description: "test registry", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_registry", - configPath: "/workspace/integration_tests/dockerfiles/config_test_registry.json", - dockerContext: buildcontextPath, - kanikoContext: buildcontextPath, - repo: "test-registry", - }, - { - description: "test onbuild", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_onbuild", - configPath: "/workspace/integration_tests/dockerfiles/config_test_onbuild.json", - dockerContext: buildcontextPath, - kanikoContext: buildcontextPath, - repo: "test-onbuild", - args: []string{ - "file=/tmp/onbuild", - }, - }, - { - description: "test scratch", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_scratch", - configPath: "/workspace/integration_tests/dockerfiles/config_test_scratch.json", - dockerContext: buildcontextPath, - kanikoContext: buildcontextPath, - repo: "test-scratch", - args: []string{ - "hello=hello-value", - "file=context/foo", - "file3=context/b*", - }, - }, - { - description: "test multistage", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_multistage", - configPath: "/workspace/integration_tests/dockerfiles/config_test_multistage.json", - dockerContext: buildcontextPath, - kanikoContext: buildcontextPath, - repo: "test-multistage", - args: []string{ - "file=/foo2", - }, - }, -} - -var structureTests = []struct { - description string - dockerfilePath string - structureTestYamlPath string - dockerBuildContext string - kanikoContext string - repo string -}{ - { - description: "test env", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_env", - repo: "test-env", - dockerBuildContext: dockerfilesPath, - kanikoContext: dockerfilesPath, - structureTestYamlPath: "/workspace/integration_tests/dockerfiles/test_env.yaml", - }, - { - description: "test metadata", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_metadata", - repo: "test-metadata", - dockerBuildContext: dockerfilesPath, - kanikoContext: dockerfilesPath, - structureTestYamlPath: "/workspace/integration_tests/dockerfiles/test_metadata.yaml", - }, - { - description: "test user command", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_user_run", - repo: "test-user", - dockerBuildContext: dockerfilesPath, - kanikoContext: dockerfilesPath, - structureTestYamlPath: "/workspace/integration_tests/dockerfiles/test_user.yaml", - }, -} - -type step struct { - Name string - Args []string - Env []string -} - -type testyaml struct { - Steps []step - Timeout string -} - -func main() { - - // First, copy container-diff in - containerDiffStep := step{ - Name: "gcr.io/cloud-builders/gsutil", - Args: []string{"cp", "gs://container-diff/latest/container-diff-linux-amd64", "."}, - } - containerDiffPermissions := step{ - Name: ubuntuImage, - Args: []string{"chmod", "+x", "container-diff-linux-amd64"}, - } - GCSBucketTarBuildContext := step{ - Name: ubuntuImage, - Args: []string{"tar", "-C", "/workspace/integration_tests/", "-zcvf", "/workspace/context.tar.gz", "."}, - } - uploadTarBuildContext := step{ - Name: "gcr.io/cloud-builders/gsutil", - Args: []string{"cp", "/workspace/context.tar.gz", "gs://kaniko-test-bucket/"}, - } - - // Build executor image - buildExecutorImage := step{ - Name: dockerImage, - Args: []string{"build", "-t", executorImage, "-f", "deploy/Dockerfile", "."}, - } - - // Build and push onbuild base images - buildOnbuildImage := step{ - Name: dockerImage, - Args: []string{"build", "-t", onbuildBaseImage, "-f", "/workspace/integration_tests/dockerfiles/Dockerfile_onbuild_base", "."}, - } - pushOnbuildBase := step{ - Name: dockerImage, - Args: []string{"push", onbuildBaseImage}, - } - y := testyaml{ - Steps: []step{containerDiffStep, containerDiffPermissions, GCSBucketTarBuildContext, - uploadTarBuildContext, buildExecutorImage, buildOnbuildImage, pushOnbuildBase}, - Timeout: "1200s", - } - for _, test := range fileTests { - // First, build the image with docker - 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{ - Name: dockerImage, - Args: append([]string{"build", "-t", dockerImageTag, "-f", test.dockerfilePath, test.dockerContext}, buildArgs...), - } - // Then, buld the image with kaniko - kanikoImage := testRepo + kanikoPrefix + test.repo - snapshotMode := "" - if test.snapshotMode != "" { - snapshotMode = "--snapshotMode=" + test.snapshotMode - } - contextFlag := "--context" - if test.kanikoContextBucket { - contextFlag = "--bucket" - } - kaniko := step{ - Name: executorImage, - Args: append([]string{"--destination", kanikoImage, "--dockerfile", test.dockerfilePath, contextFlag, test.kanikoContext, snapshotMode}, buildArgs...), - } - - // Pull the kaniko image - pullKanikoImage := step{ - Name: dockerImage, - Args: []string{"pull", kanikoImage}, - } - - daemonDockerImage := daemonPrefix + dockerImageTag - daemonKanikoImage := daemonPrefix + kanikoImage - // Run container diff on the images - args := "container-diff-linux-amd64 diff " + daemonDockerImage + " " + daemonKanikoImage + " --type=file -j >" + containerDiffOutputFile - containerDiff := step{ - Name: ubuntuImage, - Args: []string{"sh", "-c", args}, - Env: []string{"PATH=/workspace:/bin"}, - } - - catContainerDiffOutput := step{ - Name: ubuntuImage, - Args: []string{"cat", containerDiffOutputFile}, - } - compareOutputs := step{ - Name: ubuntuImage, - Args: []string{"cmp", "-b", test.configPath, containerDiffOutputFile}, - } - - y.Steps = append(y.Steps, dockerBuild, kaniko, pullKanikoImage, containerDiff, catContainerDiffOutput, compareOutputs) - } - - for _, test := range structureTests { - - // First, build the image with docker - dockerImageTag := testRepo + dockerPrefix + test.repo - dockerBuild := step{ - Name: dockerImage, - Args: []string{"build", "-t", dockerImageTag, "-f", test.dockerfilePath, test.dockerBuildContext}, - } - - // Build the image with kaniko - kanikoImage := testRepo + kanikoPrefix + test.repo - kaniko := step{ - Name: executorImage, - Args: []string{"--destination", kanikoImage, "--dockerfile", test.dockerfilePath, "--context", test.kanikoContext}, - } - // Pull the kaniko image - pullKanikoImage := step{ - Name: dockerImage, - Args: []string{"pull", kanikoImage}, - } - // Run structure tests on the kaniko and docker image - kanikoStructureTest := step{ - Name: structureTestImage, - Args: []string{"test", "--image", kanikoImage, "--config", test.structureTestYamlPath}, - } - dockerStructureTest := step{ - Name: structureTestImage, - Args: []string{"test", "--image", dockerImageTag, "--config", test.structureTestYamlPath}, - } - y.Steps = append(y.Steps, dockerBuild, kaniko, pullKanikoImage, kanikoStructureTest, dockerStructureTest) - } - - d, _ := yaml.Marshal(&y) - fmt.Println(string(d)) -} diff --git a/pkg/commands/cmd.go b/pkg/commands/cmd.go index 9d3338534..23e0e7e3e 100644 --- a/pkg/commands/cmd.go +++ b/pkg/commands/cmd.go @@ -50,6 +50,7 @@ func (c *CmdCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui logrus.Infof("Replacing CMD in config with %v", newCommand) config.Cmd = newCommand + config.ArgsEscaped = true return nil } diff --git a/pkg/commands/onbuild.go b/pkg/commands/onbuild.go index b78f32a84..10cad09db 100644 --- a/pkg/commands/onbuild.go +++ b/pkg/commands/onbuild.go @@ -18,7 +18,6 @@ package commands import ( "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" - "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/docker/docker/builder/dockerfile/instructions" "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" @@ -32,15 +31,10 @@ type OnBuildCommand struct { func (o *OnBuildCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error { logrus.Info("cmd: ONBUILD") logrus.Infof("args: %s", o.cmd.Expression) - replacementEnvs := buildArgs.ReplacementEnvs(config.Env) - resolvedExpression, err := util.ResolveEnvironmentReplacement(o.cmd.Expression, replacementEnvs, false) - if err != nil { - return err - } if config.OnBuild == nil { - config.OnBuild = []string{resolvedExpression} + config.OnBuild = []string{o.cmd.Expression} } else { - config.OnBuild = append(config.OnBuild, resolvedExpression) + config.OnBuild = append(config.OnBuild, o.cmd.Expression) } return nil } diff --git a/pkg/commands/onbuild_test.go b/pkg/commands/onbuild_test.go index 44f304184..0c9d9811d 100644 --- a/pkg/commands/onbuild_test.go +++ b/pkg/commands/onbuild_test.go @@ -34,7 +34,7 @@ var onbuildTests = []struct { expression: "RUN echo \\\"hi\\\" > $dir", onbuildArray: nil, expectedArray: []string{ - "RUN echo \"hi\" > /some/dir", + "RUN echo \\\"hi\\\" > $dir", }, }, { diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 93f37f274..dd190bd60 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -18,6 +18,7 @@ package commands import ( "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/docker/docker/builder/dockerfile/instructions" "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" @@ -61,15 +62,26 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui // If specified, run the command as a specific user if config.User != "" { userAndGroup := strings.Split(config.User, ":") + userStr := userAndGroup[0] + var groupStr string + if len(userAndGroup) > 1 { + groupStr = userAndGroup[1] + } + + uidStr, gidStr, err := util.GetUserFromUsername(userStr, groupStr) + if err != nil { + return err + } + // uid and gid need to be uint32 - uid64, err := strconv.ParseUint(userAndGroup[0], 10, 32) + uid64, err := strconv.ParseUint(uidStr, 10, 32) if err != nil { return err } uid := uint32(uid64) var gid uint32 - if len(userAndGroup) > 1 { - gid64, err := strconv.ParseUint(userAndGroup[1], 10, 32) + if gidStr != "" { + gid64, err := strconv.ParseUint(gidStr, 10, 32) if err != nil { return err } diff --git a/pkg/commands/user.go b/pkg/commands/user.go index c40b6b921..a98007e7c 100644 --- a/pkg/commands/user.go +++ b/pkg/commands/user.go @@ -22,7 +22,6 @@ import ( "github.com/docker/docker/builder/dockerfile/instructions" "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" - "os/user" "strings" ) @@ -47,43 +46,15 @@ func (r *UserCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu } } - // Lookup by username - userObj, err := user.Lookup(userStr) + _, _, err = util.GetUserFromUsername(userStr, groupStr) if err != nil { - if _, ok := err.(user.UnknownUserError); ok { - // Lookup by id - userObj, err = user.LookupId(userStr) - if err != nil { - return err - } - } else { - return err - } + return err } - // Same dance with groups - var group *user.Group if groupStr != "" { - group, err = user.LookupGroup(groupStr) - if err != nil { - if _, ok := err.(user.UnknownGroupError); ok { - group, err = user.LookupGroupId(groupStr) - if err != nil { - return err - } - } else { - return err - } - } + userStr = userStr + ":" + groupStr } - - uid := userObj.Uid - if group != nil { - uid = uid + ":" + group.Gid - } - - logrus.Infof("Setting user to %s", uid) - config.User = uid + config.User = userStr return nil } diff --git a/pkg/commands/user_test.go b/pkg/commands/user_test.go index f4e1759f3..d592dca80 100644 --- a/pkg/commands/user_test.go +++ b/pkg/commands/user_test.go @@ -31,7 +31,7 @@ var userTests = []struct { }{ { user: "root", - expectedUid: "0", + expectedUid: "root", shouldError: false, }, { @@ -46,17 +46,17 @@ var userTests = []struct { }, { user: "root:root", - expectedUid: "0:0", + expectedUid: "root:root", shouldError: false, }, { user: "0:root", - expectedUid: "0:0", + expectedUid: "0:root", shouldError: false, }, { user: "root:0", - expectedUid: "0:0", + expectedUid: "root:0", shouldError: false, }, { @@ -71,12 +71,12 @@ var userTests = []struct { }, { user: "$envuser", - expectedUid: "0", + expectedUid: "root", shouldError: false, }, { user: "root:$envgroup", - expectedUid: "0:0", + expectedUid: "root:root", shouldError: false, }, } diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 1c036b53a..21977bed7 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -50,3 +50,6 @@ const ( // KanikoBuildFiles is the list of files required to build kaniko var KanikoBuildFiles = []string{"/kaniko/executor", "/kaniko/ssl/certs/ca-certificates.crt"} + +// ScratchEnvVars are the default environment variables needed for a scratch image. +var ScratchEnvVars = []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"} diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index 7300ec1d0..e770fe03c 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -99,6 +99,9 @@ func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string) (na return nil, nil, err } imageConfig, err := sourceImage.ConfigFile() + if baseImage == constants.NoBaseImage { + imageConfig.Config.Env = constants.ScratchEnvVars + } if err != nil { return nil, nil, err } @@ -260,5 +263,8 @@ func resolveOnBuild(stage *instructions.Stage, config *v1.Config) error { // Append to the beginning of the commands in the stage stage.Commands = append(cmds, stage.Commands...) logrus.Infof("Executing %v build triggers", len(cmds)) + + // Blank out the Onbuild command list for this image + config.OnBuild = nil return nil } diff --git a/pkg/util/command_util.go b/pkg/util/command_util.go index 0547718aa..0382005e4 100644 --- a/pkg/util/command_util.go +++ b/pkg/util/command_util.go @@ -26,6 +26,7 @@ import ( "net/http" "net/url" "os" + "os/user" "path/filepath" "strings" ) @@ -273,3 +274,43 @@ Loop: config.Env = envArray return nil } + +func GetUserFromUsername(userStr string, groupStr string) (string, string, error) { + // Lookup by username + userObj, err := user.Lookup(userStr) + if err != nil { + if _, ok := err.(user.UnknownUserError); ok { + // Lookup by id + userObj, err = user.LookupId(userStr) + if err != nil { + return "", "", err + } + } else { + return "", "", err + } + } + + // Same dance with groups + var group *user.Group + if groupStr != "" { + group, err = user.LookupGroup(groupStr) + if err != nil { + if _, ok := err.(user.UnknownGroupError); ok { + group, err = user.LookupGroupId(groupStr) + if err != nil { + return "", "", err + } + } else { + return "", "", err + } + } + } + + uid := userObj.Uid + gid := "" + if group != nil { + gid = group.Gid + } + + return uid, gid, nil +}