Skip to content

Commit

Permalink
feat: add digest hint in oras tag logs (#853)
Browse files Browse the repository at this point in the history
Signed-off-by: Billy Zha <jinzha1@microsoft.com>
  • Loading branch information
qweeah committed Mar 6, 2023
1 parent 16e40b5 commit 2d8dc21
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 12 deletions.
2 changes: 1 addition & 1 deletion cmd/oras/cp.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func runCopy(opts copyOptions) error {
if len(opts.extraRefs) != 0 {
tagNOpts := oras.DefaultTagNOptions
tagNOpts.Concurrency = opts.concurrency
if _, err = oras.TagN(ctx, display.NewTagManifestStatusPrinter(dst), opts.To.Reference, opts.extraRefs, tagNOpts); err != nil {
if _, err = oras.TagN(ctx, display.NewTagStatusPrinter(dst), opts.To.Reference, opts.extraRefs, tagNOpts); err != nil {
return err
}
}
Expand Down
38 changes: 36 additions & 2 deletions cmd/oras/internal/display/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ func PrintSuccessorStatus(ctx context.Context, desc ocispec.Descriptor, status s
return nil
}

// NewTagManifestStatusPrinter creates a wrapper type for printing tag status.
func NewTagManifestStatusPrinter(target oras.Target) oras.Target {
// NewTagStatusPrinter creates a wrapper type for printing tag status.
func NewTagStatusPrinter(target oras.Target) oras.Target {
if repo, ok := target.(registry.Repository); ok {
return &tagManifestStatusForRepo{
Repository: repo,
Expand All @@ -87,12 +87,38 @@ func NewTagManifestStatusPrinter(target oras.Target) oras.Target {
}
}

// NewTagStatusHintPrinter creates a wrapper type for printing
// tag status and hint.
func NewTagStatusHintPrinter(target oras.Target, refPrefix string) oras.Target {
var printHint sync.Once
if repo, ok := target.(registry.Repository); ok {
return &tagManifestStatusForRepo{
Repository: repo,
printHint: &printHint,
refPrefix: refPrefix,
}
}
return &tagManifestStatusForTarget{
Target: target,
printHint: &printHint,
refPrefix: refPrefix,
}
}

type tagManifestStatusForRepo struct {
registry.Repository
printHint *sync.Once
refPrefix string
}

// PushReference overrides Repository.PushReference method to print off which tag(s) were added successfully.
func (p *tagManifestStatusForRepo) PushReference(ctx context.Context, expected ocispec.Descriptor, content io.Reader, reference string) error {
if p.printHint != nil {
p.printHint.Do(func() {
ref := p.refPrefix + "@" + expected.Digest.String()
Print("Tagging", ref)
})
}
if err := p.Repository.PushReference(ctx, expected, content, reference); err != nil {
return err
}
Expand All @@ -101,10 +127,18 @@ func (p *tagManifestStatusForRepo) PushReference(ctx context.Context, expected o

type tagManifestStatusForTarget struct {
oras.Target
printHint *sync.Once
refPrefix string
}

// Tag tags a descriptor with a reference string.
func (p *tagManifestStatusForTarget) Tag(ctx context.Context, desc ocispec.Descriptor, reference string) error {
if p.printHint != nil {
p.printHint.Do(func() {
ref := p.refPrefix + "@" + desc.Digest.String()
Print("Tagging", ref)
})
}
if err := p.Target.Tag(ctx, desc, reference); err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/oras/manifest/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func pushManifest(opts pushOptions) error {
}
display.Print("Pushed", opts.AnnotatedReference())
if len(opts.extraRefs) != 0 {
if _, err = oras.TagBytesN(ctx, display.NewTagManifestStatusPrinter(target), mediaType, contentBytes, opts.extraRefs, tagBytesNOpts); err != nil {
if _, err = oras.TagBytesN(ctx, display.NewTagStatusPrinter(target), mediaType, contentBytes, opts.extraRefs, tagBytesNOpts); err != nil {
return err
}
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/oras/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func runPush(opts pushOptions) error {
}
tagBytesNOpts := oras.DefaultTagBytesNOptions
tagBytesNOpts.Concurrency = opts.concurrency
if _, err = oras.TagBytesN(ctx, display.NewTagManifestStatusPrinter(dst), root.MediaType, contentBytes, opts.extraRefs, tagBytesNOpts); err != nil {
if _, err = oras.TagBytesN(ctx, display.NewTagStatusPrinter(dst), root.MediaType, contentBytes, opts.extraRefs, tagBytesNOpts); err != nil {
return err
}
}
Expand Down
10 changes: 9 additions & 1 deletion cmd/oras/tag/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ limitations under the License.
package tag

import (
"fmt"

"github.com/spf13/cobra"
"oras.land/oras-go/v2"
"oras.land/oras/cmd/oras/internal/display"
Expand Down Expand Up @@ -82,6 +84,12 @@ func tagManifest(opts tagOptions) error {

tagNOpts := oras.DefaultTagNOptions
tagNOpts.Concurrency = opts.concurrency
_, err = oras.TagN(ctx, display.NewTagManifestStatusPrinter(target), opts.Reference, opts.targetRefs, tagNOpts)
_, err = oras.TagN(
ctx,
display.NewTagStatusHintPrinter(target, fmt.Sprintf("[%s] %s", opts.Type, opts.Path)),
opts.Reference,
opts.targetRefs,
tagNOpts,
)
return err
}
20 changes: 14 additions & 6 deletions test/e2e/suite/command/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ limitations under the License.
package command

import (
"fmt"
"regexp"

. "github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"oras.land/oras/test/e2e/internal/testdata/multi_arch"
. "oras.land/oras/test/e2e/internal/utils"
)
Expand All @@ -35,22 +40,25 @@ var _ = Describe("ORAS beginners:", func() {
})

var _ = Describe("Common registry users:", func() {
var tagAndValidate = func(reg string, repo string, tagOrDigest string, tags ...string) {
ORAS(append([]string{"tag", Reference(reg, repo, tagOrDigest)}, tags...)...).MatchKeyWords(tags...).Exec()
var tagAndValidate = func(reg string, repo string, tagOrDigest string, digest string, tags ...string) {
out := ORAS(append([]string{"tag", Reference(reg, repo, tagOrDigest)}, tags...)...).MatchKeyWords(tags...).Exec().Out
hint := regexp.QuoteMeta(fmt.Sprintf("Tagging [registry] %s", Reference(reg, repo, digest)))
gomega.Expect(out).To(gbytes.Say(hint))
gomega.Expect(out).NotTo(gbytes.Say(hint)) // should only say hint once
ORAS("repo", "tags", Reference(reg, repo, "")).MatchKeyWords(tags...).Exec()
}
When("running `tag`", func() {
It("should add a tag to an existent manifest when providing tag reference", func() {
tagAndValidate(Host, ImageRepo, multi_arch.Tag, "tag-via-tag")
tagAndValidate(Host, ImageRepo, multi_arch.Tag, multi_arch.Digest, "tag-via-tag")
})
It("should add a tag to an existent manifest when providing digest reference", func() {
tagAndValidate(Host, ImageRepo, multi_arch.Digest, "tag-via-digest")
tagAndValidate(Host, ImageRepo, multi_arch.Digest, multi_arch.Digest, "tag-via-digest")
})
It("should add multiple tags to an existent manifest when providing digest reference", func() {
tagAndValidate(Host, ImageRepo, multi_arch.Digest, "tag1-via-digest", "tag2-via-digest", "tag3-via-digest")
tagAndValidate(Host, ImageRepo, multi_arch.Digest, multi_arch.Digest, "tag1-via-digest", "tag2-via-digest", "tag3-via-digest")
})
It("should add multiple tags to an existent manifest when providing tag reference", func() {
tagAndValidate(Host, ImageRepo, multi_arch.Tag, "tag1-via-tag", "tag1-via-tag", "tag1-via-tag")
tagAndValidate(Host, ImageRepo, multi_arch.Tag, multi_arch.Digest, "tag1-via-tag", "tag1-via-tag", "tag1-via-tag")
})
})
})

0 comments on commit 2d8dc21

Please sign in to comment.