Merge remote-tracking branch 'origin/master' into fix-chown

This commit is contained in:
Yoan Blanc 2020-03-18 09:01:15 +01:00
commit 03fcc537c3
No known key found for this signature in database
GPG Key ID: 6058CF4574298812
29 changed files with 858 additions and 126 deletions

View File

@ -1 +0,0 @@
vendor/

View File

@ -2,9 +2,10 @@ language: go
os: linux os: linux
dist: bionic dist: bionic
env: env:
- IMAGE_REPO=localhost:5000 global:
- IMAGE_REPO=localhost:5000 REGISTRY=localhost:5000
go: go:
- "1.13.3" - "1.14"
go_import_path: github.com/GoogleContainerTools/kaniko go_import_path: github.com/GoogleContainerTools/kaniko
jobs: jobs:
include: include:
@ -21,11 +22,16 @@ jobs:
- make travis-setup - make travis-setup
script: script:
- make integration-test-layers - make integration-test-layers
- name: build-image-and-k8s-integration-test
before_install:
- make travis-setup
- make minikube-setup
script:
- make images
- make push
- make integration-test-k8s
- name: integration-test-misc - name: integration-test-misc
before_install: before_install:
- make travis-setup - make travis-setup
script: script:
- make integration-test-misc - make integration-test-misc
- stage: build-images
script:
- make images

View File

@ -55,28 +55,36 @@ out/warmer: $(GO_FILES)
.PHONY: travis-setup .PHONY: travis-setup
travis-setup: travis-setup:
@ ./travis-setup.sh @ ./scripts/travis-setup.sh
.PHONY: minikube-setup
minikube-setup:
@ ./scripts/minikube-setup.sh
.PHONY: test .PHONY: test
test: out/executor test: out/executor
@ ./test.sh @ ./scripts/test.sh
.PHONY: integration-test .PHONY: integration-test
integration-test: integration-test:
@ ./integration-test.sh @ ./scripts/integration-test.sh
.PHONY: integration-test-run .PHONY: integration-test-run
integration-test-run: integration-test-run:
@ ./integration-test.sh -run "TestRun" @ ./scripts/integration-test.sh -run "TestRun"
.PHONY: integration-test-layers .PHONY: integration-test-layers
integration-test-layers: integration-test-layers:
@ ./integration-test.sh -run "TestLayers" @ ./scripts/integration-test.sh -run "TestLayers"
.PHONY: integration-test-k8s
integration-test-k8s:
@ ./scripts/integration-test.sh -run "TestK8s"
.PHONY: integration-test-misc .PHONY: integration-test-misc
integration-test-misc: integration-test-misc:
$(eval RUN_ARG=$(shell ./misc-integration-test.sh)) $(eval RUN_ARG=$(shell ./scripts/misc-integration-test.sh))
@ ./integration-test.sh -run "$(RUN_ARG)" @ ./scripts/integration-test.sh -run "$(RUN_ARG)"
.PHONY: images .PHONY: images
images: images:
@ -86,6 +94,6 @@ images:
.PHONY: push .PHONY: push
push: push:
docker push $(REGISTRY)/executor:latest docker push $(REGISTRY)/executor:latest
docker push $(REGISTRY)/executor:debug docker push $(REGISTRY)/executor:debug
docker push $(REGISTRY)/warmer:latest docker push $(REGISTRY)/warmer:latest

View File

