mirror of
https://github.com/containers/skopeo.git
synced 2025-07-12 14:08:37 +00:00
commit
14847101c0
@ -98,9 +98,9 @@ func (s *CopySuite) TestCopySimple(c *check.C) {
|
||||
// "pull": docker: → dir:
|
||||
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:latest", "dir:"+dir1)
|
||||
// "push": dir: → atomic:
|
||||
assertSkopeoSucceeds(c, "", "--debug", "copy", "dir:"+dir1, "atomic:myns/unsigned:unsigned")
|
||||
assertSkopeoSucceeds(c, "", "--debug", "copy", "dir:"+dir1, "atomic:localhost:5000/myns/unsigned:unsigned")
|
||||
// The result of pushing and pulling is an unmodified image.
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/unsigned:unsigned", "dir:"+dir2)
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/unsigned:unsigned", "dir:"+dir2)
|
||||
out := combinedOutputOfCommand(c, "diff", "-urN", dir1, dir2)
|
||||
c.Assert(out, check.Equals, "")
|
||||
|
||||
@ -127,10 +127,10 @@ func (s *CopySuite) TestCopyStreaming(c *check.C) {
|
||||
|
||||
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
|
||||
// streaming: docker: → atomic:
|
||||
assertSkopeoSucceeds(c, "", "--debug", "copy", "docker://estesp/busybox:amd64", "atomic:myns/unsigned:streaming")
|
||||
assertSkopeoSucceeds(c, "", "--debug", "copy", "docker://estesp/busybox:amd64", "atomic:localhost:5000/myns/unsigned:streaming")
|
||||
// Compare (copies of) the original and the copy:
|
||||
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:amd64", "dir:"+dir1)
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/unsigned:streaming", "dir:"+dir2)
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/unsigned:streaming", "dir:"+dir2)
|
||||
// The manifests will have different JWS signatures; so, compare the manifests by digests, which
|
||||
// strips the signatures, and remove them, comparing the rest file by file.
|
||||
digests := []string{}
|
||||
@ -170,34 +170,34 @@ func (s *CopySuite) TestCopySignatures(c *check.C) {
|
||||
|
||||
// type: signedBy
|
||||
// Sign the images
|
||||
assertSkopeoSucceeds(c, "", "copy", "--sign-by", "personal@example.com", "docker://busybox:1.23", "atomic:myns/personal:personal")
|
||||
assertSkopeoSucceeds(c, "", "copy", "--sign-by", "official@example.com", "docker://busybox:1.23.2", "atomic:myns/official:official")
|
||||
assertSkopeoSucceeds(c, "", "copy", "--sign-by", "personal@example.com", "docker://busybox:1.23", "atomic:localhost:5000/myns/personal:personal")
|
||||
assertSkopeoSucceeds(c, "", "copy", "--sign-by", "official@example.com", "docker://busybox:1.23.2", "atomic:localhost:5000/myns/official:official")
|
||||
// Verify that we can pull them
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:myns/personal:personal", dirDest)
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:myns/official:official", dirDest)
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:localhost:5000/myns/personal:personal", dirDest)
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:localhost:5000/myns/official:official", dirDest)
|
||||
// Verify that mis-signed images are rejected
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/personal:personal", "atomic:myns/official:attack")
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/official:official", "atomic:myns/personal:attack")
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/personal:personal", "atomic:localhost:5000/myns/official:attack")
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/personal:attack")
|
||||
assertSkopeoFails(c, ".*Source image rejected: Invalid GPG signature.*",
|
||||
"--policy", policy, "copy", "atomic:myns/personal:attack", dirDest)
|
||||
"--policy", policy, "copy", "atomic:localhost:5000/myns/personal:attack", dirDest)
|
||||
assertSkopeoFails(c, ".*Source image rejected: Invalid GPG signature.*",
|
||||
"--policy", policy, "copy", "atomic:myns/official:attack", dirDest)
|
||||
"--policy", policy, "copy", "atomic:localhost:5000/myns/official:attack", dirDest)
|
||||
|
||||
// Verify that signed identity is verified.
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/official:official", "atomic:myns/naming:test1")
|
||||
assertSkopeoFails(c, ".*Source image rejected: Signature for identity localhost:8443/myns/official:official is not accepted.*",
|
||||
"--policy", policy, "copy", "atomic:myns/naming:test1", dirDest)
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/naming:test1")
|
||||
assertSkopeoFails(c, ".*Source image rejected: Signature for identity localhost:5000/myns/official:official is not accepted.*",
|
||||
"--policy", policy, "copy", "atomic:localhost:5000/myns/naming:test1", dirDest)
|
||||
// signedIdentity works
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/official:official", "atomic:myns/naming:naming")
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:myns/naming:naming", dirDest)
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/naming:naming")
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:localhost:5000/myns/naming:naming", dirDest)
|
||||
|
||||
// Verify that cosigning requirements are enforced
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/official:official", "atomic:myns/cosigned:cosigned")
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/cosigned:cosigned")
|
||||
assertSkopeoFails(c, ".*Source image rejected: Invalid GPG signature.*",
|
||||
"--policy", policy, "copy", "atomic:myns/cosigned:cosigned", dirDest)
|
||||
"--policy", policy, "copy", "atomic:localhost:5000/myns/cosigned:cosigned", dirDest)
|
||||
|
||||
assertSkopeoSucceeds(c, "", "copy", "--sign-by", "personal@example.com", "atomic:myns/official:official", "atomic:myns/cosigned:cosigned")
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:myns/cosigned:cosigned", dirDest)
|
||||
assertSkopeoSucceeds(c, "", "copy", "--sign-by", "personal@example.com", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/cosigned:cosigned")
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:localhost:5000/myns/cosigned:cosigned", dirDest)
|
||||
}
|
||||
|
||||
// --policy copy for dir: sources
|
||||
@ -224,10 +224,10 @@ func (s *CopySuite) TestCopyDirSignatures(c *check.C) {
|
||||
// Sign the images. By coping fom a topDirDest/dirN, also test that non-/restricted paths
|
||||
// use the dir:"" default of insecureAcceptAnything.
|
||||
// (For signing, we must push to atomic: to get a Docker identity to use in the signature.)
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "--sign-by", "personal@example.com", topDirDest+"/dir1", "atomic:myns/personal:dirstaging")
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "--sign-by", "official@example.com", topDirDest+"/dir2", "atomic:myns/official:dirstaging")
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/personal:dirstaging", topDirDest+"/restricted/personal")
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/official:dirstaging", topDirDest+"/restricted/official")
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "--sign-by", "personal@example.com", topDirDest+"/dir1", "atomic:localhost:5000/myns/personal:dirstaging")
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "--sign-by", "official@example.com", topDirDest+"/dir2", "atomic:localhost:5000/myns/official:dirstaging")
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/personal:dirstaging", topDirDest+"/restricted/personal")
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/official:dirstaging", topDirDest+"/restricted/official")
|
||||
|
||||
// type: signedBy, with a signedIdentity override (necessary because dir: identities can't be signed)
|
||||
// Verify that correct images are accepted
|
||||
@ -237,8 +237,8 @@ func (s *CopySuite) TestCopyDirSignatures(c *check.C) {
|
||||
"--policy", policy, "copy", topDirDest+"/restricted/personal", topDirDest+"/dest")
|
||||
|
||||
// Verify that the signed identity is verified.
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "--sign-by", "official@example.com", topDirDest+"/dir1", "atomic:myns/personal:dirstaging2")
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/personal:dirstaging2", topDirDest+"/restricted/badidentity")
|
||||
assertSkopeoFails(c, ".*Source image rejected: .*Signature for identity localhost:8443/myns/personal:dirstaging2 is not accepted.*",
|
||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "--sign-by", "official@example.com", topDirDest+"/dir1", "atomic:localhost:5000/myns/personal:dirstaging2")
|
||||
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/personal:dirstaging2", topDirDest+"/restricted/badidentity")
|
||||
assertSkopeoFails(c, ".*Source image rejected: .*Signature for identity localhost:5000/myns/personal:dirstaging2 is not accepted.*",
|
||||
"--policy", policy, "copy", topDirDest+"/restricted/badidentity", topDirDest+"/dest")
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
"keyPath": "@keydir@/official-pubkey.gpg",
|
||||
"signedIdentity": {
|
||||
"type": "exactRepository",
|
||||
"dockerRepository": "localhost:8443/myns/official"
|
||||
"dockerRepository": "localhost:5000/myns/official"
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -31,46 +31,46 @@
|
||||
]
|
||||
},
|
||||
"atomic": {
|
||||
"localhost:8443/myns/personal": [
|
||||
"localhost:5000/myns/personal": [
|
||||
{
|
||||
"type": "signedBy",
|
||||
"keyType": "GPGKeys",
|
||||
"keyPath": "@keydir@/personal-pubkey.gpg"
|
||||
}
|
||||
],
|
||||
"localhost:8443/myns/official": [
|
||||
"localhost:5000/myns/official": [
|
||||
{
|
||||
"type": "signedBy",
|
||||
"keyType": "GPGKeys",
|
||||
"keyPath": "@keydir@/official-pubkey.gpg"
|
||||
}
|
||||
],
|
||||
"localhost:8443/myns/naming:test1": [
|
||||
"localhost:5000/myns/naming:test1": [
|
||||
{
|
||||
"type": "signedBy",
|
||||
"keyType": "GPGKeys",
|
||||
"keyPath": "@keydir@/official-pubkey.gpg"
|
||||
}
|
||||
],
|
||||
"localhost:8443/myns/naming:naming": [
|
||||
"localhost:5000/myns/naming:naming": [
|
||||
{
|
||||
"type": "signedBy",
|
||||
"keyType": "GPGKeys",
|
||||
"keyPath": "@keydir@/official-pubkey.gpg",
|
||||
"signedIdentity": {
|
||||
"type": "exactRepository",
|
||||
"dockerRepository": "localhost:8443/myns/official"
|
||||
"dockerRepository": "localhost:5000/myns/official"
|
||||
}
|
||||
}
|
||||
],
|
||||
"localhost:8443/myns/cosigned:cosigned": [
|
||||
"localhost:5000/myns/cosigned:cosigned": [
|
||||
{
|
||||
"type": "signedBy",
|
||||
"keyType": "GPGKeys",
|
||||
"keyPath": "@keydir@/official-pubkey.gpg",
|
||||
"signedIdentity": {
|
||||
"type": "exactRepository",
|
||||
"dockerRepository": "localhost:8443/myns/official"
|
||||
"dockerRepository": "localhost:5000/myns/official"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -81,4 +81,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
33
vendor/github.com/containers/image/openshift/openshift.go
generated
vendored
33
vendor/github.com/containers/image/openshift/openshift.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -21,7 +22,8 @@ import (
|
||||
|
||||
// openshiftClient is configuration for dealing with a single image stream, for reading or writing.
|
||||
type openshiftClient struct {
|
||||
ref openshiftReference
|
||||
ref openshiftReference
|
||||
baseURL *url.URL
|
||||
// Values from Kubernetes configuration
|
||||
httpClient *http.Client
|
||||
bearerToken string // "" if not used
|
||||
@ -51,9 +53,7 @@ func newOpenshiftClient(ref openshiftReference) (*openshiftClient, error) {
|
||||
return nil, err
|
||||
}
|
||||
logrus.Debugf("URL: %#v", *baseURL)
|
||||
if *baseURL != *ref.baseURL {
|
||||
return nil, fmt.Errorf("Unexpected baseURL mismatch: default %#v, reference %#v", *baseURL, *ref.baseURL)
|
||||
}
|
||||
|
||||
if httpClient == nil {
|
||||
httpClient = http.DefaultClient
|
||||
}
|
||||
@ -61,6 +61,7 @@ func newOpenshiftClient(ref openshiftReference) (*openshiftClient, error) {
|
||||
|
||||
return &openshiftClient{
|
||||
ref: ref,
|
||||
baseURL: baseURL,
|
||||
httpClient: httpClient,
|
||||
bearerToken: restConfig.BearerToken,
|
||||
username: restConfig.Username,
|
||||
@ -70,7 +71,7 @@ func newOpenshiftClient(ref openshiftReference) (*openshiftClient, error) {
|
||||
|
||||
// doRequest performs a correctly authenticated request to a specified path, and returns response body or an error object.
|
||||
func (c *openshiftClient) doRequest(method, path string, requestBody []byte) ([]byte, error) {
|
||||
url := *c.ref.baseURL
|
||||
url := *c.baseURL
|
||||
url.Path = path
|
||||
var requestBodyReader io.Reader
|
||||
if requestBody != nil {
|
||||
@ -153,19 +154,7 @@ func (c *openshiftClient) convertDockerImageReference(ref string) (string, error
|
||||
if len(parts) != 2 {
|
||||
return "", fmt.Errorf("Invalid format of docker reference %s: missing '/'", ref)
|
||||
}
|
||||
// Sanity check that the reference is at least plausibly similar, i.e. uses the hard-coded port we expect.
|
||||
if !strings.HasSuffix(parts[0], ":5000") {
|
||||
return "", fmt.Errorf("Invalid format of docker reference %s: expecting port 5000", ref)
|
||||
}
|
||||
return c.dockerRegistryHostPart() + "/" + parts[1], nil
|
||||
}
|
||||
|
||||
// dockerRegistryHostPart returns the host:port of the embedded Docker Registry API endpoint
|
||||
// FIXME: There seems to be no way to discover the correct:host port using the API, so hard-code our knowledge
|
||||
// about how the OpenShift Atomic Registry is configured, per examples/atomic-registry/run.sh:
|
||||
// -p OPENSHIFT_OAUTH_PROVIDER_URL=https://${INSTALL_HOST}:8443,COCKPIT_KUBE_URL=https://${INSTALL_HOST},REGISTRY_HOST=${INSTALL_HOST}:5000
|
||||
func (c *openshiftClient) dockerRegistryHostPart() string {
|
||||
return strings.SplitN(c.ref.baseURL.Host, ":", 2)[0] + ":5000"
|
||||
return c.ref.dockerReference.Hostname() + "/" + parts[1], nil
|
||||
}
|
||||
|
||||
type openshiftImageSource struct {
|
||||
@ -261,7 +250,7 @@ func (s *openshiftImageSource) ensureImageIsResolved() error {
|
||||
}
|
||||
var te *tagEvent
|
||||
for _, tag := range is.Status.Tags {
|
||||
if tag.Tag != s.client.ref.tag {
|
||||
if tag.Tag != s.client.ref.dockerReference.Tag() {
|
||||
continue
|
||||
}
|
||||
if len(tag.Items) > 0 {
|
||||
@ -308,7 +297,7 @@ func newImageDestination(ctx *types.SystemContext, ref openshiftReference) (type
|
||||
// FIXME: Should this always use a digest, not a tag? Uploading to Docker by tag requires the tag _inside_ the manifest to match,
|
||||
// i.e. a single signed image cannot be available under multiple tags. But with types.ImageDestination, we don't know
|
||||
// the manifest digest at this point.
|
||||
dockerRefString := fmt.Sprintf("//%s/%s/%s:%s", client.dockerRegistryHostPart(), client.ref.namespace, client.ref.stream, client.ref.tag)
|
||||
dockerRefString := fmt.Sprintf("//%s/%s/%s:%s", client.ref.dockerReference.Hostname(), client.ref.namespace, client.ref.stream, client.ref.dockerReference.Tag())
|
||||
dockerRef, err := docker.ParseReference(dockerRefString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -370,7 +359,7 @@ func (d *openshiftImageDestination) PutManifest(m []byte) error {
|
||||
}
|
||||
d.imageStreamImageName = manifestDigest
|
||||
// FIXME: We can't do what respositorymiddleware.go does because we don't know the internal address. Does any of this matter?
|
||||
dockerImageReference := fmt.Sprintf("%s/%s/%s@%s", d.client.dockerRegistryHostPart(), d.client.ref.namespace, d.client.ref.stream, manifestDigest)
|
||||
dockerImageReference := fmt.Sprintf("%s/%s/%s@%s", d.client.ref.dockerReference.Hostname(), d.client.ref.namespace, d.client.ref.stream, manifestDigest)
|
||||
ism := imageStreamMapping{
|
||||
typeMeta: typeMeta{
|
||||
Kind: "ImageStreamMapping",
|
||||
@ -387,7 +376,7 @@ func (d *openshiftImageDestination) PutManifest(m []byte) error {
|
||||
DockerImageReference: dockerImageReference,
|
||||
DockerImageManifest: string(m),
|
||||
},
|
||||
Tag: d.client.ref.tag,
|
||||
Tag: d.client.ref.dockerReference.Tag(),
|
||||
}
|
||||
body, err := json.Marshal(ism)
|
||||
if err != nil {
|
||||
|
73
vendor/github.com/containers/image/openshift/openshift_transport.go
generated
vendored
73
vendor/github.com/containers/image/openshift/openshift_transport.go
generated
vendored
@ -3,10 +3,9 @@ package openshift
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/containers/image/docker/policyconfiguration"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/docker/docker/reference"
|
||||
@ -44,67 +43,33 @@ func (t openshiftTransport) ValidatePolicyConfigurationScope(scope string) error
|
||||
|
||||
// openshiftReference is an ImageReference for OpenShift images.
|
||||
type openshiftReference struct {
|
||||
baseURL *url.URL
|
||||
namespace string
|
||||
stream string
|
||||
tag string
|
||||
dockerReference reference.Named // Computed from the above in advance, so that later references can not fail.
|
||||
dockerReference reference.NamedTagged
|
||||
namespace string // Computed from dockerReference in advance.
|
||||
stream string // Computed from dockerReference in advance.
|
||||
}
|
||||
|
||||
// FIXME: Is imageName like this a good way to refer to OpenShift images?
|
||||
// Keep this in sync with scopeRegexp!
|
||||
var imageNameRegexp = regexp.MustCompile("^([^:/]*)/([^:/]*):([^:/]*)$")
|
||||
|
||||
// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an OpenShift ImageReference.
|
||||
func ParseReference(reference string) (types.ImageReference, error) {
|
||||
// Overall, this is modelled on openshift/origin/pkg/cmd/util/clientcmd.New().ClientConfig() and openshift/origin/pkg/client.
|
||||
cmdConfig := defaultClientConfig()
|
||||
logrus.Debugf("cmdConfig: %#v", cmdConfig)
|
||||
restConfig, err := cmdConfig.ClientConfig()
|
||||
func ParseReference(ref string) (types.ImageReference, error) {
|
||||
r, err := reference.ParseNamed(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to parse image reference %q, %v", ref, err)
|
||||
}
|
||||
// REMOVED: SetOpenShiftDefaults (values are not overridable in config files, so hard-coded these defaults.)
|
||||
logrus.Debugf("restConfig: %#v", restConfig)
|
||||
baseURL, _, err := restClientFor(restConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
tagged, ok := r.(reference.NamedTagged)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid image reference %s, %#v", ref, r)
|
||||
}
|
||||
logrus.Debugf("URL: %#v", *baseURL)
|
||||
|
||||
m := imageNameRegexp.FindStringSubmatch(reference)
|
||||
if m == nil || len(m) != 4 {
|
||||
return nil, fmt.Errorf("Invalid image reference %s, %#v", reference, m)
|
||||
}
|
||||
|
||||
return NewReference(baseURL, m[1], m[2], m[3])
|
||||
return NewReference(tagged)
|
||||
}
|
||||
|
||||
// NewReference returns an OpenShift reference for a base URL, namespace, stream and tag.
|
||||
func NewReference(baseURL *url.URL, namespace, stream, tag string) (types.ImageReference, error) {
|
||||
// Precompute also dockerReference so that later references can not fail.
|
||||
//
|
||||
// This discards ref.baseURL.Path, which is unexpected for a “base URL”;
|
||||
// but openshiftClient.doRequest actually completely overrides url.Path
|
||||
// (and defaultServerURL rejects non-trivial Path values), so it is OK for
|
||||
// us to ignore it as well.
|
||||
//
|
||||
// FIXME: This is, strictly speaking, a namespace conflict with images placed in a Docker registry running on the same host.
|
||||
// Do we need to do something else, perhaps disambiguate (port number?) or namespace Docker and OpenShift separately?
|
||||
dockerRef, err := reference.WithName(fmt.Sprintf("%s/%s/%s", baseURL.Host, namespace, stream))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// NewReference returns an OpenShift reference for a reference.NamedTagged
|
||||
func NewReference(dockerRef reference.NamedTagged) (types.ImageReference, error) {
|
||||
r := strings.SplitN(dockerRef.RemoteName(), "/", 3)
|
||||
if len(r) != 2 {
|
||||
return nil, fmt.Errorf("invalid image reference %s", dockerRef.String())
|
||||
}
|
||||
dockerRef, err = reference.WithTag(dockerRef, tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return openshiftReference{
|
||||
baseURL: baseURL,
|
||||
namespace: namespace,
|
||||
stream: stream,
|
||||
tag: tag,
|
||||
namespace: r[0],
|
||||
stream: r[1],
|
||||
dockerReference: dockerRef,
|
||||
}, nil
|
||||
}
|
||||
@ -119,7 +84,7 @@ func (ref openshiftReference) Transport() types.ImageTransport {
|
||||
// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa.
|
||||
// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix.
|
||||
func (ref openshiftReference) StringWithinTransport() string {
|
||||
return fmt.Sprintf("%s/%s:%s", ref.namespace, ref.stream, ref.tag)
|
||||
return ref.dockerReference.String()
|
||||
}
|
||||
|
||||
// DockerReference returns a Docker reference associated with this reference
|
||||
|
14
vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go
generated
vendored
14
vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go
generated
vendored
@ -15,18 +15,22 @@
|
||||
package v1
|
||||
|
||||
const (
|
||||
// MediaTypeDescriptor specifies the mediaType for a content descriptor.
|
||||
// MediaTypeDescriptor specifies the media type for a content descriptor.
|
||||
MediaTypeDescriptor = "application/vnd.oci.descriptor.v1+json"
|
||||
|
||||
// MediaTypeImageManifest specifies the mediaType for an image manifest.
|
||||
// MediaTypeImageManifest specifies the media type for an image manifest.
|
||||
MediaTypeImageManifest = "application/vnd.oci.image.manifest.v1+json"
|
||||
|
||||
// MediaTypeImageManifestList specifies the mediaType for an image manifest list.
|
||||
// MediaTypeImageManifestList specifies the media type for an image manifest list.
|
||||
MediaTypeImageManifestList = "application/vnd.oci.image.manifest.list.v1+json"
|
||||
|
||||
// MediaTypeImageLayer is the mediaType used for layers referenced by the manifest.
|
||||
// MediaTypeImageLayer is the media type used for layers referenced by the manifest.
|
||||
MediaTypeImageLayer = "application/vnd.oci.image.layer.tar+gzip"
|
||||
|
||||
// MediaTypeImageConfig specifies the mediaType for the image configuration.
|
||||
// MediaTypeImageLayerNonDistributable is the media type for layers referenced by
|
||||
// the manifest but with distribution restrictions.
|
||||
MediaTypeImageLayerNonDistributable = "application/vnd.oci.image.layer.nondistributable.tar+gzip"
|
||||
|
||||
// MediaTypeImageConfig specifies the media type for the image configuration.
|
||||
MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json"
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user