Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

be able to add legible tags based on original repo name using --repo-based-tags flag #368

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/gh-test-external-registry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches:
- develop
pull_request_target:
types: [opened, reopened, synchronize]
types: [opened, reopened, synchronize, edited]
permissions:
contents: read
actions: none
Expand Down
22 changes: 20 additions & 2 deletions pkg/imgpkg/cmd/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type CopyOptions struct {

Concurrency int
IncludeNonDistributable bool
UseRepoBasedTags bool
}

// NewCopyOptions constructor for building a CopyOptions, holding values derived via flags
Expand All @@ -60,7 +61,16 @@ func NewCopyCmd(o *CopyOptions) *cobra.Command {
# NOTE: if not using ~/.docker.config for authn, use env vars as described #
# in https://carvel.dev/imgpkg/docs/v0.24.0/auth/#via-environment-variables #
# ##########################################################################
imgpkg copy -i dkalinin/app1-image --to-repo internal-registry/app1-image`,
imgpkg copy -i dkalinin/app1-image --to-repo internal-registry/app1-image

# Copy using image --repo-based-tags flag
imgpkg copy -i registry.foo.bar/some/application/app \
--to-repo other-reg.faz.baz/my-app --repo-based-tags

# If the above source repo has a tag sha256:669e010b58baf5beb2836b253c1fd5768333f0d1dbcb834f7c07a4dc93f474be,
# a new tag some-application-app-sha256-669e010b58baf5beb2836b253c1fd5768333f0d1dbcb834f7c07a4dc93f474be.imgpkg
# will be created in the destination repo. Note that the part of the new tag preceeding '-sha256' will be truncated to
# the last 49 charachters`,
}

o.ImageFlags.SetCopy(cmd)
Expand All @@ -74,6 +84,8 @@ func NewCopyCmd(o *CopyOptions) *cobra.Command {
cmd.Flags().IntVar(&o.Concurrency, "concurrency", 5, "Concurrency")
cmd.Flags().BoolVar(&o.IncludeNonDistributable, "include-non-distributable-layers", false,
"Include non-distributable layers when copying an image/bundle")
cmd.Flags().BoolVar(&o.UseRepoBasedTags, "repo-based-tags", false,
"Allow imgpkg to use repository-based tags for convenience")
return cmd
}

