Add `--digestfile` flag to output built digest to file.

This flag, when set, takes a file in the container and writes the image digest to it. This can be used to extract the exact digest of the built image by surrounding tooling without having to parse the logs from Kaniko, for example by pointing the file to a mounted volume or to a file used durint exit status, such as with Kubernetes' [Termination message policy](https://kubernetes.io/docs/tasks/debug-application-cluster/determine-reason-pod-failure/)]

When the flag is not set, the digest is not written to file and the executor behaves as before. The digest is also written to file in case of a tarball or a `--no-push`.

Closes #654
This commit is contained in:
Gijs 2019-05-02 13:34:38 +02:00
parent 404af20f7c
commit a6e3ddfc79
4 changed files with 29 additions and 0 deletions

View File

@ -40,6 +40,7 @@ _If you are interested in contributing to kaniko, see [DEVELOPMENT.md](DEVELOPME
- [--cache-dir](#--cache-dir)
- [--cache-repo](#--cache-repo)
- [--cleanup](#--cleanup)
- [--digestfile](#--digestfile)
- [--insecure](#--insecure)
- [--insecure-pull](#--insecure-pull)
- [--no-push](#--no-push)
@ -356,6 +357,18 @@ If `--destination=gcr.io/kaniko-project/test`, then cached layers will be stored
_This flag must be used in conjunction with the `--cache=true` flag._
#### --digestfile
Set this flag to specify a file in the container. This file will
receive the digest of a built image. This can be used to
automatically track the exact image built by Kaniko.
For example, setting the flag to `--digestfile=/dev/termination-log`
will write the digest to that file, which is picked up by
Kubernetes automatically as the `{{.state.terminated.message}}`
of the container.
#### --insecure-registry
Set this flag to use plain HTTP requests when accessing a registry. It is supposed to be used for testing purposes only and should not be used in production!

View File

@ -128,6 +128,7 @@ func addKanikoOptionsFlags(cmd *cobra.Command) {
RootCmd.PersistentFlags().BoolVarP(&opts.NoPush, "no-push", "", false, "Do not push the image to the registry")
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, "digestfile", "", "", "Specify a file to save the digest of the built image to.")
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")
RootCmd.PersistentFlags().DurationVarP(&opts.CacheTTL, "cache-ttl", "", time.Hour*336, "Cache timeout in hours. Defaults to two weeks.")

View File

@ -30,6 +30,7 @@ type KanikoOptions struct {
Target string
CacheRepo string
CacheDir string
DigestFile string
Destinations multiArg
BuildArgs multiArg
Insecure bool

View File

@ -19,6 +19,7 @@ package executor
import (
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
"time"
@ -74,6 +75,19 @@ func CheckPushPermissions(opts *config.KanikoOptions) error {
// 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 image != nil && opts.DigestFile != "" {
digest, err := image.Digest()
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")
}
}
destRefs := []name.Tag{}
for _, destination := range opts.Destinations {
destRef, err := name.NewTag(destination, name.WeakValidation)