podman
155 строк · 6.2 Кб
1package buildah
2
3import (
4"context"
5"fmt"
6"io"
7"time"
8
9"github.com/containers/buildah/pkg/blobcache"
10"github.com/containers/common/libimage"
11"github.com/containers/image/v5/docker/reference"
12"github.com/containers/image/v5/manifest"
13"github.com/containers/image/v5/pkg/compression"
14"github.com/containers/image/v5/transports"
15"github.com/containers/image/v5/types"
16encconfig "github.com/containers/ocicrypt/config"
17"github.com/containers/storage"
18"github.com/containers/storage/pkg/archive"
19digest "github.com/opencontainers/go-digest"
20"github.com/sirupsen/logrus"
21)
22
23// cacheLookupReferenceFunc wraps a BlobCache into a
24// libimage.LookupReferenceFunc to allow for using a BlobCache during
25// image-copy operations.
26func cacheLookupReferenceFunc(directory string, compress types.LayerCompression) libimage.LookupReferenceFunc {
27// Using a closure here allows us to reference a BlobCache without
28// having to explicitly maintain it in the libimage API.
29return func(ref types.ImageReference) (types.ImageReference, error) {
30if directory == "" {
31return ref, nil
32}
33ref, err := blobcache.NewBlobCache(ref, directory, compress)
34if err != nil {
35return nil, fmt.Errorf("using blobcache %q: %w", directory, err)
36}
37return ref, nil
38}
39}
40
41// PushOptions can be used to alter how an image is copied somewhere.
42type PushOptions struct {
43// Compression specifies the type of compression which is applied to
44// layer blobs. The default is to not use compression, but
45// archive.Gzip is recommended.
46// OBSOLETE: Use CompressionFormat instead.
47Compression archive.Compression
48// SignaturePolicyPath specifies an override location for the signature
49// policy which should be used for verifying the new image as it is
50// being written. Except in specific circumstances, no value should be
51// specified, indicating that the shared, system-wide default policy
52// should be used.
53SignaturePolicyPath string
54// ReportWriter is an io.Writer which will be used to log the writing
55// of the new image.
56ReportWriter io.Writer
57// Store is the local storage store which holds the source image.
58Store storage.Store
59// github.com/containers/image/types SystemContext to hold credentials
60// and other authentication/authorization information.
61SystemContext *types.SystemContext
62// ManifestType is the format to use
63// possible options are oci, v2s1, and v2s2
64ManifestType string
65// BlobDirectory is the name of a directory in which we'll look for
66// prebuilt copies of layer blobs that we might otherwise need to
67// regenerate from on-disk layers, substituting them in the list of
68// blobs to copy whenever possible.
69BlobDirectory string
70// Quiet is a boolean value that determines if minimal output to
71// the user will be displayed, this is best used for logging.
72// The default is false.
73Quiet bool
74// SignBy is the fingerprint of a GPG key to use for signing the image.
75SignBy string
76// RemoveSignatures causes any existing signatures for the image to be
77// discarded for the pushed copy.
78RemoveSignatures bool
79// MaxRetries is the maximum number of attempts we'll make to push any
80// one image to the external registry if the first attempt fails.
81MaxRetries int
82// RetryDelay is how long to wait before retrying a push attempt.
83RetryDelay time.Duration
84// OciEncryptConfig when non-nil indicates that an image should be encrypted.
85// The encryption options is derived from the construction of EncryptConfig object.
86OciEncryptConfig *encconfig.EncryptConfig
87// OciEncryptLayers represents the list of layers to encrypt.
88// If nil, don't encrypt any layers.
89// If non-nil and len==0, denotes encrypt all layers.
90// integers in the slice represent 0-indexed layer indices, with support for negative
91// indexing. i.e. 0 is the first layer, -1 is the last (top-most) layer.
92OciEncryptLayers *[]int
93
94// CompressionFormat is the format to use for the compression of the blobs
95CompressionFormat *compression.Algorithm
96// CompressionLevel specifies what compression level is used
97CompressionLevel *int
98// ForceCompressionFormat ensures that the compression algorithm set in
99// CompressionFormat is used exclusively, and blobs of other compression
100// algorithms are not reused.
101ForceCompressionFormat bool
102}
103
104// Push copies the contents of the image to a new location.
105func Push(ctx context.Context, image string, dest types.ImageReference, options PushOptions) (reference.Canonical, digest.Digest, error) {
106libimageOptions := &libimage.PushOptions{}
107libimageOptions.SignaturePolicyPath = options.SignaturePolicyPath
108libimageOptions.Writer = options.ReportWriter
109libimageOptions.ManifestMIMEType = options.ManifestType
110libimageOptions.SignBy = options.SignBy
111libimageOptions.RemoveSignatures = options.RemoveSignatures
112libimageOptions.RetryDelay = &options.RetryDelay
113libimageOptions.OciEncryptConfig = options.OciEncryptConfig
114libimageOptions.OciEncryptLayers = options.OciEncryptLayers
115libimageOptions.CompressionFormat = options.CompressionFormat
116libimageOptions.CompressionLevel = options.CompressionLevel
117libimageOptions.ForceCompressionFormat = options.ForceCompressionFormat
118libimageOptions.PolicyAllowStorage = true
119
120if options.Quiet {
121libimageOptions.Writer = nil
122}
123
124compress := types.PreserveOriginal
125if options.Compression == archive.Gzip {
126compress = types.Compress
127}
128libimageOptions.SourceLookupReferenceFunc = cacheLookupReferenceFunc(options.BlobDirectory, compress)
129
130runtime, err := libimage.RuntimeFromStore(options.Store, &libimage.RuntimeOptions{SystemContext: options.SystemContext})
131if err != nil {
132return nil, "", err
133}
134
135destString := fmt.Sprintf("%s:%s", dest.Transport().Name(), dest.StringWithinTransport())
136manifestBytes, err := runtime.Push(ctx, image, destString, libimageOptions)
137if err != nil {
138return nil, "", err
139}
140
141manifestDigest, err := manifest.Digest(manifestBytes)
142if err != nil {
143return nil, "", fmt.Errorf("computing digest of manifest of new image %q: %w", transports.ImageName(dest), err)
144}
145
146var ref reference.Canonical
147if name := dest.DockerReference(); name != nil {
148ref, err = reference.WithDigest(name, manifestDigest)
149if err != nil {
150logrus.Warnf("error generating canonical reference with name %q and digest %s: %v", name, manifestDigest.String(), err)
151}
152}
153
154return ref, manifestDigest, nil
155}
156