github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/libpod/image/manifests.go (about)

     1  package image
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/containers/buildah/manifests"
     8  	"github.com/containers/image/v5/docker"
     9  	"github.com/containers/image/v5/manifest"
    10  	"github.com/containers/image/v5/transports/alltransports"
    11  	"github.com/containers/image/v5/types"
    12  	"github.com/opencontainers/go-digest"
    13  )
    14  
    15  // Options for adding a manifest
    16  // swagger:model ManifestAddOpts
    17  type ManifestAddOpts struct {
    18  	All        bool              `json:"all"`
    19  	Annotation map[string]string `json:"annotation"`
    20  	Arch       string            `json:"arch"`
    21  	Features   []string          `json:"features"`
    22  	Images     []string          `json:"images"`
    23  	OS         string            `json:"os"`
    24  	OSVersion  string            `json:"os_version"`
    25  	Variant    string            `json:"variant"`
    26  }
    27  
    28  // ManifestAnnotateOptions defines the options for
    29  // manifest annotate
    30  type ManifestAnnotateOpts struct {
    31  	Annotation map[string]string `json:"annotation"`
    32  	Arch       string            `json:"arch"`
    33  	Features   []string          `json:"features"`
    34  	OS         string            `json:"os"`
    35  	OSFeatures []string          `json:"os_feature"`
    36  	OSVersion  string            `json:"os_version"`
    37  	Variant    string            `json:"variant"`
    38  }
    39  
    40  // InspectManifest returns a dockerized version of the manifest list
    41  func (i *Image) InspectManifest() (*manifest.Schema2List, error) {
    42  	list, err := i.getManifestList()
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  	return list.Docker(), nil
    47  }
    48  
    49  // RemoveManifest removes the given digest from the manifest list.
    50  func (i *Image) RemoveManifest(d digest.Digest) (string, error) {
    51  	list, err := i.getManifestList()
    52  	if err != nil {
    53  		return "", err
    54  	}
    55  	if err := list.Remove(d); err != nil {
    56  		return "", err
    57  	}
    58  	return list.SaveToImage(i.imageruntime.store, i.ID(), nil, "")
    59  }
    60  
    61  // getManifestList is a helper to obtain a manifest list
    62  func (i *Image) getManifestList() (manifests.List, error) {
    63  	_, list, err := manifests.LoadFromImage(i.imageruntime.store, i.ID())
    64  	return list, err
    65  }
    66  
    67  // CreateManifestList creates a new manifest list and can optionally add given images
    68  // to the list
    69  func CreateManifestList(rt *Runtime, systemContext types.SystemContext, names []string, imgs []string, all bool) (string, error) {
    70  	list := manifests.Create()
    71  	opts := ManifestAddOpts{Images: names, All: all}
    72  	for _, img := range imgs {
    73  		ref, err := alltransports.ParseImageName(img)
    74  		if err != nil {
    75  			dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
    76  			ref, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, img))
    77  			if err != nil {
    78  				return "", err
    79  			}
    80  		}
    81  		list, err = addManifestToList(ref, list, systemContext, opts)
    82  		if err != nil {
    83  			return "", err
    84  		}
    85  	}
    86  	return list.SaveToImage(rt.store, "", names, manifest.DockerV2ListMediaType)
    87  }
    88  
    89  func addManifestToList(ref types.ImageReference, list manifests.List, systemContext types.SystemContext, opts ManifestAddOpts) (manifests.List, error) {
    90  	d, err := list.Add(context.Background(), &systemContext, ref, opts.All)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  	if opts.OS != "" {
    95  		if err := list.SetOS(d, opts.OS); err != nil {
    96  			return nil, err
    97  		}
    98  	}
    99  	if len(opts.OSVersion) > 0 {
   100  		if err := list.SetOSVersion(d, opts.OSVersion); err != nil {
   101  			return nil, err
   102  		}
   103  	}
   104  	if len(opts.Features) > 0 {
   105  		if err := list.SetFeatures(d, opts.Features); err != nil {
   106  			return nil, err
   107  		}
   108  	}
   109  	if len(opts.Arch) > 0 {
   110  		if err := list.SetArchitecture(d, opts.Arch); err != nil {
   111  			return nil, err
   112  		}
   113  	}
   114  	if len(opts.Variant) > 0 {
   115  		if err := list.SetVariant(d, opts.Variant); err != nil {
   116  			return nil, err
   117  		}
   118  	}
   119  	if len(opts.Annotation) > 0 {
   120  		if err := list.SetAnnotations(&d, opts.Annotation); err != nil {
   121  			return nil, err
   122  		}
   123  	}
   124  	return list, err
   125  }
   126  
   127  // AddManifest adds a manifest to a given manifest list.
   128  func (i *Image) AddManifest(systemContext types.SystemContext, opts ManifestAddOpts) (string, error) {
   129  	ref, err := alltransports.ParseImageName(opts.Images[0])
   130  	if err != nil {
   131  		dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
   132  		ref, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, opts.Images[0]))
   133  		if err != nil {
   134  			return "", err
   135  		}
   136  	}
   137  	list, err := i.getManifestList()
   138  	if err != nil {
   139  		return "", err
   140  	}
   141  	list, err = addManifestToList(ref, list, systemContext, opts)
   142  	if err != nil {
   143  		return "", err
   144  	}
   145  	return list.SaveToImage(i.imageruntime.store, i.ID(), nil, "")
   146  }
   147  
   148  // PushManifest pushes a manifest to a destination
   149  func (i *Image) PushManifest(dest types.ImageReference, opts manifests.PushOptions) (digest.Digest, error) {
   150  	list, err := i.getManifestList()
   151  	if err != nil {
   152  		return "", err
   153  	}
   154  	_, d, err := list.Push(context.Background(), dest, opts)
   155  	return d, err
   156  }
   157  
   158  // AnnotateManifest updates an image configuration of a manifest list.
   159  func (i *Image) AnnotateManifest(systemContext types.SystemContext, d digest.Digest, opts ManifestAnnotateOpts) (string, error) {
   160  	list, err := i.getManifestList()
   161  	if err != nil {
   162  		return "", err
   163  	}
   164  	if len(opts.OS) > 0 {
   165  		if err := list.SetOS(d, opts.OS); err != nil {
   166  			return "", err
   167  		}
   168  	}
   169  	if len(opts.OSVersion) > 0 {
   170  		if err := list.SetOSVersion(d, opts.OSVersion); err != nil {
   171  			return "", err
   172  		}
   173  	}
   174  	if len(opts.Features) > 0 {
   175  		if err := list.SetFeatures(d, opts.Features); err != nil {
   176  			return "", err
   177  		}
   178  	}
   179  	if len(opts.OSFeatures) > 0 {
   180  		if err := list.SetOSFeatures(d, opts.OSFeatures); err != nil {
   181  			return "", err
   182  		}
   183  	}
   184  	if len(opts.Arch) > 0 {
   185  		if err := list.SetArchitecture(d, opts.Arch); err != nil {
   186  			return "", err
   187  		}
   188  	}
   189  	if len(opts.Variant) > 0 {
   190  		if err := list.SetVariant(d, opts.Variant); err != nil {
   191  			return "", err
   192  		}
   193  	}
   194  	if len(opts.Annotation) > 0 {
   195  		if err := list.SetAnnotations(&d, opts.Annotation); err != nil {
   196  			return "", err
   197  		}
   198  	}
   199  	return list.SaveToImage(i.imageruntime.store, i.ID(), nil, "")
   200  }