diff --git a/README.md b/README.md index 9e7fa2534..54a086d40 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,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: -* SHELL * HEALTHCHECK * STOPSIGNAL * ARG diff --git a/integration_tests/dockerfiles/Dockerfile_test_workdir b/integration_tests/dockerfiles/Dockerfile_test_workdir index 6c89e4c11..beb508d2b 100644 --- a/integration_tests/dockerfiles/Dockerfile_test_workdir +++ b/integration_tests/dockerfiles/Dockerfile_test_workdir @@ -1,4 +1,4 @@ -FROM gcr.io/google-appengine/debian9:latest +FROM gcr.io/google-appengine/debian9@sha256:6b3aa04751aa2ac3b0c7be4ee71148b66d693ad212ce6d3244bd2a2a147f314a COPY context/foo foo WORKDIR /test # Test that this will be appended on to the previous command, to create /test/workdir diff --git a/pkg/commands/cmd.go b/pkg/commands/cmd.go index 9d53bd98e..79f13770e 100644 --- a/pkg/commands/cmd.go +++ b/pkg/commands/cmd.go @@ -35,8 +35,13 @@ func (c *CmdCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if c.cmd.PrependShell { // This is the default shell on Linux - // TODO: Support shell command here - shell := []string{"/bin/sh", "-c"} + var shell []string + if len(config.Shell) > 0 { + shell = config.Shell + } else { + shell = append(shell, "/bin/sh", "-c") + } + newCommand = append(shell, strings.Join(c.cmd.CmdLine, " ")) } else { newCommand = c.cmd.CmdLine diff --git a/pkg/commands/entrypoint.go b/pkg/commands/entrypoint.go index a753dc5ee..7310c2faf 100644 --- a/pkg/commands/entrypoint.go +++ b/pkg/commands/entrypoint.go @@ -34,8 +34,13 @@ func (e *EntrypointCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if e.cmd.PrependShell { // This is the default shell on Linux - // TODO: Support shell command here - shell := []string{"/bin/sh", "-c"} + var shell []string + if len(config.Shell) > 0 { + shell = config.Shell + } else { + shell = append(shell, "/bin/sh", "-c") + } + newCommand = append(shell, strings.Join(e.cmd.CmdLine, " ")) } else { newCommand = e.cmd.CmdLine diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 849f012d7..7eb545f19 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -36,8 +36,13 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if r.cmd.PrependShell { // This is the default shell on Linux - // TODO: Support shell command here - shell := []string{"/bin/sh", "-c"} + var shell []string + if len(config.Shell) > 0 { + shell = config.Shell + } else { + shell = append(shell, "/bin/sh", "-c") + } + newCommand = append(shell, strings.Join(r.cmd.CmdLine, " ")) } else { newCommand = r.cmd.CmdLine diff --git a/pkg/commands/shell.go b/pkg/commands/shell.go new file mode 100644 index 000000000..89a453914 --- /dev/null +++ b/pkg/commands/shell.go @@ -0,0 +1,54 @@ +/* +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 ( + "strings" + + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" + "github.com/sirupsen/logrus" +) + +type ShellCommand struct { + cmd *instructions.ShellCommand +} + +// ExecuteCommand handles command processing similar to CMD and RUN, +func (s *ShellCommand) ExecuteCommand(config *v1.Config) error { + logrus.Info("cmd: SHELL") + var newShell []string + + newShell = s.cmd.Shell + + logrus.Infof("Replacing Shell in config with %v", newShell) + config.Shell = newShell + return nil +} + +// FilesToSnapshot returns an empty array since this is a metadata command +func (s *ShellCommand) FilesToSnapshot() []string { + return []string{} +} + +// CreatedBy returns some information about the command for the image config history +func (s *ShellCommand) CreatedBy() string { + entrypoint := []string{"SHELL"} + cmdLine := strings.Join(s.cmd.Shell, " ") + + return strings.Join(append(entrypoint, cmdLine), " ") +} diff --git a/pkg/commands/shell_test.go b/pkg/commands/shell_test.go new file mode 100644 index 000000000..524138aab --- /dev/null +++ b/pkg/commands/shell_test.go @@ -0,0 +1,55 @@ +/* +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 ( + "testing" + + "github.com/GoogleContainerTools/kaniko/testutil" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" +) + +var shellTests = []struct { + cmdLine []string + expectedShell []string +}{ + { + cmdLine: []string{"/bin/bash", "-c"}, + expectedShell: []string{"/bin/bash", "-c"}, + }, + { + cmdLine: []string{"/bin/bash"}, + expectedShell: []string{"/bin/bash"}, + }, +} + +func TestShellExecuteCmd(t *testing.T) { + + cfg := &v1.Config{ + Shell: nil, + } + + for _, test := range shellTests { + cmd := ShellCommand{ + &instructions.ShellCommand{ + Shell: test.cmdLine, + }, + } + err := cmd.ExecuteCommand(cfg) + testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedShell, cfg.Shell) + } +}