github.com/AliyunContainerService/cli@v0.0.0-20181009023821-814ced4b30d0/cli/manifest/types/types.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/docker/distribution"
     7  	"github.com/docker/distribution/manifest/manifestlist"
     8  	"github.com/docker/distribution/manifest/schema2"
     9  	"github.com/docker/distribution/reference"
    10  	"github.com/opencontainers/go-digest"
    11  	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  // ImageManifest contains info to output for a manifest object.
    16  type ImageManifest struct {
    17  	Ref        *SerializableNamed
    18  	Descriptor ocispec.Descriptor
    19  
    20  	// SchemaV2Manifest is used for inspection
    21  	// TODO: Deprecate this and store manifest blobs
    22  	SchemaV2Manifest *schema2.DeserializedManifest `json:",omitempty"`
    23  }
    24  
    25  // OCIPlatform creates an OCI platform from a manifest list platform spec
    26  func OCIPlatform(ps *manifestlist.PlatformSpec) *ocispec.Platform {
    27  	if ps == nil {
    28  		return nil
    29  	}
    30  	return &ocispec.Platform{
    31  		Architecture: ps.Architecture,
    32  		OS:           ps.OS,
    33  		OSVersion:    ps.OSVersion,
    34  		OSFeatures:   ps.OSFeatures,
    35  		Variant:      ps.Variant,
    36  	}
    37  }
    38  
    39  // PlatformSpecFromOCI creates a platform spec from OCI platform
    40  func PlatformSpecFromOCI(p *ocispec.Platform) *manifestlist.PlatformSpec {
    41  	if p == nil {
    42  		return nil
    43  	}
    44  	return &manifestlist.PlatformSpec{
    45  		Architecture: p.Architecture,
    46  		OS:           p.OS,
    47  		OSVersion:    p.OSVersion,
    48  		OSFeatures:   p.OSFeatures,
    49  		Variant:      p.Variant,
    50  	}
    51  }
    52  
    53  // Blobs returns the digests for all the blobs referenced by this manifest
    54  func (i ImageManifest) Blobs() []digest.Digest {
    55  	digests := []digest.Digest{}
    56  	for _, descriptor := range i.SchemaV2Manifest.References() {
    57  		digests = append(digests, descriptor.Digest)
    58  	}
    59  	return digests
    60  }
    61  
    62  // Payload returns the media type and bytes for the manifest
    63  func (i ImageManifest) Payload() (string, []byte, error) {
    64  	// TODO: If available, read content from a content store by digest
    65  	switch {
    66  	case i.SchemaV2Manifest != nil:
    67  		return i.SchemaV2Manifest.Payload()
    68  	default:
    69  		return "", nil, errors.Errorf("%s has no payload", i.Ref)
    70  	}
    71  }
    72  
    73  // References implements the distribution.Manifest interface. It delegates to
    74  // the underlying manifest.
    75  func (i ImageManifest) References() []distribution.Descriptor {
    76  	switch {
    77  	case i.SchemaV2Manifest != nil:
    78  		return i.SchemaV2Manifest.References()
    79  	default:
    80  		return nil
    81  	}
    82  }
    83  
    84  // NewImageManifest returns a new ImageManifest object. The values for Platform
    85  // are initialized from those in the image
    86  func NewImageManifest(ref reference.Named, desc ocispec.Descriptor, manifest *schema2.DeserializedManifest) ImageManifest {
    87  	return ImageManifest{
    88  		Ref:              &SerializableNamed{Named: ref},
    89  		Descriptor:       desc,
    90  		SchemaV2Manifest: manifest,
    91  	}
    92  }
    93  
    94  // SerializableNamed is a reference.Named that can be serialzied and deserialized
    95  // from JSON
    96  type SerializableNamed struct {
    97  	reference.Named
    98  }
    99  
   100  // UnmarshalJSON loads the Named reference from JSON bytes
   101  func (s *SerializableNamed) UnmarshalJSON(b []byte) error {
   102  	var raw string
   103  	if err := json.Unmarshal(b, &raw); err != nil {
   104  		return errors.Wrapf(err, "invalid named reference bytes: %s", b)
   105  	}
   106  	var err error
   107  	s.Named, err = reference.ParseNamed(raw)
   108  	return err
   109  }
   110  
   111  // MarshalJSON returns the JSON bytes representation
   112  func (s *SerializableNamed) MarshalJSON() ([]byte, error) {
   113  	return json.Marshal(s.String())
   114  }