github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/libpod/image/manifests.go (about)

     1  package image
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/containers/buildah/manifests"
     7  	"github.com/containers/image/v5/manifest"
     8  	"github.com/containers/image/v5/transports/alltransports"
     9  	"github.com/containers/image/v5/types"
    10  	"github.com/opencontainers/go-digest"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  // Options for adding a manifest
    15  // swagger:model ManifestAddOpts
    16  type ManifestAddOpts struct {
    17  	All        bool              `json:"all"`
    18  	Annotation map[string]string `json:"annotation"`
    19  	Arch       string            `json:"arch"`
    20  	Features   []string          `json:"features"`
    21  	Images     []string          `json:"images"`
    22  	OSVersion  string            `json:"os_version"`
    23  	Variant    string            `json:"variant"`
    24  }
    25  
    26  // InspectManifest returns a dockerized version of the manifest list
    27  func (i *Image) InspectManifest() (*manifest.Schema2List, error) {
    28  	list, err := i.getManifestList()
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	return list.Docker(), nil
    33  }
    34  
    35  // RemoveManifest removes the given digest from the manifest list.
    36  func (i *Image) RemoveManifest(d digest.Digest) (string, error) {
    37  	list, err := i.getManifestList()
    38  	if err != nil {
    39  		return "", err
    40  	}
    41  	if err := list.Remove(d); err != nil {
    42  		return "", err
    43  	}
    44  	return list.SaveToImage(i.imageruntime.store, i.ID(), nil, "")
    45  }
    46  
    47  // getManifestList is a helper to obtain a manifest list
    48  func (i *Image) getManifestList() (manifests.List, error) {
    49  	_, list, err := manifests.LoadFromImage(i.imageruntime.store, i.ID())
    50  	return list, err
    51  }
    52  
    53  // CreateManifestList creates a new manifest list and can optionally add given images
    54  // to the list
    55  func CreateManifestList(rt *Runtime, systemContext types.SystemContext, names []string, imgs []string, all bool) (string, error) {
    56  	list := manifests.Create()
    57  	opts := ManifestAddOpts{Images: names, All: all}
    58  	for _, img := range imgs {
    59  		var ref types.ImageReference
    60  		newImage, err := rt.NewFromLocal(img)
    61  		if err == nil {
    62  			ir, err := newImage.toImageRef(context.Background())
    63  			if err != nil {
    64  				return "", err
    65  			}
    66  			if ir == nil {
    67  				return "", errors.New("unable to convert image to ImageReference")
    68  			}
    69  			ref = ir.Reference()
    70  		} else {
    71  			ref, err = alltransports.ParseImageName(img)
    72  			if err != nil {
    73  				return "", err
    74  			}
    75  		}
    76  		list, err = addManifestToList(ref, list, systemContext, opts)
    77  		if err != nil {
    78  			return "", err
    79  		}
    80  	}
    81  	return list.SaveToImage(rt.store, "", names, manifest.DockerV2ListMediaType)
    82  }
    83  
    84  func addManifestToList(ref types.ImageReference, list manifests.List, systemContext types.SystemContext, opts ManifestAddOpts) (manifests.List, error) {
    85  	d, err := list.Add(context.Background(), &systemContext, ref, opts.All)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  	if len(opts.OSVersion) > 0 {
    90  		if err := list.SetOSVersion(d, opts.OSVersion); err != nil {
    91  			return nil, err
    92  		}
    93  	}
    94  	if len(opts.Features) > 0 {
    95  		if err := list.SetFeatures(d, opts.Features); err != nil {
    96  			return nil, err
    97  		}
    98  	}
    99  	if len(opts.Arch) > 0 {
   100  		if err := list.SetArchitecture(d, opts.Arch); err != nil {
   101  			return nil, err
   102  		}
   103  	}
   104  	if len(opts.Variant) > 0 {
   105  		if err := list.SetVariant(d, opts.Variant); err != nil {
   106  			return nil, err
   107  		}
   108  	}
   109  	if len(opts.Annotation) > 0 {
   110  		if err := list.SetAnnotations(&d, opts.Annotation); err != nil {
   111  			return nil, err
   112  		}
   113  	}
   114  	return list, err
   115  }
   116  
   117  // AddManifest adds a manifest to a given manifest list.
   118  func (i *Image) AddManifest(systemContext types.SystemContext, opts ManifestAddOpts) (string, error) {
   119  	var (
   120  		ref types.ImageReference
   121  	)
   122  	newImage, err := i.imageruntime.NewFromLocal(opts.Images[0])
   123  	if err == nil {
   124  		ir, err := newImage.toImageRef(context.Background())
   125  		if err != nil {
   126  			return "", err
   127  		}
   128  		ref = ir.Reference()
   129  	} else {
   130  		ref, err = alltransports.ParseImageName(opts.Images[0])
   131  		if err != nil {
   132  			return "", err
   133  		}
   134  	}
   135  	list, err := i.getManifestList()
   136  	if err != nil {
   137  		return "", err
   138  	}
   139  	list, err = addManifestToList(ref, list, systemContext, opts)
   140  	if err != nil {
   141  		return "", err
   142  	}
   143  	return list.SaveToImage(i.imageruntime.store, i.ID(), nil, "")
   144  }
   145  
   146  // PushManifest pushes a manifest to a destination
   147  func (i *Image) PushManifest(dest types.ImageReference, opts manifests.PushOptions) (digest.Digest, error) {
   148  	list, err := i.getManifestList()
   149  	if err != nil {
   150  		return "", err
   151  	}
   152  	_, d, err := list.Push(context.Background(), dest, opts)
   153  	return d, err
   154  }