From eab4fd7456854ae427f186e62584f20dfa84d32b Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 11 Dec 2024 10:14:16 +0000 Subject: [PATCH 1/8] chore: code clean Signed-off-by: Billy Zha --- .../internal/display/metadata/interface.go | 3 ++- .../internal/display/metadata/text/attach.go | 23 ++++++++++--------- cmd/oras/root/attach.go | 2 -- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cmd/oras/internal/display/metadata/interface.go b/cmd/oras/internal/display/metadata/interface.go index 8099bd872..145a65d0a 100644 --- a/cmd/oras/internal/display/metadata/interface.go +++ b/cmd/oras/internal/display/metadata/interface.go @@ -35,8 +35,9 @@ type Renderer interface { // AttachHandler handles metadata output for attach events. type AttachHandler interface { - OnAttached(target *option.Target, root ocispec.Descriptor, subject ocispec.Descriptor) Renderer + + OnAttached(target *option.Target, root ocispec.Descriptor, subject ocispec.Descriptor) } // DiscoverHandler handles metadata output for discover events. diff --git a/cmd/oras/internal/display/metadata/text/attach.go b/cmd/oras/internal/display/metadata/text/attach.go index dfc4cfc0f..de707fb28 100644 --- a/cmd/oras/internal/display/metadata/text/attach.go +++ b/cmd/oras/internal/display/metadata/text/attach.go @@ -28,9 +28,8 @@ import ( // AttachHandler handles text metadata output for attach events. type AttachHandler struct { printer *output.Printer - target *option.Target + path string root ocispec.Descriptor - subject ocispec.Descriptor } // NewAttachHandler returns a new handler for attach events. @@ -42,21 +41,23 @@ func NewAttachHandler(printer *output.Printer) metadata.AttachHandler { // OnAttached implements AttachHandler. func (ah *AttachHandler) OnAttached(target *option.Target, root ocispec.Descriptor, subject ocispec.Descriptor) { - ah.target = target + digest := subject.Digest.String() + if !strings.HasSuffix(target.RawReference, digest) { + // use subject digest instead of tag + newTarget := *target + newTarget.RawReference = fmt.Sprintf("%s@%s", target.Path, subject.Digest) + ah.path = newTarget.AnnotatedReference() + } else { + ah.path = target.AnnotatedReference() + } ah.root = root - ah.subject = subject } // Render is called when the attach command is complete. func (ah *AttachHandler) Render() error { - digest := ah.subject.Digest.String() - if !strings.HasSuffix(ah.target.RawReference, digest) { - ah.target.RawReference = fmt.Sprintf("%s@%s", ah.target.Path, ah.subject.Digest) - } - err := ah.printer.Println("Attached to", ah.target.AnnotatedReference()) + err := ah.printer.Println("Attached to", ah.path) if err != nil { return err } - err = ah.printer.Println("Digest:", ah.root.Digest) - return err + return ah.printer.Println("Digest:", ah.root.Digest) } diff --git a/cmd/oras/root/attach.go b/cmd/oras/root/attach.go index 0085deb3c..60734e8cb 100644 --- a/cmd/oras/root/attach.go +++ b/cmd/oras/root/attach.go @@ -210,9 +210,7 @@ func runAttach(cmd *cobra.Command, opts *attachOptions) error { if err != nil { return err } - metadataHandler.OnAttached(&opts.Target, root, subject) - err = metadataHandler.Render() if err != nil { return err From 903f73ce3938526107fd319ac553becc3362199f Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 11 Dec 2024 12:20:29 +0000 Subject: [PATCH 2/8] code clean Signed-off-by: Billy Zha --- .../internal/display/metadata/text/attach.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/cmd/oras/internal/display/metadata/text/attach.go b/cmd/oras/internal/display/metadata/text/attach.go index de707fb28..687b5a889 100644 --- a/cmd/oras/internal/display/metadata/text/attach.go +++ b/cmd/oras/internal/display/metadata/text/attach.go @@ -27,9 +27,9 @@ import ( // AttachHandler handles text metadata output for attach events. type AttachHandler struct { - printer *output.Printer - path string - root ocispec.Descriptor + printer *output.Printer + subjectRefByDigest string + root ocispec.Descriptor } // NewAttachHandler returns a new handler for attach events. @@ -41,21 +41,19 @@ func NewAttachHandler(printer *output.Printer) metadata.AttachHandler { // OnAttached implements AttachHandler. func (ah *AttachHandler) OnAttached(target *option.Target, root ocispec.Descriptor, subject ocispec.Descriptor) { - digest := subject.Digest.String() - if !strings.HasSuffix(target.RawReference, digest) { + ah.subjectRefByDigest = target.AnnotatedReference() + if !strings.HasSuffix(target.RawReference, subject.Digest.String()) { // use subject digest instead of tag newTarget := *target newTarget.RawReference = fmt.Sprintf("%s@%s", target.Path, subject.Digest) - ah.path = newTarget.AnnotatedReference() - } else { - ah.path = target.AnnotatedReference() + ah.subjectRefByDigest = newTarget.AnnotatedReference() } ah.root = root } // Render is called when the attach command is complete. func (ah *AttachHandler) Render() error { - err := ah.printer.Println("Attached to", ah.path) + err := ah.printer.Println("Attached to", ah.subjectRefByDigest) if err != nil { return err } From 8fc2cfa6202b9885f7c68741c110e21ee9b5f65f Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 11 Dec 2024 12:33:00 +0000 Subject: [PATCH 3/8] chore: update attach metadata handler for attach Signed-off-by: Billy Zha --- cmd/oras/internal/display/metadata/template/attach.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/oras/internal/display/metadata/template/attach.go b/cmd/oras/internal/display/metadata/template/attach.go index d792daede..223da7a0c 100644 --- a/cmd/oras/internal/display/metadata/template/attach.go +++ b/cmd/oras/internal/display/metadata/template/attach.go @@ -29,7 +29,7 @@ import ( type AttachHandler struct { template string out io.Writer - target *option.Target + path string root ocispec.Descriptor } @@ -43,11 +43,11 @@ func NewAttachHandler(out io.Writer, template string) metadata.AttachHandler { // OnAttached implements AttachHandler. func (ah *AttachHandler) OnAttached(target *option.Target, root ocispec.Descriptor, _ ocispec.Descriptor) { - ah.target = target + ah.path = target.Path ah.root = root } // Render formats the metadata of attach command. func (ah *AttachHandler) Render() error { - return output.ParseAndWrite(ah.out, model.NewAttach(ah.root, ah.target.Path), ah.template) + return output.ParseAndWrite(ah.out, model.NewAttach(ah.root, ah.path), ah.template) } From 83a8be4f913c94f85a127b32fd260814370ee7a5 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 11 Dec 2024 12:37:19 +0000 Subject: [PATCH 4/8] chore: clean code of json metadata output for attach Signed-off-by: Billy Zha --- cmd/oras/internal/display/metadata/json/attach.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/oras/internal/display/metadata/json/attach.go b/cmd/oras/internal/display/metadata/json/attach.go index 91cda78b2..a684534f6 100644 --- a/cmd/oras/internal/display/metadata/json/attach.go +++ b/cmd/oras/internal/display/metadata/json/attach.go @@ -27,9 +27,9 @@ import ( // AttachHandler handles json metadata output for attach events. type AttachHandler struct { - out io.Writer - target *option.Target - root ocispec.Descriptor + out io.Writer + path string + root ocispec.Descriptor } // NewAttachHandler creates a new handler for attach events. @@ -41,11 +41,11 @@ func NewAttachHandler(out io.Writer) metadata.AttachHandler { // OnAttached implements AttachHandler. func (ah *AttachHandler) OnAttached(target *option.Target, root ocispec.Descriptor, _ ocispec.Descriptor) { - ah.target = target + ah.path = target.Path ah.root = root } // Render is called when the attach command is completed. func (ah *AttachHandler) Render() error { - return output.PrintPrettyJSON(ah.out, model.NewAttach(ah.root, ah.target.Path)) + return output.PrintPrettyJSON(ah.out, model.NewAttach(ah.root, ah.path)) } From d9590f0ffb74048f0c8c7f924e37ec541c1deca7 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 11 Dec 2024 12:52:06 +0000 Subject: [PATCH 5/8] test(e2e): validate attach status output Signed-off-by: Billy Zha --- .../display/metadata/text/attach_test.go | 54 +++++++++++++++++++ test/e2e/suite/command/attach.go | 9 ++-- 2 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 cmd/oras/internal/display/metadata/text/attach_test.go diff --git a/cmd/oras/internal/display/metadata/text/attach_test.go b/cmd/oras/internal/display/metadata/text/attach_test.go new file mode 100644 index 000000000..066a47cad --- /dev/null +++ b/cmd/oras/internal/display/metadata/text/attach_test.go @@ -0,0 +1,54 @@ +/* +Copyright The ORAS Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package text + +import ( + "testing" + + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "oras.land/oras/cmd/oras/internal/option" + "oras.land/oras/cmd/oras/internal/output" +) + +func TestAttachHandler_OnAttached(t *testing.T) { + type fields struct { + printer *output.Printer + subjectRefByDigest string + root ocispec.Descriptor + } + type args struct { + target *option.Target + root ocispec.Descriptor + subject ocispec.Descriptor + } + tests := []struct { + name string + fields fields + args args + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ah := &AttachHandler{ + printer: tt.fields.printer, + subjectRefByDigest: tt.fields.subjectRefByDigest, + root: tt.fields.root, + } + ah.OnAttached(tt.args.target, tt.args.root, tt.args.subject) + }) + } +} diff --git a/test/e2e/suite/command/attach.go b/test/e2e/suite/command/attach.go index 509615919..ee19f0ba1 100644 --- a/test/e2e/suite/command/attach.go +++ b/test/e2e/suite/command/attach.go @@ -143,18 +143,17 @@ var _ = Describe("1.1 registry users:", func() { subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(PrepareTempFiles()). + MatchKeyWords(fmt.Sprintf("Attached to [registry] %s", RegistryRef(ZOTHost, testRepo, foobar.Digest))). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() }) It("should attach a file to an arch-specific subject", func() { + // prepare testRepo := attachTestRepo("arch-specific") - // Below line will cause unexpected 500 - // pending for https://github.com/project-zot/zot/pull/2351 to be released - // CopyZOTRepo(ImageRepo, testRepo) + CopyZOTRepo(ImageRepo, testRepo) + // test subjectRef := RegistryRef(ZOTHost, testRepo, multi_arch.Tag) - ORAS("cp", RegistryRef(ZOTHost, ImageRepo, multi_arch.Tag), subjectRef).Exec() artifactType := "test/attach" - // test out := ORAS("attach", "--artifact-type", artifactType, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--format", "go-template={{.digest}}", "--platform", "linux/amd64"). WithWorkDir(PrepareTempFiles()).Exec().Out.Contents() // validate From 9c31ec0ab297a9c6efd136a1414cdbfc693c5ba7 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 11 Dec 2024 12:56:28 +0000 Subject: [PATCH 6/8] chore: remove unwanted file Signed-off-by: Billy Zha --- .../display/metadata/text/attach_test.go | 54 ------------------- 1 file changed, 54 deletions(-) delete mode 100644 cmd/oras/internal/display/metadata/text/attach_test.go diff --git a/cmd/oras/internal/display/metadata/text/attach_test.go b/cmd/oras/internal/display/metadata/text/attach_test.go deleted file mode 100644 index 066a47cad..000000000 --- a/cmd/oras/internal/display/metadata/text/attach_test.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright The ORAS Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package text - -import ( - "testing" - - ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "oras.land/oras/cmd/oras/internal/option" - "oras.land/oras/cmd/oras/internal/output" -) - -func TestAttachHandler_OnAttached(t *testing.T) { - type fields struct { - printer *output.Printer - subjectRefByDigest string - root ocispec.Descriptor - } - type args struct { - target *option.Target - root ocispec.Descriptor - subject ocispec.Descriptor - } - tests := []struct { - name string - fields fields - args args - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ah := &AttachHandler{ - printer: tt.fields.printer, - subjectRefByDigest: tt.fields.subjectRefByDigest, - root: tt.fields.root, - } - ah.OnAttached(tt.args.target, tt.args.root, tt.args.subject) - }) - } -} From d24fb9a181835bda6f4eabb538298f9de8753b85 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Fri, 13 Dec 2024 08:56:30 +0000 Subject: [PATCH 7/8] resolve comment Signed-off-by: Billy Zha --- cmd/oras/internal/display/metadata/text/attach.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/oras/internal/display/metadata/text/attach.go b/cmd/oras/internal/display/metadata/text/attach.go index 687b5a889..86a76dcc3 100644 --- a/cmd/oras/internal/display/metadata/text/attach.go +++ b/cmd/oras/internal/display/metadata/text/attach.go @@ -41,14 +41,15 @@ func NewAttachHandler(printer *output.Printer) metadata.AttachHandler { // OnAttached implements AttachHandler. func (ah *AttachHandler) OnAttached(target *option.Target, root ocispec.Descriptor, subject ocispec.Descriptor) { - ah.subjectRefByDigest = target.AnnotatedReference() - if !strings.HasSuffix(target.RawReference, subject.Digest.String()) { + ah.root = root + if strings.HasSuffix(target.RawReference, subject.Digest.String()) { + ah.subjectRefByDigest = target.AnnotatedReference() + } else { // use subject digest instead of tag newTarget := *target newTarget.RawReference = fmt.Sprintf("%s@%s", target.Path, subject.Digest) ah.subjectRefByDigest = newTarget.AnnotatedReference() } - ah.root = root } // Render is called when the attach command is complete. From 90c796c2fe6ed6eedd9659aa54ec2478445c5abc Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Fri, 13 Dec 2024 09:08:34 +0000 Subject: [PATCH 8/8] increase coverage Signed-off-by: Billy Zha --- test/e2e/suite/command/attach.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/e2e/suite/command/attach.go b/test/e2e/suite/command/attach.go index ee19f0ba1..da86130c3 100644 --- a/test/e2e/suite/command/attach.go +++ b/test/e2e/suite/command/attach.go @@ -138,7 +138,7 @@ var _ = Describe("ORAS beginners:", func() { var _ = Describe("1.1 registry users:", func() { When("running attach command", func() { It("should attach a file to a subject and output status", func() { - testRepo := attachTestRepo("simple") + testRepo := attachTestRepo("attach-tag") CopyZOTRepo(ImageRepo, testRepo) subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). @@ -147,6 +147,16 @@ var _ = Describe("1.1 registry users:", func() { MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() }) + It("should attach a file to a subject and output status", func() { + testRepo := attachTestRepo("attach-digest") + CopyZOTRepo(ImageRepo, testRepo) + subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Digest) + ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). + WithWorkDir(PrepareTempFiles()). + MatchKeyWords(fmt.Sprintf("Attached to [registry] %s", subjectRef)). + MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() + }) + It("should attach a file to an arch-specific subject", func() { // prepare testRepo := attachTestRepo("arch-specific")