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: support --format in manifest fetch command #1295

Merged
merged 46 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
67dad87
feat: support `--format` in `manifest fetch` command
qweeah Mar 18, 2024
fa0f2a1
add comment
qweeah Mar 18, 2024
d832fbe
Merge remote-tracking branch 'upstream/main' into format-manifest-fetch
qweeah Mar 19, 2024
3669aff
Merge remote-tracking branch 'upstream/main' into format-manifest-fetch
qweeah Mar 19, 2024
fc2bccc
Merge remote-tracking branch 'upstream/main' into format-manifest-fetch
qweeah Apr 1, 2024
e9c1226
refactor
qweeah Apr 1, 2024
9c73b0d
Merge remote-tracking branch 'upstream/main' into format-manifest-fetch
qweeah Apr 1, 2024
6614c92
use new printer
qweeah Apr 1, 2024
eb5f62d
bug fix
qweeah Apr 1, 2024
ce6bc89
fix struct fields with json tags
qweeah Apr 2, 2024
5dc8583
Merge remote-tracking branch 'upstream/main' into format-manifest-fetch
qweeah Apr 3, 2024
c13ee29
remove raw discarder
qweeah Apr 3, 2024
4b1e2f9
fix e2e
qweeah Apr 3, 2024
5689580
Merge remote-tracking branch 'upstream/main' into format-manifest-fetch
qweeah Apr 7, 2024
c7488d6
fix e2e
qweeah Apr 7, 2024
42ab0a3
refactor
qweeah Apr 7, 2024
d954405
add discard handler for raw output
qweeah Apr 7, 2024
00a5895
Merge remote-tracking branch 'upstream/main' into format-manifest-fetch
qweeah Apr 7, 2024
7460060
revert focus
qweeah Apr 7, 2024
de6acf1
rename to content handler
qweeah Apr 7, 2024
4709b62
fix e2e
qweeah Apr 7, 2024
3fcab69
add e2e
qweeah Apr 7, 2024
f8c2dbf
fix e2e
qweeah Apr 7, 2024
90a3141
use unmarshal and enhance e2e
qweeah Apr 8, 2024
ca0f082
code clean
qweeah Apr 8, 2024
a1addb4
resolve comments
qweeah Apr 8, 2024
998ad76
fix e2e
qweeah Apr 8, 2024
f93ba89
code clean
qweeah Apr 8, 2024
e66ed8e
Merge remote-tracking branch 'upstream/main' into format-manifest-fetch
qweeah Apr 8, 2024
a7656be
Merge remote-tracking branch 'upstream/main' into format-manifest-fetch
qweeah Apr 8, 2024
b54a2e6
code clean
qweeah Apr 8, 2024
e682458
code clean
qweeah Apr 8, 2024
faa8c63
code clean
qweeah Apr 8, 2024
9c3a426
Merge remote-tracking branch 'upstream/main' into format-manifest-fetch
qweeah Apr 9, 2024
4eb5b9f
add fetched model
qweeah Apr 10, 2024
3cbbf9b
add experimental mark
qweeah Apr 10, 2024
7b09792
fix e2e
qweeah Apr 10, 2024
cb98a26
fix e2e
qweeah Apr 10, 2024
6615478
resolve comments
qweeah Apr 10, 2024
a8c3de8
add json test
qweeah Apr 10, 2024
1dfd284
fix e2e
qweeah Apr 10, 2024
dfb8dce
resolve comments
qweeah Apr 10, 2024
6c5e2cf
resolve comments
qweeah Apr 10, 2024
bb69b39
add e2e coverage
qweeah Apr 10, 2024
57d2078
remove used code
qweeah Apr 10, 2024
4ec65f9
use create file instead of open file
qweeah Apr 10, 2024
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
30 changes: 30 additions & 0 deletions cmd/oras/internal/display/content/discard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
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 content

import ocispec "github.com/opencontainers/image-spec/specs-go/v1"

type discardHandler struct{}

// OnContentFetched implements ManifestFetchHandler.
func (discardHandler) OnContentFetched(ocispec.Descriptor, []byte) error {
return nil
}

