...

Source file src/github.com/docker/distribution/manifest/schema2/manifest.go

Documentation: github.com/docker/distribution/manifest/schema2

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

View as plain text