Integration tests for run cmd
This commit is contained in:
parent
6668fa0d6f
commit
cefb4448b1
4
Makefile
4
Makefile
|
|
@ -29,13 +29,13 @@ REPOPATH ?= $(ORG)/$(PROJECT)
|
||||||
|
|
||||||
GO_FILES := $(shell find . -type f -name '*.go' -not -path "./vendor/*")
|
GO_FILES := $(shell find . -type f -name '*.go' -not -path "./vendor/*")
|
||||||
GO_LDFLAGS := '-extldflags "-static"'
|
GO_LDFLAGS := '-extldflags "-static"'
|
||||||
GO_BUILD_TAGS := "containers_image_ostree_stub containers_image_openpgp exclude_graphdriver_devicemapper exclude_graphdriver_btrfs"
|
GO_BUILD_TAGS := "containers_image_ostree_stub containers_image_openpgp exclude_graphdriver_devicemapper exclude_graphdriver_btrfs exclude_graphdriver_overlay"
|
||||||
|
|
||||||
EXECUTOR_PACKAGE = $(REPOPATH)/executor
|
EXECUTOR_PACKAGE = $(REPOPATH)/executor
|
||||||
KBUILD_PACKAGE = $(REPOPATH)/kbuild
|
KBUILD_PACKAGE = $(REPOPATH)/kbuild
|
||||||
|
|
||||||
out/executor: $(GO_FILES)
|
out/executor: $(GO_FILES)
|
||||||
GOOS=$* GOARCH=$(GOARCH) CGO_ENABLED=1 go build -ldflags $(GO_LDFLAGS) -tags $(GO_BUILD_TAGS) -o $@ $(EXECUTOR_PACKAGE)
|
GOOS=$* GOARCH=$(GOARCH) CGO_ENABLED=0 go build -ldflags $(GO_LDFLAGS) -tags $(GO_BUILD_TAGS) -o $@ $(EXECUTOR_PACKAGE)
|
||||||
|
|
||||||
|
|
||||||
out/kbuild: $(GO_FILES)
|
out/kbuild: $(GO_FILES)
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,13 @@ limitations under the License.
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/commands"
|
||||||
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/constants"
|
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/constants"
|
||||||
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/dockerfile"
|
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/dockerfile"
|
||||||
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/image"
|
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/image"
|
||||||
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/snapshot"
|
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/snapshot"
|
||||||
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/util"
|
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/util"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
@ -88,7 +90,57 @@ func execute() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute commands here
|
// Execute commands here
|
||||||
|
if err := image.SetEnvVariables(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently only supports single stage builds
|
||||||
|
for _, stage := range stages {
|
||||||
|
for _, cmd := range stage.Commands {
|
||||||
|
dockerCommand := commands.GetCommand(cmd)
|
||||||
|
if dockerCommand == nil {
|
||||||
|
return errors.Errorf("Invalid or unsupported docker command: %v", cmd)
|
||||||
|
}
|
||||||
|
if err := dockerCommand.ExecuteCommand(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Now, we get the files to snapshot from this command
|
||||||
|
// If this is nil, snapshot the entire filesystem
|
||||||
|
// Else take a snapshot of the specific files
|
||||||
|
snapshotFiles := dockerCommand.FilesToSnapshot()
|
||||||
|
if snapshotFiles == nil {
|
||||||
|
logrus.Info("Taking snapshot of full filesystem...")
|
||||||
|
contents, filesAdded, err := snapshotter.TakeSnapshot()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !filesAdded {
|
||||||
|
logrus.Info("No files were changed, appending empty layer to config.")
|
||||||
|
image.AppendConfigHistory(dockerCommand.Author(), true)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Append the layer to the image
|
||||||
|
if err := image.AppendLayer(contents, dockerCommand.Author()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logrus.Infof("Taking snapshot of files %v...", snapshotFiles)
|
||||||
|
contents, err := snapshotter.TakeSnapshotOfFiles(snapshotFiles)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if contents == nil {
|
||||||
|
logrus.Info("No files were changed, appending empty layer to config.")
|
||||||
|
image.AppendConfigHistory(dockerCommand.Author(), true)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Append the layer to the image
|
||||||
|
if err := image.AppendLayer(contents, dockerCommand.Author()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Push the image
|
// Push the image
|
||||||
return image.PushImage(destination)
|
return image.PushImage(destination)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
FROM gcr.io/google-appengine/debian9
|
||||||
|
RUN echo "hey" > /etc/foo
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
bzr \
|
||||||
|
cvs \
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"Image1": "gcr.io/kbuild-test/docker-test-run:latest",
|
||||||
|
"Image2": "gcr.io/kbuild-test/kbuild-test-run:latest",
|
||||||
|
"DiffType": "File",
|
||||||
|
"Diff": {
|
||||||
|
"Adds": [
|
||||||
|
{
|
||||||
|
"Name": "/bin/bzcat",
|
||||||
|
"Size": 35448
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "/bin/bzip2",
|
||||||
|
"Size": 35448
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Dels": null,
|
||||||
|
"Mods": [
|
||||||
|
{
|
||||||
|
"Name": "/var/log/dpkg.log",
|
||||||
|
"Size1": 57425,
|
||||||
|
"Size2": 57425
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "/var/log/apt/term.log",
|
||||||
|
"Size1": 24400,
|
||||||
|
"Size2": 24400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "/var/cache/ldconfig/aux-cache",
|
||||||
|
"Size1": 8057,
|
||||||
|
"Size2": 8057
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "/var/log/apt/history.log",
|
||||||
|
"Size1": 5089,
|
||||||
|
"Size2": 5089
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "/var/log/alternatives.log",
|
||||||
|
"Size1": 2579,
|
||||||
|
"Size2": 2579
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "/usr/lib/python2.7/dist-packages/keyrings/__init__.pyc",
|
||||||
|
"Size1": 140,
|
||||||
|
"Size2": 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "/usr/lib/python2.7/dist-packages/lazr/__init__.pyc",
|
||||||
|
"Size1": 136,
|
||||||
|
"Size2": 136
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -35,6 +35,13 @@ var tests = []struct {
|
||||||
context: "integration_tests/dockerfiles/",
|
context: "integration_tests/dockerfiles/",
|
||||||
repo: "extract-filesystem",
|
repo: "extract-filesystem",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "test run",
|
||||||
|
dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_run",
|
||||||
|
configPath: "/workspace/integration_tests/dockerfiles/config_test_run.json",
|
||||||
|
context: "integration_tests/dockerfiles/",
|
||||||
|
repo: "test-run",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
type step struct {
|
type step struct {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Google LLC
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DockerCommand interface {
|
||||||
|
ExecuteCommand() error
|
||||||
|
// The config file has an "author" field, should return information about the command
|
||||||
|
Author() string
|
||||||
|
// A list of files to snapshot, empty for metadata commands or nil if we don't know
|
||||||
|
FilesToSnapshot() []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCommand(cmd instructions.Command) DockerCommand {
|
||||||
|
switch c := cmd.(type) {
|
||||||
|
case *instructions.RunCommand:
|
||||||
|
return &RunCommand{cmd: c}
|
||||||
|
}
|
||||||
|
logrus.Errorf("%s is not a supported command.", cmd.Name())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Google LLC
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/docker/builder/dockerfile/instructions"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RunCommand struct {
|
||||||
|
cmd *instructions.RunCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RunCommand) ExecuteCommand() error {
|
||||||
|
var newCommand []string
|
||||||
|
if r.cmd.PrependShell {
|
||||||
|
// This is the default shell on Linux
|
||||||
|
shell := []string{"/bin/sh", "-c"}
|
||||||
|
newCommand = append(shell, strings.Join(r.cmd.CmdLine, " "))
|
||||||
|
} else {
|
||||||
|
newCommand = r.cmd.CmdLine
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Infof("cmd: %s", newCommand[0])
|
||||||
|
logrus.Infof("args: %s", newCommand[1:])
|
||||||
|
|
||||||
|
cmd := exec.Command(newCommand[0], newCommand[1:]...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilesToSnapshot returns nil for this command because we don't know which files
|
||||||
|
// have changed, so we snapshot the entire system.
|
||||||
|
func (r *RunCommand) FilesToSnapshot() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Author returns some information about the command for the image config
|
||||||
|
func (r *RunCommand) Author() string {
|
||||||
|
return "kbuild /bin/sh -c" + strings.Join(r.cmd.CmdLine, " ")
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/containers/image/signature"
|
"github.com/containers/image/signature"
|
||||||
"github.com/containers/image/transports/alltransports"
|
"github.com/containers/image/transports/alltransports"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// sourceImage is the image that will be modified by the executor
|
// sourceImage is the image that will be modified by the executor
|
||||||
|
|
@ -45,6 +46,7 @@ func InitializeSourceImage(srcImg string) error {
|
||||||
|
|
||||||
// AppendLayer appends a layer onto the base image
|
// AppendLayer appends a layer onto the base image
|
||||||
func AppendLayer(contents []byte, author string) error {
|
func AppendLayer(contents []byte, author string) error {
|
||||||
|
logrus.Info("Appending layer to base image")
|
||||||
return sourceImage.AppendLayer(contents, author)
|
return sourceImage.AppendLayer(contents, author)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,6 +68,23 @@ func PushImage(destImg string) error {
|
||||||
return copy.Image(policyContext, destRef, srcRef, nil)
|
return copy.Image(policyContext, destRef, srcRef, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendConfigHistory appends to the source image config history
|
||||||
|
func AppendConfigHistory(author string, emptyLayer bool) {
|
||||||
|
sourceImage.AppendConfigHistory(author, emptyLayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEnvVariables sets environment variables as specified in the image
|
||||||
|
func SetEnvVariables() error {
|
||||||
|
envVars := sourceImage.Env()
|
||||||
|
for key, val := range envVars {
|
||||||
|
if err := os.Setenv(key, val); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Debugf("Setting environment variable %s=%s", key, val)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getPolicyContext() (*signature.PolicyContext, error) {
|
func getPolicyContext() (*signature.PolicyContext, error) {
|
||||||
policyContext, err := signature.NewPolicyContext(&signature.Policy{
|
policyContext, err := signature.NewPolicyContext(&signature.Policy{
|
||||||
Default: signature.PolicyRequirements{signature.NewPRInsecureAcceptAnything()},
|
Default: signature.PolicyRequirements{signature.NewPRInsecureAcceptAnything()},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue