diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index 199f3fa7a..ca3a43ba5 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -70,6 +70,9 @@ var RootCmd = &cobra.Command{ if err := resolveDockerfilePath(); err != nil { return errors.Wrap(err, "error resolving dockerfile path") } + if len(opts.Destinations) == 0 && opts.ImageNameDigestFile != "" { + return errors.New("You must provide --destination if setting ImageNameDigestFile") + } } return nil }, @@ -134,6 +137,7 @@ func addKanikoOptionsFlags(cmd *cobra.Command) { RootCmd.PersistentFlags().StringVarP(&opts.CacheRepo, "cache-repo", "", "", "Specify a repository to use as a cache, otherwise one will be inferred from the destination provided") RootCmd.PersistentFlags().StringVarP(&opts.CacheDir, "cache-dir", "", "/cache", "Specify a local directory to use as a cache.") RootCmd.PersistentFlags().StringVarP(&opts.DigestFile, "digest-file", "", "", "Specify a file to save the digest of the built image to.") + RootCmd.PersistentFlags().StringVarP(&opts.ImageNameDigestFile, "image-name-with-digest-file", "", "", "Specify a file to save the image name w/ digest of the built image to.") RootCmd.PersistentFlags().StringVarP(&opts.OCILayoutPath, "oci-layout-path", "", "", "Path to save the OCI image layout of the built image.") RootCmd.PersistentFlags().BoolVarP(&opts.Cache, "cache", "", false, "Use cache when building image") RootCmd.PersistentFlags().BoolVarP(&opts.Cleanup, "cleanup", "", false, "Clean the filesystem at the end") @@ -240,6 +244,7 @@ func resolveRelativePaths() error { &opts.CacheDir, &opts.TarPath, &opts.DigestFile, + &opts.ImageNameDigestFile, } for _, p := range optsPaths { diff --git a/pkg/config/options.go b/pkg/config/options.go index 44af681ec..268c6390f 100644 --- a/pkg/config/options.go +++ b/pkg/config/options.go @@ -37,6 +37,7 @@ type KanikoOptions struct { Target string CacheRepo string DigestFile string + ImageNameDigestFile string OCILayoutPath string Destinations multiArg BuildArgs multiArg diff --git a/pkg/executor/push.go b/pkg/executor/push.go index 565ac52a4..772febcb3 100644 --- a/pkg/executor/push.go +++ b/pkg/executor/push.go @@ -96,16 +96,27 @@ func CheckPushPermissions(opts *config.KanikoOptions) error { return nil } +func getDigest(image v1.Image) ([]byte, error){ + digest, err := image.Digest() + if err != nil { + return nil, err + } + return []byte(digest.String()), nil +} + // DoPush is responsible for pushing image to the destinations specified in opts func DoPush(image v1.Image, opts *config.KanikoOptions) error { t := timing.Start("Total Push Time") if opts.DigestFile != "" { - digest, err := image.Digest() + // digest, err := image.Digest() + // if err != nil { + // return errors.Wrap(err, "error fetching digest") + // } + digestByteArray, err := getDigest(image) if err != nil { return errors.Wrap(err, "error fetching digest") } - digestByteArray := []byte(digest.String()) err = ioutil.WriteFile(opts.DigestFile, digestByteArray, 0644) if err != nil { return errors.Wrap(err, "writing digest to file failed") @@ -128,6 +139,17 @@ func DoPush(image v1.Image, opts *config.KanikoOptions) error { if err != nil { return errors.Wrap(err, "getting tag for destination") } + if opts.ImageNameDigestFile != "" { + digestByteArray, err := getDigest(image) + if err != nil { + return errors.Wrap(err, "error fetching digest") + } + imageName := []byte(destination + "@") + err = ioutil.WriteFile(opts.ImageNameDigestFile, append(imageName, digestByteArray...), 0644) + if err != nil { + return errors.Wrap(err, "writing digest to file failed") + } + } destRefs = append(destRefs, destRef) }