diff --git a/integration_tests/dockerfiles/Dockerfile_test_metadata b/integration_tests/dockerfiles/Dockerfile_test_metadata new file mode 100644 index 0000000000..261db4d5b9 --- /dev/null +++ b/integration_tests/dockerfiles/Dockerfile_test_metadata @@ -0,0 +1,7 @@ +FROM gcr.io/distroless/base:latest +CMD ["command", "one"] +CMD ["command", "two"] +CMD echo "hello" + +ENTRYPOINT ["execute", "something"] +ENTRYPOINT ["execute", "entrypoint"] diff --git a/integration_tests/dockerfiles/test_metadata.yaml b/integration_tests/dockerfiles/test_metadata.yaml new file mode 100644 index 0000000000..cb0024311b --- /dev/null +++ b/integration_tests/dockerfiles/test_metadata.yaml @@ -0,0 +1,4 @@ +schemaVersion: '2.0.0' +metadataTest: + cmd: ["/bin/sh", "-c", "echo \"hello\""] + entrypoint: ["execute", "entrypoint"] diff --git a/integration_tests/integration_test_yaml.go b/integration_tests/integration_test_yaml.go index e81d4269dc..3129456ff6 100644 --- a/integration_tests/integration_test_yaml.go +++ b/integration_tests/integration_test_yaml.go @@ -73,6 +73,13 @@ var structureTests = []struct { dockerBuildContext: "/workspace/integration_tests/dockerfiles/", structureTestYamlPath: "/workspace/integration_tests/dockerfiles/test_env.yaml", }, + { + description: "test metadata", + dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_metadata", + repo: "test-metadata", + dockerBuildContext: "/workspace/integration_tests/dockerfiles/", + structureTestYamlPath: "/workspace/integration_tests/dockerfiles/test_metadata.yaml", + }, } type step struct { diff --git a/pkg/commands/cmd.go b/pkg/commands/cmd.go new file mode 100644 index 0000000000..4d49234b20 --- /dev/null +++ b/pkg/commands/cmd.go @@ -0,0 +1,65 @@ +/* +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/containers/image/manifest" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/sirupsen/logrus" + "strings" +) + +type CmdCommand struct { + cmd *instructions.CmdCommand +} + +// ExecuteCommand executes the CMD command +// Argument handling is the same as RUN. +func (c *CmdCommand) ExecuteCommand(config *manifest.Schema2Config) error { + logrus.Info("cmd: CMD") + var newCommand []string + if c.cmd.PrependShell { + // This is the default shell on Linux + // TODO: Support shell command here + shell := []string{"/bin/sh", "-c"} + newCommand = append(shell, strings.Join(c.cmd.CmdLine, " ")) + } else { + newCommand = c.cmd.CmdLine + } + + logrus.Infof("Replacing CMD in config with %v", newCommand) + config.Cmd = newCommand + return nil +} + +// FilesToSnapshot returns an empty array since this is a metadata command +func (c *CmdCommand) FilesToSnapshot() []string { + return []string{} +} + +// CreatedBy returns some information about the command for the image config history +func (c *CmdCommand) CreatedBy() string { + cmd := []string{"CMD"} + cmdLine := strings.Join(c.cmd.CmdLine, " ") + if c.cmd.PrependShell { + // TODO: Support shell command here + shell := []string{"/bin/sh", "-c"} + appendedShell := append(cmd, shell...) + return strings.Join(append(appendedShell, cmdLine), " ") + } + return strings.Join(append(cmd, cmdLine), " ") +} diff --git a/pkg/commands/cmd_test.go b/pkg/commands/cmd_test.go new file mode 100644 index 0000000000..3a966da113 --- /dev/null +++ b/pkg/commands/cmd_test.go @@ -0,0 +1,61 @@ +/* +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/GoogleCloudPlatform/k8s-container-builder/testutil" + "github.com/containers/image/manifest" + "github.com/containers/image/pkg/strslice" + "github.com/docker/docker/builder/dockerfile/instructions" + "testing" +) + +var cmdTests = []struct { + prependShell bool + cmdLine []string + expectedCmd strslice.StrSlice +}{ + { + prependShell: true, + cmdLine: []string{"echo", "cmd1"}, + expectedCmd: strslice.StrSlice{"/bin/sh", "-c", "echo cmd1"}, + }, + { + prependShell: false, + cmdLine: []string{"echo", "cmd2"}, + expectedCmd: strslice.StrSlice{"echo", "cmd2"}, + }, +} + +func TestExecuteCmd(t *testing.T) { + + cfg := &manifest.Schema2Config{ + Cmd: nil, + } + + for _, test := range cmdTests { + cmd := CmdCommand{ + &instructions.CmdCommand{ + ShellDependantCmdLine: instructions.ShellDependantCmdLine{ + PrependShell: test.prependShell, + CmdLine: test.cmdLine, + }, + }, + } + err := cmd.ExecuteCommand(cfg) + testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedCmd, cfg.Cmd) + } +} diff --git a/pkg/commands/commands.go b/pkg/commands/commands.go index 7a485649d5..08fa3ceb17 100644 --- a/pkg/commands/commands.go +++ b/pkg/commands/commands.go @@ -44,6 +44,10 @@ func GetCommand(cmd instructions.Command, buildcontext string) (DockerCommand, e return &ExposeCommand{cmd: c}, nil case *instructions.EnvCommand: return &EnvCommand{cmd: c}, nil + case *instructions.CmdCommand: + return &CmdCommand{cmd: c}, nil + case *instructions.EntrypointCommand: + return &EntrypointCommand{cmd: c}, nil case *instructions.LabelCommand: return &LabelCommand{cmd: c}, nil } diff --git a/pkg/commands/entrypoint.go b/pkg/commands/entrypoint.go new file mode 100644 index 0000000000..a7fd5f3ed3 --- /dev/null +++ b/pkg/commands/entrypoint.go @@ -0,0 +1,64 @@ +/* +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/containers/image/manifest" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/sirupsen/logrus" + "strings" +) + +type EntrypointCommand struct { + cmd *instructions.EntrypointCommand +} + +// ExecuteCommand handles command processing similar to CMD and RUN, +func (e *EntrypointCommand) ExecuteCommand(config *manifest.Schema2Config) error { + logrus.Info("cmd: ENTRYPOINT") + var newCommand []string + if e.cmd.PrependShell { + // This is the default shell on Linux + // TODO: Support shell command here + shell := []string{"/bin/sh", "-c"} + newCommand = append(shell, strings.Join(e.cmd.CmdLine, " ")) + } else { + newCommand = e.cmd.CmdLine + } + + logrus.Infof("Replacing Entrypoint in config with %v", newCommand) + config.Entrypoint = newCommand + return nil +} + +// FilesToSnapshot returns an empty array since this is a metadata command +func (e *EntrypointCommand) FilesToSnapshot() []string { + return []string{} +} + +// CreatedBy returns some information about the command for the image config history +func (e *EntrypointCommand) CreatedBy() string { + entrypoint := []string{"ENTRYPOINT"} + cmdLine := strings.Join(e.cmd.CmdLine, " ") + if e.cmd.PrependShell { + // TODO: Support shell command here + shell := []string{"/bin/sh", "-c"} + appendedShell := append(entrypoint, shell...) + return strings.Join(append(appendedShell, cmdLine), " ") + } + return strings.Join(append(entrypoint, cmdLine), " ") +} diff --git a/pkg/commands/entrypoint_test.go b/pkg/commands/entrypoint_test.go new file mode 100644 index 0000000000..0835de07eb --- /dev/null +++ b/pkg/commands/entrypoint_test.go @@ -0,0 +1,61 @@ +/* +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/GoogleCloudPlatform/k8s-container-builder/testutil" + "github.com/containers/image/manifest" + "github.com/containers/image/pkg/strslice" + "github.com/docker/docker/builder/dockerfile/instructions" + "testing" +) + +var entrypointTests = []struct { + prependShell bool + cmdLine []string + expectedCmd strslice.StrSlice +}{ + { + prependShell: true, + cmdLine: []string{"echo", "cmd1"}, + expectedCmd: strslice.StrSlice{"/bin/sh", "-c", "echo cmd1"}, + }, + { + prependShell: false, + cmdLine: []string{"echo", "cmd2"}, + expectedCmd: strslice.StrSlice{"echo", "cmd2"}, + }, +} + +func TestEntrypointExecuteCmd(t *testing.T) { + + cfg := &manifest.Schema2Config{ + Cmd: nil, + } + + for _, test := range entrypointTests { + cmd := EntrypointCommand{ + &instructions.EntrypointCommand{ + ShellDependantCmdLine: instructions.ShellDependantCmdLine{ + PrependShell: test.prependShell, + CmdLine: test.cmdLine, + }, + }, + } + err := cmd.ExecuteCommand(cfg) + testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedCmd, cfg.Entrypoint) + } +}