// NewDiscardHandler returns a new discard handler.
func NewDiscardHandler() ManifestFetchHandler {
return discardHandler{}
}
26 changes: 26 additions & 0 deletions cmd/oras/internal/display/content/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
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 content

import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

// ManifestFetchHandler handles raw output for manifest fetch events.
type ManifestFetchHandler interface {
// OnContentFetched is called after the manifest content is fetched.
OnContentFetched(desc ocispec.Descriptor, content []byte) error
}
54 changes: 54 additions & 0 deletions cmd/oras/internal/display/content/manifest_fetch.go
Original file line number Diff line number Diff line change
@@ -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 content

import (
"fmt"
"io"
"os"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/cmd/oras/internal/display/utils"
)

// manifestFetch handles raw content output.
type manifestFetch struct {
pretty bool
stdout io.Writer
outputPath string
}

func (h *manifestFetch) OnContentFetched(desc ocispec.Descriptor, manifest []byte) error {
out := h.stdout
if h.outputPath != "-" && h.outputPath != "" {
f, err := os.OpenFile(h.outputPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return fmt.Errorf("failed to open %q: %w", h.outputPath, err)

Check warning on line 39 in cmd/oras/internal/display/content/manifest_fetch.go

View check run for this annotation

Codecov / codecov/patch

cmd/oras/internal/display/content/manifest_fetch.go#L39

Added line #L39 was not covered by tests
}
defer f.Close()
out = f
}
return utils.PrintJSON(out, manifest, h.pretty)
}

// NewManifestFetchHandler creates a new handler.
func NewManifestFetchHandler(out io.Writer, pretty bool, outputPath string) ManifestFetchHandler {
return &manifestFetch{
pretty: pretty,
stdout: out,
outputPath: outputPath,
}
}
35 changes: 35 additions & 0 deletions cmd/oras/internal/display/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
"io"
"os"

"oras.land/oras/cmd/oras/internal/display/content"
"oras.land/oras/cmd/oras/internal/display/metadata"
"oras.land/oras/cmd/oras/internal/display/metadata/descriptor"
"oras.land/oras/cmd/oras/internal/display/metadata/json"
"oras.land/oras/cmd/oras/internal/display/metadata/template"
"oras.land/oras/cmd/oras/internal/display/metadata/text"
Expand Down Expand Up @@ -94,3 +96,36 @@
}
return statusHandler, metadataHandler
}

// NewManifestFetchHandler returns a manifest fetch handler.
func NewManifestFetchHandler(out io.Writer, format string, outputDescriptor, pretty bool, outputPath string) (metadata.ManifestFetchHandler, content.ManifestFetchHandler) {
var metadataHandler metadata.ManifestFetchHandler
var contentHandler content.ManifestFetchHandler

switch format {
case "":
// raw
if outputDescriptor {
metadataHandler = descriptor.NewManifestFetchHandler(out, pretty)
} else {
metadataHandler = metadata.NewDiscardHandler()
}
case "json":
// json
metadataHandler = json.NewManifestFetchHandler(out)
if outputPath == "" {
contentHandler = content.NewDiscardHandler()

Check warning on line 117 in cmd/oras/internal/display/handler.go

View check run for this annotation

Codecov / codecov/patch

cmd/oras/internal/display/handler.go#L117

Added line #L117 was not covered by tests
}
default:
// go template
metadataHandler = template.NewManifestFetchHandler(out, format)
if outputPath == "" {
contentHandler = content.NewDiscardHandler()
}
}

if contentHandler == nil {
contentHandler = content.NewManifestFetchHandler(out, pretty, outputPath)
}
return metadataHandler, contentHandler
}
49 changes: 49 additions & 0 deletions cmd/oras/internal/display/metadata/descriptor/manifest_fetch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
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 descriptor

import (
"encoding/json"
"fmt"
"io"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/cmd/oras/internal/display/metadata"
"oras.land/oras/cmd/oras/internal/display/utils"
)

// manifestFetchHandler handles metadata descriptor output.
type manifestFetchHandler struct {
pretty bool
out io.Writer
}

