mirror of
https://github.com/containers/skopeo.git
synced 2025-06-24 13:52:27 +00:00
vendor containers/image
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
parent
f69a78fa0b
commit
dc1e560d4e
@ -96,8 +96,11 @@ func fileFromFixture(c *check.C, inputPath string, edits map[string]string) stri
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
// The most basic (skopeo copy) use:
|
func (s *CopySuite) TestCopyFailsWithManifestList(c *check.C) {
|
||||||
func (s *CopySuite) TestCopySimple(c *check.C) {
|
assertSkopeoFails(c, ".*can not copy docker://estesp/busybox:latest: manifest contains multiple images.*", "copy", "docker://estesp/busybox:latest", "dir:somedir")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CopySuite) TestCopySimpleAtomicRegistry(c *check.C) {
|
||||||
dir1, err := ioutil.TempDir("", "copy-1")
|
dir1, err := ioutil.TempDir("", "copy-1")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
defer os.RemoveAll(dir1)
|
defer os.RemoveAll(dir1)
|
||||||
@ -107,13 +110,35 @@ func (s *CopySuite) TestCopySimple(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.
|
||||||
// "pull": docker: → dir:
|
// "pull": docker: → dir:
|
||||||
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:latest", "dir:"+dir1)
|
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:amd64", "dir:"+dir1)
|
||||||
// "push": dir: → atomic:
|
// "push": dir: → atomic:
|
||||||
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "dir:"+dir1, "atomic:localhost:5000/myns/unsigned:unsigned")
|
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--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, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/unsigned:unsigned", "dir:"+dir2)
|
assertSkopeoSucceeds(c, "", "--tls-verify=false", "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, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The most basic (skopeo copy) use:
|
||||||
|
func (s *CopySuite) TestCopySimple(c *check.C) {
|
||||||
|
const ourRegistry = "docker://" + v2DockerRegistryURL + "/"
|
||||||
|
|
||||||
|
dir1, err := ioutil.TempDir("", "copy-1")
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
defer os.RemoveAll(dir1)
|
||||||
|
dir2, err := ioutil.TempDir("", "copy-2")
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
defer os.RemoveAll(dir2)
|
||||||
|
|
||||||
|
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
|
||||||
|
// "pull": docker: → dir:
|
||||||
|
assertSkopeoSucceeds(c, "", "copy", "docker://busybox", "dir:"+dir1)
|
||||||
|
// "push": dir: → docker(v2s2):
|
||||||
|
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "dir:"+dir1, ourRegistry+"busybox:unsigned")
|
||||||
|
// The result of pushing and pulling is an unmodified image.
|
||||||
|
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", ourRegistry+"busybox:unsigned", "dir:"+dir2)
|
||||||
|
out := combinedOutputOfCommand(c, "diff", "-urN", dir1, dir2)
|
||||||
|
c.Assert(out, check.Equals, "")
|
||||||
|
|
||||||
// docker v2s2 -> OCI image layout
|
// docker v2s2 -> OCI image layout
|
||||||
// ociDest will be created by oci: if it doesn't exist
|
// ociDest will be created by oci: if it doesn't exist
|
||||||
@ -123,8 +148,6 @@ func (s *CopySuite) TestCopySimple(c *check.C) {
|
|||||||
assertSkopeoSucceeds(c, "", "copy", "docker://busybox:latest", "oci:"+ociDest)
|
assertSkopeoSucceeds(c, "", "copy", "docker://busybox:latest", "oci:"+ociDest)
|
||||||
_, err = os.Stat(ociDest)
|
_, err = os.Stat(ociDest)
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
// FIXME: Also check pushing to docker://
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Streaming (skopeo copy)
|
// Streaming (skopeo copy)
|
||||||
|
8
vendor/github.com/containers/image/copy/copy.go
generated
vendored
8
vendor/github.com/containers/image/copy/copy.go
generated
vendored
@ -112,6 +112,14 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
|
|||||||
src := image.FromSource(rawSource)
|
src := image.FromSource(rawSource)
|
||||||
defer src.Close()
|
defer src.Close()
|
||||||
|
|
||||||
|
multiImage, err := src.IsMultiImage()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if multiImage {
|
||||||
|
return fmt.Errorf("can not copy %s: manifest contains multiple images", transports.ImageName(srcRef))
|
||||||
|
}
|
||||||
|
|
||||||
// Please keep this policy check BEFORE reading any other information about the image.
|
// Please keep this policy check BEFORE reading any other information about the image.
|
||||||
if allowed, err := policyContext.IsRunningImageAllowed(src); !allowed || err != nil { // Be paranoid and fail if either return value indicates so.
|
if allowed, err := policyContext.IsRunningImageAllowed(src); !allowed || err != nil { // Be paranoid and fail if either return value indicates so.
|
||||||
return fmt.Errorf("Source image rejected: %v", err)
|
return fmt.Errorf("Source image rejected: %v", err)
|
||||||
|
5
vendor/github.com/containers/image/directory/directory_src.go
generated
vendored
5
vendor/github.com/containers/image/directory/directory_src.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package directory
|
package directory
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@ -37,6 +38,10 @@ func (s *dirImageSource) GetManifest() ([]byte, string, error) {
|
|||||||
return m, "", err
|
return m, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *dirImageSource) GetTargetManifest(digest string) ([]byte, string, error) {
|
||||||
|
return nil, "", fmt.Errorf("Getting target manifest not supported by dir:")
|
||||||
|
}
|
||||||
|
|
||||||
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
||||||
func (s *dirImageSource) GetBlob(digest string) (io.ReadCloser, int64, error) {
|
func (s *dirImageSource) GetBlob(digest string) (io.ReadCloser, int64, error) {
|
||||||
r, err := os.Open(s.ref.layerPath(digest))
|
r, err := os.Open(s.ref.layerPath(digest))
|
||||||
|
74
vendor/github.com/containers/image/docker/docker_client.go
generated
vendored
74
vendor/github.com/containers/image/docker/docker_client.go
generated
vendored
@ -243,49 +243,58 @@ func (c *dockerClient) getBearerToken(realm, service, scope string) (string, err
|
|||||||
return tokenStruct.Token, nil
|
return tokenStruct.Token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAuth(hostname string) (string, string, error) {
|
func getAuth(registry string) (string, string, error) {
|
||||||
// TODO(runcom): get this from *cli.Context somehow
|
// TODO(runcom): get this from *cli.Context somehow
|
||||||
//if username != "" && password != "" {
|
//if username != "" && password != "" {
|
||||||
//return username, password, nil
|
//return username, password, nil
|
||||||
//}
|
//}
|
||||||
if hostname == dockerHostname {
|
var dockerAuth dockerConfigFile
|
||||||
hostname = dockerAuthRegistry
|
|
||||||
}
|
|
||||||
dockerCfgPath := filepath.Join(getDefaultConfigDir(".docker"), dockerCfgFileName)
|
dockerCfgPath := filepath.Join(getDefaultConfigDir(".docker"), dockerCfgFileName)
|
||||||
if _, err := os.Stat(dockerCfgPath); err == nil {
|
if _, err := os.Stat(dockerCfgPath); err == nil {
|
||||||
j, err := ioutil.ReadFile(dockerCfgPath)
|
j, err := ioutil.ReadFile(dockerCfgPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
var dockerAuth dockerConfigFile
|
|
||||||
if err := json.Unmarshal(j, &dockerAuth); err != nil {
|
if err := json.Unmarshal(j, &dockerAuth); err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
// try the normal case
|
|
||||||
if c, ok := dockerAuth.AuthConfigs[hostname]; ok {
|
|
||||||
return decodeDockerAuth(c.Auth)
|
|
||||||
}
|
|
||||||
} else if os.IsNotExist(err) {
|
} else if os.IsNotExist(err) {
|
||||||
|
// try old config path
|
||||||
oldDockerCfgPath := filepath.Join(getDefaultConfigDir(dockerCfgObsolete))
|
oldDockerCfgPath := filepath.Join(getDefaultConfigDir(dockerCfgObsolete))
|
||||||
if _, err := os.Stat(oldDockerCfgPath); err != nil {
|
if _, err := os.Stat(oldDockerCfgPath); err != nil {
|
||||||
return "", "", nil //missing file is not an error
|
if os.IsNotExist(err) {
|
||||||
|
return "", "", nil
|
||||||
|
}
|
||||||
|
return "", "", fmt.Errorf("%s - %v", oldDockerCfgPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
j, err := ioutil.ReadFile(oldDockerCfgPath)
|
j, err := ioutil.ReadFile(oldDockerCfgPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
var dockerAuthOld map[string]dockerAuthConfigObsolete
|
if err := json.Unmarshal(j, &dockerAuth.AuthConfigs); err != nil {
|
||||||
if err := json.Unmarshal(j, &dockerAuthOld); err != nil {
|
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
if c, ok := dockerAuthOld[hostname]; ok {
|
|
||||||
return decodeDockerAuth(c.Auth)
|
} else if err != nil {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// if file is there but we can't stat it for any reason other
|
|
||||||
// than it doesn't exist then stop
|
|
||||||
return "", "", fmt.Errorf("%s - %v", dockerCfgPath, err)
|
return "", "", fmt.Errorf("%s - %v", dockerCfgPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I'm feeling lucky
|
||||||
|
if c, exists := dockerAuth.AuthConfigs[registry]; exists {
|
||||||
|
return decodeDockerAuth(c.Auth)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bad luck; let's normalize the entries first
|
||||||
|
registry = normalizeRegistry(registry)
|
||||||
|
normalizedAuths := map[string]dockerAuthConfig{}
|
||||||
|
for k, v := range dockerAuth.AuthConfigs {
|
||||||
|
normalizedAuths[normalizeRegistry(k)] = v
|
||||||
|
}
|
||||||
|
if c, exists := normalizedAuths[registry]; exists {
|
||||||
|
return decodeDockerAuth(c.Auth)
|
||||||
|
}
|
||||||
return "", "", nil
|
return "", "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,10 +351,6 @@ func getDefaultConfigDir(confPath string) string {
|
|||||||
return filepath.Join(homedir.Get(), confPath)
|
return filepath.Join(homedir.Get(), confPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
type dockerAuthConfigObsolete struct {
|
|
||||||
Auth string `json:"auth"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type dockerAuthConfig struct {
|
type dockerAuthConfig struct {
|
||||||
Auth string `json:"auth,omitempty"`
|
Auth string `json:"auth,omitempty"`
|
||||||
}
|
}
|
||||||
@ -368,3 +373,28 @@ func decodeDockerAuth(s string) (string, string, error) {
|
|||||||
password := strings.Trim(parts[1], "\x00")
|
password := strings.Trim(parts[1], "\x00")
|
||||||
return user, password, nil
|
return user, password, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convertToHostname converts a registry url which has http|https prepended
|
||||||
|
// to just an hostname.
|
||||||
|
// Copied from github.com/docker/docker/registry/auth.go
|
||||||
|
func convertToHostname(url string) string {
|
||||||
|
stripped := url
|
||||||
|
if strings.HasPrefix(url, "http://") {
|
||||||
|
stripped = strings.TrimPrefix(url, "http://")
|
||||||
|
} else if strings.HasPrefix(url, "https://") {
|
||||||
|
stripped = strings.TrimPrefix(url, "https://")
|
||||||
|
}
|
||||||
|
|
||||||
|
nameParts := strings.SplitN(stripped, "/", 2)
|
||||||
|
|
||||||
|
return nameParts[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizeRegistry(registry string) string {
|
||||||
|
normalized := convertToHostname(registry)
|
||||||
|
switch normalized {
|
||||||
|
case "registry-1.docker.io", "docker.io":
|
||||||
|
return "index.docker.io"
|
||||||
|
}
|
||||||
|
return normalized
|
||||||
|
}
|
||||||
|
48
vendor/github.com/containers/image/docker/docker_image_src.go
generated
vendored
48
vendor/github.com/containers/image/docker/docker_image_src.go
generated
vendored
@ -15,12 +15,13 @@ import (
|
|||||||
"github.com/containers/image/types"
|
"github.com/containers/image/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type errFetchManifest struct {
|
// ErrFetchManifest provides the error when fetching the manifest fails
|
||||||
|
type ErrFetchManifest struct {
|
||||||
statusCode int
|
statusCode int
|
||||||
body []byte
|
body []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e errFetchManifest) Error() string {
|
func (e ErrFetchManifest) Error() string {
|
||||||
return fmt.Sprintf("error fetching manifest: status code: %d, body: %s", e.statusCode, string(e.body))
|
return fmt.Sprintf("error fetching manifest: status code: %d, body: %s", e.statusCode, string(e.body))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +84,31 @@ func (s *dockerImageSource) GetManifest() ([]byte, string, error) {
|
|||||||
return s.cachedManifest, s.cachedManifestMIMEType, nil
|
return s.cachedManifest, s.cachedManifestMIMEType, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *dockerImageSource) fetchManifest(tagOrDigest string) ([]byte, string, error) {
|
||||||
|
url := fmt.Sprintf(manifestURL, s.ref.ref.RemoteName(), tagOrDigest)
|
||||||
|
headers := make(map[string][]string)
|
||||||
|
headers["Accept"] = s.requestedManifestMIMETypes
|
||||||
|
res, err := s.c.makeRequest("GET", url, headers, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
manblob, err := ioutil.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
if res.StatusCode != http.StatusOK {
|
||||||
|
return nil, "", ErrFetchManifest{res.StatusCode, manblob}
|
||||||
|
}
|
||||||
|
return manblob, simplifyContentType(res.Header.Get("Content-Type")), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTargetManifest returns an image's manifest given a digest.
|
||||||
|
// This is mainly used to retrieve a single image's manifest out of a manifest list.
|
||||||
|
func (s *dockerImageSource) GetTargetManifest(digest string) ([]byte, string, error) {
|
||||||
|
return s.fetchManifest(digest)
|
||||||
|
}
|
||||||
|
|
||||||
// ensureManifestIsLoaded sets s.cachedManifest and s.cachedManifestMIMEType
|
// ensureManifestIsLoaded sets s.cachedManifest and s.cachedManifestMIMEType
|
||||||
//
|
//
|
||||||
// ImageSource implementations are not required or expected to do any caching,
|
// ImageSource implementations are not required or expected to do any caching,
|
||||||
@ -99,26 +125,14 @@ func (s *dockerImageSource) ensureManifestIsLoaded() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
url := fmt.Sprintf(manifestURL, s.ref.ref.RemoteName(), reference)
|
|
||||||
// TODO(runcom) set manifest version header! schema1 for now - then schema2 etc etc and v1
|
manblob, mt, err := s.fetchManifest(reference)
|
||||||
// TODO(runcom) NO, switch on the resulter manifest like Docker is doing
|
|
||||||
headers := make(map[string][]string)
|
|
||||||
headers["Accept"] = s.requestedManifestMIMETypes
|
|
||||||
res, err := s.c.makeRequest("GET", url, headers, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
|
||||||
manblob, err := ioutil.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if res.StatusCode != http.StatusOK {
|
|
||||||
return errFetchManifest{res.StatusCode, manblob}
|
|
||||||
}
|
|
||||||
// We might validate manblob against the Docker-Content-Digest header here to protect against transport errors.
|
// We might validate manblob against the Docker-Content-Digest header here to protect against transport errors.
|
||||||
s.cachedManifest = manblob
|
s.cachedManifest = manblob
|
||||||
s.cachedManifestMIMEType = simplifyContentType(res.Header.Get("Content-Type"))
|
s.cachedManifestMIMEType = mt
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
52
vendor/github.com/containers/image/image/docker_list.go
generated
vendored
Normal file
52
vendor/github.com/containers/image/image/docker_list.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package image
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/containers/image/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type platformSpec struct {
|
||||||
|
Architecture string `json:"architecture"`
|
||||||
|
OS string `json:"os"`
|
||||||
|
OSVersion string `json:"os.version,omitempty"`
|
||||||
|
OSFeatures []string `json:"os.features,omitempty"`
|
||||||
|
Variant string `json:"variant,omitempty"`
|
||||||
|
Features []string `json:"features,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// A manifestDescriptor references a platform-specific manifest.
|
||||||
|
type manifestDescriptor struct {
|
||||||
|
descriptor
|
||||||
|
Platform platformSpec `json:"platform"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type manifestList struct {
|
||||||
|
SchemaVersion int `json:"schemaVersion"`
|
||||||
|
MediaType string `json:"mediaType"`
|
||||||
|
Manifests []manifestDescriptor `json:"manifests"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func manifestSchema2FromManifestList(src types.ImageSource, manblob []byte) (genericManifest, error) {
|
||||||
|
list := manifestList{}
|
||||||
|
if err := json.Unmarshal(manblob, &list); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var targetManifestDigest string
|
||||||
|
for _, d := range list.Manifests {
|
||||||
|
if d.Platform.Architecture == runtime.GOARCH && d.Platform.OS == runtime.GOOS {
|
||||||
|
targetManifestDigest = d.Digest
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if targetManifestDigest == "" {
|
||||||
|
return nil, errors.New("no supported platform found in manifest list")
|
||||||
|
}
|
||||||
|
manblob, mt, err := src.GetTargetManifest(targetManifestDigest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return manifestInstanceFromBlob(src, manblob, mt)
|
||||||
|
}
|
16
vendor/github.com/containers/image/image/image.go
generated
vendored
16
vendor/github.com/containers/image/image/image.go
generated
vendored
@ -120,6 +120,18 @@ func (i *genericImage) getParsedManifest() (genericManifest, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return manifestInstanceFromBlob(i.src, manblob, mt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *genericImage) IsMultiImage() (bool, error) {
|
||||||
|
_, mt, err := i.Manifest()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return mt == manifest.DockerV2ListMediaType, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func manifestInstanceFromBlob(src types.ImageSource, manblob []byte, mt string) (genericManifest, error) {
|
||||||
switch mt {
|
switch mt {
|
||||||
// "application/json" is a valid v2s1 value per https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-1.md .
|
// "application/json" is a valid v2s1 value per https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-1.md .
|
||||||
// This works for now, when nothing else seems to return "application/json"; if that were not true, the mapping/detection might
|
// This works for now, when nothing else seems to return "application/json"; if that were not true, the mapping/detection might
|
||||||
@ -127,7 +139,9 @@ func (i *genericImage) getParsedManifest() (genericManifest, error) {
|
|||||||
case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType, "application/json":
|
case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType, "application/json":
|
||||||
return manifestSchema1FromManifest(manblob)
|
return manifestSchema1FromManifest(manblob)
|
||||||
case manifest.DockerV2Schema2MediaType:
|
case manifest.DockerV2Schema2MediaType:
|
||||||
return manifestSchema2FromManifest(i.src, manblob)
|
return manifestSchema2FromManifest(src, manblob)
|
||||||
|
case manifest.DockerV2ListMediaType:
|
||||||
|
return manifestSchema2FromManifestList(src, manblob)
|
||||||
case "":
|
case "":
|
||||||
return nil, errors.New("could not guess manifest media type")
|
return nil, errors.New("could not guess manifest media type")
|
||||||
default:
|
default:
|
||||||
|
1
vendor/github.com/containers/image/manifest/manifest.go
generated
vendored
1
vendor/github.com/containers/image/manifest/manifest.go
generated
vendored
@ -30,6 +30,7 @@ var DefaultRequestedManifestMIMETypes = []string{
|
|||||||
DockerV2Schema2MediaType,
|
DockerV2Schema2MediaType,
|
||||||
DockerV2Schema1SignedMediaType,
|
DockerV2Schema1SignedMediaType,
|
||||||
DockerV2Schema1MediaType,
|
DockerV2Schema1MediaType,
|
||||||
|
DockerV2ListMediaType,
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuessMIMEType guesses MIME type of a manifest and returns it _if it is recognized_, or "" if unknown or unrecognized.
|
// GuessMIMEType guesses MIME type of a manifest and returns it _if it is recognized_, or "" if unknown or unrecognized.
|
||||||
|
7
vendor/github.com/containers/image/openshift/openshift.go
generated
vendored
7
vendor/github.com/containers/image/openshift/openshift.go
generated
vendored
@ -196,6 +196,13 @@ func (s *openshiftImageSource) Close() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *openshiftImageSource) GetTargetManifest(digest string) ([]byte, string, error) {
|
||||||
|
if err := s.ensureImageIsResolved(); err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
return s.docker.GetTargetManifest(digest)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *openshiftImageSource) GetManifest() ([]byte, string, error) {
|
func (s *openshiftImageSource) GetManifest() ([]byte, string, error) {
|
||||||
if err := s.ensureImageIsResolved(); err != nil {
|
if err := s.ensureImageIsResolved(); err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
|
5
vendor/github.com/containers/image/types/types.go
generated
vendored
5
vendor/github.com/containers/image/types/types.go
generated
vendored
@ -106,6 +106,9 @@ type ImageSource interface {
|
|||||||
// GetManifest returns the image's manifest along with its MIME type. The empty string is returned if the MIME type is unknown.
|
// GetManifest returns the image's manifest along with its MIME type. The empty string is returned if the MIME type is unknown.
|
||||||
// It may use a remote (= slow) service.
|
// It may use a remote (= slow) service.
|
||||||
GetManifest() ([]byte, string, error)
|
GetManifest() ([]byte, string, error)
|
||||||
|
// GetTargetManifest returns an image's manifest given a digest. This is mainly used to retrieve a single image's manifest
|
||||||
|
// out of a manifest list.
|
||||||
|
GetTargetManifest(digest string) ([]byte, string, error)
|
||||||
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
||||||
GetBlob(digest string) (io.ReadCloser, int64, error)
|
GetBlob(digest string) (io.ReadCloser, int64, error)
|
||||||
// GetSignatures returns the image's signatures. It may use a remote (= slow) service.
|
// GetSignatures returns the image's signatures. It may use a remote (= slow) service.
|
||||||
@ -180,6 +183,8 @@ type Image interface {
|
|||||||
// UpdatedManifest returns the image's manifest modified according to options.
|
// UpdatedManifest returns the image's manifest modified according to options.
|
||||||
// This does not change the state of the Image object.
|
// This does not change the state of the Image object.
|
||||||
UpdatedManifest(options ManifestUpdateOptions) ([]byte, error)
|
UpdatedManifest(options ManifestUpdateOptions) ([]byte, error)
|
||||||
|
// IsMultiImage returns true if the image's manifest is a list of images, false otherwise.
|
||||||
|
IsMultiImage() (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ManifestUpdateOptions is a way to pass named optional arguments to Image.UpdatedManifest
|
// ManifestUpdateOptions is a way to pass named optional arguments to Image.UpdatedManifest
|
||||||
|
Loading…
Reference in New Issue
Block a user