From 6c82c703749216032c5614131f8d0b0a3bafbf1e Mon Sep 17 00:00:00 2001 From: sharifelgamal Date: Mon, 18 Jun 2018 10:32:11 -0700 Subject: [PATCH 1/6] adding reproducible test --- Gopkg.lock | 2 +- cmd/executor/cmd/root.go | 4 +- integration/integration_test.go | 2 +- pkg/executor/executor.go | 11 +- .../pkg/v1/mutate/mutate.go | 153 +++++++++++++++--- 5 files changed, 145 insertions(+), 27 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index c9da819725..48db8b2829 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -393,7 +393,7 @@ "pkg/v1/types", "pkg/v1/v1util" ] - revision = "5e2bd1f4bf61add62944828d54e239d352daaabf" + revision = "5f3e1b6ff67cb53937e5c271cc98bb0a8b90fd28" [[projects]] name = "github.com/googleapis/gax-go" diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index 43dbc547c9..26ff196a59 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -40,6 +40,7 @@ var ( force bool buildArgs multiArg tarPath string + reproducible bool ) func init() { @@ -54,6 +55,7 @@ func init() { RootCmd.PersistentFlags().StringVarP(&logLevel, "verbosity", "v", constants.DefaultLogLevel, "Log level (debug, info, warn, error, fatal, panic") RootCmd.PersistentFlags().BoolVarP(&force, "force", "", false, "Force building outside of a container") RootCmd.PersistentFlags().StringVarP(&tarPath, "tarPath", "", "", "Path to save the image in as a tarball instead of pushing") + RootCmd.PersistentFlags().BoolVarP(&reproducible, "reproducible", "", true, "Strip timestamps out of the image to make it reproducible") } var RootCmd = &cobra.Command{ @@ -79,7 +81,7 @@ var RootCmd = &cobra.Command{ logrus.Error(err) os.Exit(1) } - ref, image, err := executor.DoBuild(dockerfilePath, srcContext, snapshotMode, buildArgs) + ref, image, err := executor.DoBuild(dockerfilePath, srcContext, snapshotMode, buildArgs, reproducible) if err != nil { logrus.Error(err) os.Exit(1) diff --git a/integration/integration_test.go b/integration/integration_test.go index 06e40e07fc..12e4f20bcb 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -159,7 +159,7 @@ func TestRun(t *testing.T) { "-v", cwd + ":/workspace", executorImage, "-f", path.Join(buildContextPath, dockerfilesPath, dockerfile), - "-d", kanikoImage, + "-d", kanikoImage, "--reproducible", contextFlag, contextPath}, buildArgs...)..., ) diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index d5f80b060a..d0d6c0da10 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -45,7 +45,7 @@ import ( "github.com/sirupsen/logrus" ) -func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string) (name.Reference, v1.Image, error) { +func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string, reproducible bool) (name.Reference, v1.Image, error) { // Parse dockerfile and unpack base image to root d, err := ioutil.ReadFile(dockerfilePath) if err != nil { @@ -161,6 +161,15 @@ func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string) (na if err != nil { return nil, nil, err } + + if reproducible { + sourceImage, err = mutate.Canonical(sourceImage) + } + + if err != nil { + return nil, nil, err + } + return ref, sourceImage, nil } if err := saveStageDependencies(index, stages, buildArgs.Clone()); err != nil { diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go index e557645675..64c58bee2c 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go @@ -21,12 +21,17 @@ import ( "errors" "fmt" "io" + "io/ioutil" "path/filepath" "strings" + "time" "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/empty" "github.com/google/go-containerregistry/pkg/v1/partial" + "github.com/google/go-containerregistry/pkg/v1/tarball" "github.com/google/go-containerregistry/pkg/v1/types" + "github.com/google/go-containerregistry/pkg/v1/v1util" ) const whiteoutPrefix = ".wh." @@ -128,22 +133,26 @@ func Append(base v1.Image, adds ...Addendum) (v1.Image, error) { // Config mutates the provided v1.Image to have the provided v1.Config func Config(base v1.Image, cfg v1.Config) (v1.Image, error) { - m, err := base.Manifest() + cf, err := base.ConfigFile() if err != nil { return nil, err } - cf, err := base.ConfigFile() + cf.Config = cfg + + return configFile(base, cf) +} + +func configFile(base v1.Image, cfg *v1.ConfigFile) (v1.Image, error) { + m, err := base.Manifest() if err != nil { return nil, err } - cf.Config = cfg - image := &image{ Image: base, manifest: m.DeepCopy(), - configFile: cf.DeepCopy(), + configFile: cfg, digestMap: make(map[v1.Hash]v1.Layer), } @@ -160,13 +169,8 @@ func Config(base v1.Image, cfg v1.Config) (v1.Image, error) { return image, nil } -// Created mutates the provided v1.Image to have the provided v1.Time +// CreatedAt mutates the provided v1.Image to have the provided v1.Time func CreatedAt(base v1.Image, created v1.Time) (v1.Image, error) { - m, err := base.Manifest() - if err != nil { - return nil, err - } - cf, err := base.ConfigFile() if err != nil { return nil, err @@ -175,18 +179,7 @@ func CreatedAt(base v1.Image, created v1.Time) (v1.Image, error) { cfg := cf.DeepCopy() cfg.Created = created - image := &image{ - Image: base, - manifest: m.DeepCopy(), - configFile: cfg, - digestMap: make(map[v1.Hash]v1.Layer), - } - - image.manifest.Config.Digest, err = image.ConfigName() - if err != nil { - return nil, err - } - return image, nil + return configFile(base, cfg) } type image struct { @@ -392,3 +385,117 @@ func inWhiteoutDir(fileMap map[string]bool, file string) bool { } return false } + +// Time sets all timestamps in an image to the given timestamp. +func Time(img v1.Image, t time.Time) (v1.Image, error) { + newImage := empty.Image + + layers, err := img.Layers() + if err != nil { + + return nil, fmt.Errorf("Error getting image layers: %v", err) + } + + // Strip away all timestamps from layers + var newLayers []v1.Layer + for _, layer := range layers { + newLayer, err := layerTime(layer, t) + if err != nil { + return nil, fmt.Errorf("Error setting layer times: %v", err) + } + newLayers = append(newLayers, newLayer) + } + + newImage, err = AppendLayers(newImage, newLayers...) + if err != nil { + return nil, fmt.Errorf("Error appending layers: %v", err) + } + + // Strip away timestamps from the config file + cf, err := newImage.ConfigFile() + if err != nil { + return nil, fmt.Errorf("Error setting config file: %v", err) + } + + cfg := cf.DeepCopy() + cfg.Created = v1.Time{Time: t} + + for _, h := range cfg.History { + h.Created = v1.Time{Time: t} + } + + return configFile(newImage, cfg) +} + +func layerTime(layer v1.Layer, t time.Time) (v1.Layer, error) { + layerReader, err := layer.Uncompressed() + if err != nil { + return nil, fmt.Errorf("Error getting layer: %v", err) + } + w := new(bytes.Buffer) + tarWriter := tar.NewWriter(w) + defer tarWriter.Close() + + tarReader := tar.NewReader(layerReader) + for { + header, err := tarReader.Next() + if err == io.EOF { + break + } + if err != nil { + return nil, fmt.Errorf("Error reading layer: %v", err) + } + + header.ModTime = t + if err := tarWriter.WriteHeader(header); err != nil { + return nil, fmt.Errorf("Error writing tar header: %v", err) + } + + if header.Typeflag == tar.TypeReg { + if _, err = io.Copy(tarWriter, tarReader); err != nil { + return nil, fmt.Errorf("Error writing layer file: %v", err) + } + } + } + + // gzip the contents, then create the layer + opener := func() (io.ReadCloser, error) { + g, err := v1util.GzipReadCloser(ioutil.NopCloser(w)) + if err != nil { + return nil, fmt.Errorf("Error compressing layer: %v", err) + } + return g, nil + } + layer, err = tarball.LayerFromOpener(opener) + if err != nil { + return nil, fmt.Errorf("Error creating layer: %v", err) + } + + return layer, nil +} + +// Canonical is a helper function to combine Time and configFile +// to remove any randomness during a docker build. +func Canonical(img v1.Image) (v1.Image, error) { + // Set all timestamps to 0 + created := time.Time{} + img, err := Time(img, created) + if err != nil { + return nil, err + } + + cf, err := img.ConfigFile() + if err != nil { + return nil, err + } + + // Get rid of host-dependent random config + cfg := cf.DeepCopy() + + cfg.Container = "" + cfg.Config.Hostname = "" + cfg.ContainerConfig.Hostname = "" + cfg.DockerVersion = "" + + return configFile(img, cfg) +} From 59d223dd68d805b5301ca65a30900c720bbd2393 Mon Sep 17 00:00:00 2001 From: sharifelgamal Date: Wed, 20 Jun 2018 10:49:43 -0700 Subject: [PATCH 2/6] newer version of go-containerregistry --- Gopkg.lock | 2 +- .../Dockerfile_test_copy_reproducible | 20 ++++++ integration/integration_test.go | 12 +++- .../pkg/v1/mutate/mutate.go | 4 +- .../pkg/v1/remote/image.go | 45 +++++++++++--- .../pkg/v1/remote/mount.go | 16 ++--- .../pkg/v1/remote/options.go | 61 +++++++++++++++++++ .../pkg/v1/remote/write.go | 4 +- 8 files changed, 141 insertions(+), 23 deletions(-) create mode 100644 integration/dockerfiles/Dockerfile_test_copy_reproducible create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/remote/options.go diff --git a/Gopkg.lock b/Gopkg.lock index 48db8b2829..bec814b93f 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -393,7 +393,7 @@ "pkg/v1/types", "pkg/v1/v1util" ] - revision = "5f3e1b6ff67cb53937e5c271cc98bb0a8b90fd28" + revision = "000ebf1ac80466c7e9054b0e5e5c367bddb79959" [[projects]] name = "github.com/googleapis/gax-go" diff --git a/integration/dockerfiles/Dockerfile_test_copy_reproducible b/integration/dockerfiles/Dockerfile_test_copy_reproducible new file mode 100644 index 0000000000..fd184394d5 --- /dev/null +++ b/integration/dockerfiles/Dockerfile_test_copy_reproducible @@ -0,0 +1,20 @@ +FROM alpine:3.7 +COPY context/foo foo +COPY context/foo /foodir/ +COPY context/bar/b* bar/ +COPY context/fo? /foo2 +COPY context/bar/doesnotexist* context/foo hello +COPY ./context/empty /empty +COPY ./ dir/ +COPY . newdir +COPY context/bar /baz/ +COPY ["context/foo", "/tmp/foo" ] +COPY context/b* /baz/ +COPY context/foo context/bar/ba? /test/ +COPY context/arr[[]0].txt /mydir/ +COPY context/bar/bat . + +ENV contextenv ./context +COPY ${contextenv}/foo /tmp/foo2 +COPY $contextenv/foo /tmp/foo3 +COPY $contextenv/* /tmp/${contextenv}/ diff --git a/integration/integration_test.go b/integration/integration_test.go index 12e4f20bcb..790b4272eb 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -108,6 +108,8 @@ func TestRun(t *testing.T) { bucketContextTests := []string{"Dockerfile_test_copy_bucket"} + reproducibleTests := []string{"Docker_test_copy_reproducible"} + // TODO: remove test_user_run from this when https://github.com/GoogleContainerTools/container-diff/issues/237 is fixed testsToIgnore := []string{"Dockerfile_test_user_run"} @@ -151,6 +153,14 @@ func TestRun(t *testing.T) { } } + reproducibleFlag := "" + for _, d := range reproducibleTests { + if d == dockerfile { + reproducibleFlag = "--reproducible" + break + } + } + // build kaniko image kanikoImage := strings.ToLower(testRepo + kanikoPrefix + dockerfile) kanikoCmd := exec.Command("docker", @@ -159,7 +169,7 @@ func TestRun(t *testing.T) { "-v", cwd + ":/workspace", executorImage, "-f", path.Join(buildContextPath, dockerfilesPath, dockerfile), - "-d", kanikoImage, "--reproducible", + "-d", kanikoImage, reproducibleFlag, contextFlag, contextPath}, buildArgs...)..., ) diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go index 64c58bee2c..3a5a0a8574 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go @@ -458,12 +458,14 @@ func layerTime(layer v1.Layer, t time.Time) (v1.Layer, error) { } } + b := w.Bytes() // gzip the contents, then create the layer opener := func() (io.ReadCloser, error) { - g, err := v1util.GzipReadCloser(ioutil.NopCloser(w)) + g, err := v1util.GzipReadCloser(ioutil.NopCloser(bytes.NewReader(b))) if err != nil { return nil, fmt.Errorf("Error compressing layer: %v", err) } + return g, nil } layer, err = tarball.LayerFromOpener(opener) diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/image.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/image.go index ab1764cd22..c532e46b4d 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/image.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/image.go @@ -42,30 +42,55 @@ type remoteImage struct { config []byte } +type ImageOption func(*imageOpener) error + var _ partial.CompressedImageCore = (*remoteImage)(nil) -// Image accesses a given image reference over the provided transport, with the provided authentication. -func Image(ref name.Reference, auth authn.Authenticator, t http.RoundTripper) (v1.Image, error) { - scopes := []string{ref.Scope(transport.PullScope)} - tr, err := transport.New(ref.Context().Registry, auth, t, scopes) +type imageOpener struct { + auth authn.Authenticator + transport http.RoundTripper + ref name.Reference + client *http.Client +} + +func (i *imageOpener) Open() (v1.Image, error) { + tr, err := transport.New(i.ref.Context().Registry, i.auth, i.transport, []string{i.ref.Scope(transport.PullScope)}) if err != nil { return nil, err } - img, err := partial.CompressedToImage(&remoteImage{ - ref: ref, + ri := &remoteImage{ + ref: i.ref, client: &http.Client{Transport: tr}, - }) + } + imgCore, err := partial.CompressedToImage(ri) if err != nil { - return nil, err + return imgCore, err } // Wrap the v1.Layers returned by this v1.Image in a hint for downstream // remote.Write calls to facilitate cross-repo "mounting". return &mountableImage{ - Image: img, - Repository: ref.Context(), + Image: imgCore, + Reference: i.ref, }, nil } +// Image provides access to a remote image reference, applying functional options +// to the underlying imageOpener before resolving the reference into a v1.Image. +func Image(ref name.Reference, options ...ImageOption) (v1.Image, error) { + img := &imageOpener{ + auth: authn.Anonymous, + transport: http.DefaultTransport, + ref: ref, + } + + for _, option := range options { + if err := option(img); err != nil { + return nil, err + } + } + return img.Open() +} + func (r *remoteImage) url(resource, identifier string) url.URL { return url.URL{ Scheme: transport.Scheme(r.ref.Context().Registry), diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/mount.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/mount.go index fb65b34da0..13b79064da 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/mount.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/mount.go @@ -24,7 +24,7 @@ import ( type MountableLayer struct { v1.Layer - Repository name.Repository + Reference name.Reference } // mountableImage wraps the v1.Layer references returned by the embedded v1.Image @@ -33,7 +33,7 @@ type MountableLayer struct { type mountableImage struct { v1.Image - Repository name.Repository + Reference name.Reference } // Layers implements v1.Image @@ -45,8 +45,8 @@ func (mi *mountableImage) Layers() ([]v1.Layer, error) { mls := make([]v1.Layer, 0, len(ls)) for _, l := range ls { mls = append(mls, &MountableLayer{ - Layer: l, - Repository: mi.Repository, + Layer: l, + Reference: mi.Reference, }) } return mls, nil @@ -59,8 +59,8 @@ func (mi *mountableImage) LayerByDigest(d v1.Hash) (v1.Layer, error) { return nil, err } return &MountableLayer{ - Layer: l, - Repository: mi.Repository, + Layer: l, + Reference: mi.Reference, }, nil } @@ -71,7 +71,7 @@ func (mi *mountableImage) LayerByDiffID(d v1.Hash) (v1.Layer, error) { return nil, err } return &MountableLayer{ - Layer: l, - Repository: mi.Repository, + Layer: l, + Reference: mi.Reference, }, nil } diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/options.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/options.go new file mode 100644 index 0000000000..7299055acb --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/options.go @@ -0,0 +1,61 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// 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 remote + +import ( + "net/http" + + "github.com/google/go-containerregistry/pkg/authn" +) + +// WithTransport is a functional option for overriding the default transport +// on a remote image +func WithTransport(t http.RoundTripper) ImageOption { + return func(i *imageOpener) error { + return i.setTransport(t) + } +} + +// WithAuth is a functional option for overriding the default authenticator +// on a remote image +func WithAuth(auth authn.Authenticator) ImageOption { + return func(i *imageOpener) error { + return i.setAuth(auth) + } +} + +// WithAuthFromKeychain is a functional option for overriding the default +// authenticator on a remote image using an authn.Keychain +func WithAuthFromKeychain(keys authn.Keychain) ImageOption { + return func(i *imageOpener) error { + auth, err := keys.Resolve(i.ref.Context().Registry) + if err != nil { + return err + } + return i.setAuth(auth) + } +} + +// Set client on image using provided transport, and the default authenticator +func (i *imageOpener) setTransport(t http.RoundTripper) error { + i.transport = t + return nil +} + +// Set client on image using provided authenticator, and the default transport +func (i *imageOpener) setAuth(auth authn.Authenticator) error { + i.auth = auth + return nil +} diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go index 283f817c85..57e4a1fad5 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go @@ -45,7 +45,7 @@ func Write(ref name.Reference, img v1.Image, auth authn.Authenticator, t http.Ro scopes := []string{ref.Scope(transport.PushScope)} for _, l := range ls { if ml, ok := l.(*MountableLayer); ok { - scopes = append(scopes, ml.Repository.Scope(transport.PullScope)) + scopes = append(scopes, ml.Reference.Context().Scope(transport.PullScope)) } } @@ -145,7 +145,7 @@ func (w *writer) initiateUpload(h v1.Hash) (location string, mounted bool, err e // if "mount" is specified, even if no "from" sources are specified. If this turns out // to not be broadly applicable then we should replace mounts without "from"s with a HEAD. if ml, ok := l.(*MountableLayer); ok { - uv["from"] = []string{ml.Repository.RepositoryStr()} + uv["from"] = []string{ml.Reference.Context().RepositoryStr()} } u.RawQuery = uv.Encode() From b9c18c7b4b74ca7bc397fabd164e107ffd75b9d2 Mon Sep 17 00:00:00 2001 From: sharifelgamal Date: Wed, 20 Jun 2018 11:28:31 -0700 Subject: [PATCH 3/6] new ImageOptions --- pkg/dockerfile/dockerfile.go | 2 +- pkg/executor/executor.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/dockerfile/dockerfile.go b/pkg/dockerfile/dockerfile.go index 8a79129e68..308e78b68b 100644 --- a/pkg/dockerfile/dockerfile.go +++ b/pkg/dockerfile/dockerfile.go @@ -108,7 +108,7 @@ func Dependencies(index int, stages []instructions.Stage, buildArgs *BuildArgs) if err != nil { return nil, err } - sourceImage, err = remote.Image(ref, auth, http.DefaultTransport) + sourceImage, err = remote.Image(ref, remote.WithAuth(auth), remote.WithTransport(http.DefaultTransport)) if err != nil { return nil, err } diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index d0d6c0da10..222eb63269 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -85,7 +85,7 @@ func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string, rep if err != nil { return nil, nil, err } - sourceImage, err = remote.Image(ref, auth, http.DefaultTransport) + sourceImage, err = remote.Image(ref, remote.WithAuth(auth), remote.WithTransport(http.DefaultTransport)) if err != nil { return nil, nil, err } From c80151d51ec46ee3023a4caa6e6f44932875e79a Mon Sep 17 00:00:00 2001 From: sharifelgamal Date: Wed, 20 Jun 2018 18:19:50 -0700 Subject: [PATCH 4/6] switch reproducible flag to default to false --- cmd/executor/cmd/root.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index 26ff196a59..4ad2718c60 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -55,7 +55,7 @@ func init() { RootCmd.PersistentFlags().StringVarP(&logLevel, "verbosity", "v", constants.DefaultLogLevel, "Log level (debug, info, warn, error, fatal, panic") RootCmd.PersistentFlags().BoolVarP(&force, "force", "", false, "Force building outside of a container") RootCmd.PersistentFlags().StringVarP(&tarPath, "tarPath", "", "", "Path to save the image in as a tarball instead of pushing") - RootCmd.PersistentFlags().BoolVarP(&reproducible, "reproducible", "", true, "Strip timestamps out of the image to make it reproducible") + RootCmd.PersistentFlags().BoolVarP(&reproducible, "reproducible", "", false, "Strip timestamps out of the image to make it reproducible") } var RootCmd = &cobra.Command{ From ad8a1e46431ee9e199f77c175de2700da755bb17 Mon Sep 17 00:00:00 2001 From: sharifelgamal Date: Thu, 21 Jun 2018 14:53:57 -0700 Subject: [PATCH 5/6] small fixes --- integration/integration_test.go | 2 +- pkg/executor/executor.go | 7 +++---- .../google/go-containerregistry/pkg/v1/mutate/mutate.go | 9 ++++++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/integration/integration_test.go b/integration/integration_test.go index 790b4272eb..d47dda4960 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -108,7 +108,7 @@ func TestRun(t *testing.T) { bucketContextTests := []string{"Dockerfile_test_copy_bucket"} - reproducibleTests := []string{"Docker_test_copy_reproducible"} + reproducibleTests := []string{"Dockerfile_test_env"} // TODO: remove test_user_run from this when https://github.com/GoogleContainerTools/container-diff/issues/237 is fixed testsToIgnore := []string{"Dockerfile_test_user_run"} diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index 222eb63269..85b3839769 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -164,10 +164,9 @@ func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string, rep if reproducible { sourceImage, err = mutate.Canonical(sourceImage) - } - - if err != nil { - return nil, nil, err + if err != nil { + return nil, nil, err + } } return ref, sourceImage, nil diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go index 3a5a0a8574..32b58bd8d6 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go @@ -411,13 +411,20 @@ func Time(img v1.Image, t time.Time) (v1.Image, error) { return nil, fmt.Errorf("Error appending layers: %v", err) } - // Strip away timestamps from the config file + // Copy config over + ocf, err := img.ConfigFile() + cf, err := newImage.ConfigFile() if err != nil { return nil, fmt.Errorf("Error setting config file: %v", err) } cfg := cf.DeepCopy() + + cfg.Config = ocf.Config + cfg.ContainerConfig = ocf.ContainerConfig + + // Strip away timestamps from the config file cfg.Created = v1.Time{Time: t} for _, h := range cfg.History { From 4e5e0cab433ad7b9c061b70ce6512c363f00d872 Mon Sep 17 00:00:00 2001 From: sharifelgamal Date: Thu, 21 Jun 2018 16:17:18 -0700 Subject: [PATCH 6/6] update dep --- Gopkg.lock | 2 +- .../google/go-containerregistry/pkg/v1/mutate/mutate.go | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index bec814b93f..4d8e0486ef 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -393,7 +393,7 @@ "pkg/v1/types", "pkg/v1/v1util" ] - revision = "000ebf1ac80466c7e9054b0e5e5c367bddb79959" + revision = "3f6471078a9661a9a439bd5e71a371aff429566a" [[projects]] name = "github.com/googleapis/gax-go" diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go index 32b58bd8d6..b24d6896b8 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go @@ -411,8 +411,10 @@ func Time(img v1.Image, t time.Time) (v1.Image, error) { return nil, fmt.Errorf("Error appending layers: %v", err) } - // Copy config over ocf, err := img.ConfigFile() + if err != nil { + return nil, fmt.Errorf("Error getting original config file: %v", err) + } cf, err := newImage.ConfigFile() if err != nil { @@ -421,6 +423,7 @@ func Time(img v1.Image, t time.Time) (v1.Image, error) { cfg := cf.DeepCopy() + // Copy basic config over cfg.Config = ocf.Config cfg.ContainerConfig = ocf.ContainerConfig