diff --git a/cmd/oras/internal/option/referrers.go b/cmd/oras/internal/option/referrers.go index d9b16a431..9284788a3 100644 --- a/cmd/oras/internal/option/referrers.go +++ b/cmd/oras/internal/option/referrers.go @@ -16,8 +16,7 @@ limitations under the License. package option import ( - "errors" - + "github.com/sirupsen/logrus" "github.com/spf13/pflag" "oras.land/oras-go/v2/registry/remote" ) @@ -33,11 +32,10 @@ func (opts *Referrers) ApplyFlags(fs *pflag.FlagSet) { } // SetReferrersGC sets the referrers GC option for the passed-in target. -func (opts *Referrers) SetReferrersGC(target any) error { +func (opts *Referrers) SetReferrersGC(target any, logger logrus.FieldLogger) { if repo, ok := target.(*remote.Repository); ok { repo.SkipReferrersGC = opts.SkipDeleteReferrers } else if !opts.SkipDeleteReferrers { - return errors.New("referrers deletion can only be enforced upon registry targets") + logger.Warnln("referrers deletion can only be enforced upon registry") } - return nil } diff --git a/cmd/oras/root/attach.go b/cmd/oras/root/attach.go index 9de992440..69d4f7f6b 100644 --- a/cmd/oras/root/attach.go +++ b/cmd/oras/root/attach.go @@ -99,7 +99,7 @@ Example - Attach file to the manifest tagged 'v1' in an OCI layout folder 'layou } func runAttach(ctx context.Context, opts attachOptions) error { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) annotations, err := opts.LoadManifestAnnotations() if err != nil { return err @@ -123,9 +123,7 @@ func runAttach(ctx context.Context, opts attachOptions) error { if err := opts.EnsureReferenceNotEmpty(); err != nil { return err } - if err = opts.SetReferrersGC(dst); err != nil { - return err - } + opts.SetReferrersGC(dst, logger) subject, err := dst.Resolve(ctx, opts.Reference) if err != nil { diff --git a/cmd/oras/root/cp.go b/cmd/oras/root/cp.go index 5a1a07a24..5e0982625 100644 --- a/cmd/oras/root/cp.go +++ b/cmd/oras/root/cp.go @@ -97,7 +97,7 @@ Example - Copy an artifact with multiple tags with concurrency tuned: } func runCopy(ctx context.Context, opts copyOptions) error { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) // Prepare source src, err := opts.From.NewReadonlyTarget(ctx, opts.Common) @@ -113,9 +113,7 @@ func runCopy(ctx context.Context, opts copyOptions) error { if err != nil { return err } - if err = opts.SetReferrersGC(dst); err != nil { - return err - } + opts.SetReferrersGC(dst, logger) // Prepare copy options committed := &sync.Map{} diff --git a/cmd/oras/root/manifest/push.go b/cmd/oras/root/manifest/push.go index c0b115420..1d3e8ce08 100644 --- a/cmd/oras/root/manifest/push.go +++ b/cmd/oras/root/manifest/push.go @@ -105,16 +105,14 @@ Example - Push a manifest to an OCI layout folder 'layout-dir' and tag with 'v1' } func pushManifest(ctx context.Context, opts pushOptions) error { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) var target oras.Target var err error target, err = opts.NewTarget(opts.Common) if err != nil { return err } - if err = opts.SetReferrersGC(target); err != nil { - return err - } + opts.SetReferrersGC(target, logger) if repo, ok := target.(*remote.Repository); ok { target = repo.Manifests() } diff --git a/test/e2e/suite/command/attach.go b/test/e2e/suite/command/attach.go index b36c7e9d5..9896acd56 100644 --- a/test/e2e/suite/command/attach.go +++ b/test/e2e/suite/command/attach.go @@ -205,15 +205,6 @@ var _ = Describe("OCI image layout users:", func() { ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Tag), Flags.ToLayout, LayoutRef(root, foobar.Tag)).Exec() } - It("should fail to specify referrers garbage collection", func() { - root := PrepareTempFiles() - subjectRef := LayoutRef(root, foobar.Tag) - ORAS("attach", "--artifact-type", "test.attach", "--skip-delete-referrers=false", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). - ExpectFailure(). - MatchContent("Error: referrers deletion can only be enforced upon registry targets\n"). - Exec() - }) - It("should attach a file to a subject", func() { root := PrepareTempFiles() subjectRef := LayoutRef(root, foobar.Tag) @@ -223,6 +214,15 @@ var _ = Describe("OCI image layout users:", func() { MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() }) + It("should attach and output warning for referrers deletion by default", func() { + root := PrepareTempFiles() + subjectRef := LayoutRef(root, foobar.Tag) + prepare(root) + ORAS("attach", "--artifact-type", "test.attach", "-v", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). + MatchContent("Error: referrers deletion can only be enforced upon registry\n"). + Exec() + }) + It("should attach a file to a subject and export the built manifest", func() { // prepare root := PrepareTempFiles() diff --git a/test/e2e/suite/command/cp.go b/test/e2e/suite/command/cp.go index 161782d23..d5decaa3f 100644 --- a/test/e2e/suite/command/cp.go +++ b/test/e2e/suite/command/cp.go @@ -323,12 +323,6 @@ var _ = Describe("OCI spec 1.0 registry users:", func() { var _ = Describe("OCI layout users:", func() { When("running `cp`", func() { - It("should fail to specify referrers garbage collection", func() { - ORAS("cp", RegistryRef(Host, ArtifactRepo, foobar.Tag), GinkgoT().TempDir(), Flags.ToLayout, "--skip-delete-referrers=false"). - ExpectFailure(). - MatchContent("Error: referrers deletion can only be enforced upon registry targets\n"). - Exec() - }) It("should copy an image from a registry to an OCI image layout via tag", func() { dst := LayoutRef(GinkgoT().TempDir(), "copied") src := RegistryRef(Host, ImageRepo, foobar.Tag) @@ -339,6 +333,12 @@ var _ = Describe("OCI layout users:", func() { Expect(srcManifest).To(Equal(dstManifest)) }) + It("should copy and output verbosed warning for Feferrers deletion by default", func() { + ORAS("cp", RegistryRef(Host, ArtifactRepo, foobar.Tag), GinkgoT().TempDir(), Flags.ToLayout, "-v"). + MatchErrKeyWords("referrers deletion can only be enforced upon registry\n"). + Exec() + }) + It("should copy an image from an OCI image layout to a registry via tag", func() { layoutDir := GinkgoT().TempDir() src := LayoutRef(layoutDir, "copied") diff --git a/test/e2e/suite/command/manifest.go b/test/e2e/suite/command/manifest.go index e190d2cd0..9cf86543c 100644 --- a/test/e2e/suite/command/manifest.go +++ b/test/e2e/suite/command/manifest.go @@ -547,13 +547,13 @@ var _ = Describe("OCI image layout users:", func() { } descriptor := "{\"mediaType\":\"application/vnd.oci.image.manifest.v1+json\",\"digest\":\"sha256:f20c43161d73848408ef247f0ec7111b19fe58ffebc0cbcaa0d2c8bda4967268\",\"size\":246}" - It("should fail to specify referrers garbage collection", func() { + It("should push and output verbosed warning for Feferrers deletion by default", func() { manifestPath := WriteTempFile("manifest.json", manifest) root := filepath.Dir(manifestPath) + prepare(root) ORAS("manifest", "push", root, Flags.Layout, manifestPath, "--skip-delete-referrers=false"). WithWorkDir(root). - ExpectFailure(). - MatchContent("Error: referrers deletion can only be enforced upon registry targets\n").Exec() + MatchErrKeyWords("referrers deletion can only be enforced upon registry\n").Exec() }) It("should push a manifest from stdin", func() {