Skip to content

Commit

Permalink
Add --image-name-tag-with-digest flag (#1541)
Browse files Browse the repository at this point in the history
  • Loading branch information
Or-Geva committed Jan 19, 2021
1 parent ece215c commit b3e036a
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 30 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ _If you are interested in contributing to kaniko, see [DEVELOPMENT.md](DEVELOPME
- [--force](#--force)
- [--git](#--git)
- [--image-name-with-digest-file](#--image-name-with-digest-file)
- [--image-name-tag-with-digest-file](#--image-name-tag-with-digest-file)
- [--insecure](#--insecure)
- [--insecure-pull](#--insecure-pull)
- [--insecure-registry](#--insecure-registry)
Expand Down Expand Up @@ -458,9 +459,9 @@ docker run -ti --rm -e GOOGLE_APPLICATION_CREDENTIALS=/kaniko/config.json \
```

#### Pushing to GCR using Workload Identity
If you have enabled Workload Indentity on your GKE cluster then you can use the workload identity to push built images to GCR without adding a `GOOGLE_APPLICATION_CREDENTIALS` in your kaniko pod specification.
If you have enabled Workload Indentity on your GKE cluster then you can use the workload identity to push built images to GCR without adding a `GOOGLE_APPLICATION_CREDENTIALS` in your kaniko pod specification.

Learn more on how to [enable](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#enable_on_cluster) and [migrate existing apps](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#migrate_applications_to) to workload identity.
Learn more on how to [enable](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#enable_on_cluster) and [migrate existing apps](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#migrate_applications_to) to workload identity.

To authenticate using workload identity you need to run the kaniko pod using the Kubernetes Service Account (KSA) bound to Google Service Account (GSA) which as `Storage.Admin` permissions to push images to Google Container registry.

Expand Down Expand Up @@ -608,6 +609,9 @@ Branch to clone if build context is a git repository (default branch=,single-bra

Specify a file to save the image name w/ digest of the built image to.

#### --image-name-tag-with-digest-file
Specify a file to save the image name w/ image tag and digest of the built image to.

#### --insecure

Set this flag if you want to push images to a plain HTTP registry. It is supposed to be used for testing purposes only and should not be used in production!
Expand Down Expand Up @@ -765,7 +769,7 @@ You may be able to achieve the same default seccomp profile that Docker uses in
## Kaniko Builds - Profiling
If your builds are taking long, we recently added support to analyze kaniko function
calls using [Slow Jam](https://github.com/google/slowjam)
To start profiling,
To start profiling,
1. Add an environment variable `STACKLOG_PATH` to your [pod definition](https://github.com/GoogleContainerTools/kaniko/blob/master/examples/pod-build-profile.yaml#L15).
2. If you are using the kaniko `debug` image, you can copy the file in the `pre-stop` container lifecyle hook.

Expand Down
5 changes: 5 additions & 0 deletions cmd/executor/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ var RootCmd = &cobra.Command{
if len(opts.Destinations) == 0 && opts.ImageNameDigestFile != "" {
return errors.New("You must provide --destination if setting ImageNameDigestFile")
}
if len(opts.Destinations) == 0 && opts.ImageNameTagDigestFile != "" {
return errors.New("You must provide --destination if setting ImageNameTagDigestFile")
}
// Update ignored paths
util.UpdateInitialIgnoreList(opts.IgnoreVarRun)
}
Expand Down Expand Up @@ -165,6 +168,7 @@ func addKanikoOptionsFlags() {
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.ImageNameTagDigestFile, "image-name-tag-with-digest-file", "", "", "Specify a file to save the image name w/ image tag 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")
Expand Down Expand Up @@ -301,6 +305,7 @@ func resolveRelativePaths() error {
&opts.TarPath,
&opts.DigestFile,
&opts.ImageNameDigestFile,
&opts.ImageNameTagDigestFile,
}

for _, p := range optsPaths {
Expand Down
49 changes: 25 additions & 24 deletions pkg/config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,30 +46,31 @@ type RegistryOptions struct {
type KanikoOptions struct {
CacheOptions
RegistryOptions
DockerfilePath string
SrcContext string
SnapshotMode string
CustomPlatform string
Bucket string
TarPath string
Target string
CacheRepo string
DigestFile string
ImageNameDigestFile string
OCILayoutPath string
Destinations multiArg
BuildArgs multiArg
Labels multiArg
SingleSnapshot bool
Reproducible bool
NoPush bool
Cache bool
Cleanup bool
IgnoreVarRun bool
SkipUnusedStages bool
RunV2 bool
CacheCopyLayers bool
Git KanikoGitOptions
DockerfilePath string
SrcContext string
SnapshotMode string
CustomPlatform string
Bucket string
TarPath string
Target string
CacheRepo string
DigestFile string
ImageNameDigestFile string
ImageNameTagDigestFile string
OCILayoutPath string
Destinations multiArg
BuildArgs multiArg
Labels multiArg
SingleSnapshot bool
Reproducible bool
NoPush bool
Cache bool
Cleanup bool
IgnoreVarRun bool
SkipUnusedStages bool
RunV2 bool
CacheCopyLayers bool
Git KanikoGitOptions
}

type KanikoGitOptions struct {
Expand Down
17 changes: 14 additions & 3 deletions pkg/executor/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func DoPush(image v1.Image, opts *config.KanikoOptions) error {
t := timing.Start("Total Push Time")
var digestByteArray []byte
var builder strings.Builder
if opts.DigestFile != "" || opts.ImageNameDigestFile != "" {
if opts.DigestFile != "" || opts.ImageNameDigestFile != "" || opts.ImageNameTagDigestFile != "" {
var err error
digestByteArray, err = getDigest(image)
if err != nil {
Expand Down Expand Up @@ -200,8 +200,12 @@ func DoPush(image v1.Image, opts *config.KanikoOptions) error {
if err != nil {
return errors.Wrap(err, "getting tag for destination")
}
if opts.ImageNameDigestFile != "" {
imageName := []byte(destRef.Repository.Name() + "@")
if opts.ImageNameDigestFile != "" || opts.ImageNameTagDigestFile != "" {
tag := ""
if opts.ImageNameTagDigestFile != "" && destRef.TagStr() != "" {
tag = ":" + destRef.TagStr()
}
imageName := []byte(destRef.Repository.Name() + tag + "@")
builder.Write(append(imageName, digestByteArray...))
builder.WriteString("\n")
}
Expand All @@ -215,6 +219,13 @@ func DoPush(image v1.Image, opts *config.KanikoOptions) error {
}
}

if opts.ImageNameTagDigestFile != "" {
err := ioutil.WriteFile(opts.ImageNameTagDigestFile, []byte(builder.String()), 0644)
if err != nil {
return errors.Wrap(err, "writing image name with image tag and digest to file failed")
}
}

if opts.TarPath != "" {
tagToImage := map[name.Tag]v1.Image{}

Expand Down
30 changes: 30 additions & 0 deletions pkg/executor/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,36 @@ func TestImageNameDigestFile(t *testing.T) {

}

func TestImageNameTagDigestFile(t *testing.T) {
image, err := random.Image(1024, 4)
if err != nil {
t.Fatalf("could not create image: %s", err)
}

digest, err := image.Digest()
if err != nil {
t.Fatalf("could not get image digest: %s", err)
}

opts := config.KanikoOptions{
NoPush: true,
Destinations: []string{"gcr.io/foo/bar:123", "bob/image"},
ImageNameTagDigestFile: "tmpFile",
}

defer os.Remove("tmpFile")

if err := DoPush(image, &opts); err != nil {
t.Fatalf("could not push image: %s", err)
}

want := []byte("gcr.io/foo/bar:123@" + digest.String() + "\nindex.docker.io/bob/image:latest@" + digest.String() + "\n")

got, err := ioutil.ReadFile("tmpFile")

testutil.CheckErrorAndDeepEqual(t, false, err, want, got)
}

var calledExecCommand = []bool{}
var calledCheckPushPermission = false

Expand Down

0 comments on commit b3e036a

Please sign in to comment.