Skip to content

Commit

Permalink
Merge pull request #141 from priyawadhwa/multistage
Browse files Browse the repository at this point in the history
Support multi stage builds
  • Loading branch information
priyawadhwa authored May 14, 2018
2 parents fbe3e05 + 459ddff commit cde277c
Show file tree
Hide file tree
Showing 23 changed files with 494 additions and 193 deletions.
12 changes: 8 additions & 4 deletions cmd/executor/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ import (
"os"
"path/filepath"

"github.com/GoogleContainerTools/kaniko/pkg/executor"
"github.com/genuinetools/amicontained/container"

"github.com/GoogleContainerTools/kaniko/pkg/constants"
"github.com/GoogleContainerTools/kaniko/pkg/executor"
"github.com/GoogleContainerTools/kaniko/pkg/util"
"github.com/genuinetools/amicontained/container"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -78,7 +77,12 @@ var RootCmd = &cobra.Command{
logrus.Error(err)
os.Exit(1)
}
if err := executor.DoBuild(dockerfilePath, srcContext, destination, snapshotMode, dockerInsecureSkipTLSVerify, buildArgs); err != nil {
ref, image, err := executor.DoBuild(dockerfilePath, srcContext, snapshotMode, buildArgs)
if err != nil {
logrus.Error(err)
os.Exit(1)
}
if err := executor.DoPush(ref, image, destination); err != nil {
logrus.Error(err)
os.Exit(1)
}
Expand Down
10 changes: 10 additions & 0 deletions integration_tests/dockerfiles/Dockerfile_test_multistage
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM gcr.io/distroless/base:latest
COPY . .

FROM scratch as second
ENV foopath context/foo
COPY --from=0 $foopath context/b* /foo/

FROM gcr.io/distroless/base:latest
ARG file
COPY --from=second /foo $file
12 changes: 12 additions & 0 deletions integration_tests/dockerfiles/config_test_multistage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"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
}
}
]
11 changes: 11 additions & 0 deletions integration_tests/integration_test_yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,17 @@ var fileTests = []struct {
"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 {
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (a *AddCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
logrus.Infof("dest: %s", dest)

// First, resolve any environment replacement
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
resolvedEnvs, err := util.ResolveEnvironmentReplacementList(a.cmd.SourcesAndDest, replacementEnvs, true)
if err != nil {
return err
Expand Down
6 changes: 5 additions & 1 deletion pkg/commands/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
logrus.Infof("cmd: copy %s", srcs)
logrus.Infof("dest: %s", dest)

replacementEnvs := util.ReplacementEnvs(config, buildArgs)
// Resolve from
if c.cmd.From != "" {
c.buildcontext = filepath.Join(constants.KanikoDir, c.cmd.From)
}
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
// First, resolve any environment replacement
resolvedEnvs, err := util.ResolveEnvironmentReplacementList(c.cmd.SourcesAndDest, replacementEnvs, true)
if err != nil {
Expand Down
53 changes: 2 additions & 51 deletions pkg/commands/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,57 +33,8 @@ type EnvCommand struct {
func (e *EnvCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
logrus.Info("cmd: ENV")
newEnvs := e.cmd.Env
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
for index, pair := range newEnvs {
expandedKey, err := util.ResolveEnvironmentReplacement(pair.Key, replacementEnvs, false)
if err != nil {
return err
}
expandedValue, err := util.ResolveEnvironmentReplacement(pair.Value, replacementEnvs, false)
if err != nil {
return err
}
newEnvs[index] = instructions.KeyValuePair{
Key: expandedKey,
Value: expandedValue,
}
}
return updateConfigEnv(newEnvs, config)
}

func updateConfigEnv(newEnvs []instructions.KeyValuePair, config *v1.Config) error {
// First, convert config.Env array to []instruction.KeyValuePair
var kvps []instructions.KeyValuePair
for _, env := range config.Env {
entry := strings.Split(env, "=")
kvps = append(kvps, instructions.KeyValuePair{
Key: entry[0],
Value: entry[1],
})
}
// Iterate through new environment variables, and replace existing keys
// We can't use a map because we need to preserve the order of the environment variables
Loop:
for _, newEnv := range newEnvs {
for index, kvp := range kvps {
// If key exists, replace the KeyValuePair...
if kvp.Key == newEnv.Key {
logrus.Debugf("Replacing environment variable %v with %v in config", kvp, newEnv)
kvps[index] = newEnv
continue Loop
}
}
// ... Else, append it as a new env variable
kvps = append(kvps, newEnv)
}
// Convert back to array and set in config
envArray := []string{}
for _, kvp := range kvps {
entry := kvp.Key + "=" + kvp.Value
envArray = append(envArray, entry)
}
config.Env = envArray
return nil
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
return util.UpdateConfigEnv(newEnvs, config, replacementEnvs)
}

// We know that no files have changed, so return an empty array
Expand Down
31 changes: 0 additions & 31 deletions pkg/commands/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,6 @@ import (
"testing"
)

func TestUpdateEnvConfig(t *testing.T) {
cfg := &v1.Config{
Env: []string{
"PATH=/path/to/dir",
"hey=hey",
},
}

newEnvs := []instructions.KeyValuePair{
{
Key: "foo",
Value: "foo2",
},
{
Key: "PATH",
Value: "/new/path/",
},
{
Key: "foo",
Value: "newfoo",
},
}

expectedEnvArray := []string{
"PATH=/new/path/",
"hey=hey",
"foo=newfoo",
}
updateConfigEnv(newEnvs, cfg)
testutil.CheckErrorAndDeepEqual(t, false, nil, expectedEnvArray, cfg.Env)
}
func Test_EnvExecute(t *testing.T) {
cfg := &v1.Config{
Env: []string{
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/expose.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (r *ExposeCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.
if existingPorts == nil {
existingPorts = make(map[string]struct{})
}
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
// Add any new ones in
for _, p := range r.cmd.Ports {
// Resolve any environment variables
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func updateLabels(labels []instructions.KeyValuePair, config *v1.Config, buildAr
existingLabels = make(map[string]string)
}
// Let's unescape values before setting the label
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
for index, kvp := range labels {
key, err := util.ResolveEnvironmentReplacement(kvp.Key, replacementEnvs, false)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/onbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ 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 := util.ReplacementEnvs(config, buildArgs)
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
resolvedExpression, err := util.ResolveEnvironmentReplacement(o.cmd.Expression, replacementEnvs, false)
if err != nil {
return err
Expand Down
3 changes: 1 addition & 2 deletions pkg/commands/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -55,7 +54,7 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
cmd := exec.Command(newCommand[0], newCommand[1:]...)
cmd.Dir = config.WorkingDir
cmd.Stdout = os.Stdout
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
cmd.Env = replacementEnvs

// If specified, run the command as a specific user
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/stopsignal.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (s *StopSignalCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerf
logrus.Info("cmd: STOPSIGNAL")

// resolve possible environment variables
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
resolvedEnvs, err := util.ResolveEnvironmentReplacementList([]string{s.cmd.Signal}, replacementEnvs, false)
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (r *UserCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
logrus.Info("cmd: USER")
u := r.cmd.User
userAndGroup := strings.Split(u, ":")
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
userStr, err := util.ResolveEnvironmentReplacement(userAndGroup[0], replacementEnvs, false)
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type VolumeCommand struct {
func (v *VolumeCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
logrus.Info("cmd: VOLUME")
volumes := v.cmd.Volumes
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
resolvedVolumes, err := util.ResolveEnvironmentReplacementList(volumes, replacementEnvs, true)
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/workdir.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type WorkdirCommand struct {
func (w *WorkdirCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
logrus.Info("cmd: workdir")
workdirPath := w.cmd.Path
replacementEnvs := util.ReplacementEnvs(config, buildArgs)
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
resolvedWorkingDir, err := util.ResolveEnvironmentReplacement(workdirPath, replacementEnvs, true)
if err != nil {
return err
Expand Down
6 changes: 6 additions & 0 deletions pkg/dockerfile/buildargs.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ func NewBuildArgs(args []string) *BuildArgs {
*d.NewBuildArgs(argsFromOptions),
}
}

// ReplacementEnvs returns a list of filtered environment variables
func (b *BuildArgs) ReplacementEnvs(envs []string) []string {
filtered := b.FilterAllowed(envs)
return append(envs, filtered...)
}
Loading

0 comments on commit cde277c

Please sign in to comment.