add mimetypes

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
Antonio Murdaca 2016-05-23 10:08:04 +02:00
parent 814a2a6f94
commit 7d12b66fb8
9 changed files with 87 additions and 15 deletions

View File

@ -54,7 +54,7 @@ func copyHandler(context *cli.Context) {
}
signBy := context.String("sign-by")
manifest, err := src.GetManifest()
manifest, _, err := src.GetManifest()
if err != nil {
logrus.Fatalf("Error reading manifest: %s", err.Error())
}

View File

@ -84,8 +84,13 @@ func (s *dirImageSource) IntendedDockerReference() string {
return ""
}
func (s *dirImageSource) GetManifest() ([]byte, error) {
return ioutil.ReadFile(manifestPath(s.dir))
// it's up to the caller to determine the MIME type of the returned manifest's bytes
func (s *dirImageSource) GetManifest() ([]byte, string, error) {
m, err := ioutil.ReadFile(manifestPath(s.dir))
if err != nil {
return nil, "", err
}
return m, "", err
}
func (s *dirImageSource) GetLayer(digest string) (io.ReadCloser, error) {

View File

@ -44,7 +44,7 @@ func (i *dockerImage) IntendedDockerReference() string {
// Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need.
func (i *dockerImage) Manifest() ([]byte, error) {
if i.cachedManifest == nil {
m, err := i.src.GetManifest()
m, _, err := i.src.GetManifest()
if err != nil {
return nil, err
}

View File

@ -55,24 +55,24 @@ func (s *dockerImageSource) IntendedDockerReference() string {
return fmt.Sprintf("%s:%s", s.ref.Name(), s.tag)
}
func (s *dockerImageSource) GetManifest() ([]byte, error) {
func (s *dockerImageSource) GetManifest() ([]byte, string, error) {
url := fmt.Sprintf(manifestURL, s.ref.RemoteName(), s.tag)
// TODO(runcom) set manifest version header! schema1 for now - then schema2 etc etc and v1
// TODO(runcom) NO, switch on the resulter manifest like Docker is doing
res, err := s.c.makeRequest("GET", url, nil, nil)
if err != nil {
return nil, err
return nil, "", err
}
defer res.Body.Close()
manblob, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
return nil, "", err
}
if res.StatusCode != http.StatusOK {
return nil, errFetchManifest{res.StatusCode, manblob}
return nil, "", errFetchManifest{res.StatusCode, manblob}
}
// We might validate manblob against the Docker-Content-Digest header here to protect against transport errors.
return manblob, nil
return manblob, res.Header.Get("Content-Type"), nil
}
func (s *dockerImageSource) GetLayer(digest string) (io.ReadCloser, error) {

View File

@ -0,0 +1,56 @@
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v1+json",
"size": 2094,
"digest": "sha256:7820f9a86d4ad15a2c4f0c0e5479298df2aa7c2f6871288e2ef8546f3e7b6783",
"platform": {
"architecture": "ppc64le",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v1+json",
"size": 1922,
"digest": "sha256:ae1b0e06e8ade3a11267564a26e750585ba2259c0ecab59ab165ad1af41d1bdd",
"platform": {
"architecture": "amd64",
"os": "linux",
"features": [
"sse"
]
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v1+json",
"size": 2084,
"digest": "sha256:e4c0df75810b953d6717b8f8f28298d73870e8aa2a0d5e77b8391f16fdfbbbe2",
"platform": {
"architecture": "s390x",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v1+json",
"size": 2084,
"digest": "sha256:07ebe243465ef4a667b78154ae6c3ea46fdb1582936aac3ac899ea311a701b40",
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "armv7"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v1+json",
"size": 2090,
"digest": "sha256:fb2fc0707b86dafa9959fe3d29e66af8787aee4d9a23581714be65db4265ad8a",
"platform": {
"architecture": "arm64",
"os": "linux",
"variant": "armv8"
}
}
]
}

View File

@ -10,11 +10,22 @@ import (
// FIXME: Should we just use docker/distribution and docker/docker implementations directly?
// ManifestMIMETypes returns a slice of supported MIME types
func ManifestMIMETypes() []string {
return []string{
DockerV2Schema1MIMEType,
DockerV2Schema2MIMEType,
DockerV2ListMIMEType,
}
}
const (
// DockerV2Schema1MIMEType MIME type represents Docker manifest schema 1
DockerV2Schema1MIMEType = "application/vnd.docker.distribution.manifest.v1+json"
// DockerV2Schema2MIMEType MIME type represents Docker manifest schema 2
DockerV2Schema2MIMEType = "application/vnd.docker.distribution.manifest.v2+json"
// DockerV2ListMIMEType MIME type represents Docker manifest schema 2 list
DockerV2ListMIMEType = "application/vnd.docker.distribution.manifest.list.v2+json"
)
// GuessManifestMIMEType guesses MIME type of a manifest and returns it _if it is recognized_, or "" if unknown or unrecognized.
@ -32,7 +43,7 @@ func GuessManifestMIMEType(manifest []byte) string {
}
switch meta.MediaType {
case DockerV2Schema2MIMEType: // A recognized type.
case DockerV2Schema2MIMEType, DockerV2ListMIMEType: // A recognized type.
return meta.MediaType
}
switch meta.SchemaVersion {

View File

@ -15,6 +15,7 @@ func TestGuessManifestMIMEType(t *testing.T) {
mimeType string
}{
{"v2s2.manifest.json", DockerV2Schema2MIMEType},
{"v2list.manifest.json", DockerV2ListMIMEType},
{"v2s1.manifest.json", DockerV2Schema1MIMEType},
{"v2s1-invalid-signatures.manifest.json", DockerV2Schema1MIMEType},
{"v2s2nomime.manifest.json", DockerV2Schema2MIMEType}, // It is unclear whether this one is legal, but we should guess v2s2 if anything at all.

View File

@ -193,9 +193,9 @@ func (s *openshiftImageSource) IntendedDockerReference() string {
return s.client.canonicalDockerReference()
}
func (s *openshiftImageSource) GetManifest() ([]byte, error) {
func (s *openshiftImageSource) GetManifest() ([]byte, string, error) {
if err := s.ensureImageIsResolved(); err != nil {
return nil, err
return nil, "", err
}
return s.docker.GetManifest()
}

View File

@ -27,9 +27,8 @@ type ImageSource interface {
// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image.
// May be "" if unknown.
IntendedDockerReference() string
// GetManifest returns the image's manifest. It may use a remote (= slow) service.
// FIXME? This should also return a MIME type if known, to differentiate between schema versions.
GetManifest() ([]byte, error)
// 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.
GetManifest() ([]byte, string, error)
// Note: Calling GetLayer() may have ordering dependencies WRT other methods of this type. FIXME: How does this work with (docker save) on stdin?
GetLayer(digest string) (io.ReadCloser, error)
// GetSignatures returns the image's signatures. It may use a remote (= slow) service.