restore push/pull and util API
Restore the push and pull API that commit dcd2a92e56
removed.
These changes would break vendoring into openshift/builder due
to build errors.
For the same reason, restore `util.FindImage` and `util.AddImageNames`
but deprecate the `findRegistry` argument.
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
parent
eb52311c23
commit
fb331c1861
|
@ -235,7 +235,7 @@ func manifestCreateCmd(c *cobra.Command, args []string, opts manifestCreateOpts)
|
|||
if err != nil {
|
||||
if ref, err = alltransports.ParseImageName(util.DefaultTransport + imageSpec); err != nil {
|
||||
// check if the local image exists
|
||||
if ref, _, err = util.FindImage(store, systemContext, imageSpec); err != nil {
|
||||
if ref, _, err = util.FindImage(store, "", systemContext, imageSpec); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ func manifestAddCmd(c *cobra.Command, args []string, opts manifestAddOpts) error
|
|||
return errors.Wrapf(err, "error building system context")
|
||||
}
|
||||
|
||||
_, listImage, err := util.FindImage(store, systemContext, listImageSpec)
|
||||
_, listImage, err := util.FindImage(store, "", systemContext, listImageSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ func manifestAddCmd(c *cobra.Command, args []string, opts manifestAddOpts) error
|
|||
if err != nil {
|
||||
if ref, err = alltransports.ParseImageName(util.DefaultTransport + imageSpec); err != nil {
|
||||
// check if the local image exists
|
||||
if ref, _, err = util.FindImage(store, systemContext, imageSpec); err != nil {
|
||||
if ref, _, err = util.FindImage(store, "", systemContext, imageSpec); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ func manifestAddCmd(c *cobra.Command, args []string, opts manifestAddOpts) error
|
|||
if err != nil {
|
||||
var storeErr error
|
||||
// check if the local image exists
|
||||
if ref, _, storeErr = util.FindImage(store, systemContext, imageSpec); storeErr != nil {
|
||||
if ref, _, storeErr = util.FindImage(store, "", systemContext, imageSpec); storeErr != nil {
|
||||
return err
|
||||
}
|
||||
digest, storeErr = list.Add(getContext(), systemContext, ref, opts.all)
|
||||
|
@ -404,7 +404,7 @@ func manifestRemoveCmd(c *cobra.Command, args []string, opts manifestRemoveOpts)
|
|||
return errors.Wrapf(err, "error building system context")
|
||||
}
|
||||
|
||||
_, listImage, err := util.FindImage(store, systemContext, listImageSpec)
|
||||
_, listImage, err := util.FindImage(store, "", systemContext, listImageSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -461,7 +461,7 @@ func manifestAnnotateCmd(c *cobra.Command, args []string, opts manifestAnnotateO
|
|||
return errors.Wrapf(err, "error building system context")
|
||||
}
|
||||
|
||||
_, listImage, err := util.FindImage(store, systemContext, listImageSpec)
|
||||
_, listImage, err := util.FindImage(store, "", systemContext, listImageSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -474,7 +474,7 @@ func manifestAnnotateCmd(c *cobra.Command, args []string, opts manifestAnnotateO
|
|||
digest, err := digest.Parse(imageSpec)
|
||||
if err != nil {
|
||||
ctx := getContext()
|
||||
ref, _, err := util.FindImage(store, systemContext, imageSpec)
|
||||
ref, _, err := util.FindImage(store, "", systemContext, imageSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -581,7 +581,7 @@ func manifestInspect(ctx context.Context, store storage.Store, systemContext *ty
|
|||
logrus.Debugf("error parsing reference to image %q: %v", imageSpec, err)
|
||||
}
|
||||
|
||||
if ref, _, err := util.FindImage(store, systemContext, imageSpec); err == nil {
|
||||
if ref, _, err := util.FindImage(store, "", systemContext, imageSpec); err == nil {
|
||||
refs = append(refs, ref)
|
||||
} else if ref, err := alltransports.ParseImageName(imageSpec); err == nil {
|
||||
refs = append(refs, ref)
|
||||
|
@ -679,7 +679,7 @@ func manifestPushCmd(c *cobra.Command, args []string, opts pushOptions) error {
|
|||
}
|
||||
|
||||
func manifestPush(systemContext *types.SystemContext, store storage.Store, listImageSpec, destSpec string, opts pushOptions) error {
|
||||
_, listImage, err := util.FindImage(store, systemContext, listImageSpec)
|
||||
_, listImage, err := util.FindImage(store, "", systemContext, listImageSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,32 +1,31 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/containers/buildah/pkg/blobcache"
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/buildah/define"
|
||||
buildahcli "github.com/containers/buildah/pkg/cli"
|
||||
"github.com/containers/buildah/pkg/parse"
|
||||
"github.com/containers/common/libimage"
|
||||
libimageTypes "github.com/containers/common/libimage/types"
|
||||
"github.com/containers/common/pkg/auth"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type pullOptions struct {
|
||||
// We can feed many flags directly to the options of libmage.
|
||||
libimage.PullOptions
|
||||
|
||||
// Other flags need some massaging and validation.
|
||||
allTags bool
|
||||
authfile string
|
||||
blobCache string
|
||||
pullPolicy string
|
||||
decryptionKeys []string
|
||||
tlsVerify bool
|
||||
certDir string
|
||||
creds string
|
||||
signaturePolicy string
|
||||
quiet bool
|
||||
removeSignatures bool
|
||||
tlsVerify bool
|
||||
decryptionKeys []string
|
||||
pullPolicy string
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -43,7 +42,7 @@ func init() {
|
|||
Short: "Pull an image from the specified location",
|
||||
Long: pullDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return pullCmd(cmd, args, &opts)
|
||||
return pullCmd(cmd, args, opts)
|
||||
},
|
||||
Example: `buildah pull imagename
|
||||
buildah pull docker-daemon:imagename:imagetag
|
||||
|
@ -53,22 +52,22 @@ func init() {
|
|||
|
||||
flags := pullCommand.Flags()
|
||||
flags.SetInterspersed(false)
|
||||
flags.BoolVarP(&opts.AllTags, "all-tags", "a", false, "download all tagged images in the repository")
|
||||
flags.StringVar(&opts.AuthFilePath, "authfile", auth.GetDefaultAuthFile(), "path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
|
||||
flags.BoolVarP(&opts.allTags, "all-tags", "a", false, "download all tagged images in the repository")
|
||||
flags.StringVar(&opts.authfile, "authfile", auth.GetDefaultAuthFile(), "path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
|
||||
flags.StringVar(&opts.blobCache, "blob-cache", "", "store copies of pulled image blobs in the specified directory")
|
||||
flags.StringVar(&opts.CertDirPath, "cert-dir", "", "use certificates at the specified path to access the registry")
|
||||
flags.StringVar(&opts.Credentials, "creds", "", "use `[username[:password]]` for accessing the registry")
|
||||
flags.StringVar(&opts.certDir, "cert-dir", "", "use certificates at the specified path to access the registry")
|
||||
flags.StringVar(&opts.creds, "creds", "", "use `[username[:password]]` for accessing the registry")
|
||||
flags.StringVar(&opts.pullPolicy, "policy", "missing", "missing, always, or never.")
|
||||
flags.BoolVarP(&opts.RemoveSignatures, "remove-signatures", "", false, "don't copy signatures when pulling image")
|
||||
flags.StringVar(&opts.SignaturePolicyPath, "signature-policy", "", "`pathname` of signature policy file (not usually used)")
|
||||
flags.BoolVarP(&opts.removeSignatures, "remove-signatures", "", false, "don't copy signatures when pulling image")
|
||||
flags.StringVar(&opts.signaturePolicy, "signature-policy", "", "`pathname` of signature policy file (not usually used)")
|
||||
flags.StringSliceVar(&opts.decryptionKeys, "decryption-key", nil, "key needed to decrypt the image")
|
||||
if err := flags.MarkHidden("signature-policy"); err != nil {
|
||||
panic(fmt.Sprintf("error marking signature-policy as hidden: %v", err))
|
||||
}
|
||||
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "don't output progress information when pulling images")
|
||||
flags.StringVar(&opts.OS, "os", runtime.GOOS, "prefer `OS` instead of the running OS for choosing images")
|
||||
flags.StringVar(&opts.Architecture, "arch", runtime.GOARCH, "prefer `ARCH` instead of the architecture of the machine for choosing images")
|
||||
flags.StringVar(&opts.Variant, "variant", "", "override the `variant` of the specified image")
|
||||
flags.String("os", runtime.GOOS, "prefer `OS` instead of the running OS for choosing images")
|
||||
flags.String("arch", runtime.GOARCH, "prefer `ARCH` instead of the architecture of the machine for choosing images")
|
||||
flags.String("variant", "", "override the `variant` of the specified image")
|
||||
flags.BoolVar(&opts.tlsVerify, "tls-verify", true, "require HTTPS and verify certificates when accessing the registry. TLS verification cannot be used when talking to an insecure registry.")
|
||||
if err := flags.MarkHidden("blob-cache"); err != nil {
|
||||
panic(fmt.Sprintf("error marking blob-cache as hidden: %v", err))
|
||||
|
@ -77,8 +76,7 @@ func init() {
|
|||
rootCmd.AddCommand(pullCommand)
|
||||
}
|
||||
|
||||
func pullCmd(c *cobra.Command, args []string, options *pullOptions) error {
|
||||
var err error
|
||||
func pullCmd(c *cobra.Command, args []string, iopts pullOptions) error {
|
||||
if len(args) == 0 {
|
||||
return errors.Errorf("an image name must be specified")
|
||||
}
|
||||
|
@ -88,27 +86,7 @@ func pullCmd(c *cobra.Command, args []string, options *pullOptions) error {
|
|||
if len(args) > 1 {
|
||||
return errors.Errorf("too many arguments specified")
|
||||
}
|
||||
if err := auth.CheckAuthFile(options.AuthFilePath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
options.OciDecryptConfig, err = getDecryptConfig(options.decryptionKeys)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to obtain decrypt config")
|
||||
}
|
||||
|
||||
options.Writer = os.Stderr
|
||||
if options.quiet {
|
||||
options.Writer = nil
|
||||
}
|
||||
|
||||
if options.blobCache != "" {
|
||||
// options.SourceLookupReferenceFunc = blobcache.CacheLookupReferenceFunc(options.blobCache, types.PreserveOriginal)
|
||||
options.DestinationLookupReferenceFunc = blobcache.CacheLookupReferenceFunc(options.blobCache, types.PreserveOriginal)
|
||||
}
|
||||
|
||||
pullPolicy, err := libimageTypes.ParsePullPolicy(options.pullPolicy)
|
||||
if err != nil {
|
||||
if err := auth.CheckAuthFile(iopts.authfile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -122,19 +100,37 @@ func pullCmd(c *cobra.Command, args []string, options *pullOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
runtime, err := libimage.RuntimeFromStore(store, &libimage.RuntimeOptions{SystemContext: systemContext})
|
||||
decConfig, err := getDecryptConfig(iopts.decryptionKeys)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to obtain decrypt config")
|
||||
}
|
||||
|
||||
policy, ok := define.PolicyMap[iopts.pullPolicy]
|
||||
if !ok {
|
||||
return fmt.Errorf("unsupported pull policy %q", iopts.pullPolicy)
|
||||
}
|
||||
options := buildah.PullOptions{
|
||||
SignaturePolicyPath: iopts.signaturePolicy,
|
||||
Store: store,
|
||||
SystemContext: systemContext,
|
||||
BlobDirectory: iopts.blobCache,
|
||||
AllTags: iopts.allTags,
|
||||
ReportWriter: os.Stderr,
|
||||
RemoveSignatures: iopts.removeSignatures,
|
||||
MaxRetries: maxPullPushRetries,
|
||||
RetryDelay: pullPushRetryDelay,
|
||||
OciDecryptConfig: decConfig,
|
||||
PullPolicy: policy,
|
||||
}
|
||||
|
||||
if iopts.quiet {
|
||||
options.ReportWriter = nil // Turns off logging output
|
||||
}
|
||||
|
||||
id, err := buildah.Pull(getContext(), args[0], options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pulledImages, err := runtime.Pull(context.Background(), args[0], pullPolicy, &options.PullOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, pulledImage := range pulledImages {
|
||||
fmt.Printf("%s\n", pulledImage.ID())
|
||||
}
|
||||
|
||||
fmt.Printf("%s\n", id)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/buildah/pkg/blobcache"
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/buildah/define"
|
||||
buildahcli "github.com/containers/buildah/pkg/cli"
|
||||
"github.com/containers/buildah/pkg/parse"
|
||||
"github.com/containers/common/libimage"
|
||||
"github.com/containers/buildah/util"
|
||||
"github.com/containers/common/pkg/auth"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/image/v5/transports/alltransports"
|
||||
"github.com/containers/storage"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -41,55 +41,6 @@ type pushOptions struct {
|
|||
encryptLayers []int
|
||||
}
|
||||
|
||||
// translates the pushOptions into libimage.PushOptions.
|
||||
func (iopts *pushOptions) toLibimagePushOptions() (*libimage.PushOptions, error) {
|
||||
pushOptions := &libimage.PushOptions{}
|
||||
pushOptions.PolicyAllowStorage = true
|
||||
pushOptions.AuthFilePath = iopts.authfile
|
||||
pushOptions.CertDirPath = iopts.certDir
|
||||
pushOptions.Credentials = iopts.creds
|
||||
pushOptions.RemoveSignatures = iopts.removeSignatures
|
||||
pushOptions.SignaturePolicyPath = iopts.signaturePolicy
|
||||
pushOptions.SignBy = iopts.signBy
|
||||
|
||||
if iopts.blobCache != "" {
|
||||
compress := types.Compress
|
||||
if iopts.disableCompression {
|
||||
compress = types.PreserveOriginal
|
||||
}
|
||||
pushOptions.SourceLookupReferenceFunc = blobcache.CacheLookupReferenceFunc(iopts.blobCache, compress)
|
||||
}
|
||||
|
||||
var manifestType string
|
||||
if iopts.format != "" {
|
||||
switch iopts.format {
|
||||
case "oci":
|
||||
manifestType = imgspecv1.MediaTypeImageManifest
|
||||
case "v2s1":
|
||||
manifestType = manifest.DockerV2Schema1SignedMediaType
|
||||
case "v2s2", "docker":
|
||||
manifestType = manifest.DockerV2Schema2MediaType
|
||||
default:
|
||||
return nil, errors.Errorf("unknown format %q. Choose on of the supported formats: 'oci', 'v2s1', or 'v2s2'", iopts.format)
|
||||
}
|
||||
}
|
||||
pushOptions.ManifestMIMEType = manifestType
|
||||
|
||||
encConfig, encLayers, err := getEncryptConfig(iopts.encryptionKeys, iopts.encryptLayers)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to obtain encryption config")
|
||||
}
|
||||
pushOptions.OciEncryptConfig = encConfig
|
||||
pushOptions.OciEncryptLayers = encLayers
|
||||
pushOptions.InsecureSkipTLSVerify = types.NewOptionalBool(!iopts.tlsVerify)
|
||||
|
||||
if !iopts.quiet {
|
||||
pushOptions.Writer = os.Stderr
|
||||
}
|
||||
|
||||
return pushOptions, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
var (
|
||||
opts pushOptions
|
||||
|
@ -174,52 +125,108 @@ func pushCmd(c *cobra.Command, args []string, iopts pushOptions) error {
|
|||
return errors.New("Only two arguments are necessary to push: source and destination")
|
||||
}
|
||||
|
||||
compress := define.Gzip
|
||||
if iopts.disableCompression {
|
||||
compress = define.Uncompressed
|
||||
}
|
||||
|
||||
store, err := getStore(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dest, err := alltransports.ParseImageName(destSpec)
|
||||
// add the docker:// transport to see if they neglected it.
|
||||
if err != nil {
|
||||
destTransport := strings.Split(destSpec, ":")[0]
|
||||
if t := transports.Get(destTransport); t != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.Contains(destSpec, "://") {
|
||||
return err
|
||||
}
|
||||
|
||||
destSpec = "docker://" + destSpec
|
||||
dest2, err2 := alltransports.ParseImageName(destSpec)
|
||||
if err2 != nil {
|
||||
return err
|
||||
}
|
||||
dest = dest2
|
||||
logrus.Debugf("Assuming docker:// as the transport method for DESTINATION: %s", destSpec)
|
||||
}
|
||||
|
||||
systemContext, err := parse.SystemContextFromOptions(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error building system context")
|
||||
}
|
||||
|
||||
runtime, err := libimage.RuntimeFromStore(store, &libimage.RuntimeOptions{SystemContext: systemContext})
|
||||
if err != nil {
|
||||
return err
|
||||
var manifestType string
|
||||
if iopts.format != "" {
|
||||
switch iopts.format {
|
||||
case "oci":
|
||||
manifestType = imgspecv1.MediaTypeImageManifest
|
||||
case "v2s1":
|
||||
manifestType = manifest.DockerV2Schema1SignedMediaType
|
||||
case "v2s2", "docker":
|
||||
manifestType = manifest.DockerV2Schema2MediaType
|
||||
default:
|
||||
return errors.Errorf("unknown format %q. Choose on of the supported formats: 'oci', 'v2s1', or 'v2s2'", iopts.format)
|
||||
}
|
||||
}
|
||||
|
||||
pushOptions, err := iopts.toLibimagePushOptions()
|
||||
encConfig, encLayers, err := getEncryptConfig(iopts.encryptionKeys, iopts.encryptLayers)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "unable to obtain encryption config")
|
||||
}
|
||||
|
||||
pushedManifestBytes, pushError := runtime.Push(context.Background(), src, destSpec, pushOptions)
|
||||
if pushError != nil {
|
||||
// TODO: maybe we find a way to handle that transparently in libimage?
|
||||
if errors.Cause(pushError) != storage.ErrImageUnknown {
|
||||
options := buildah.PushOptions{
|
||||
Compression: compress,
|
||||
ManifestType: manifestType,
|
||||
SignaturePolicyPath: iopts.signaturePolicy,
|
||||
Store: store,
|
||||
SystemContext: systemContext,
|
||||
BlobDirectory: iopts.blobCache,
|
||||
RemoveSignatures: iopts.removeSignatures,
|
||||
SignBy: iopts.signBy,
|
||||
MaxRetries: maxPullPushRetries,
|
||||
RetryDelay: pullPushRetryDelay,
|
||||
OciEncryptConfig: encConfig,
|
||||
OciEncryptLayers: encLayers,
|
||||
}
|
||||
if !iopts.quiet {
|
||||
options.ReportWriter = os.Stderr
|
||||
}
|
||||
|
||||
ref, digest, err := buildah.Push(getContext(), src, dest, options)
|
||||
if err != nil {
|
||||
if errors.Cause(err) != storage.ErrImageUnknown {
|
||||
// Image might be a manifest so attempt a manifest push
|
||||
if manifestsErr := manifestPush(systemContext, store, src, destSpec, iopts); manifestsErr == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return pushError
|
||||
return util.GetFailureCause(err, errors.Wrapf(err, "error pushing image %q to %q", src, destSpec))
|
||||
}
|
||||
if ref != nil {
|
||||
logrus.Debugf("pushed image %q with digest %s", ref, digest.String())
|
||||
} else {
|
||||
logrus.Debugf("pushed image with digest %s", digest.String())
|
||||
}
|
||||
|
||||
logrus.Debugf("Successfully pushed %s with digest %s", transports.ImageName(dest), digest.String())
|
||||
|
||||
if iopts.digestfile != "" {
|
||||
manifestDigest, err := manifest.Digest(pushedManifestBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(iopts.digestfile, []byte(manifestDigest.String()), 0644); err != nil {
|
||||
return err
|
||||
if err = ioutil.WriteFile(iopts.digestfile, []byte(digest.String()), 0644); err != nil {
|
||||
return util.GetFailureCause(err, errors.Wrapf(err, "failed to write digest to file %q", iopts.digestfile))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getListOfTransports gets the transports supported from the image library
|
||||
// and strips of the "tarball" transport from the string of transports returned
|
||||
func getListOfTransports() string {
|
||||
allTransports := strings.Join(transports.ListNames(), ",")
|
||||
return strings.Replace(allTransports, ",tarball", "", 1)
|
||||
|
|
|
@ -174,7 +174,7 @@ func (b *Builder) addManifest(ctx context.Context, manifestName string, imageSpe
|
|||
var create bool
|
||||
systemContext := &types.SystemContext{}
|
||||
var list manifests.List
|
||||
_, listImage, err := util.FindImage(b.store, systemContext, manifestName)
|
||||
_, listImage, err := util.FindImage(b.store, "", systemContext, manifestName)
|
||||
if err != nil {
|
||||
create = true
|
||||
list = manifests.Create()
|
||||
|
@ -194,7 +194,7 @@ func (b *Builder) addManifest(ctx context.Context, manifestName string, imageSpe
|
|||
if err != nil {
|
||||
if ref, err = alltransports.ParseImageName(util.DefaultTransport + imageSpec); err != nil {
|
||||
// check if the local image exists
|
||||
if ref, _, err = util.FindImage(b.store, systemContext, imageSpec); err != nil {
|
||||
if ref, _, err = util.FindImage(b.store, "", systemContext, imageSpec); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
|
|||
if err != nil {
|
||||
return imgID, nil, "", errors.Wrapf(err, "error locating just-written image %q", transports.ImageName(dest))
|
||||
}
|
||||
if err = util.TagImage(b.store, systemContext, img, options.AdditionalTags); err != nil {
|
||||
if err = util.AddImageNames(b.store, "", systemContext, img, options.AdditionalTags); err != nil {
|
||||
return imgID, nil, "", errors.Wrapf(err, "error setting image names to %v", append(img.Names, options.AdditionalTags...))
|
||||
}
|
||||
logrus.Debugf("assigned names %v to image %q", img.Names, img.ID)
|
||||
|
|
|
@ -684,7 +684,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
|
|||
return imageID, ref, errors.Wrapf(err, "error locating just-written image %q", transports.ImageName(dest))
|
||||
}
|
||||
if len(b.additionalTags) > 0 {
|
||||
if err = util.TagImage(b.store, b.systemContext, img, b.additionalTags); err != nil {
|
||||
if err = util.AddImageNames(b.store, "", b.systemContext, img, b.additionalTags); err != nil {
|
||||
return imageID, ref, errors.Wrapf(err, "error setting image names to %v", append(img.Names, b.additionalTags...))
|
||||
}
|
||||
logrus.Debugf("assigned names %v to image %q", img.Names, img.ID)
|
||||
|
|
|
@ -153,7 +153,7 @@ func importBuilderFromImage(ctx context.Context, store storage.Store, options Im
|
|||
|
||||
systemContext := getSystemContext(store, options.SystemContext, options.SignaturePolicyPath)
|
||||
|
||||
_, img, err := util.FindImage(store, systemContext, options.Image)
|
||||
_, img, err := util.FindImage(store, "", systemContext, options.Image)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "importing settings")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package buildah
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/containers/buildah/define"
|
||||
"github.com/containers/buildah/pkg/blobcache"
|
||||
"github.com/containers/common/libimage"
|
||||
libimageTypes "github.com/containers/common/libimage/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
encconfig "github.com/containers/ocicrypt/config"
|
||||
"github.com/containers/storage"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// PullOptions can be used to alter how an image is copied in from somewhere.
|
||||
type PullOptions struct {
|
||||
// SignaturePolicyPath specifies an override location for the signature
|
||||
// policy which should be used for verifying the new image as it is
|
||||
// being written. Except in specific circumstances, no value should be
|
||||
// specified, indicating that the shared, system-wide default policy
|
||||
// should be used.
|
||||
SignaturePolicyPath string
|
||||
// ReportWriter is an io.Writer which will be used to log the writing
|
||||
// of the new image.
|
||||
ReportWriter io.Writer
|
||||
// Store is the local storage store which holds the source image.
|
||||
Store storage.Store
|
||||
// github.com/containers/image/types SystemContext to hold credentials
|
||||
// and other authentication/authorization information.
|
||||
SystemContext *types.SystemContext
|
||||
// BlobDirectory is the name of a directory in which we'll attempt to
|
||||
// store copies of layer blobs that we pull down, if any. It should
|
||||
// already exist.
|
||||
BlobDirectory string
|
||||
// AllTags is a boolean value that determines if all tagged images
|
||||
// will be downloaded from the repository. The default is false.
|
||||
AllTags bool
|
||||
// RemoveSignatures causes any existing signatures for the image to be
|
||||
// discarded when pulling it.
|
||||
RemoveSignatures bool
|
||||
// MaxRetries is the maximum number of attempts we'll make to pull any
|
||||
// one image from the external registry if the first attempt fails.
|
||||
MaxRetries int
|
||||
// RetryDelay is how long to wait before retrying a pull attempt.
|
||||
RetryDelay time.Duration
|
||||
// OciDecryptConfig contains the config that can be used to decrypt an image if it is
|
||||
// encrypted if non-nil. If nil, it does not attempt to decrypt an image.
|
||||
OciDecryptConfig *encconfig.DecryptConfig
|
||||
// PullPolicy takes the value PullIfMissing, PullAlways, PullIfNewer, or PullNever.
|
||||
PullPolicy define.PullPolicy
|
||||
}
|
||||
|
||||
// Pull copies the contents of the image from somewhere else to local storage. Returns the
|
||||
// ID of the local image or an error.
|
||||
func Pull(ctx context.Context, imageName string, options PullOptions) (imageID string, err error) {
|
||||
libimageOptions := &libimage.PullOptions{}
|
||||
libimageOptions.SignaturePolicyPath = options.SignaturePolicyPath
|
||||
libimageOptions.Writer = options.ReportWriter
|
||||
libimageOptions.RemoveSignatures = options.RemoveSignatures
|
||||
libimageOptions.OciDecryptConfig = options.OciDecryptConfig
|
||||
libimageOptions.AllTags = options.AllTags
|
||||
libimageOptions.RetryDelay = &options.RetryDelay
|
||||
|
||||
if options.MaxRetries > 0 {
|
||||
retries := uint(options.MaxRetries)
|
||||
libimageOptions.MaxRetries = &retries
|
||||
}
|
||||
|
||||
if options.BlobDirectory != "" {
|
||||
libimageOptions.DestinationLookupReferenceFunc = blobcache.CacheLookupReferenceFunc(options.BlobDirectory, types.PreserveOriginal)
|
||||
}
|
||||
|
||||
pullPolicy, err := libimageTypes.ParsePullPolicy(options.PullPolicy.String())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
runtime, err := libimage.RuntimeFromStore(options.Store, &libimage.RuntimeOptions{SystemContext: options.SystemContext})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
pulledImages, err := runtime.Pull(context.Background(), imageName, pullPolicy, libimageOptions)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(pulledImages) == 0 {
|
||||
return "", errors.Errorf("internal error pulling %s: no image pulled and no error", imageName)
|
||||
}
|
||||
|
||||
return pulledImages[0].ID(), nil
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
package buildah
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/containers/buildah/pkg/blobcache"
|
||||
"github.com/containers/common/libimage"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
encconfig "github.com/containers/ocicrypt/config"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// PushOptions can be used to alter how an image is copied somewhere.
|
||||
type PushOptions struct {
|
||||
// Compression specifies the type of compression which is applied to
|
||||
// layer blobs. The default is to not use compression, but
|
||||
// archive.Gzip is recommended.
|
||||
Compression archive.Compression
|
||||
// SignaturePolicyPath specifies an override location for the signature
|
||||
// policy which should be used for verifying the new image as it is
|
||||
// being written. Except in specific circumstances, no value should be
|
||||
// specified, indicating that the shared, system-wide default policy
|
||||
// should be used.
|
||||
SignaturePolicyPath string
|
||||
// ReportWriter is an io.Writer which will be used to log the writing
|
||||
// of the new image.
|
||||
ReportWriter io.Writer
|
||||
// Store is the local storage store which holds the source image.
|
||||
Store storage.Store
|
||||
// github.com/containers/image/types SystemContext to hold credentials
|
||||
// and other authentication/authorization information.
|
||||
SystemContext *types.SystemContext
|
||||
// ManifestType is the format to use when saving the image using the 'dir' transport
|
||||
// possible options are oci, v2s1, and v2s2
|
||||
ManifestType string
|
||||
// BlobDirectory is the name of a directory in which we'll look for
|
||||
// prebuilt copies of layer blobs that we might otherwise need to
|
||||
// regenerate from on-disk layers, substituting them in the list of
|
||||
// blobs to copy whenever possible.
|
||||
BlobDirectory string
|
||||
// Quiet is a boolean value that determines if minimal output to
|
||||
// the user will be displayed, this is best used for logging.
|
||||
// The default is false.
|
||||
Quiet bool
|
||||
// SignBy is the fingerprint of a GPG key to use for signing the image.
|
||||
SignBy string
|
||||
// RemoveSignatures causes any existing signatures for the image to be
|
||||
// discarded for the pushed copy.
|
||||
RemoveSignatures bool
|
||||
// MaxRetries is the maximum number of attempts we'll make to push any
|
||||
// one image to the external registry if the first attempt fails.
|
||||
MaxRetries int
|
||||
// RetryDelay is how long to wait before retrying a push attempt.
|
||||
RetryDelay time.Duration
|
||||
// OciEncryptConfig when non-nil indicates that an image should be encrypted.
|
||||
// The encryption options is derived from the construction of EncryptConfig object.
|
||||
OciEncryptConfig *encconfig.EncryptConfig
|
||||
// OciEncryptLayers represents the list of layers to encrypt.
|
||||
// If nil, don't encrypt any layers.
|
||||
// If non-nil and len==0, denotes encrypt all layers.
|
||||
// integers in the slice represent 0-indexed layer indices, with support for negativ
|
||||
// indexing. i.e. 0 is the first layer, -1 is the last (top-most) layer.
|
||||
OciEncryptLayers *[]int
|
||||
}
|
||||
|
||||
// Push copies the contents of the image to a new location.
|
||||
func Push(ctx context.Context, image string, dest types.ImageReference, options PushOptions) (reference.Canonical, digest.Digest, error) {
|
||||
libimageOptions := &libimage.PushOptions{}
|
||||
libimageOptions.SignaturePolicyPath = options.SignaturePolicyPath
|
||||
libimageOptions.Writer = options.ReportWriter
|
||||
libimageOptions.ManifestMIMEType = options.ManifestType
|
||||
libimageOptions.SignBy = options.SignBy
|
||||
libimageOptions.RemoveSignatures = options.RemoveSignatures
|
||||
libimageOptions.RetryDelay = &options.RetryDelay
|
||||
libimageOptions.OciEncryptConfig = options.OciEncryptConfig
|
||||
libimageOptions.OciEncryptLayers = options.OciEncryptLayers
|
||||
libimageOptions.PolicyAllowStorage = true
|
||||
|
||||
if options.Quiet {
|
||||
libimageOptions.Writer = nil
|
||||
}
|
||||
|
||||
if options.BlobDirectory != "" {
|
||||
compress := types.PreserveOriginal
|
||||
if options.Compression == archive.Gzip {
|
||||
compress = types.Compress
|
||||
}
|
||||
libimageOptions.SourceLookupReferenceFunc = blobcache.CacheLookupReferenceFunc(options.BlobDirectory, compress)
|
||||
}
|
||||
|
||||
runtime, err := libimage.RuntimeFromStore(options.Store, &libimage.RuntimeOptions{SystemContext: options.SystemContext})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
destString := fmt.Sprintf("%s:%s", dest.Transport().Name(), dest.StringWithinTransport())
|
||||
manifestBytes, err := runtime.Push(ctx, image, destString, libimageOptions)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
manifestDigest, err := manifest.Digest(manifestBytes)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "error computing digest of manifest of new image %q", transports.ImageName(dest))
|
||||
}
|
||||
|
||||
var ref reference.Canonical
|
||||
if name := dest.DockerReference(); name != nil {
|
||||
ref, err = reference.WithDigest(name, manifestDigest)
|
||||
if err != nil {
|
||||
logrus.Warnf("error generating canonical reference with name %q and digest %s: %v", name, manifestDigest.String(), err)
|
||||
}
|
||||
}
|
||||
|
||||
return ref, manifestDigest, nil
|
||||
}
|
|
@ -105,7 +105,7 @@ func main() {
|
|||
manifestType := ""
|
||||
configType := ""
|
||||
|
||||
ref, _, err := util.FindImage(store, systemContext, image)
|
||||
ref, _, err := util.FindImage(store, "", systemContext, image)
|
||||
if err != nil {
|
||||
ref2, err2 := alltransports.ParseImageName(image)
|
||||
if err2 != nil {
|
||||
|
|
10
util/util.go
10
util/util.go
|
@ -161,7 +161,9 @@ func ExpandNames(names []string, systemContext *types.SystemContext, store stora
|
|||
}
|
||||
|
||||
// FindImage locates the locally-stored image which corresponds to a given name.
|
||||
func FindImage(store storage.Store, systemContext *types.SystemContext, image string) (types.ImageReference, *storage.Image, error) {
|
||||
// Please note that the `firstRegistry` argument has been deprecated and has no
|
||||
// effect anymore.
|
||||
func FindImage(store storage.Store, firstRegistry string, systemContext *types.SystemContext, image string) (types.ImageReference, *storage.Image, error) {
|
||||
runtime, err := libimage.RuntimeFromStore(store, &libimage.RuntimeOptions{SystemContext: systemContext})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -212,8 +214,10 @@ func ResolveNameToReferences(
|
|||
return refs, nil
|
||||
}
|
||||
|
||||
// TagImage adds the specified names to the specified image.
|
||||
func TagImage(store storage.Store, systemContext *types.SystemContext, image *storage.Image, addNames []string) error {
|
||||
// AddImageNames adds the specified names to the specified image. Please note
|
||||
// that the `firstRegistry` argument has been deprecated and has no effect
|
||||
// anymore.
|
||||
func AddImageNames(store storage.Store, firstRegistry string, systemContext *types.SystemContext, image *storage.Image, addNames []string) error {
|
||||
runtime, err := libimage.RuntimeFromStore(store, &libimage.RuntimeOptions{SystemContext: systemContext})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
Loading…
Reference in New Issue