Expand All @@ -97,7 +109,13 @@ func (c *CopyOptions) Run() error {
levelLogger := util.NewUILevelLogger(util.LogWarn, prefixedLogger)
imagesUploaderLogger := util.NewProgressBar(levelLogger, "done uploading images", "Error uploading images")

imageSet := ctlimgset.NewImageSet(c.Concurrency, prefixedLogger)
var tagGen util.TagGenerator
tagGen = util.DefaultTagGenerator{}
if c.UseRepoBasedTags {
tagGen = util.RepoBasedTagGenerator{}
}

imageSet := ctlimgset.NewImageSet(c.Concurrency, prefixedLogger, tagGen)
tarImageSet := ctlimgset.NewTarImageSet(imageSet, c.Concurrency, prefixedLogger)

var signatureRetriever SignatureRetriever
Expand Down
7 changes: 3 additions & 4 deletions pkg/imgpkg/cmd/copy_repo_src.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ func (c CopyRepoSrc) getAllSourceImages() (*ctlimgset.UnprocessedImageRefs, []*c

func (c CopyRepoSrc) getProvidedSourceImages() (*ctlimgset.UnprocessedImageRefs, []*ctlbundle.Bundle, error) {
unprocessedImageRefs := ctlimgset.NewUnprocessedImageRefs()

switch {
case c.LockInputFlags.LockFilePath != "":
bundleLock, imagesLock, err := lockconfig.NewLockFromPath(c.LockInputFlags.LockFilePath)
Expand Down Expand Up @@ -229,17 +228,17 @@ func (c CopyRepoSrc) getProvidedSourceImages() (*ctlimgset.UnprocessedImageRefs,
}

for _, img := range imagesRef.ImageRefs() {
unprocessedImageRefs.Add(ctlimgset.UnprocessedImageRef{DigestRef: img.PrimaryLocation()})
unprocessedImageRefs.Add(ctlimgset.UnprocessedImageRef{DigestRef: img.PrimaryLocation(), OrigRef: img.Image})
}

unprocessedImageRefs.Add(ctlimgset.UnprocessedImageRef{
DigestRef: bundle.DigestRef(),
Tag: bundle.Tag(),
Labels: map[string]string{
rootBundleLabelKey: "",
}},
},
OrigRef: bundle.DigestRef()},
)

return unprocessedImageRefs, allBundles, nil
}
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/imgpkg/cmd/copy_repo_src_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ func TestMain(m *testing.M) {
defer confUI.Flush()
uiLogger := util.NewUILevelLogger(util.LogWarn, confUI)

imageSet := imageset.NewImageSet(1, confUI)
tagGen := util.DefaultTagGenerator{}
imageSet := imageset.NewImageSet(1, confUI, tagGen)

subject = CopyRepoSrc{
ui: uiLogger,
Expand Down
4 changes: 2 additions & 2 deletions pkg/imgpkg/imagedesc/described_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ func (r DescribedReader) Read() []ImageOrIndex {
switch {
case td.Image != nil:
var img ImageWithRef = NewDescribedImage(*td.Image, r.layerProvider)
result = append(result, ImageOrIndex{Image: &img, Labels: td.Image.Labels})
result = append(result, ImageOrIndex{Image: &img, Labels: td.Image.Labels, OrigRef: td.OrigRef()})

case td.ImageIndex != nil:
idx := r.buildIndex(*td.ImageIndex)
result = append(result, ImageOrIndex{Index: &idx, Labels: td.ImageIndex.Labels})
result = append(result, ImageOrIndex{Index: &idx, Labels: td.ImageIndex.Labels, OrigRef: td.OrigRef()})

default:
panic("Unknown item")
Expand Down
17 changes: 10 additions & 7 deletions pkg/imgpkg/imagedesc/image_ref_descriptors.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ type Registry interface {
}

type Metadata struct {
Ref regname.Reference
Tag string
Labels map[string]string
Ref regname.Reference
Tag string
Labels map[string]string
OrigRef string
}

type ImageRefDescriptors struct {
Expand Down Expand Up @@ -120,6 +121,7 @@ func (ids *ImageRefDescriptors) buildImageIndex(ref Metadata, regDesc regv1.Desc
Digest: regDesc.Digest.String(),
Tag: ref.Tag,
Labels: ref.Labels,
OrigRef: ref.OrigRef,
}

imgIndex, err := ids.registry.Index(ref.Ref)
Expand All @@ -141,13 +143,13 @@ func (ids *ImageRefDescriptors) buildImageIndex(ref Metadata, regDesc regv1.Desc

for _, manDesc := range imgIndexManifest.Manifests {
if ids.isImageIndex(manDesc) {
imgIndexTd, err := ids.buildImageIndex(Metadata{ids.buildRef(ref.Ref, manDesc.Digest.String()), ref.Tag, ref.Labels}, manDesc)
imgIndexTd, err := ids.buildImageIndex(Metadata{ids.buildRef(ref.Ref, manDesc.Digest.String()), ref.Tag, ref.Labels, ref.OrigRef}, manDesc)
if err != nil {
return ImageIndexDescriptor{}, err
}
td.Indexes = append(td.Indexes, imgIndexTd)
} else {
imgTd, err := ids.buildImage(Metadata{ids.buildRef(ref.Ref, manDesc.Digest.String()), ref.Tag, ref.Labels})
imgTd, err := ids.buildImage(Metadata{ids.buildRef(ref.Ref, manDesc.Digest.String()), ref.Tag, ref.Labels, ref.OrigRef})
if err != nil {
return ImageIndexDescriptor{}, err
}
Expand Down Expand Up @@ -201,8 +203,9 @@ func (ids *ImageRefDescriptors) buildImage(ref Metadata) (ImageDescriptor, error
Digest: manifestDigest.String(),
Raw: string(manifestBlob),
},
Tag: ref.Tag,
Labels: ref.Labels,
Tag: ref.Tag,
Labels: ref.Labels,
OrigRef: ref.OrigRef,
}

layers, err := img.Layers()
Expand Down
21 changes: 18 additions & 3 deletions pkg/imgpkg/imagedesc/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ type ImageOrIndex struct {
Index *ImageIndexWithRef

Labels map[string]string
}

OrigRef string
}
type ImageWithRef interface {
regv1.Image
Ref() string
Expand Down Expand Up @@ -57,6 +58,7 @@ type ImageIndexDescriptor struct {
Digest string
Raw string
Tag string
OrigRef string

Labels map[string]string
}
Expand All @@ -68,8 +70,8 @@ type ImageDescriptor struct {
Config ConfigDescriptor
Manifest ManifestDescriptor
Tag string

Labels map[string]string
OrigRef string
Labels map[string]string
}

type ImageLayerDescriptor struct {
Expand Down Expand Up @@ -110,6 +112,19 @@ func (td ImageOrImageIndexDescriptor) SortKey() string {
}
}

// OrigRef returns ImagesLock's image value
// of an Image or an ImageIndex
func (td ImageOrImageIndexDescriptor) OrigRef() string {
switch {
case td.Image != nil:
return (*td.Image).OrigRef
case td.ImageIndex != nil:
return (*td.ImageIndex).OrigRef
default:
panic("Unknown item")
}
}

func (td ImageIndexDescriptor) SortKey() string { return td.Digest }
func (td ImageDescriptor) SortKey() string { return td.Manifest.Digest + "/" + td.Config.Digest }

Expand Down
39 changes: 39 additions & 0 deletions pkg/imgpkg/imagedigest/imagedigest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2020 VMware, Inc.
// SPDX-License-Identifier: Apache-2.0

package imagedigest

import (
regname "github.com/google/go-containerregistry/pkg/name"
)

// DigestWrap holds regname.Digest and orig reference
// retrieved from ImagesLock's image field
type DigestWrap struct {
regnameDigest regname.Digest
origRef string
}

// DigestWrap sets regnameDigest and origRef fields' values
func (dw *DigestWrap) DigestWrap(imgIdxRef string, origRef string) error {
regnameDigest, err := regname.NewDigest(imgIdxRef)
if err != nil {
return err
}
dw.regnameDigest = regnameDigest
dw.origRef = origRef

return nil
}

// RegnameDigest returns regnameDigest value of
// DigestWrap instance
func (dw *DigestWrap) RegnameDigest() regname.Digest {
return dw.regnameDigest
}

// OrigRef returns origRef value of
// DigestWrap instance
func (dw *DigestWrap) OrigRef() string {
return dw.origRef
}
28 changes: 19 additions & 9 deletions pkg/imgpkg/imageset/image_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
regv1 "github.com/google/go-containerregistry/pkg/v1"
regremote "github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/vmware-tanzu/carvel-imgpkg/pkg/imgpkg/imagedesc"
"github.com/vmware-tanzu/carvel-imgpkg/pkg/imgpkg/imagedigest"
"github.com/vmware-tanzu/carvel-imgpkg/pkg/imgpkg/internal/util"
"github.com/vmware-tanzu/carvel-imgpkg/pkg/imgpkg/registry"
)
Expand All @@ -23,16 +24,16 @@ type Logger interface {
type ImageSet struct {
concurrency int
ui goui.UI
tagGen util.TagGenerator
}

// NewImageSet constructor for creating an ImageSet
func NewImageSet(concurrency int, ui goui.UI) ImageSet {
return ImageSet{concurrency, ui}
func NewImageSet(concurrency int, ui goui.UI, tagGen util.TagGenerator) ImageSet {
return ImageSet{concurrency, ui, tagGen}
}

func (i ImageSet) Relocate(foundImages *UnprocessedImageRefs,
importRepo regname.Repository, registry registry.ImagesReaderWriter) (*ProcessedImages, error) {

ids, err := i.Export(foundImages, registry)
if err != nil {
return nil, err
Expand Down Expand Up @@ -60,7 +61,7 @@ func (i ImageSet) Export(foundImages *UnprocessedImageRefs,
}

i.ui.BeginLinef("will export %s\n", img.DigestRef)
refs = append(refs, imagedesc.Metadata{Ref: ref, Tag: img.Tag, Labels: img.Labels})
refs = append(refs, imagedesc.Metadata{Ref: ref, Tag: img.Tag, Labels: img.Labels, OrigRef: img.OrigRef})
}

ids, err := imagedesc.NewImageRefDescriptors(refs, imagesMetadata)
Expand Down Expand Up @@ -147,19 +148,24 @@ func checkForAnyAsyncErrors(imgOrIndexes []imagedesc.ImageOrIndex, errCh chan er
}

func (i ImageSet) getImageOrImageIndexForMultiWrite(item imagedesc.ImageOrIndex, importRepo regname.Repository, registry registry.ImagesReaderWriter) (regname.Tag, regremote.Taggable, error) {
uploadTagRef, err := util.BuildDefaultUploadTagRef(item, importRepo)
digestWrap := imagedigest.DigestWrap{}
err := digestWrap.DigestWrap(item.Ref(), item.OrigRef)
if err != nil {
return regname.Tag{}, nil, err
}
uploadTagRef, err := i.tagGen.GenerateTag(digestWrap, importRepo)
if err != nil {
return regname.Tag{}, nil, err
}

var artifactToWrite regremote.Taggable

switch {
case item.Image != nil:
artifactToWrite, err = i.mountableImage(*item.Image, uploadTagRef, registry)
if err != nil {
return regname.Tag{}, nil, err
}

case item.Index != nil:
artifactToWrite = *item.Index
default:
Expand Down Expand Up @@ -211,7 +217,7 @@ func (i *ImageSet) verifyImageOrIndex(item imagedesc.ImageOrIndex, importRepo re
regImageIndex = *item.Index
}
return ProcessedImage{
UnprocessedImageRef: UnprocessedImageRef{existingRef.Name(), item.Tag(), item.Labels},
UnprocessedImageRef: UnprocessedImageRef{existingRef.Name(), item.Tag(), item.Labels, item.OrigRef},
DigestRef: importDigestRef.Name(),
Image: regImage,
ImageIndex: regImageIndex,
Expand All @@ -230,7 +236,12 @@ func (i *ImageSet) verifyItemCopied(item imagedesc.ImageOrIndex, importRepo regn
}

// AWS ECR doesnt like using digests for manifest uploads
uploadTagRef, err := util.BuildDefaultUploadTagRef(item, importRepo)
digestWrap := imagedigest.DigestWrap{}
err = digestWrap.DigestWrap(item.Ref(), item.OrigRef)
if err != nil {
return regname.Digest{}, nil
}
uploadTagRef, err := i.tagGen.GenerateTag(digestWrap, importRepo)
if err != nil {
return regname.Digest{}, err
}
Expand All @@ -248,7 +259,6 @@ func (i *ImageSet) verifyItemCopied(item imagedesc.ImageOrIndex, importRepo regn

func (i *ImageSet) verifyTagDigest(
uploadTagRef regname.Reference, importDigestRef regname.Digest, registry registry.ImagesReaderWriter) error {

resultURL, err := getResolvedImageURL(uploadTagRef.Name(), registry)
if err != nil {
return fmt.Errorf("Verifying imported image %s: %s", uploadTagRef.Name(), err)
Expand Down
4 changes: 2 additions & 2 deletions pkg/imgpkg/imageset/unprocessed_image_refs.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
type UnprocessedImageRef struct {
DigestRef string
Tag string

Labels map[string]string
Labels map[string]string
OrigRef string
}

func (u UnprocessedImageRef) Key() string {
Expand Down
Loading