@ -146,6 +146,7 @@ When running kaniko, use the `--context` flag with the appropriate prefix to spe
| Source | Prefix | Example | | Source | Prefix | Example |
|---------|---------|---------| |---------|---------|---------|
| Local Directory | dir://[path to a directory in the kaniko container] | `dir:///workspace` | | Local Directory | dir://[path to a directory in the kaniko container] | `dir:///workspace` |
| Local Tar Gz | tar://[path to a .tar.gz in the kaniko container] | `tar://path/to/context.tar.gz` |
| GCS Bucket | gs://[bucket name]/[path to .tar.gz] | `gs://kaniko-bucket/path/to/context.tar.gz` | | GCS Bucket | gs://[bucket name]/[path to .tar.gz] | `gs://kaniko-bucket/path/to/context.tar.gz` |
| S3 Bucket | s3://[bucket name]/[path to .tar.gz] | `s3://kaniko-bucket/path/to/context.tar.gz` | | S3 Bucket | s3://[bucket name]/[path to .tar.gz] | `s3://kaniko-bucket/path/to/context.tar.gz` |
| Azure Blob Storage| https://[account].[azureblobhostsuffix]/[container]/[path to .tar.gz] | `https://myaccount.blob.core.windows.net/container/path/to/context.tar.gz` | | Azure Blob Storage| https://[account].[azureblobhostsuffix]/[container]/[path to .tar.gz] | `https://myaccount.blob.core.windows.net/container/path/to/context.tar.gz` |
@ -260,21 +261,24 @@ kaniko will build and push the final image in this build step.
Requirements: Requirements:
- [Docker](https://docs.docker.com/install/) - [Docker](https://docs.docker.com/install/)
- [gcloud](https://cloud.google.com/sdk/install)
We can run the kaniko executor image locally in a Docker daemon to build and push an image from a Dockerfile. We can run the kaniko executor image locally in a Docker daemon to build and push an image from a Dockerfile.
1. Load the executor image into the Docker daemon by running: For example, when using gcloud and GCR you could run Kaniko as follows:
```shell
docker run \
-v "$HOME"/.config/gcloud:/root/.config/gcloud \
-v /path/to/context:/workspace \
gcr.io/kaniko-project/executor:latest \
--dockerfile /workspace/Dockerfile
--destination "gcr.io/$PROJECT_ID/$IMAGE_NAME:$TAG"
--context dir:///workspace/"
```
```shell There is also a utility script [`run_in_docker.sh`](./run_in_docker.sh) that can be used as follows:
make images ```shell
``` ./run_in_docker.sh <path to Dockerfile> <path to build context> <destination of final image>
```
2. Run kaniko in Docker using [`run_in_docker.sh`](./run_in_docker.sh):
```shell
./run_in_docker.sh <path to Dockerfile> <path to build context> <destination of final image>
```
_NOTE: `run_in_docker.sh` expects a path to a _NOTE: `run_in_docker.sh` expects a path to a
Dockerfile relative to the absolute path of the build context._ Dockerfile relative to the absolute path of the build context._
@ -284,7 +288,7 @@ context in the local directory `/home/user/kaniko-project`, and a Google Contain
as a remote image destination: as a remote image destination:
```shell ```shell
./run_in_docker.sh /workspace/Dockerfile /home/user/kaniko-project gcr.io//<project-id>/<tag> ./run_in_docker.sh /workspace/Dockerfile /home/user/kaniko-project gcr.io/$PROJECT_ID/$TAG
``` ```
### Caching ### Caching

View File

@ -233,7 +233,7 @@ func copyDockerfile() error {
return nil return nil
} }
// resolveSourceContext unpacks the source context if it is a tar in a bucket // resolveSourceContext unpacks the source context if it is a tar in a bucket or in kaniko container
// it resets srcContext to be the path to the unpacked build context within the image // it resets srcContext to be the path to the unpacked build context within the image
func resolveSourceContext() error { func resolveSourceContext() error {
if opts.SrcContext == "" && opts.Bucket == "" { if opts.SrcContext == "" && opts.Bucket == "" {

View File

@ -14,7 +14,7 @@
# Builds the static Go image to execute in a Kubernetes job # Builds the static Go image to execute in a Kubernetes job
FROM golang:1.13 FROM golang:1.14
ARG GOARCH=amd64 ARG GOARCH=amd64
WORKDIR /go/src/github.com/GoogleContainerTools/kaniko WORKDIR /go/src/github.com/GoogleContainerTools/kaniko
# Get GCR credential helper # Get GCR credential helper
@ -35,7 +35,7 @@ FROM scratch
COPY --from=0 /go/src/github.com/GoogleContainerTools/kaniko/out/executor /kaniko/executor COPY --from=0 /go/src/github.com/GoogleContainerTools/kaniko/out/executor /kaniko/executor
COPY --from=0 /usr/local/bin/docker-credential-gcr /kaniko/docker-credential-gcr COPY --from=0 /usr/local/bin/docker-credential-gcr /kaniko/docker-credential-gcr
COPY --from=0 /go/src/github.com/awslabs/amazon-ecr-credential-helper/bin/linux-amd64/docker-credential-ecr-login /kaniko/docker-credential-ecr-login COPY --from=0 /go/src/github.com/awslabs/amazon-ecr-credential-helper/bin/linux-amd64/docker-credential-ecr-login /kaniko/docker-credential-ecr-login
COPY --from=0 /usr/local/bin/docker-credential-acr-linux /kaniko/docker-credential-acr-linux COPY --from=0 /usr/local/bin/docker-credential-acr-linux /kaniko/docker-credential-acr
COPY files/ca-certificates.crt /kaniko/ssl/certs/ COPY files/ca-certificates.crt /kaniko/ssl/certs/
COPY --from=0 /root/.docker/config.json /kaniko/.docker/config.json COPY --from=0 /root/.docker/config.json /kaniko/.docker/config.json
ENV HOME /root ENV HOME /root

View File

@ -15,7 +15,7 @@
# Builds the static Go image to execute in a Kubernetes job # Builds the static Go image to execute in a Kubernetes job
# Stage 0: Build the executor binary and get credential helpers # Stage 0: Build the executor binary and get credential helpers
FROM golang:1.13 FROM golang:1.14
ARG GOARCH=amd64 ARG GOARCH=amd64
WORKDIR /go/src/github.com/GoogleContainerTools/kaniko WORKDIR /go/src/github.com/GoogleContainerTools/kaniko
# Get GCR credential helper # Get GCR credential helper
@ -25,6 +25,10 @@ RUN docker-credential-gcr configure-docker
# Get Amazon ECR credential helper # Get Amazon ECR credential helper
RUN go get -u github.com/awslabs/amazon-ecr-credential-helper/ecr-login/cli/docker-credential-ecr-login RUN go get -u github.com/awslabs/amazon-ecr-credential-helper/ecr-login/cli/docker-credential-ecr-login
RUN make -C /go/src/github.com/awslabs/amazon-ecr-credential-helper linux-amd64 RUN make -C /go/src/github.com/awslabs/amazon-ecr-credential-helper linux-amd64
# ACR docker credential helper
ADD https://aadacr.blob.core.windows.net/acr-docker-credential-helper/docker-credential-acr-linux-amd64.tar.gz /usr/local/bin
RUN tar -C /usr/local/bin/ -xvzf /usr/local/bin/docker-credential-acr-linux-amd64.tar.gz
COPY . . COPY . .
RUN make GOARCH=${GOARCH} && make out/warmer RUN make GOARCH=${GOARCH} && make out/warmer
@ -39,6 +43,7 @@ FROM scratch
COPY --from=0 /go/src/github.com/GoogleContainerTools/kaniko/out/* /kaniko/ COPY --from=0 /go/src/github.com/GoogleContainerTools/kaniko/out/* /kaniko/
COPY --from=0 /usr/local/bin/docker-credential-gcr /kaniko/docker-credential-gcr COPY --from=0 /usr/local/bin/docker-credential-gcr /kaniko/docker-credential-gcr
COPY --from=0 /go/src/github.com/awslabs/amazon-ecr-credential-helper/bin/linux-amd64/docker-credential-ecr-login /kaniko/docker-credential-ecr-login COPY --from=0 /go/src/github.com/awslabs/amazon-ecr-credential-helper/bin/linux-amd64/docker-credential-ecr-login /kaniko/docker-credential-ecr-login
COPY --from=0 /usr/local/bin/docker-credential-acr-linux /kaniko/docker-credential-acr
COPY --from=1 /distroless/bazel-bin/experimental/busybox/busybox/ /busybox/ COPY --from=1 /distroless/bazel-bin/experimental/busybox/busybox/ /busybox/
# Declare /busybox as a volume to get it automatically whitelisted # Declare /busybox as a volume to get it automatically whitelisted
VOLUME /busybox VOLUME /busybox

View File

@ -14,7 +14,7 @@
# Builds the static Go image to execute in a Kubernetes job # Builds the static Go image to execute in a Kubernetes job
FROM golang:1.13 FROM golang:1.14
ARG GOARCH=amd64 ARG GOARCH=amd64
WORKDIR /go/src/github.com/GoogleContainerTools/kaniko WORKDIR /go/src/github.com/GoogleContainerTools/kaniko
# Get GCR credential helper # Get GCR credential helper
@ -24,6 +24,9 @@ RUN docker-credential-gcr configure-docker
# Get Amazon ECR credential helper # Get Amazon ECR credential helper
RUN go get -u github.com/awslabs/amazon-ecr-credential-helper/ecr-login/cli/docker-credential-ecr-login RUN go get -u github.com/awslabs/amazon-ecr-credential-helper/ecr-login/cli/docker-credential-ecr-login
RUN make -C /go/src/github.com/awslabs/amazon-ecr-credential-helper linux-amd64 RUN make -C /go/src/github.com/awslabs/amazon-ecr-credential-helper linux-amd64
# ACR docker credential helper
ADD https://aadacr.blob.core.windows.net/acr-docker-credential-helper/docker-credential-acr-linux-amd64.tar.gz /usr/local/bin
RUN tar -C /usr/local/bin/ -xvzf /usr/local/bin/docker-credential-acr-linux-amd64.tar.gz
COPY . . COPY . .
RUN make GOARCH=${GOARCH} out/warmer RUN make GOARCH=${GOARCH} out/warmer
@ -32,6 +35,7 @@ FROM scratch
COPY --from=0 /go/src/github.com/GoogleContainerTools/kaniko/out/warmer /kaniko/warmer COPY --from=0 /go/src/github.com/GoogleContainerTools/kaniko/out/warmer /kaniko/warmer
COPY --from=0 /usr/local/bin/docker-credential-gcr /kaniko/docker-credential-gcr COPY --from=0 /usr/local/bin/docker-credential-gcr /kaniko/docker-credential-gcr
COPY --from=0 /go/src/github.com/awslabs/amazon-ecr-credential-helper/bin/linux-amd64/docker-credential-ecr-login /kaniko/docker-credential-ecr-login COPY --from=0 /go/src/github.com/awslabs/amazon-ecr-credential-helper/bin/linux-amd64/docker-credential-ecr-login /kaniko/docker-credential-ecr-login
COPY --from=0 /usr/local/bin/docker-credential-acr-linux /kaniko/docker-credential-acr
COPY files/ca-certificates.crt /kaniko/ssl/certs/ COPY files/ca-certificates.crt /kaniko/ssl/certs/
COPY --from=0 /root/.docker/config.json /kaniko/.docker/config.json COPY --from=0 /root/.docker/config.json /kaniko/.docker/config.json
ENV HOME /root ENV HOME /root

View File

@ -2,18 +2,21 @@ steps:
# First, build kaniko # First, build kaniko
- name: "gcr.io/cloud-builders/docker" - name: "gcr.io/cloud-builders/docker"
args: ["build", "-f", "deploy/Dockerfile", args: ["build", "-f", "deploy/Dockerfile",
"-t", "gcr.io/kaniko-project/executor:${COMMIT_SHA}", "."] "-t", "gcr.io/$PROJECT_ID/${_EXECUTOR_IMAGE_NAME}:${COMMIT_SHA}", "."]
# Then, we want to build kaniko:debug # Then, we want to build kaniko:debug
- name: "gcr.io/cloud-builders/docker" - name: "gcr.io/cloud-builders/docker"
args: ["build", "-f", "deploy/Dockerfile_debug", args: ["build", "-f", "deploy/Dockerfile_debug",
"-t", "gcr.io/kaniko-project/executor:debug-${COMMIT_SHA}", "."] "-t", "gcr.io/$PROJECT_ID/${_EXECUTOR_IMAGE_NAME}:debug-${COMMIT_SHA}", "."]
- name: "gcr.io/cloud-builders/docker" - name: "gcr.io/cloud-builders/docker"
args: ["build", "-f", "deploy/Dockerfile_debug", args: ["build", "-f", "deploy/Dockerfile_debug",
"-t", "gcr.io/kaniko-project/executor:debug", "."] "-t", "gcr.io/$PROJECT_ID/${_EXECUTOR_IMAGE_NAME}:debug", "."]
# Then, we want to build the cache warmer # Then, we want to build the cache warmer
- name: "gcr.io/cloud-builders/docker" - name: "gcr.io/cloud-builders/docker"
args: ["build", "-f", "deploy/Dockerfile_warmer", args: ["build", "-f", "deploy/Dockerfile_warmer",
"-t", "gcr.io/kaniko-project/warmer:${COMMIT_SHA}", "."] "-t", "gcr.io/$PROJECT_ID/${_WARMER_IMAGE_NAME}:${COMMIT_SHA}", "."]
images: ["gcr.io/kaniko-project/executor:${COMMIT_SHA}", images: ["gcr.io/$PROJECT_ID/${_EXECUTOR_IMAGE_NAME}:${COMMIT_SHA}",
"gcr.io/kaniko-project/executor:debug-${COMMIT_SHA}", "gcr.io/$PROJECT_ID/${_EXECUTOR_IMAGE_NAME}:debug-${COMMIT_SHA}",
"gcr.io/kaniko-project/warmer:${COMMIT_SHA}"] "gcr.io/$PROJECT_ID/${_WARMER_IMAGE_NAME}:${COMMIT_SHA}"]
substitutions:
_EXECUTOR_IMAGE_NAME: executor
_WARMER_IMAGE_NAME: warmer

2
go.mod
View File

@ -1,6 +1,6 @@
module github.com/GoogleContainerTools/kaniko module github.com/GoogleContainerTools/kaniko
go 1.13 go 1.14
replace ( replace (
github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf => github.com/containerd/containerd v0.0.0-20191014053712-acdcf13d5eaf github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf => github.com/containerd/containerd v0.0.0-20191014053712-acdcf13d5eaf

View File

@ -20,7 +20,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if ! [ -x "$(command -v golangci-lint)" ]; then if ! [ -x "$(command -v golangci-lint)" ]; then
echo "Installing GolangCI-Lint" echo "Installing GolangCI-Lint"
${DIR}/install_golint.sh -b $GOPATH/bin v1.21.0 ${DIR}/install_golint.sh -b $GOPATH/bin v1.23.7
fi fi
golangci-lint run golangci-lint run

View File

@ -1,40 +0,0 @@
#!/bin/bash
# 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.
set -ex
GCS_BUCKET="${GCS_BUCKET:-gs://kaniko-test-bucket}"
IMAGE_REPO="${IMAGE_REPO:-gcr.io/kaniko-test}"
docker version
# Sets up a kokoro (Google internal integration testing tool) environment
if [ -f "$KOKORO_GFILE_DIR"/common.sh ]; then
echo "Installing dependencies..."
source "$KOKORO_GFILE_DIR/common.sh"
mkdir -p /usr/local/go/src/github.com/GoogleContainerTools/
cp -r github/kaniko /usr/local/go/src/github.com/GoogleContainerTools/
pushd /usr/local/go/src/github.com/GoogleContainerTools/kaniko
echo "Installing container-diff..."
mv $KOKORO_GFILE_DIR/container-diff-linux-amd64 $KOKORO_GFILE_DIR/container-diff
chmod +x $KOKORO_GFILE_DIR/container-diff
export PATH=$PATH:$KOKORO_GFILE_DIR
cp $KOKORO_ROOT/src/keystore/72508_gcr_application_creds $HOME/.config/gcloud/application_default_credentials.json
fi
echo "Running integration tests..."
make out/executor
make out/warmer
go test ./integration/... -v --bucket "${GCS_BUCKET}" --repo "${IMAGE_REPO}" --timeout 50m "$@"

1
integration-test.sh Symbolic link
View File

@ -0,0 +1 @@
scripts/integration-test.sh

View File

@ -185,23 +185,8 @@ func addServiceAccountFlags(flags []string, serviceAccount string) []string {
return flags return flags
} }
// BuildImage will build dockerfile (located at dockerfilesPath) using both kaniko and docker. func (d *DockerFileBuilder) BuildDockerImage(imageRepo, dockerfilesPath, dockerfile, contextDir string) error {
// The resulting image will be tagged with imageRepo. If the dockerfile will be built with fmt.Printf("Building image for Dockerfile %s\n", dockerfile)
// context (i.e. it is in `buildContextTests`) the context will be pulled from gcsBucket.
func (d *DockerFileBuilder) BuildImage(config *integrationTestConfig, dockerfilesPath, dockerfile string) error {
_, ex, _, _ := runtime.Caller(0)
cwd := filepath.Dir(ex)
return d.BuildImageWithContext(config, dockerfilesPath, dockerfile, cwd)
}
func (d *DockerFileBuilder) BuildImageWithContext(config *integrationTestConfig, dockerfilesPath, dockerfile, contextDir string) error {
if _, present := d.filesBuilt[dockerfile]; present {
return nil
}
gcsBucket, serviceAccount, imageRepo := config.gcsBucket, config.serviceAccount, config.imageRepo
fmt.Printf("Building images for Dockerfile %s\n", dockerfile)
var buildArgs []string var buildArgs []string
buildArgFlag := "--build-arg" buildArgFlag := "--build-arg"
@ -230,13 +215,39 @@ func (d *DockerFileBuilder) BuildImageWithContext(config *integrationTestConfig,
dockerCmd.Env = append(dockerCmd.Env, env...) dockerCmd.Env = append(dockerCmd.Env, env...)
} }
timer := timing.Start(dockerfile + "_docker")
out, err := RunCommandWithoutTest(dockerCmd) out, err := RunCommandWithoutTest(dockerCmd)
timing.DefaultRun.Stop(timer)
if err != nil { if err != nil {
return fmt.Errorf("Failed to build image %s with docker command \"%s\": %s %s", dockerImage, dockerCmd.Args, err, string(out)) return fmt.Errorf("Failed to build image %s with docker command \"%s\": %s %s", dockerImage, dockerCmd.Args, err, string(out))
} }
fmt.Printf("Build image for Dockerfile %s as %s. docker build output: %s \n", dockerfile, dockerImage, out) fmt.Printf("Build image for Dockerfile %s as %s. docker build output: %s \n", dockerfile, dockerImage, out)
return nil
}
// BuildImage will build dockerfile (located at dockerfilesPath) using both kaniko and docker.
// The resulting image will be tagged with imageRepo. If the dockerfile will be built with
// context (i.e. it is in `buildContextTests`) the context will be pulled from gcsBucket.
func (d *DockerFileBuilder) BuildImage(config *integrationTestConfig, dockerfilesPath, dockerfile string) error {
_, ex, _, _ := runtime.Caller(0)
cwd := filepath.Dir(ex)
return d.BuildImageWithContext(config, dockerfilesPath, dockerfile, cwd)
}
func (d *DockerFileBuilder) BuildImageWithContext(config *integrationTestConfig, dockerfilesPath, dockerfile, contextDir string) error {
if _, present := d.filesBuilt[dockerfile]; present {
return nil
}
gcsBucket, serviceAccount, imageRepo := config.gcsBucket, config.serviceAccount, config.imageRepo
var buildArgs []string
buildArgFlag := "--build-arg"
for _, arg := range argsMap[dockerfile] {
buildArgs = append(buildArgs, buildArgFlag, arg)
}
timer := timing.Start(dockerfile + "_docker")
d.BuildDockerImage(imageRepo, dockerfilesPath, dockerfile, contextDir)
timing.DefaultRun.Stop(timer)
contextFlag := "-c" contextFlag := "-c"
contextPath := buildContextPath contextPath := buildContextPath
@ -269,7 +280,7 @@ func (d *DockerFileBuilder) BuildImageWithContext(config *integrationTestConfig,
} }
// build kaniko image // build kaniko image
additionalFlags = append(buildArgs, additionalKanikoFlagsMap[dockerfile]...) additionalFlags := append(buildArgs, additionalKanikoFlagsMap[dockerfile]...)
kanikoImage := GetKanikoImage(imageRepo, dockerfile) kanikoImage := GetKanikoImage(imageRepo, dockerfile)
fmt.Printf("Going to build image with kaniko: %s, flags: %s \n", kanikoImage, additionalFlags) fmt.Printf("Going to build image with kaniko: %s, flags: %s \n", kanikoImage, additionalFlags)
@ -301,16 +312,16 @@ func (d *DockerFileBuilder) BuildImageWithContext(config *integrationTestConfig,
kanikoCmd := exec.Command("docker", dockerRunFlags...) kanikoCmd := exec.Command("docker", dockerRunFlags...)
timer = timing.Start(dockerfile + "_kaniko") timer = timing.Start(dockerfile + "_kaniko")
out, err = RunCommandWithoutTest(kanikoCmd) out, err := RunCommandWithoutTest(kanikoCmd)
timing.DefaultRun.Stop(timer) timing.DefaultRun.Stop(timer)
if err != nil { if err != nil {
return fmt.Errorf("Failed to build image %s with kaniko command \"%s\": %s %s", dockerImage, kanikoCmd.Args, err, string(out)) return fmt.Errorf("Failed to build image %s with kaniko command \"%s\": %s %s", kanikoImage, kanikoCmd.Args, err, string(out))
} }
if outputCheck := outputChecks[dockerfile]; outputCheck != nil { if outputCheck := outputChecks[dockerfile]; outputCheck != nil {
if err := outputCheck(dockerfile, out); err != nil { if err := outputCheck(dockerfile, out); err != nil {
return fmt.Errorf("Output check failed for image %s with kaniko command \"%s\": %s %s", dockerImage, kanikoCmd.Args, err, string(out)) return fmt.Errorf("Output check failed for image %s with kaniko command \"%s\": %s %s", kanikoImage, kanikoCmd.Args, err, string(out))
} }
} }

View File

@ -33,11 +33,10 @@ import (
"github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/daemon" "github.com/google/go-containerregistry/pkg/v1/daemon"
"github.com/pkg/errors"
"github.com/GoogleContainerTools/kaniko/pkg/timing" "github.com/GoogleContainerTools/kaniko/pkg/timing"
"github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/pkg/util"
"github.com/GoogleContainerTools/kaniko/testutil" "github.com/GoogleContainerTools/kaniko/testutil"
"github.com/pkg/errors"
) )
var config *integrationTestConfig var config *integrationTestConfig

22
integration/k8s-job.yaml Normal file
View File

@ -0,0 +1,22 @@
apiVersion: batch/v1
kind: Job
metadata:
name: kaniko-test-{{.Name}}
spec:
template:
spec:
hostNetwork: true
containers:
- name: kaniko
image: localhost:5000/executor:debug
args: [ "--context=dir:///workspace",
"--destination={{.KanikoImage}}"]
volumeMounts:
- name: context
mountPath: /workspace
restartPolicy: Never
volumes:
- name: context
hostPath:
path: {{.Context}}
backoffLimit: 1

106
integration/k8s_test.go Normal file
View File

@ -0,0 +1,106 @@
/*
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 integration
import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"testing"
"text/template"
)
type K8sConfig struct {
KanikoImage string
Context string
Name string
}
func TestK8s(t *testing.T) {
cwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
dir := filepath.Join(cwd, "dockerfiles-with-context")
testDirs, err := ioutil.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
builder := NewDockerFileBuilder()
for _, tdInfo := range testDirs {
name := tdInfo.Name()
testDir := filepath.Join(dir, name)
t.Run("test_k8s_with_context_"+name, func(t *testing.T) {
t.Parallel()
if err := builder.BuildDockerImage(
config.imageRepo, "", name, testDir,
); err != nil {
t.Fatal(err)
}
dockerImage := GetDockerImage(config.imageRepo, name)
kanikoImage := GetKanikoImage(config.imageRepo, name)
tmpfile, err := ioutil.TempFile("", "k8s-job-*.yaml")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tmpfile.Name()) // clean up
tmpl := template.Must(template.ParseFiles("k8s-job.yaml"))
job := K8sConfig{KanikoImage: kanikoImage, Context: testDir, Name: name}
if err := tmpl.Execute(tmpfile, job); err != nil {
t.Fatal(err)
}
fmt.Printf("Testing K8s based Kaniko building of dockerfile %s and push to %s \n",
testDir, kanikoImage)
content, err := ioutil.ReadFile(tmpfile.Name())
if err != nil {
log.Fatal(err)
}
fmt.Printf("K8s template %s:\n%s\n", tmpfile.Name(), content)
kubeCmd := exec.Command("kubectl", "apply", "-f", tmpfile.Name())
RunCommand(kubeCmd, t)
fmt.Printf("Waiting for K8s kaniko build job to finish: %s\n",
"job/kaniko-test-"+job.Name)
kubeWaitCmd := exec.Command("kubectl", "wait", "--for=condition=complete", "--timeout=60s",
"job/kaniko-test-"+job.Name)
RunCommand(kubeWaitCmd, t)
diff := containerDiff(t, daemonPrefix+dockerImage, kanikoImage, "--no-cache")
expected := fmt.Sprintf(emptyContainerDiff, dockerImage, kanikoImage, dockerImage, kanikoImage)
checkContainerDiffOutput(t, diff, expected)
})
}
if err := logBenchmarks("benchmark"); err != nil {
t.Logf("Failed to create benchmark file: %v", err)
}
}

View File

@ -43,12 +43,12 @@ func (b *AzureBlob) UnpackTarFromBuildContext() (string, error) {
return "", errors.New("AZURE_STORAGE_ACCESS_KEY environment variable is not set") return "", errors.New("AZURE_STORAGE_ACCESS_KEY environment variable is not set")
} }
// Get storage accoutname for Azure Blob Storage // Get storage accountName for Azure Blob Storage
u, _ := url.Parse(b.context) u, _ := url.Parse(b.context)
parts := azblob.NewBlobURLParts(*u) parts := azblob.NewBlobURLParts(*u)
accountName := strings.Split(parts.Host, ".")[0] accountName := strings.Split(parts.Host, ".")[0]
// Generate credentail with accountname and accountkey // Generate credential with accountName and accountKey
credential, err := azblob.NewSharedKeyCredential(accountName, accountKey) credential, err := azblob.NewSharedKeyCredential(accountName, accountKey)
if err != nil { if err != nil {
return parts.Host, err return parts.Host, err
@ -62,7 +62,7 @@ func (b *AzureBlob) UnpackTarFromBuildContext() (string, error) {
return tarPath, err return tarPath, err
} }
// Downloading contextfile from Azure Blob Storage // Downloading context file from Azure Blob Storage
p := azblob.NewPipeline(credential, azblob.PipelineOptions{}) p := azblob.NewPipeline(credential, azblob.PipelineOptions{})
blobURL := azblob.NewBlobURL(*u, p) blobURL := azblob.NewBlobURL(*u, p)
ctx := context.Background() ctx := context.Background()

View File

@ -24,6 +24,10 @@ import (
"github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/pkg/util"
) )
const (
TarBuildContextPrefix = "tar://"
)
// BuildContext unifies calls to download and unpack the build context. // BuildContext unifies calls to download and unpack the build context.
type BuildContext interface { type BuildContext interface {
// Unpacks a build context and returns the directory where it resides // Unpacks a build context and returns the directory where it resides
@ -51,6 +55,8 @@ func GetBuildContext(srcContext string) (BuildContext, error) {
return &AzureBlob{context: srcContext}, nil return &AzureBlob{context: srcContext}, nil
} }
return nil, errors.New("url provided for https context is not in a supported format, please use the https url for Azure Blob Storage") return nil, errors.New("url provided for https context is not in a supported format, please use the https url for Azure Blob Storage")
case TarBuildContextPrefix:
return &Tar{context: context}, nil
} }
return nil, errors.New("unknown build context prefix provided, please use one of the following: gs://, dir://, s3://, git://, https://") return nil, errors.New("unknown build context prefix provided, please use one of the following: gs://, dir://, tar://, s3://, git://, https://")
} }

40
pkg/buildcontext/tar.go Normal file
View File

@ -0,0 +1,40 @@
/*
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 buildcontext
import (
"os"
"github.com/GoogleContainerTools/kaniko/pkg/constants"
"github.com/GoogleContainerTools/kaniko/pkg/util"
"github.com/pkg/errors"
)
// Tar unifies calls to download and unpack the build context.
type Tar struct {
context string
}
// UnpackTarFromBuildContext unpack the compressed tar file
func (t *Tar) UnpackTarFromBuildContext() (string, error) {
directory := constants.BuildContextDir
if err := os.MkdirAll(directory, 0750); err != nil {
return "", errors.Wrap(err, "unpacking tar from build context")
}
return directory, util.UnpackCompressedTar(t.context, directory)
}

View File

@ -0,0 +1,158 @@
/*
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 buildcontext
import (
"bytes"
"compress/gzip"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"sync"
"testing"
"github.com/GoogleContainerTools/kaniko/pkg/util"
"github.com/GoogleContainerTools/kaniko/testutil"
)
func TestBuildWithLocalTar(t *testing.T) {
_, ex, _, _ := runtime.Caller(0)
cwd := filepath.Dir(ex)
testDir := "test_dir"
testDirLongPath := filepath.Join(cwd, testDir)
dirUnpack := filepath.Join(testDirLongPath, "dir_where_to_unpack")
if err := os.MkdirAll(dirUnpack, 0750); err != nil {
t.Errorf("Failed to create dir_where_to_extract: %v", err)
}
validDockerfile := "Dockerfile_valid"
invalidDockerfile := "Dockerfile_invalid"
nonExistingDockerfile := "Dockerfile_non_existing"
files := map[string]string{
validDockerfile: "FROM debian:9.11\nRUN echo \"valid\"",
invalidDockerfile: "FROM debian:9.11\nRUN echo \"invalid\"",
}
if err := testutil.SetupFiles(testDir, files); err != nil {
t.Errorf("Failed to setup files %v on %s: %v", files, testDir, err)
}
if err := os.Chdir(testDir); err != nil {
t.Fatalf("Failed to Chdir on %s: %v", testDir, err)
}
validTarPath := fmt.Sprintf("%s.tar.gz", validDockerfile)
invalidTarPath := fmt.Sprintf("%s.tar.gz", invalidDockerfile)
nonExistingTarPath := fmt.Sprintf("%s.tar.gz", nonExistingDockerfile)
var wg sync.WaitGroup
wg.Add(1)
// Create Tar Gz File with dockerfile inside
go func(wg *sync.WaitGroup) {
defer wg.Done()
validTarFile, err := os.Create(validTarPath)
if err != nil {
t.Errorf("Failed to create %s: %v", validTarPath, err)
}
defer validTarFile.Close()
invalidTarFile, err := os.Create(invalidTarPath)
if err != nil {
t.Errorf("Failed to create %s: %v", invalidTarPath, err)
}
defer invalidTarFile.Close()
gw := gzip.NewWriter(validTarFile)
defer gw.Close()
tw := util.NewTar(gw)
defer tw.Close()
if err := tw.AddFileToTar(validDockerfile); err != nil {
t.Errorf("Failed to add %s to %s: %v", validDockerfile, validTarPath, err)
}
}(&wg)
// Waiting for the Tar Gz file creation to be done before moving on
wg.Wait()
tests := []struct {
dockerfile string
srcContext string
unpackShouldErr bool
srcShaShouldErr bool
destShaShouldErr bool
}{
{
dockerfile: validDockerfile,
srcContext: filepath.Join(testDir, validTarPath),
unpackShouldErr: false,
srcShaShouldErr: false,
destShaShouldErr: false,
},
{
dockerfile: invalidDockerfile,
srcContext: filepath.Join(testDir, invalidTarPath),
unpackShouldErr: true,
srcShaShouldErr: false,
destShaShouldErr: true,
},
{
dockerfile: nonExistingDockerfile,
srcContext: filepath.Join(testDir, nonExistingTarPath),
unpackShouldErr: true,
srcShaShouldErr: true,
destShaShouldErr: true,
},
}
for _, tt := range tests {
t.Run(tt.dockerfile, func(t *testing.T) {
err := util.UnpackCompressedTar(filepath.Join(cwd, tt.srcContext), dirUnpack)
testutil.CheckError(t, tt.unpackShouldErr, err)
srcSHA, err := getSHAFromFilePath(tt.dockerfile)
testutil.CheckError(t, tt.srcShaShouldErr, err)
destSHA, err := getSHAFromFilePath(filepath.Join(dirUnpack, tt.dockerfile))
testutil.CheckError(t, tt.destShaShouldErr, err)
if err == nil {
testutil.CheckDeepEqual(t, srcSHA, destSHA)
}
})
}
if err := os.RemoveAll(testDirLongPath); err != nil {
t.Errorf("Failed to remove %s: %v", testDirLongPath, err)
}
}
func getSHAFromFilePath(f string) (string, error) {
data, err := ioutil.ReadFile(f)
if err != nil {
return "", err
}
sha, err := util.SHA256(bytes.NewReader(data))
if err != nil {
return "", err
}
return sha, nil
}

View File

@ -73,7 +73,7 @@ type stageBuilder struct {
stageIdxToDigest map[string]string stageIdxToDigest map[string]string
snapshotter snapShotter snapshotter snapShotter
layerCache cache.LayerCache layerCache cache.LayerCache
pushCache cachePusher pushLayerToCache cachePusher
} }
// newStageBuilder returns a new type stageBuilder which contains all the information required to build the stage // newStageBuilder returns a new type stageBuilder which contains all the information required to build the stage
@ -116,7 +116,7 @@ func newStageBuilder(opts *config.KanikoOptions, stage config.KanikoStage, cross
layerCache: &cache.RegistryCache{ layerCache: &cache.RegistryCache{
Opts: opts, Opts: opts,
}, },
pushCache: pushLayerToCache, pushLayerToCache: pushLayerToCache,
} }
for _, cmd := range s.stage.Commands { for _, cmd := range s.stage.Commands {
@ -166,9 +166,15 @@ func initializeConfig(img partial.WithConfigFile, opts *config.KanikoOptions) (*
return imageConfig, nil return imageConfig, nil
} }
func (s *stageBuilder) populateCompositeKey(command fmt.Stringer, files []string, compositeKey CompositeCache) (CompositeCache, error) { func (s *stageBuilder) populateCompositeKey(command fmt.Stringer, files []string, compositeKey CompositeCache, args *dockerfile.BuildArgs, env []string) (CompositeCache, error) {
// First replace all the environment variables or args in the command
replacementEnvs := args.ReplacementEnvs(env)
resolvedCmd, err := util.ResolveEnvironmentReplacement(command.String(), replacementEnvs, false)
if err != nil {
return compositeKey, err
}
// Add the next command to the cache key. // Add the next command to the cache key.
compositeKey.AddKey(command.String()) compositeKey.AddKey(resolvedCmd)
switch v := command.(type) { switch v := command.(type) {
case *commands.CopyCommand: case *commands.CopyCommand:
compositeKey = s.populateCopyCmdCompositeKey(command, v.From(), compositeKey) compositeKey = s.populateCopyCmdCompositeKey(command, v.From(), compositeKey)
@ -221,7 +227,7 @@ func (s *stageBuilder) optimize(compositeKey CompositeCache, cfg v1.Config) erro
return errors.Wrap(err, "failed to get files used from context") return errors.Wrap(err, "failed to get files used from context")
} }
compositeKey, err = s.populateCompositeKey(command, files, compositeKey) compositeKey, err = s.populateCompositeKey(command, files, compositeKey, s.args, cfg.Env)
if err != nil { if err != nil {
return err return err
} }
@ -271,8 +277,6 @@ func (s *stageBuilder) build() error {
compositeKey = NewCompositeCache(s.baseImageDigest) compositeKey = NewCompositeCache(s.baseImageDigest)
} }
compositeKey.AddKey(s.opts.BuildArgs...)
// Apply optimizations to the instructions. // Apply optimizations to the instructions.
if err := s.optimize(*compositeKey, s.cf.Config); err != nil { if err := s.optimize(*compositeKey, s.cf.Config); err != nil {
return errors.Wrap(err, "failed to optimize instructions") return errors.Wrap(err, "failed to optimize instructions")
@ -329,7 +333,7 @@ func (s *stageBuilder) build() error {
return errors.Wrap(err, "failed to get files used from context") return errors.Wrap(err, "failed to get files used from context")
} }
*compositeKey, err = s.populateCompositeKey(command, files, *compositeKey) *compositeKey, err = s.populateCompositeKey(command, files, *compositeKey, s.args, s.cf.Config.Env)
if err != nil { if err != nil {
return err return err
} }
@ -378,7 +382,7 @@ func (s *stageBuilder) build() error {
// Push layer to cache (in parallel) now along with new config file // Push layer to cache (in parallel) now along with new config file
if s.opts.Cache && command.ShouldCacheOutput() { if s.opts.Cache && command.ShouldCacheOutput() {
cacheGroup.Go(func() error { cacheGroup.Go(func() error {
return s.pushCache(s.opts, ck, tarPath, command.String()) return s.pushLayerToCache(s.opts, ck, tarPath, command.String())
}) })
} }
if err := s.saveSnapshotToImage(command.String(), tarPath); err != nil { if err := s.saveSnapshotToImage(command.String(), tarPath); err != nil {

View File

@ -497,7 +497,8 @@ func Test_stageBuilder_optimize(t *testing.T) {
cf := &v1.ConfigFile{} cf := &v1.ConfigFile{}
snap := fakeSnapShotter{} snap := fakeSnapShotter{}
lc := &fakeLayerCache{retrieve: tc.retrieve} lc := &fakeLayerCache{retrieve: tc.retrieve}
sb := &stageBuilder{opts: tc.opts, cf: cf, snapshotter: snap, layerCache: lc} sb := &stageBuilder{opts: tc.opts, cf: cf, snapshotter: snap, layerCache: lc,
args: dockerfile.NewBuildArgs([]string{})}
ck := CompositeCache{} ck := CompositeCache{}
file, err := ioutil.TempFile("", "foo") file, err := ioutil.TempFile("", "foo")
if err != nil { if err != nil {
@ -517,10 +518,135 @@ func Test_stageBuilder_optimize(t *testing.T) {
} }
} }
type stageContext struct {
command fmt.Stringer
args *dockerfile.BuildArgs
env []string
}
func newStageContext(command string, args map[string]string, env []string) stageContext {
dockerArgs := dockerfile.NewBuildArgs([]string{})
for k, v := range args {
dockerArgs.AddArg(k, &v)
}
return stageContext{MockDockerCommand{command: command}, dockerArgs, env}
}
func Test_stageBuilder_populateCompositeKey(t *testing.T) {
testCases := []struct {
description string
cmd1 stageContext
cmd2 stageContext
shdEqual bool
}{
{
description: "cache key for same command, different buildargs, args not used in command",
cmd1: newStageContext(
"RUN echo const > test",
map[string]string{"ARG": "foo"},
[]string{"ENV=foo1"},
),
cmd2: newStageContext(
"RUN echo const > test",
map[string]string{"ARG": "bar"},
[]string{"ENV=bar1"},
),
shdEqual: true,
},
{
description: "cache key for same command with same build args",
cmd1: newStageContext(
"RUN echo $ARG > test",
map[string]string{"ARG": "foo"},
[]string{},
),
cmd2: newStageContext(
"RUN echo $ARG > test",
map[string]string{"ARG": "foo"},
[]string{},
),
shdEqual: true,
},
{
description: "cache key for same command with same env",
cmd1: newStageContext(
"RUN echo $ENV > test",
map[string]string{"ARG": "foo"},
[]string{"ENV=same"},
),
cmd2: newStageContext(
"RUN echo $ENV > test",
map[string]string{"ARG": "bar"},
[]string{"ENV=same"},
),
shdEqual: true,
},
{
description: "cache key for same command with a build arg values",
cmd1: newStageContext(
"RUN echo $ARG > test",
map[string]string{"ARG": "foo"},
[]string{},
),
cmd2: newStageContext(
"RUN echo $ARG > test",
map[string]string{"ARG": "bar"},
[]string{},
),
},
{
description: "cache key for same command with different env values",
cmd1: newStageContext(
"RUN echo $ENV > test",
map[string]string{"ARG": "foo"},
[]string{"ENV=1"},
),
cmd2: newStageContext(
"RUN echo $ENV > test",
map[string]string{"ARG": "foo"},
[]string{"ENV=2"},
),
},
{
description: "cache key for different command same context",
cmd1: newStageContext(
"RUN echo other > test",
map[string]string{"ARG": "foo"},
[]string{"ENV=1"},
),
cmd2: newStageContext(
"RUN echo another > test",
map[string]string{"ARG": "foo"},
[]string{"ENV=1"},
),
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
sb := &stageBuilder{opts: &config.KanikoOptions{SrcContext: "workspace"}}
ck := CompositeCache{}
ck1, err := sb.populateCompositeKey(tc.cmd1.command, []string{}, ck, tc.cmd1.args, tc.cmd1.env)
if err != nil {
t.Errorf("Expected error to be nil but was %v", err)
}
ck2, err := sb.populateCompositeKey(tc.cmd2.command, []string{}, ck, tc.cmd2.args, tc.cmd2.env)
if err != nil {
t.Errorf("Expected error to be nil but was %v", err)
}
key1, key2 := hashCompositeKeys(t, ck1, ck2)
if b := key1 == key2; b != tc.shdEqual {
t.Errorf("expected keys to be equal as %t but found %t", tc.shdEqual, !tc.shdEqual)
}
})
}
}
func Test_stageBuilder_build(t *testing.T) { func Test_stageBuilder_build(t *testing.T) {
type testcase struct { type testcase struct {
description string description string
opts *config.KanikoOptions opts *config.KanikoOptions
args map[string]string
layerCache *fakeLayerCache layerCache *fakeLayerCache
expectedCacheKeys []string expectedCacheKeys []string
pushedCacheKeys []string pushedCacheKeys []string
@ -544,6 +670,7 @@ func Test_stageBuilder_build(t *testing.T) {
t.Errorf("couldn't create hash %v", err) t.Errorf("couldn't create hash %v", err)
} }
command := MockDockerCommand{ command := MockDockerCommand{
command: "meow",
contextFiles: []string{filePath}, contextFiles: []string{filePath},
cacheCommand: MockCachedDockerCommand{ cacheCommand: MockCachedDockerCommand{
contextFiles: []string{filePath}, contextFiles: []string{filePath},
@ -576,6 +703,7 @@ func Test_stageBuilder_build(t *testing.T) {
t.Errorf("couldn't create hash %v", err) t.Errorf("couldn't create hash %v", err)
} }
command := MockDockerCommand{ command := MockDockerCommand{
command: "meow",
contextFiles: []string{filePath}, contextFiles: []string{filePath},
cacheCommand: MockCachedDockerCommand{ cacheCommand: MockCachedDockerCommand{
contextFiles: []string{filePath}, contextFiles: []string{filePath},
@ -838,6 +966,117 @@ COPY %s bar.txt
commands: getCommands(dir, cmds), commands: getCommands(dir, cmds),
} }
}(), }(),
func() testcase {
dir, _ := tempDirAndFile(t)
ch := NewCompositeCache("")
ch.AddKey("RUN foobar")
hash, err := ch.Hash()
if err != nil {
t.Errorf("couldn't create hash %v", err)
}
command := MockDockerCommand{
command: "RUN foobar",
contextFiles: []string{},
cacheCommand: MockCachedDockerCommand{
contextFiles: []string{},
},
}
return testcase{
description: "cached run command with no build arg value used uses cached layer and does not push anything",
config: &v1.ConfigFile{Config: v1.Config{WorkingDir: dir}},
opts: &config.KanikoOptions{Cache: true},
args: map[string]string{
"test": "value",
},
expectedCacheKeys: []string{hash},
commands: []commands.DockerCommand{command},
// layer key needs to be read.
layerCache: &fakeLayerCache{
img: &fakeImage{ImageLayers: []v1.Layer{fakeLayer{}}},
keySequence: []string{hash},
},
rootDir: dir,
}
}(),
func() testcase {
dir, _ := tempDirAndFile(t)
ch := NewCompositeCache("")
ch.AddKey("RUN value")
hash, err := ch.Hash()
if err != nil {
t.Errorf("couldn't create hash %v", err)
}
command := MockDockerCommand{
command: "RUN $arg",
contextFiles: []string{},
cacheCommand: MockCachedDockerCommand{
contextFiles: []string{},
},
}
return testcase{
description: "cached run command with same build arg does not push layer",
config: &v1.ConfigFile{Config: v1.Config{WorkingDir: dir}},
opts: &config.KanikoOptions{Cache: true},
args: map[string]string{
"arg": "value",
},
// layer key that exists
layerCache: &fakeLayerCache{
img: &fakeImage{ImageLayers: []v1.Layer{fakeLayer{}}},
keySequence: []string{hash},
},
expectedCacheKeys: []string{hash},
commands: []commands.DockerCommand{command},
rootDir: dir,
}
}(),
func() testcase {
dir, _ := tempDirAndFile(t)
ch1 := NewCompositeCache("")
ch1.AddKey("RUN value")
hash1, err := ch1.Hash()
if err != nil {
t.Errorf("couldn't create hash %v", err)
}
ch2 := NewCompositeCache("")
ch2.AddKey("RUN anotherValue")
hash2, err := ch2.Hash()
if err != nil {
t.Errorf("couldn't create hash %v", err)
}
command := MockDockerCommand{
command: "RUN $arg",
contextFiles: []string{},
cacheCommand: MockCachedDockerCommand{
contextFiles: []string{},
},
}
return testcase{
description: "cached run command with another build arg pushes layer",
config: &v1.ConfigFile{Config: v1.Config{WorkingDir: dir}},
opts: &config.KanikoOptions{Cache: true},
args: map[string]string{
"arg": "anotherValue",
},
// layer for arg=value already exists
layerCache: &fakeLayerCache{
img: &fakeImage{ImageLayers: []v1.Layer{fakeLayer{}}},
keySequence: []string{hash1},
},
expectedCacheKeys: []string{hash2},
pushedCacheKeys: []string{hash2},
commands: []commands.DockerCommand{command},
rootDir: dir,
}
}(),
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) { t.Run(tc.description, func(t *testing.T) {
@ -875,18 +1114,21 @@ COPY %s bar.txt
} }
keys := []string{} keys := []string{}
sb := &stageBuilder{ sb := &stageBuilder{
args: &dockerfile.BuildArgs{}, //required or code will panic args: dockerfile.NewBuildArgs([]string{}), //required or code will panic
image: tc.image, image: tc.image,
opts: tc.opts, opts: tc.opts,
cf: cf, cf: cf,
snapshotter: snap, snapshotter: snap,
layerCache: lc, layerCache: lc,
pushCache: func(_ *config.KanikoOptions, cacheKey, _, _ string) error { pushLayerToCache: func(_ *config.KanikoOptions, cacheKey, _, _ string) error {
keys = append(keys, cacheKey) keys = append(keys, cacheKey)
return nil return nil
}, },
} }
sb.cmds = tc.commands sb.cmds = tc.commands
for key, value := range tc.args {
sb.args.AddArg(key, &value)
}
tmp := commands.RootDir tmp := commands.RootDir
if tc.rootDir != "" { if tc.rootDir != "" {
commands.RootDir = tc.rootDir commands.RootDir = tc.rootDir
@ -993,3 +1235,15 @@ func generateTar(t *testing.T, dir string, fileNames ...string) []byte {
} }
return buf.Bytes() return buf.Bytes()
} }
func hashCompositeKeys(t *testing.T, ck1 CompositeCache, ck2 CompositeCache) (string, string) {
key1, err := ck1.Hash()
if err != nil {
t.Errorf("could not hash composite key due to %s", err)
}
key2, err := ck2.Hash()
if err != nil {
t.Errorf("could not hash composite key due to %s", err)
}
return key1, key2
}

View File

@ -43,13 +43,14 @@ func (f fakeSnapShotter) TakeSnapshot(_ []string) (string, error) {
} }
type MockDockerCommand struct { type MockDockerCommand struct {
command string
contextFiles []string contextFiles []string
cacheCommand commands.DockerCommand cacheCommand commands.DockerCommand
} }
func (m MockDockerCommand) ExecuteCommand(c *v1.Config, args *dockerfile.BuildArgs) error { return nil } func (m MockDockerCommand) ExecuteCommand(c *v1.Config, args *dockerfile.BuildArgs) error { return nil }
func (m MockDockerCommand) String() string { func (m MockDockerCommand) String() string {
return "meow" return m.command
} }
func (m MockDockerCommand) FilesToSnapshot() []string { func (m MockDockerCommand) FilesToSnapshot() []string {
return []string{"meow-snapshot-no-cache"} return []string{"meow-snapshot-no-cache"}

40
scripts/integration-test.sh Executable file
View File

@ -0,0 +1,40 @@
#!/bin/bash
# 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.
set -ex
GCS_BUCKET="${GCS_BUCKET:-gs://kaniko-test-bucket}"
IMAGE_REPO="${IMAGE_REPO:-gcr.io/kaniko-test}"
docker version
# Sets up a kokoro (Google internal integration testing tool) environment
if [ -f "$KOKORO_GFILE_DIR"/common.sh ]; then
echo "Installing dependencies..."
source "$KOKORO_GFILE_DIR/common.sh"
mkdir -p /usr/local/go/src/github.com/GoogleContainerTools/
cp -r github/kaniko /usr/local/go/src/github.com/GoogleContainerTools/
pushd /usr/local/go/src/github.com/GoogleContainerTools/kaniko
echo "Installing container-diff..."
mv $KOKORO_GFILE_DIR/container-diff-linux-amd64 $KOKORO_GFILE_DIR/container-diff
chmod +x $KOKORO_GFILE_DIR/container-diff
export PATH=$PATH:$KOKORO_GFILE_DIR
cp $KOKORO_ROOT/src/keystore/72508_gcr_application_creds $HOME/.config/gcloud/application_default_credentials.json
fi
echo "Running integration tests..."
make out/executor
make out/warmer
go test ./integration/... -v --bucket "${GCS_BUCKET}" --repo "${IMAGE_REPO}" --timeout 50m "$@"

33
scripts/minikube-setup.sh Executable file
View File

@ -0,0 +1,33 @@
#!/bin/bash
# Copyright 2020 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.
set -ex
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
kubectl version --client
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
chmod +x minikube
sudo mv minikube /usr/local/bin/
sudo apt-get update
sudo apt-get install -y liblz4-tool
sudo minikube start --vm-driver=none
sudo minikube status
sudo chown -R $USER $HOME/.kube $HOME/.minikube
kubectl cluster-info

View File

@ -17,9 +17,9 @@
# TestRun and TestLayers # TestRun and TestLayers
set -e set -e
TESTS=$(./integration-test.sh -list=Test -mod=vendor) TESTS=$(./scripts/integration-test.sh -list=Test -mod=vendor)
TESTS=$(echo $TESTS | tr ' ' '\n' | grep 'Test'| grep -v 'TestRun' | grep -v 'TestLayers') TESTS=$(echo $TESTS | tr ' ' '\n' | grep 'Test'| grep -v 'TestRun' | grep -v 'TestLayers' | grep -v 'TestK8s')
RUN_ARG='' RUN_ARG=''
count=0 count=0

68
vendor/modules.txt vendored
View File

@ -1,4 +1,5 @@
# cloud.google.com/go v0.26.0 # cloud.google.com/go v0.26.0
## explicit
cloud.google.com/go/compute/metadata cloud.google.com/go/compute/metadata
cloud.google.com/go/iam cloud.google.com/go/iam
cloud.google.com/go/internal cloud.google.com/go/internal
@ -7,11 +8,13 @@ cloud.google.com/go/internal/trace
cloud.google.com/go/internal/version cloud.google.com/go/internal/version
cloud.google.com/go/storage cloud.google.com/go/storage
# github.com/Azure/azure-pipeline-go v0.2.2 # github.com/Azure/azure-pipeline-go v0.2.2
## explicit
github.com/Azure/azure-pipeline-go/pipeline github.com/Azure/azure-pipeline-go/pipeline
# github.com/Azure/azure-sdk-for-go v19.1.1+incompatible # github.com/Azure/azure-sdk-for-go v19.1.1+incompatible
github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2017-10-01/containerregistry github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2017-10-01/containerregistry
github.com/Azure/azure-sdk-for-go/version github.com/Azure/azure-sdk-for-go/version
# github.com/Azure/azure-storage-blob-go v0.8.0 # github.com/Azure/azure-storage-blob-go v0.8.0
## explicit
github.com/Azure/azure-storage-blob-go/azblob github.com/Azure/azure-storage-blob-go/azblob
# github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 # github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78
github.com/Azure/go-ansiterm github.com/Azure/go-ansiterm
@ -28,7 +31,12 @@ github.com/Azure/go-autorest/version
# github.com/Microsoft/go-winio v0.4.14 # github.com/Microsoft/go-winio v0.4.14
github.com/Microsoft/go-winio github.com/Microsoft/go-winio
github.com/Microsoft/go-winio/pkg/guid github.com/Microsoft/go-winio/pkg/guid
# github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7
## explicit
# github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239
## explicit
# github.com/aws/aws-sdk-go v1.25.19 # github.com/aws/aws-sdk-go v1.25.19
## explicit
github.com/aws/aws-sdk-go/aws github.com/aws/aws-sdk-go/aws
github.com/aws/aws-sdk-go/aws/awserr github.com/aws/aws-sdk-go/aws/awserr
github.com/aws/aws-sdk-go/aws/awsutil github.com/aws/aws-sdk-go/aws/awsutil
@ -71,6 +79,7 @@ github.com/aws/aws-sdk-go/service/s3/s3manager
github.com/aws/aws-sdk-go/service/sts github.com/aws/aws-sdk-go/service/sts
github.com/aws/aws-sdk-go/service/sts/stsiface github.com/aws/aws-sdk-go/service/sts/stsiface
# github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 # github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973
## explicit
github.com/beorn7/perks/quantile github.com/beorn7/perks/quantile
# github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf => github.com/containerd/containerd v0.0.0-20191014053712-acdcf13d5eaf # github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf => github.com/containerd/containerd v0.0.0-20191014053712-acdcf13d5eaf
github.com/containerd/containerd/cio github.com/containerd/containerd/cio
@ -102,6 +111,7 @@ github.com/docker/distribution/digestset
github.com/docker/distribution/reference github.com/docker/distribution/reference
github.com/docker/distribution/registry/api/errcode github.com/docker/distribution/registry/api/errcode
# github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c => github.com/docker/docker v0.0.0-20190319215453-e7b5f7dbe98c # github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c => github.com/docker/docker v0.0.0-20190319215453-e7b5f7dbe98c
## explicit
github.com/docker/docker/api github.com/docker/docker/api
github.com/docker/docker/api/types github.com/docker/docker/api/types
github.com/docker/docker/api/types/backend github.com/docker/docker/api/types/backend
@ -194,10 +204,12 @@ github.com/docker/go-connections/tlsconfig
# github.com/docker/go-events v0.0.0-20170721190031-9461782956ad # github.com/docker/go-events v0.0.0-20170721190031-9461782956ad
github.com/docker/go-events github.com/docker/go-events
# github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 # github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916
## explicit
github.com/docker/go-metrics github.com/docker/go-metrics
# github.com/docker/go-units v0.4.0 # github.com/docker/go-units v0.4.0
github.com/docker/go-units github.com/docker/go-units
# github.com/docker/swarmkit v1.12.1-0.20180726190244-7567d47988d8 # github.com/docker/swarmkit v1.12.1-0.20180726190244-7567d47988d8
## explicit
github.com/docker/swarmkit/agent/exec github.com/docker/swarmkit/agent/exec
github.com/docker/swarmkit/api github.com/docker/swarmkit/api
github.com/docker/swarmkit/api/deepcopy github.com/docker/swarmkit/api/deepcopy
@ -207,18 +219,24 @@ github.com/docker/swarmkit/manager/raftselector
github.com/docker/swarmkit/protobuf/plugin github.com/docker/swarmkit/protobuf/plugin
github.com/docker/swarmkit/protobuf/ptypes github.com/docker/swarmkit/protobuf/ptypes
# github.com/emirpasic/gods v1.9.0 # github.com/emirpasic/gods v1.9.0
## explicit
github.com/emirpasic/gods/containers github.com/emirpasic/gods/containers
github.com/emirpasic/gods/lists github.com/emirpasic/gods/lists
github.com/emirpasic/gods/lists/arraylist github.com/emirpasic/gods/lists/arraylist
github.com/emirpasic/gods/trees github.com/emirpasic/gods/trees
github.com/emirpasic/gods/trees/binaryheap github.com/emirpasic/gods/trees/binaryheap
github.com/emirpasic/gods/utils github.com/emirpasic/gods/utils
# github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568
## explicit
# github.com/fsnotify/fsnotify v1.4.7 # github.com/fsnotify/fsnotify v1.4.7
github.com/fsnotify/fsnotify github.com/fsnotify/fsnotify
# github.com/genuinetools/amicontained v0.4.3 # github.com/genuinetools/amicontained v0.4.3
## explicit
github.com/genuinetools/amicontained/container github.com/genuinetools/amicontained/container
# github.com/ghodss/yaml v1.0.0 # github.com/ghodss/yaml v1.0.0
github.com/ghodss/yaml github.com/ghodss/yaml
# github.com/gliderlabs/ssh v0.2.2
## explicit
# github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d # github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d
github.com/gogo/protobuf/gogoproto github.com/gogo/protobuf/gogoproto
github.com/gogo/protobuf/proto github.com/gogo/protobuf/proto
@ -228,6 +246,7 @@ github.com/gogo/protobuf/types
# github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b # github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/glog github.com/golang/glog
# github.com/golang/mock v1.3.1 # github.com/golang/mock v1.3.1
## explicit
github.com/golang/mock/gomock github.com/golang/mock/gomock
# github.com/golang/protobuf v1.3.2 # github.com/golang/protobuf v1.3.2
github.com/golang/protobuf/proto github.com/golang/protobuf/proto
@ -239,12 +258,14 @@ github.com/golang/protobuf/ptypes/timestamp
# github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a # github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a
github.com/google/btree github.com/google/btree
# github.com/google/go-cmp v0.3.0 # github.com/google/go-cmp v0.3.0
## explicit
github.com/google/go-cmp/cmp github.com/google/go-cmp/cmp
github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/diff
github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/flags
github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/function
github.com/google/go-cmp/cmp/internal/value github.com/google/go-cmp/cmp/internal/value
# github.com/google/go-containerregistry v0.0.0-20191218175032-34fb8ff33bed # github.com/google/go-containerregistry v0.0.0-20191218175032-34fb8ff33bed
## explicit
github.com/google/go-containerregistry/pkg/authn github.com/google/go-containerregistry/pkg/authn
github.com/google/go-containerregistry/pkg/authn/k8schain github.com/google/go-containerregistry/pkg/authn/k8schain
github.com/google/go-containerregistry/pkg/internal/retry github.com/google/go-containerregistry/pkg/internal/retry
@ -266,12 +287,19 @@ github.com/google/go-containerregistry/pkg/v1/types
github.com/google/go-containerregistry/pkg/v1/v1util github.com/google/go-containerregistry/pkg/v1/v1util
github.com/google/go-containerregistry/pkg/v1/validate github.com/google/go-containerregistry/pkg/v1/validate
# github.com/google/go-github v17.0.0+incompatible # github.com/google/go-github v17.0.0+incompatible
## explicit
github.com/google/go-github/github github.com/google/go-github/github
# github.com/google/go-querystring v1.0.0 # github.com/google/go-querystring v1.0.0
## explicit
github.com/google/go-querystring/query github.com/google/go-querystring/query
# github.com/google/gofuzz v1.0.0 # github.com/google/gofuzz v1.0.0
github.com/google/gofuzz github.com/google/gofuzz
# github.com/google/martian v2.1.0+incompatible
## explicit
# github.com/google/uuid v1.0.0
## explicit
# github.com/googleapis/gax-go v2.0.0+incompatible # github.com/googleapis/gax-go v2.0.0+incompatible
## explicit
github.com/googleapis/gax-go github.com/googleapis/gax-go
# github.com/googleapis/gnostic v0.2.2 # github.com/googleapis/gnostic v0.2.2
github.com/googleapis/gnostic/OpenAPIv2 github.com/googleapis/gnostic/OpenAPIv2
@ -285,34 +313,45 @@ github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc
# github.com/hashicorp/go-immutable-radix v1.0.0 # github.com/hashicorp/go-immutable-radix v1.0.0
github.com/hashicorp/go-immutable-radix github.com/hashicorp/go-immutable-radix
# github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71 # github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71
## explicit
github.com/hashicorp/go-memdb github.com/hashicorp/go-memdb
# github.com/hashicorp/go-uuid v1.0.1
## explicit
# github.com/hashicorp/golang-lru v0.5.0 # github.com/hashicorp/golang-lru v0.5.0
github.com/hashicorp/golang-lru/simplelru github.com/hashicorp/golang-lru/simplelru
# github.com/inconshreveable/mousetrap v1.0.0 # github.com/inconshreveable/mousetrap v1.0.0
github.com/inconshreveable/mousetrap github.com/inconshreveable/mousetrap
# github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 # github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
## explicit
github.com/jbenet/go-context/io github.com/jbenet/go-context/io
# github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af # github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af
github.com/jmespath/go-jmespath github.com/jmespath/go-jmespath
# github.com/json-iterator/go v1.1.8 # github.com/json-iterator/go v1.1.8
github.com/json-iterator/go github.com/json-iterator/go
# github.com/karrick/godirwalk v1.7.7 # github.com/karrick/godirwalk v1.7.7
## explicit
github.com/karrick/godirwalk github.com/karrick/godirwalk
# github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e # github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e
## explicit
github.com/kevinburke/ssh_config github.com/kevinburke/ssh_config
# github.com/konsorten/go-windows-terminal-sequences v1.0.2 # github.com/konsorten/go-windows-terminal-sequences v1.0.2
github.com/konsorten/go-windows-terminal-sequences github.com/konsorten/go-windows-terminal-sequences
# github.com/mattn/go-ieproxy v0.0.0-20190805055040-f9202b1cfdeb # github.com/mattn/go-ieproxy v0.0.0-20190805055040-f9202b1cfdeb
## explicit
github.com/mattn/go-ieproxy github.com/mattn/go-ieproxy
# github.com/mattn/go-shellwords v1.0.3 # github.com/mattn/go-shellwords v1.0.3
## explicit
github.com/mattn/go-shellwords github.com/mattn/go-shellwords
# github.com/matttproud/golang_protobuf_extensions v1.0.1 # github.com/matttproud/golang_protobuf_extensions v1.0.1
## explicit
github.com/matttproud/golang_protobuf_extensions/pbutil github.com/matttproud/golang_protobuf_extensions/pbutil
# github.com/minio/highwayhash v1.0.0 # github.com/minio/highwayhash v1.0.0
## explicit
github.com/minio/highwayhash github.com/minio/highwayhash
# github.com/mitchellh/go-homedir v1.1.0 # github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/go-homedir github.com/mitchellh/go-homedir
# github.com/moby/buildkit v0.0.0-20191111154543-00bfbab0390c # github.com/moby/buildkit v0.0.0-20191111154543-00bfbab0390c
## explicit
github.com/moby/buildkit/frontend/dockerfile/command github.com/moby/buildkit/frontend/dockerfile/command
github.com/moby/buildkit/frontend/dockerfile/instructions github.com/moby/buildkit/frontend/dockerfile/instructions
github.com/moby/buildkit/frontend/dockerfile/parser github.com/moby/buildkit/frontend/dockerfile/parser
@ -338,28 +377,37 @@ github.com/opencontainers/runc/libcontainer/devices
github.com/opencontainers/runc/libcontainer/system github.com/opencontainers/runc/libcontainer/system
github.com/opencontainers/runc/libcontainer/user github.com/opencontainers/runc/libcontainer/user
# github.com/opencontainers/runtime-spec v1.0.1 # github.com/opencontainers/runtime-spec v1.0.1
## explicit
github.com/opencontainers/runtime-spec/specs-go github.com/opencontainers/runtime-spec/specs-go
# github.com/opencontainers/selinux v1.0.0-rc1 # github.com/opencontainers/selinux v1.0.0-rc1
## explicit
github.com/opencontainers/selinux/go-selinux github.com/opencontainers/selinux/go-selinux
github.com/opencontainers/selinux/go-selinux/label github.com/opencontainers/selinux/go-selinux/label
# github.com/opentracing/opentracing-go v1.0.2 # github.com/opentracing/opentracing-go v1.0.2
## explicit
github.com/opentracing/opentracing-go github.com/opentracing/opentracing-go
github.com/opentracing/opentracing-go/ext github.com/opentracing/opentracing-go/ext
github.com/opentracing/opentracing-go/log github.com/opentracing/opentracing-go/log
# github.com/otiai10/copy v1.0.2 # github.com/otiai10/copy v1.0.2
## explicit
github.com/otiai10/copy github.com/otiai10/copy
# github.com/pelletier/go-buffruneio v0.2.0 # github.com/pelletier/go-buffruneio v0.2.0
## explicit
github.com/pelletier/go-buffruneio github.com/pelletier/go-buffruneio
# github.com/peterbourgon/diskv v2.0.1+incompatible # github.com/peterbourgon/diskv v2.0.1+incompatible
github.com/peterbourgon/diskv github.com/peterbourgon/diskv
# github.com/pkg/errors v0.9.1 # github.com/pkg/errors v0.9.1
## explicit
github.com/pkg/errors github.com/pkg/errors
# github.com/prometheus/client_golang v0.9.0-pre1.0.20180210140205-a40133b69fbd # github.com/prometheus/client_golang v0.9.0-pre1.0.20180210140205-a40133b69fbd
## explicit
github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus
github.com/prometheus/client_golang/prometheus/promhttp github.com/prometheus/client_golang/prometheus/promhttp
# github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 # github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910
## explicit
github.com/prometheus/client_model/go github.com/prometheus/client_model/go
# github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1 # github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1
## explicit
github.com/prometheus/common/expfmt github.com/prometheus/common/expfmt
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
github.com/prometheus/common/model github.com/prometheus/common/model
@ -367,17 +415,23 @@ github.com/prometheus/common/model
github.com/prometheus/procfs github.com/prometheus/procfs
github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/fs
# github.com/sergi/go-diff v1.0.0 # github.com/sergi/go-diff v1.0.0
## explicit
github.com/sergi/go-diff/diffmatchpatch github.com/sergi/go-diff/diffmatchpatch
# github.com/sirupsen/logrus v1.4.2 # github.com/sirupsen/logrus v1.4.2
## explicit
github.com/sirupsen/logrus github.com/sirupsen/logrus
# github.com/spf13/afero v1.2.1 # github.com/spf13/afero v1.2.1
## explicit
github.com/spf13/afero github.com/spf13/afero
github.com/spf13/afero/mem github.com/spf13/afero/mem
# github.com/spf13/cobra v0.0.5 # github.com/spf13/cobra v0.0.5
## explicit
github.com/spf13/cobra github.com/spf13/cobra
# github.com/spf13/pflag v1.0.5 # github.com/spf13/pflag v1.0.5
## explicit
github.com/spf13/pflag github.com/spf13/pflag
# github.com/src-d/gcfg v1.3.0 # github.com/src-d/gcfg v1.3.0
## explicit
github.com/src-d/gcfg github.com/src-d/gcfg
github.com/src-d/gcfg/scanner github.com/src-d/gcfg/scanner
github.com/src-d/gcfg/token github.com/src-d/gcfg/token
@ -385,17 +439,21 @@ github.com/src-d/gcfg/types
# github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 # github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
github.com/syndtr/gocapability/capability github.com/syndtr/gocapability/capability
# github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1 # github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1
## explicit
github.com/tonistiigi/fsutil github.com/tonistiigi/fsutil
github.com/tonistiigi/fsutil/types github.com/tonistiigi/fsutil/types
# github.com/vbatts/tar-split v0.10.2 # github.com/vbatts/tar-split v0.10.2
## explicit
github.com/vbatts/tar-split/archive/tar github.com/vbatts/tar-split/archive/tar
github.com/vbatts/tar-split/tar/asm github.com/vbatts/tar-split/tar/asm
github.com/vbatts/tar-split/tar/storage github.com/vbatts/tar-split/tar/storage
# github.com/xanzy/ssh-agent v0.2.0 # github.com/xanzy/ssh-agent v0.2.0
## explicit
github.com/xanzy/ssh-agent github.com/xanzy/ssh-agent
# go.etcd.io/bbolt v1.3.3 # go.etcd.io/bbolt v1.3.3
go.etcd.io/bbolt go.etcd.io/bbolt
# go.opencensus.io v0.14.0 # go.opencensus.io v0.14.0
## explicit
go.opencensus.io go.opencensus.io
go.opencensus.io/exporter/stackdriver/propagation go.opencensus.io/exporter/stackdriver/propagation
go.opencensus.io/internal go.opencensus.io/internal
@ -430,6 +488,7 @@ golang.org/x/crypto/ssh/agent
golang.org/x/crypto/ssh/knownhosts golang.org/x/crypto/ssh/knownhosts
golang.org/x/crypto/ssh/terminal golang.org/x/crypto/ssh/terminal
# golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 # golang.org/x/net v0.0.0-20191004110552-13f9640d40b9
## explicit
golang.org/x/net/context golang.org/x/net/context
golang.org/x/net/context/ctxhttp golang.org/x/net/context/ctxhttp
golang.org/x/net/http/httpguts golang.org/x/net/http/httpguts
@ -442,12 +501,14 @@ golang.org/x/net/internal/timeseries
golang.org/x/net/proxy golang.org/x/net/proxy
golang.org/x/net/trace golang.org/x/net/trace
# golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be # golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
## explicit
golang.org/x/oauth2 golang.org/x/oauth2
golang.org/x/oauth2/google golang.org/x/oauth2/google
golang.org/x/oauth2/internal golang.org/x/oauth2/internal
golang.org/x/oauth2/jws golang.org/x/oauth2/jws
golang.org/x/oauth2/jwt golang.org/x/oauth2/jwt
# golang.org/x/sync v0.0.0-20190423024810-112230192c58 # golang.org/x/sync v0.0.0-20190423024810-112230192c58
## explicit
golang.org/x/sync/errgroup golang.org/x/sync/errgroup
golang.org/x/sync/singleflight golang.org/x/sync/singleflight
golang.org/x/sync/syncmap golang.org/x/sync/syncmap
@ -464,6 +525,7 @@ golang.org/x/text/unicode/norm
# golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 # golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2
golang.org/x/time/rate golang.org/x/time/rate
# google.golang.org/api v0.0.0-20180730000901-31ca0e01cd79 # google.golang.org/api v0.0.0-20180730000901-31ca0e01cd79
## explicit
google.golang.org/api/gensupport google.golang.org/api/gensupport
google.golang.org/api/googleapi google.golang.org/api/googleapi
google.golang.org/api/googleapi/internal/uritemplates google.golang.org/api/googleapi/internal/uritemplates
@ -528,12 +590,16 @@ google.golang.org/grpc/tap
# gopkg.in/inf.v0 v0.9.1 # gopkg.in/inf.v0 v0.9.1
gopkg.in/inf.v0 gopkg.in/inf.v0
# gopkg.in/src-d/go-billy.v4 v4.2.0 # gopkg.in/src-d/go-billy.v4 v4.2.0
## explicit
gopkg.in/src-d/go-billy.v4 gopkg.in/src-d/go-billy.v4
gopkg.in/src-d/go-billy.v4/helper/chroot gopkg.in/src-d/go-billy.v4/helper/chroot
gopkg.in/src-d/go-billy.v4/helper/polyfill gopkg.in/src-d/go-billy.v4/helper/polyfill
gopkg.in/src-d/go-billy.v4/osfs gopkg.in/src-d/go-billy.v4/osfs
gopkg.in/src-d/go-billy.v4/util gopkg.in/src-d/go-billy.v4/util
# gopkg.in/src-d/go-git-fixtures.v3 v3.5.0
## explicit
# gopkg.in/src-d/go-git.v4 v4.6.0 # gopkg.in/src-d/go-git.v4 v4.6.0
## explicit
gopkg.in/src-d/go-git.v4 gopkg.in/src-d/go-git.v4
gopkg.in/src-d/go-git.v4/config gopkg.in/src-d/go-git.v4/config
gopkg.in/src-d/go-git.v4/internal/revision gopkg.in/src-d/go-git.v4/internal/revision
@ -575,6 +641,7 @@ gopkg.in/src-d/go-git.v4/utils/merkletrie/index
gopkg.in/src-d/go-git.v4/utils/merkletrie/internal/frame gopkg.in/src-d/go-git.v4/utils/merkletrie/internal/frame
gopkg.in/src-d/go-git.v4/utils/merkletrie/noder gopkg.in/src-d/go-git.v4/utils/merkletrie/noder
# gopkg.in/warnings.v0 v0.1.2 # gopkg.in/warnings.v0 v0.1.2
## explicit
gopkg.in/warnings.v0 gopkg.in/warnings.v0
# gopkg.in/yaml.v2 v2.2.4 # gopkg.in/yaml.v2 v2.2.4
gopkg.in/yaml.v2 gopkg.in/yaml.v2
@ -699,3 +766,4 @@ k8s.io/kubernetes/pkg/credentialprovider/aws
k8s.io/kubernetes/pkg/credentialprovider/azure k8s.io/kubernetes/pkg/credentialprovider/azure
k8s.io/kubernetes/pkg/credentialprovider/gcp k8s.io/kubernetes/pkg/credentialprovider/gcp
k8s.io/kubernetes/pkg/credentialprovider/secrets k8s.io/kubernetes/pkg/credentialprovider/secrets
# github.com/tonistiigi/fsutil v0.0.0-20190819224149-3d2716dd0a4d => github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1