-
Notifications
You must be signed in to change notification settings - Fork 181
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 compatibility mode for push and attach cmd #741
Changes from 15 commits
48cdfbc
9b14cbb
324b06b
a17a690
54236d6
aef998d
c154ef8
95623ba
6e87ff4
61e6618
6b2874d
d4f0123
3002b46
6f53121
e552ae6
8d3e2c4
7b350fb
4b13256
cb47414
a6cbc9f
7d570b0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
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 option | ||
|
||
import ( | ||
"fmt" | ||
|
||
ocispec "github.com/opencontainers/image-spec/specs-go/v1" | ||
|
||
"github.com/spf13/pflag" | ||
qweeah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
|
||
const MediaTypeAutoManifest = "" | ||
qweeah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// ImageSpec option struct. | ||
type ImageSpec struct { | ||
// Manifest type for building artifact | ||
ManifestMediaType string | ||
// specFlag should be provided in form of `<version>-<manifest type>` | ||
qweeah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
specFlag string | ||
} | ||
|
||
// Parse parses flags into the option. | ||
func (opts *ImageSpec) Parse() error { | ||
switch opts.specFlag { | ||
case "": | ||
opts.ManifestMediaType = MediaTypeAutoManifest | ||
case "v1.1-image": | ||
opts.ManifestMediaType = ocispec.MediaTypeImageManifest | ||
case "v1.1-artifact": | ||
opts.ManifestMediaType = ocispec.MediaTypeArtifactManifest | ||
default: | ||
return fmt.Errorf("unknown image specification flag: %q", opts.specFlag) | ||
} | ||
return nil | ||
} | ||
|
||
// ApplyFlags applies flags to a command flag set. | ||
func (opts *ImageSpec) ApplyFlags(fs *pflag.FlagSet) { | ||
fs.StringVar(&opts.specFlag, "image-spec", "", "specify manifest type for building artifact. options: v1.1-image, v1.1-artifact") | ||
} | ||
|
||
// DistributionSpec option struct. | ||
type DistributionSpec struct { | ||
// ReferrersAPI indicates the preference of the implementation of the Referrers API. | ||
// Set to true for referrers API, false for referrers tag scheme, and nil for auto fallback. | ||
ReferrersAPI *bool | ||
// specFlag should be provided in form of`<version>-<api>-<option>` | ||
specFlag string | ||
} | ||
|
||
// Parse parses flags into the option. | ||
func (opts *DistributionSpec) Parse() error { | ||
switch opts.specFlag { | ||
case "": | ||
opts.ReferrersAPI = nil | ||
case "v1.1-referrers-api", "v1.1-referrers-tag": | ||
isApi := opts.specFlag == "v1.1-referrers-api" | ||
opts.ReferrersAPI = &isApi | ||
qweeah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
default: | ||
return fmt.Errorf("unknown image specification flag: %q", opts.specFlag) | ||
} | ||
return nil | ||
} | ||
|
||
// ApplyFlags applies flags to a command flag set. | ||
func (opts *DistributionSpec) ApplyFlags(fs *pflag.FlagSet) { | ||
fs.StringVar(&opts.specFlag, "distribution-spec", "", "set OCI distribution spec version and API option. options: v1.1-referrers-api, v1.1-referrers-tag") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,7 @@ type pushOptions struct { | |
option.Common | ||
option.Remote | ||
option.Packer | ||
option.ImageSpec | ||
|
||
targetRef string | ||
extraRefs []string | ||
|
@@ -73,6 +74,10 @@ Example - Push file "hi.txt" with config type "application/vnd.me.config": | |
Example - Push file "hi.txt" with the custom manifest config "config.json" of the custom media type "application/vnd.me.config": | ||
oras push --config config.json:application/vnd.me.config localhost:5000/hello:latest hi.txt | ||
|
||
Example - Push file "hi.txt" and enforce packed manifest type: | ||
qweeah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
oras push --image-spec v1.1-image localhost:5000/hello:latest hi.txt # OCI image | ||
oras push --image-spec v1.1-artifact localhost:5000/hello:latest hi.txt # OCI artifact | ||
qweeah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Example - Push file to the insecure registry: | ||
oras push --insecure localhost:5000/hello:latest hi.txt | ||
|
||
|
@@ -99,6 +104,9 @@ Example - Push file "hi.txt" with multiple tags and concurrency level tuned: | |
return option.Parse(&opts) | ||
}, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
if opts.ManifestMediaType == ocispec.MediaTypeArtifactManifest && opts.manifestConfigRef != "" { | ||
return errors.New("cannot pack an OCI artifact with manifest config at the same time") | ||
qweeah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It reminds me that there will be a feature request eventually to support There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? The content of config doesn't matter and the media type of config can be deducted from artifact type. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If they could, they will ask. |
||
refs := strings.Split(args[0], ",") | ||
opts.targetRef = refs[0] | ||
opts.extraRefs = refs[1:] | ||
|
@@ -142,6 +150,9 @@ func runPush(opts pushOptions) error { | |
packOpts.ConfigDescriptor = &desc | ||
packOpts.PackImageManifest = true | ||
} | ||
if opts.ManifestMediaType == ocispec.MediaTypeImageManifest { | ||
packOpts.PackImageManifest = true | ||
} | ||
descs, err := loadFiles(ctx, store, annotations, opts.FileRefs, opts.Verbose) | ||
if err != nil { | ||
return err | ||
|
@@ -175,7 +186,7 @@ func runPush(opts pushOptions) error { | |
} | ||
|
||
// Push | ||
root, err := pushArtifact(dst, pack, &packOpts, copy, ©Options.CopyGraphOptions, opts.Verbose) | ||
root, err := pushArtifact(dst, pack, &packOpts, copy, ©Options.CopyGraphOptions, opts.ManifestMediaType == option.MediaTypeAutoManifest, opts.Verbose) | ||
if err != nil { | ||
return err | ||
} | ||
|
@@ -218,7 +229,7 @@ func updateDisplayOption(opts *oras.CopyGraphOptions, store content.Fetcher, ver | |
type packFunc func() (ocispec.Descriptor, error) | ||
type copyFunc func(desc ocispec.Descriptor) error | ||
|
||
func pushArtifact(dst *remote.Repository, pack packFunc, packOpts *oras.PackOptions, copy copyFunc, copyOpts *oras.CopyGraphOptions, verbose bool) (ocispec.Descriptor, error) { | ||
func pushArtifact(dst *remote.Repository, pack packFunc, packOpts *oras.PackOptions, copy copyFunc, copyOpts *oras.CopyGraphOptions, allowFallback bool, verbose bool) (ocispec.Descriptor, error) { | ||
root, err := pack() | ||
if err != nil { | ||
return ocispec.Descriptor{}, err | ||
|
@@ -243,7 +254,7 @@ func pushArtifact(dst *remote.Repository, pack packFunc, packOpts *oras.PackOpti | |
return root, nil | ||
} | ||
|
||
if !copyRootAttempted || root.MediaType != ocispec.MediaTypeArtifactManifest || | ||
if !allowFallback || !copyRootAttempted || root.MediaType != ocispec.MediaTypeArtifactManifest || | ||
!isManifestUnsupported(err) { | ||
return ocispec.Descriptor{}, err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest always splitting the sample commands into multiple examples. If you have more than two options under a flag and put all of those sample commands under a flag example, the layout looks too verbose.