// OnFetched implements ManifestFetchHandler.
func (h *manifestFetchHandler) OnFetched(_ string, desc ocispec.Descriptor, _ []byte) error {
descBytes, err := json.Marshal(desc)
if err != nil {
return fmt.Errorf("invalid descriptor: %w", err)

Check warning on line 38 in cmd/oras/internal/display/metadata/descriptor/manifest_fetch.go

View check run for this annotation

Codecov / codecov/patch

cmd/oras/internal/display/metadata/descriptor/manifest_fetch.go#L38

Added line #L38 was not covered by tests
}
return utils.PrintJSON(h.out, descBytes, h.pretty)
}

// NewManifestFetchHandler creates a new handler.
func NewManifestFetchHandler(out io.Writer, pretty bool) metadata.ManifestFetchHandler {
return &manifestFetchHandler{
pretty: pretty,
out: out,
}
}
30 changes: 30 additions & 0 deletions cmd/oras/internal/display/metadata/discard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
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 metadata

import ocispec "github.com/opencontainers/image-spec/specs-go/v1"

type discard struct{}

// NewDiscardHandler creates a new handler that discards output for all events.
func NewDiscardHandler() ManifestFetchHandler {
return discard{}
}

// OnFetched implements ManifestFetchHandler.
func (discard) OnFetched(string, ocispec.Descriptor, []byte) error {
return nil
}
6 changes: 6 additions & 0 deletions cmd/oras/internal/display/metadata/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ type AttachHandler interface {
OnCompleted(opts *option.Target, root, subject ocispec.Descriptor) error
}

// ManifestFetchHandler handles metadata output for manifest fetch events.
type ManifestFetchHandler interface {
// OnFetched is called after the manifest content is fetched.
OnFetched(path string, desc ocispec.Descriptor, content []byte) error
}

// PullHandler handles metadata output for pull events.
type PullHandler interface {
// OnLayerSkipped is called when a layer is skipped.
Expand Down
44 changes: 44 additions & 0 deletions cmd/oras/internal/display/metadata/json/manifest_fetch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
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 json

import (
"encoding/json"
"io"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/cmd/oras/internal/display/metadata"
"oras.land/oras/cmd/oras/internal/display/metadata/model"
)

// manifestFetchHandler handles JSON metadata output for manifest fetch events.
type manifestFetchHandler struct {
out io.Writer
}

// NewManifestFetchHandler creates a new handler for manifest fetch events.
func NewManifestFetchHandler(out io.Writer) metadata.ManifestFetchHandler {
return &manifestFetchHandler{
out: out,
}
}

// OnFetched is called after the manifest fetch is completed.
func (h *manifestFetchHandler) OnFetched(path string, desc ocispec.Descriptor, content []byte) error {
var manifest map[string]any
_ = json.Unmarshal(content, &manifest)
return printJSON(h.out, model.NewFetched(path, desc, manifest))
}
31 changes: 31 additions & 0 deletions cmd/oras/internal/display/metadata/model/fetched.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
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 model

import ocispec "github.com/opencontainers/image-spec/specs-go/v1"

type fetched struct {
Descriptor
Content any
}

// NewFetched creates a new fetched metadata.
func NewFetched(path string, desc ocispec.Descriptor, content any) any {
return &fetched{
Descriptor: FromDescriptor(path, desc),
Content: content,
}
}
46 changes: 46 additions & 0 deletions cmd/oras/internal/display/metadata/template/manifest_fetch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
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 template

import (
"encoding/json"
"io"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/cmd/oras/internal/display/metadata"
"oras.land/oras/cmd/oras/internal/display/metadata/model"
)

// manifestFetchHandler handles JSON metadata output for manifest fetch events.
type manifestFetchHandler struct {
template string
out io.Writer
}

// NewManifestFetchHandler creates a new handler for manifest fetch events.
func NewManifestFetchHandler(out io.Writer, template string) metadata.ManifestFetchHandler {
return &manifestFetchHandler{
template: template,
out: out,
}
}

// OnFetched is called after the manifest fetch is completed.
func (h *manifestFetchHandler) OnFetched(path string, desc ocispec.Descriptor, content []byte) error {
var manifest map[string]any
_ = json.Unmarshal(content, &manifest)
return parseAndWrite(h.out, model.NewFetched(path, desc, manifest), h.template)
}
Loading
Loading