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

feat: add digest hint in oras tag logs #853

Merged
merged 14 commits into from
Mar 6, 2023
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 {
}
}

qweeah marked this conversation as resolved.
Show resolved Hide resolved
// 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")
})
})
})