Fix bug with docker compatibility

ArgsEscaped according to Docker docs should only be set in Windows
environments: https://docs.docker.com/engine/api/v1.30/

It was causing integration test to fail with following message:
```
FAIL: TestRun/test_Dockerfile_test_metadata (8.48s)
           "Diff": {
             "Adds": [
               "ArgsEscaped: true"
             ],
             "Dels": [
               "ArgsEscaped: false"
             ]
```

However docker 18.xx returns ArgsEscaped: true
whereas docker 19.xx returns ArgsEscaped: false
Hence this patch also adds the docker version check to the integration
to ignore ArgsEscaped being different when 18.xx is used.
This commit is contained in:
Sam Stoelinga 2020-01-11 22:40:13 -08:00
parent aecc915e03
commit 64bfc3eabb
4 changed files with 94 additions and 19 deletions

View File

@ -18,6 +18,8 @@ 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..."

View File

@ -154,7 +154,8 @@ func addServiceAccountFlags(flags []string, serviceAccount string) []string {
// 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(imageRepo, gcsBucket, dockerfilesPath, dockerfile, serviceAccount string) error {
func (d *DockerFileBuilder) BuildImage(config *gcpConfig, dockerfilesPath, dockerfile string) error {
gcsBucket, serviceAccount, imageRepo := config.gcsBucket, config.serviceAccount, config.imageRepo
_, ex, _, _ := runtime.Caller(0)
cwd := filepath.Dir(ex)
@ -268,7 +269,8 @@ func populateVolumeCache() error {
}
// buildCachedImages builds the images for testing caching via kaniko where version is the nth time this image has been built
func (d *DockerFileBuilder) buildCachedImages(imageRepo, cacheRepo, dockerfilesPath, serviceAccount string, version int) error {
func (d *DockerFileBuilder) buildCachedImages(config *gcpConfig, cacheRepo, dockerfilesPath string, version int) error {
imageRepo, serviceAccount := config.imageRepo, config.serviceAccount
_, ex, _, _ := runtime.Caller(0)
cwd := filepath.Dir(ex)

View File

@ -67,12 +67,27 @@ const (
]`
)
func getDockerMajorVersion() int {
out, err := exec.Command("docker", "version", "--format", "{{.Server.Version}}").Output()
if err != nil {
log.Fatal("Error getting docker version of server:", err)
}
versionArr := strings.Split(string(out), ".")
ver, err := strconv.Atoi(versionArr[0])
if err != nil {
log.Fatal("Error getting docker version of server during parsing version string:", err)
}
return ver
}
func TestMain(m *testing.M) {
if !meetsRequirements() {
fmt.Println("Missing required tools")
os.Exit(1)
}
config = initGCPConfig()
contextFile, err := CreateIntegrationTarball()
if err != nil {
fmt.Println("Failed to create tarball of integration files for build context", err)
@ -307,9 +322,7 @@ func buildImage(t *testing.T, dockerfile string, imageBuilder *DockerFileBuilder
return
}
if err := imageBuilder.BuildImage(
config.imageRepo, config.gcsBucket, dockerfilesPath, dockerfile, config.serviceAccount,
); err != nil {
if err := imageBuilder.BuildImage(config, dockerfilesPath, dockerfile); err != nil {
t.Errorf("Error building image: %s", err)
t.FailNow()
}
@ -324,13 +337,14 @@ func TestCache(t *testing.T) {
t.Run("test_cache_"+dockerfile, func(t *testing.T) {
dockerfile := dockerfile
t.Parallel()
cache := filepath.Join(config.imageRepo, "cache", fmt.Sprintf("%v", time.Now().UnixNano()))
// Build the initial image which will cache layers
if err := imageBuilder.buildCachedImages(config.imageRepo, cache, dockerfilesPath, config.serviceAccount, 0); err != nil {
if err := imageBuilder.buildCachedImages(config, cache, dockerfilesPath, 0); err != nil {
t.Fatalf("error building cached image for the first time: %v", err)
}
// Build the second image which should pull from the cache
if err := imageBuilder.buildCachedImages(config.imageRepo, cache, dockerfilesPath, config.serviceAccount, 1); err != nil {
if err := imageBuilder.buildCachedImages(config, cache, dockerfilesPath, 1); err != nil {
t.Fatalf("error building cached image for the first time: %v", err)
}
// Make sure both images are the same
@ -384,14 +398,46 @@ type fileDiff struct {
Size int
}
type fileDiffResult struct {
Adds []fileDiff
Dels []fileDiff
}
type metaDiffResult struct {
Adds []string
Dels []string
}
type diffOutput struct {
Image1 string
Image2 string
DiffType string
Diff struct {
Adds []fileDiff
Dels []fileDiff
Diff interface{}
}
func (diff *diffOutput) UnmarshalJSON(data []byte) error {
type Alias diffOutput
aux := &struct{ *Alias }{Alias: (*Alias)(diff)}
var rawJSON json.RawMessage
aux.Diff = &rawJSON
err := json.Unmarshal(data, &aux)
if err != nil {
return err
}
switch diff.DiffType {
case "File":
var dst fileDiffResult
err = json.Unmarshal(rawJSON, &dst)
diff.Diff = &dst
case "Metadata":
var dst metaDiffResult
err = json.Unmarshal(rawJSON, &dst)
diff.Diff = &dst
}
if err != nil {
return err
}
return err
}
var allowedDiffPaths = []string{"/sys"}
@ -415,13 +461,35 @@ func checkContainerDiffOutput(t *testing.T, diff []byte, expected string) {
}
// Some differences (whitelisted paths, etc.) are known and expected.
diffInt[0].Diff.Adds = filterDiff(diffInt[0].Diff.Adds)
diffInt[0].Diff.Dels = filterDiff(diffInt[0].Diff.Dels)
fdr := diffInt[0].Diff.(*fileDiffResult)
fdr.Adds = filterFileDiff(fdr.Adds)
fdr.Dels = filterFileDiff(fdr.Dels)
// Remove some of the meta diffs that shouldn't be checked
mdr := diffInt[1].Diff.(*metaDiffResult)
mdr.Adds = filterMetaDiff(mdr.Adds)
mdr.Dels = filterMetaDiff(mdr.Dels)
testutil.CheckErrorAndDeepEqual(t, false, nil, expectedInt, diffInt)
}
func filterDiff(f []fileDiff) []fileDiff {
func filterMetaDiff(metaDiff []string) []string {
// TODO remove this once we agree testing shouldn't run on docker 18.xx
// currently docker 18.xx will build an image with Metadata set
// ArgsEscaped: true, however Docker 19.xx will build an image and have
// ArgsEscaped: false
if config.dockerMajorVersion == 19 {
return metaDiff
}
newDiffs := []string{}
for _, meta := range metaDiff {
if !strings.HasPrefix(meta, "ArgsEscaped") {
newDiffs = append(newDiffs, meta)
}
}
return newDiffs
}
func filterFileDiff(f []fileDiff) []fileDiff {
var newDiffs []fileDiff
for _, diff := range f {
isWhitelisted := false
@ -493,11 +561,12 @@ func logBenchmarks(benchmark string) error {
}
type gcpConfig struct {
gcsBucket string
imageRepo string
onbuildBaseImage string
hardlinkBaseImage string
serviceAccount string
gcsBucket string
imageRepo string
onbuildBaseImage string
hardlinkBaseImage string
serviceAccount string
dockerMajorVersion int
}
type imageDetails struct {
@ -535,6 +604,7 @@ func initGCPConfig() *gcpConfig {
if !strings.HasSuffix(c.imageRepo, "/") {
c.imageRepo = c.imageRepo + "/"
}
c.dockerMajorVersion = getDockerMajorVersion()
c.onbuildBaseImage = c.imageRepo + "onbuild-base:latest"
c.hardlinkBaseImage = c.imageRepo + "hardlink-base:latest"
return &c

View File

@ -49,7 +49,8 @@ func (c *CmdCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
}
config.Cmd = newCommand
config.ArgsEscaped = true
// ArgsEscaped is only used in windows environments
config.ArgsEscaped = false
return nil
}