github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/manifest/schema2/manifest.go (about) 1 package schema2 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 8 "github.com/docker/distribution" 9 "github.com/docker/distribution/digest" 10 "github.com/docker/distribution/manifest" 11 ) 12 13 const ( 14 // MediaTypeManifest specifies the mediaType for the current version. 15 MediaTypeManifest = "application/vnd.docker.distribution.manifest.v2+json" 16 17 // MediaTypeConfig specifies the mediaType for the image configuration. 18 MediaTypeConfig = "application/vnd.docker.container.image.v1+json" 19 20 // MediaTypeLayer is the mediaType used for layers referenced by the 21 // manifest. 22 MediaTypeLayer = "application/vnd.docker.image.rootfs.diff.tar.gzip" 23 ) 24 25 var ( 26 // SchemaVersion provides a pre-initialized version structure for this 27 // packages version of the manifest. 28 SchemaVersion = manifest.Versioned{ 29 SchemaVersion: 2, 30 MediaType: MediaTypeManifest, 31 } 32 ) 33 34 func init() { 35 schema2Func := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) { 36 m := new(DeserializedManifest) 37 err := m.UnmarshalJSON(b) 38 if err != nil { 39 return nil, distribution.Descriptor{}, err 40 } 41 42 dgst := digest.FromBytes(b) 43 return m, distribution.Descriptor{Digest: dgst, Size: int64(len(b)), MediaType: MediaTypeManifest}, err 44 } 45 err := distribution.RegisterManifestSchema(MediaTypeManifest, schema2Func) 46 if err != nil { 47 panic(fmt.Sprintf("Unable to register manifest: %s", err)) 48 } 49 } 50 51 // Manifest defines a schema2 manifest. 52 type Manifest struct { 53 manifest.Versioned 54 55 // Config references the image configuration as a blob. 56 Config distribution.Descriptor `json:"config"` 57 58 // Layers lists descriptors for the layers referenced by the 59 // configuration. 60 Layers []distribution.Descriptor `json:"layers"` 61 } 62 63 // References returnes the descriptors of this manifests references. 64 func (m Manifest) References() []distribution.Descriptor { 65 return m.Layers 66 67 } 68 69 // Target returns the target of this signed manifest. 70 func (m Manifest) Target() distribution.Descriptor { 71 return m.Config 72 } 73 74 // DeserializedManifest wraps Manifest with a copy of the original JSON. 75 // It satisfies the distribution.Manifest interface. 76 type DeserializedManifest struct { 77 Manifest 78 79 // canonical is the canonical byte representation of the Manifest. 80 canonical []byte 81 } 82 83 // FromStruct takes a Manifest structure, marshals it to JSON, and returns a 84 // DeserializedManifest which contains the manifest and its JSON representation. 85 func FromStruct(m Manifest) (*DeserializedManifest, error) { 86 var deserialized DeserializedManifest 87 deserialized.Manifest = m 88 89 var err error 90 deserialized.canonical, err = json.MarshalIndent(&m, "", " ") 91 return &deserialized, err 92 } 93 94 // UnmarshalJSON populates a new Manifest struct from JSON data. 95 func (m *DeserializedManifest) UnmarshalJSON(b []byte) error { 96 m.canonical = make([]byte, len(b), len(b)) 97 // store manifest in canonical 98 copy(m.canonical, b) 99 100 // Unmarshal canonical JSON into Manifest object 101 var manifest Manifest 102 if err := json.Unmarshal(m.canonical, &manifest); err != nil { 103 return err 104 } 105 106 m.Manifest = manifest 107 108 return nil 109 } 110 111 // MarshalJSON returns the contents of canonical. If canonical is empty, 112 // marshals the inner contents. 113 func (m *DeserializedManifest) MarshalJSON() ([]byte, error) { 114 if len(m.canonical) > 0 { 115 return m.canonical, nil 116 } 117 118 return nil, errors.New("JSON representation not initialized in DeserializedManifest") 119 } 120 121 // Payload returns the raw content of the manifest. The contents can be used to 122 // calculate the content identifier. 123 func (m DeserializedManifest) Payload() (string, []byte, error) { 124 return m.MediaType, m.canonical, nil 125 }