mirror of
https://github.com/containers/skopeo.git
synced 2025-07-13 14:34:44 +00:00
commit
14847101c0
@ -98,9 +98,9 @@ func (s *CopySuite) TestCopySimple(c *check.C) {
|
|||||||
// "pull": docker: → dir:
|
// "pull": docker: → dir:
|
||||||
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:latest", "dir:"+dir1)
|
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:latest", "dir:"+dir1)
|
||||||
// "push": dir: → atomic:
|
// "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.
|
// 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)
|
out := combinedOutputOfCommand(c, "diff", "-urN", dir1, dir2)
|
||||||
c.Assert(out, check.Equals, "")
|
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.
|
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
|
||||||
// streaming: docker: → atomic:
|
// 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:
|
// Compare (copies of) the original and the copy:
|
||||||
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:amd64", "dir:"+dir1)
|
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
|
// 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.
|
// strips the signatures, and remove them, comparing the rest file by file.
|
||||||
digests := []string{}
|
digests := []string{}
|
||||||
@ -170,34 +170,34 @@ func (s *CopySuite) TestCopySignatures(c *check.C) {
|
|||||||
|
|
||||||
// type: signedBy
|
// type: signedBy
|
||||||
// Sign the images
|
// Sign the images
|
||||||
assertSkopeoSucceeds(c, "", "copy", "--sign-by", "personal@example.com", "docker://busybox:1.23", "atomic:myns/personal:personal")
|
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:myns/official:official")
|
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
|
// Verify that we can pull them
|
||||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:myns/personal:personal", dirDest)
|
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:localhost:5000/myns/personal:personal", dirDest)
|
||||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:myns/official:official", dirDest)
|
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:localhost:5000/myns/official:official", dirDest)
|
||||||
// Verify that mis-signed images are rejected
|
// Verify that mis-signed images are rejected
|
||||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/personal:personal", "atomic:myns/official:attack")
|
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/personal:personal", "atomic:localhost:5000/myns/official:attack")
|
||||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/official:official", "atomic:myns/personal:attack")
|
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/personal:attack")
|
||||||
assertSkopeoFails(c, ".*Source image rejected: Invalid GPG signature.*",
|
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.*",
|
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.
|
// Verify that signed identity is verified.
|
||||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/official:official", "atomic:myns/naming:test1")
|
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/naming:test1")
|
||||||
assertSkopeoFails(c, ".*Source image rejected: Signature for identity localhost:8443/myns/official:official is not accepted.*",
|
assertSkopeoFails(c, ".*Source image rejected: Signature for identity localhost:5000/myns/official:official is not accepted.*",
|
||||||
"--policy", policy, "copy", "atomic:myns/naming:test1", dirDest)
|
"--policy", policy, "copy", "atomic:localhost:5000/myns/naming:test1", dirDest)
|
||||||
// signedIdentity works
|
// signedIdentity works
|
||||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/official:official", "atomic:myns/naming:naming")
|
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/naming:naming")
|
||||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:myns/naming:naming", dirDest)
|
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:localhost:5000/myns/naming:naming", dirDest)
|
||||||
|
|
||||||
// Verify that cosigning requirements are enforced
|
// 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.*",
|
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, "", "copy", "--sign-by", "personal@example.com", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/cosigned:cosigned")
|
||||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:myns/cosigned:cosigned", dirDest)
|
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "atomic:localhost:5000/myns/cosigned:cosigned", dirDest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --policy copy for dir: sources
|
// --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
|
// Sign the images. By coping fom a topDirDest/dirN, also test that non-/restricted paths
|
||||||
// use the dir:"" default of insecureAcceptAnything.
|
// use the dir:"" default of insecureAcceptAnything.
|
||||||
// (For signing, we must push to atomic: to get a Docker identity to use in the signature.)
|
// (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", "personal@example.com", topDirDest+"/dir1", "atomic:localhost:5000/myns/personal:dirstaging")
|
||||||
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "--sign-by", "official@example.com", topDirDest+"/dir2", "atomic:myns/official:dirstaging")
|
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "--sign-by", "official@example.com", topDirDest+"/dir2", "atomic:localhost:5000/myns/official:dirstaging")
|
||||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/personal:dirstaging", topDirDest+"/restricted/personal")
|
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/personal:dirstaging", topDirDest+"/restricted/personal")
|
||||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/official:dirstaging", topDirDest+"/restricted/official")
|
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)
|
// type: signedBy, with a signedIdentity override (necessary because dir: identities can't be signed)
|
||||||
// Verify that correct images are accepted
|
// 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")
|
"--policy", policy, "copy", topDirDest+"/restricted/personal", topDirDest+"/dest")
|
||||||
|
|
||||||
// Verify that the signed identity is verified.
|
// 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, "", "--policy", policy, "copy", "--sign-by", "official@example.com", topDirDest+"/dir1", "atomic:localhost:5000/myns/personal:dirstaging2")
|
||||||
assertSkopeoSucceeds(c, "", "copy", "atomic:myns/personal:dirstaging2", topDirDest+"/restricted/badidentity")
|
assertSkopeoSucceeds(c, "", "copy", "atomic:localhost:5000/myns/personal:dirstaging2", topDirDest+"/restricted/badidentity")
|
||||||
assertSkopeoFails(c, ".*Source image rejected: .*Signature for identity localhost:8443/myns/personal:dirstaging2 is not accepted.*",
|
assertSkopeoFails(c, ".*Source image rejected: .*Signature for identity localhost:5000/myns/personal:dirstaging2 is not accepted.*",
|
||||||
"--policy", policy, "copy", topDirDest+"/restricted/badidentity", topDirDest+"/dest")
|
"--policy", policy, "copy", topDirDest+"/restricted/badidentity", topDirDest+"/dest")
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
"keyPath": "@keydir@/official-pubkey.gpg",
|
"keyPath": "@keydir@/official-pubkey.gpg",
|
||||||
"signedIdentity": {
|
"signedIdentity": {
|
||||||
"type": "exactRepository",
|
"type": "exactRepository",
|
||||||
"dockerRepository": "localhost:8443/myns/official"
|
"dockerRepository": "localhost:5000/myns/official"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -31,46 +31,46 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"atomic": {
|
"atomic": {
|
||||||
"localhost:8443/myns/personal": [
|
"localhost:5000/myns/personal": [
|
||||||
{
|
{
|
||||||
"type": "signedBy",
|
"type": "signedBy",
|
||||||
"keyType": "GPGKeys",
|
"keyType": "GPGKeys",
|
||||||
"keyPath": "@keydir@/personal-pubkey.gpg"
|
"keyPath": "@keydir@/personal-pubkey.gpg"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"localhost:8443/myns/official": [
|
"localhost:5000/myns/official": [
|
||||||
{
|
{
|
||||||
"type": "signedBy",
|
"type": "signedBy",
|
||||||
"keyType": "GPGKeys",
|
"keyType": "GPGKeys",
|
||||||
"keyPath": "@keydir@/official-pubkey.gpg"
|
"keyPath": "@keydir@/official-pubkey.gpg"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"localhost:8443/myns/naming:test1": [
|
"localhost:5000/myns/naming:test1": [
|
||||||
{
|
{
|
||||||
"type": "signedBy",
|
"type": "signedBy",
|
||||||
"keyType": "GPGKeys",
|
"keyType": "GPGKeys",
|
||||||
"keyPath": "@keydir@/official-pubkey.gpg"
|
"keyPath": "@keydir@/official-pubkey.gpg"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"localhost:8443/myns/naming:naming": [
|
"localhost:5000/myns/naming:naming": [
|
||||||
{
|
{
|
||||||
"type": "signedBy",
|
"type": "signedBy",
|
||||||
"keyType": "GPGKeys",
|
"keyType": "GPGKeys",
|
||||||
"keyPath": "@keydir@/official-pubkey.gpg",
|
"keyPath": "@keydir@/official-pubkey.gpg",
|
||||||
"signedIdentity": {
|
"signedIdentity": {
|
||||||
"type": "exactRepository",
|
"type": "exactRepository",
|
||||||
"dockerRepository": "localhost:8443/myns/official"
|
"dockerRepository": "localhost:5000/myns/official"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"localhost:8443/myns/cosigned:cosigned": [
|
"localhost:5000/myns/cosigned:cosigned": [
|
||||||
{
|
{
|
||||||
"type": "signedBy",
|
"type": "signedBy",
|
||||||
"keyType": "GPGKeys",
|
"keyType": "GPGKeys",
|
||||||
"keyPath": "@keydir@/official-pubkey.gpg",
|
"keyPath": "@keydir@/official-pubkey.gpg",
|
||||||
"signedIdentity": {
|
"signedIdentity": {
|
||||||
"type": "exactRepository",
|
"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"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -21,7 +22,8 @@ import (
|
|||||||
|
|
||||||
// openshiftClient is configuration for dealing with a single image stream, for reading or writing.
|
// openshiftClient is configuration for dealing with a single image stream, for reading or writing.
|
||||||
type openshiftClient struct {
|
type openshiftClient struct {
|
||||||
ref openshiftReference
|
ref openshiftReference
|
||||||
|
baseURL *url.URL
|
||||||
// Values from Kubernetes configuration
|
// Values from Kubernetes configuration
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
bearerToken string // "" if not used
|
bearerToken string // "" if not used
|
||||||
@ -51,9 +53,7 @@ func newOpenshiftClient(ref openshiftReference) (*openshiftClient, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
logrus.Debugf("URL: %#v", *baseURL)
|
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 {
|
if httpClient == nil {
|
||||||
httpClient = http.DefaultClient
|
httpClient = http.DefaultClient
|
||||||
}
|
}
|
||||||
@ -61,6 +61,7 @@ func newOpenshiftClient(ref openshiftReference) (*openshiftClient, error) {
|
|||||||
|
|
||||||
return &openshiftClient{
|
return &openshiftClient{
|
||||||
ref: ref,
|
ref: ref,
|
||||||
|
baseURL: baseURL,
|
||||||
httpClient: httpClient,
|
httpClient: httpClient,
|
||||||
bearerToken: restConfig.BearerToken,
|
bearerToken: restConfig.BearerToken,
|
||||||
username: restConfig.Username,
|
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.
|
// 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) {
|
func (c *openshiftClient) doRequest(method, path string, requestBody []byte) ([]byte, error) {
|
||||||
url := *c.ref.baseURL
|
url := *c.baseURL
|
||||||
url.Path = path
|
url.Path = path
|
||||||
var requestBodyReader io.Reader
|
var requestBodyReader io.Reader
|
||||||
if requestBody != nil {
|
if requestBody != nil {
|
||||||
@ -153,19 +154,7 @@ func (c *openshiftClient) convertDockerImageReference(ref string) (string, error
|
|||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
return "", fmt.Errorf("Invalid format of docker reference %s: missing '/'", ref)
|
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.
|
return c.ref.dockerReference.Hostname() + "/" + parts[1], nil
|
||||||
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"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type openshiftImageSource struct {
|
type openshiftImageSource struct {
|
||||||
@ -261,7 +250,7 @@ func (s *openshiftImageSource) ensureImageIsResolved() error {
|
|||||||
}
|
}
|
||||||
var te *tagEvent
|
var te *tagEvent
|
||||||
for _, tag := range is.Status.Tags {
|
for _, tag := range is.Status.Tags {
|
||||||
if tag.Tag != s.client.ref.tag {
|
if tag.Tag != s.client.ref.dockerReference.Tag() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(tag.Items) > 0 {
|
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,
|
// 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
|
// 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.
|
// 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)
|
dockerRef, err := docker.ParseReference(dockerRefString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -370,7 +359,7 @@ func (d *openshiftImageDestination) PutManifest(m []byte) error {
|
|||||||
}
|
}
|
||||||
d.imageStreamImageName = manifestDigest
|
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?
|
// 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{
|
ism := imageStreamMapping{
|
||||||
typeMeta: typeMeta{
|
typeMeta: typeMeta{
|
||||||
Kind: "ImageStreamMapping",
|
Kind: "ImageStreamMapping",
|
||||||
@ -387,7 +376,7 @@ func (d *openshiftImageDestination) PutManifest(m []byte) error {
|
|||||||
DockerImageReference: dockerImageReference,
|
DockerImageReference: dockerImageReference,
|
||||||
DockerImageManifest: string(m),
|
DockerImageManifest: string(m),
|
||||||
},
|
},
|
||||||
Tag: d.client.ref.tag,
|
Tag: d.client.ref.dockerReference.Tag(),
|
||||||
}
|
}
|
||||||
body, err := json.Marshal(ism)
|
body, err := json.Marshal(ism)
|
||||||
if err != nil {
|
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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
|
||||||
"github.com/containers/image/docker/policyconfiguration"
|
"github.com/containers/image/docker/policyconfiguration"
|
||||||
"github.com/containers/image/types"
|
"github.com/containers/image/types"
|
||||||
"github.com/docker/docker/reference"
|
"github.com/docker/docker/reference"
|
||||||
@ -44,67 +43,33 @@ func (t openshiftTransport) ValidatePolicyConfigurationScope(scope string) error
|
|||||||
|
|
||||||
// openshiftReference is an ImageReference for OpenShift images.
|
// openshiftReference is an ImageReference for OpenShift images.
|
||||||
type openshiftReference struct {
|
type openshiftReference struct {
|
||||||
baseURL *url.URL
|
dockerReference reference.NamedTagged
|
||||||
namespace string
|
namespace string // Computed from dockerReference in advance.
|
||||||
stream string
|
stream string // Computed from dockerReference in advance.
|
||||||
tag string
|
|
||||||
dockerReference reference.Named // Computed from the above in advance, so that later references can not fail.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an OpenShift ImageReference.
|
||||||
func ParseReference(reference string) (types.ImageReference, error) {
|
func ParseReference(ref string) (types.ImageReference, error) {
|
||||||
// Overall, this is modelled on openshift/origin/pkg/cmd/util/clientcmd.New().ClientConfig() and openshift/origin/pkg/client.
|
r, err := reference.ParseNamed(ref)
|
||||||
cmdConfig := defaultClientConfig()
|
|
||||||
logrus.Debugf("cmdConfig: %#v", cmdConfig)
|
|
||||||
restConfig, err := cmdConfig.ClientConfig()
|
|
||||||
if err != nil {
|
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.)
|
tagged, ok := r.(reference.NamedTagged)
|
||||||
logrus.Debugf("restConfig: %#v", restConfig)
|
if !ok {
|
||||||
baseURL, _, err := restClientFor(restConfig)
|
return nil, fmt.Errorf("invalid image reference %s, %#v", ref, r)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
logrus.Debugf("URL: %#v", *baseURL)
|
return NewReference(tagged)
|
||||||
|
|
||||||
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])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReference returns an OpenShift reference for a base URL, namespace, stream and tag.
|
// NewReference returns an OpenShift reference for a reference.NamedTagged
|
||||||
func NewReference(baseURL *url.URL, namespace, stream, tag string) (types.ImageReference, error) {
|
func NewReference(dockerRef reference.NamedTagged) (types.ImageReference, error) {
|
||||||
// Precompute also dockerReference so that later references can not fail.
|
r := strings.SplitN(dockerRef.RemoteName(), "/", 3)
|
||||||
//
|
if len(r) != 2 {
|
||||||
// This discards ref.baseURL.Path, which is unexpected for a “base URL”;
|
return nil, fmt.Errorf("invalid image reference %s", dockerRef.String())
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
dockerRef, err = reference.WithTag(dockerRef, tag)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return openshiftReference{
|
return openshiftReference{
|
||||||
baseURL: baseURL,
|
namespace: r[0],
|
||||||
namespace: namespace,
|
stream: r[1],
|
||||||
stream: stream,
|
|
||||||
tag: tag,
|
|
||||||
dockerReference: dockerRef,
|
dockerReference: dockerRef,
|
||||||
}, nil
|
}, 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.
|
// 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.
|
// 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 {
|
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
|
// 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
|
package v1
|
||||||
|
|
||||||
const (
|
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"
|
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"
|
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"
|
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"
|
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"
|
MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json"
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user