Skip to content

Commit

Permalink
Merge pull request #204 from priyawadhwa/snapshot
Browse files Browse the repository at this point in the history
Add --single-snapshot flag to snapshot once after the build
  • Loading branch information
priyawadhwa authored Jun 22, 2018
2 parents 9ad8647 + 2adf82c commit 4198901
Show file tree
Hide file tree
Showing 128 changed files with 5,554 additions and 14 deletions.
8 changes: 7 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion cmd/executor/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var (
force bool
buildArgs multiArg
tarPath string
singleSnapshot bool
)

func init() {
Expand All @@ -54,6 +55,7 @@ func init() {
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().StringVarP(&tarPath, "tarPath", "", "", "Path to save the image in as a tarball instead of pushing")
RootCmd.PersistentFlags().BoolVarP(&singleSnapshot, "single-snapshot", "", false, "Set this flag to take a single snapshot at the end of the build.")
}

var RootCmd = &cobra.Command{
Expand All @@ -79,7 +81,13 @@ var RootCmd = &cobra.Command{
logrus.Error(err)
os.Exit(1)
}
ref, image, err := executor.DoBuild(dockerfilePath, srcContext, snapshotMode, buildArgs)
ref, image, err := executor.DoBuild(executor.KanikoBuildArgs{
DockerfilePath: dockerfilePath,
SrcContext: srcContext,
SnapshotMode: snapshotMode,
Args: buildArgs,
SingleSnapshot: singleSnapshot,
})
if err != nil {
logrus.Error(err)
os.Exit(1)
Expand Down
82 changes: 78 additions & 4 deletions integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package integration
import (
"encoding/json"
"fmt"
"math"
"os"
"os/exec"
"path"
Expand All @@ -27,6 +28,9 @@ import (
"strings"
"testing"

"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/daemon"

"github.com/GoogleContainerTools/kaniko/testutil"
)

Expand Down Expand Up @@ -65,6 +69,9 @@ const (
]`
)

// TODO: remove test_user_run from this when https://github.com/GoogleContainerTools/container-diff/issues/237 is fixed
var testsToIgnore = []string{"Dockerfile_test_user_run"}

func TestMain(m *testing.M) {
buildKaniko := exec.Command("docker", "build", "-t", executorImage, "-f", "../deploy/Dockerfile", "..")
err := buildKaniko.Run()
Expand Down Expand Up @@ -106,10 +113,13 @@ func TestRun(t *testing.T) {
"Dockerfile_test_multistage": {"file=/foo2"},
}

bucketContextTests := []string{"Dockerfile_test_copy_bucket"}
// Map for additional flags
additionalFlagsMap := map[string][]string{
"Dockerfile_test_add": {"--single-snapshot"},
"Dockerfile_test_scratch": {"--single-snapshot"},
}

// TODO: remove test_user_run from this when https://github.com/GoogleContainerTools/container-diff/issues/237 is fixed
testsToIgnore := []string{"Dockerfile_test_user_run"}
bucketContextTests := []string{"Dockerfile_test_copy_bucket"}

_, ex, _, _ := runtime.Caller(0)
cwd := filepath.Dir(ex)
Expand Down Expand Up @@ -152,6 +162,7 @@ func TestRun(t *testing.T) {
}

// build kaniko image
additionalFlags := append(buildArgs, additionalFlagsMap[dockerfile]...)
kanikoImage := strings.ToLower(testRepo + kanikoPrefix + dockerfile)
kanikoCmd := exec.Command("docker",
append([]string{"run",
Expand All @@ -161,7 +172,7 @@ func TestRun(t *testing.T) {
"-f", path.Join(buildContextPath, dockerfilesPath, dockerfile),
"-d", kanikoImage,
contextFlag, contextPath},
buildArgs...)...,
additionalFlags...)...,
)

RunCommand(kanikoCmd, t)
Expand Down Expand Up @@ -198,6 +209,69 @@ func TestRun(t *testing.T) {
}
}

func TestLayers(t *testing.T) {
dockerfiles, err := filepath.Glob(path.Join(dockerfilesPath, "Dockerfile_test*"))
if err != nil {
t.Error(err)
t.FailNow()
}
offset := map[string]int{
"Dockerfile_test_add": 9,
"Dockerfile_test_scratch": 3,
// the Docker built image combined some of the dirs defined by separate VOLUME commands into one layer
// which is why this offset exists
"Dockerfile_test_volume": 1,
}
for _, dockerfile := range dockerfiles {
t.Run("test_layer_"+dockerfile, func(t *testing.T) {
dockerfile = dockerfile[len("dockerfile/")+1:]
for _, ignore := range testsToIgnore {
if dockerfile == ignore {
t.SkipNow()
}
}
// Pull the kaniko image
dockerImage := strings.ToLower(testRepo + dockerPrefix + dockerfile)
kanikoImage := strings.ToLower(testRepo + kanikoPrefix + dockerfile)
pullCmd := exec.Command("docker", "pull", kanikoImage)
RunCommand(pullCmd, t)
if err := checkLayers(dockerImage, kanikoImage, offset[dockerfile]); err != nil {
t.Error(err)
t.Fail()
}
})
}
}

func checkLayers(image1, image2 string, offset int) error {
lenImage1, err := numLayers(image1)
if err != nil {
return err
}
lenImage2, err := numLayers(image2)
if err != nil {
return err
}
actualOffset := int(math.Abs(float64(lenImage1 - lenImage2)))
if actualOffset != offset {
return fmt.Errorf("incorrect offset between layers of %s and %s: expected %d but got %d", image1, image2, offset, actualOffset)
}
return nil
}

func numLayers(image string) (int, error) {
ref, err := name.ParseReference(image, name.WeakValidation)
if err != nil {
return 0, err
}
img, err := daemon.Image(ref, &daemon.ReadOptions{})
if err != nil {
return 0, err
}
layers, err := img.Layers()
return len(layers), err
}

func RunCommand(cmd *exec.Cmd, t *testing.T) []byte {
output, err := cmd.CombinedOutput()
if err != nil {
Expand Down
29 changes: 21 additions & 8 deletions pkg/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,18 @@ import (
"github.com/sirupsen/logrus"
)

func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string) (name.Reference, v1.Image, error) {
// KanikoBuildArgs contains all the args required to build the image
type KanikoBuildArgs struct {
DockerfilePath string
SrcContext string
SnapshotMode string
Args []string
SingleSnapshot bool
}

func DoBuild(k KanikoBuildArgs) (name.Reference, v1.Image, error) {
// Parse dockerfile and unpack base image to root
d, err := ioutil.ReadFile(dockerfilePath)
d, err := ioutil.ReadFile(k.DockerfilePath)
if err != nil {
return nil, nil, err
}
Expand All @@ -58,12 +67,12 @@ func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string) (na
}
dockerfile.ResolveStages(stages)

hasher, err := getHasher(snapshotMode)
hasher, err := getHasher(k.SnapshotMode)
if err != nil {
return nil, nil, err
}
for index, stage := range stages {
baseImage, err := util.ResolveEnvironmentReplacement(stage.BaseName, args, false)
baseImage, err := util.ResolveEnvironmentReplacement(stage.BaseName, k.Args, false)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -109,9 +118,10 @@ func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string) (na
if err := resolveOnBuild(&stage, &imageConfig.Config); err != nil {
return nil, nil, err
}
buildArgs := dockerfile.NewBuildArgs(args)
for _, cmd := range stage.Commands {
dockerCommand, err := commands.GetCommand(cmd, srcContext)
buildArgs := dockerfile.NewBuildArgs(k.Args)
for index, cmd := range stage.Commands {
finalCmd := index == len(stage.Commands)-1
dockerCommand, err := commands.GetCommand(cmd, k.SrcContext)
if err != nil {
return nil, nil, err
}
Expand All @@ -121,11 +131,14 @@ func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string) (na
if err := dockerCommand.ExecuteCommand(&imageConfig.Config, buildArgs); err != nil {
return nil, nil, err
}
if !finalStage {
if !finalStage || (k.SingleSnapshot && !finalCmd) {
continue
}
// Now, we get the files to snapshot from this command and take the snapshot
snapshotFiles := dockerCommand.FilesToSnapshot()
if k.SingleSnapshot && finalCmd {
snapshotFiles = nil
}
contents, err := snapshotter.TakeSnapshot(snapshotFiles)
if err != nil {
return nil, nil, err
Expand Down
52 changes: 52 additions & 0 deletions vendor/github.com/docker/docker/api/types/events/events.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 4198901

Please sign in to comment.