mirror of
https://github.com/containers/podman.git
synced 2025-12-03 03:39:44 +08:00
Vendor in new new buildah/ci
libpod requires new buildah and container image versions to resolve bug #1640298 Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
13
vendor/github.com/containers/buildah/buildah.go
generated
vendored
13
vendor/github.com/containers/buildah/buildah.go
generated
vendored
@@ -457,6 +457,10 @@ func OpenBuilderByPath(store storage.Store, path string) (*Builder, error) {
|
||||
}
|
||||
buildstate, err := ioutil.ReadFile(filepath.Join(cdir, stateFile))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
logrus.Debugf("error reading %q: %v, ignoring container %q", filepath.Join(cdir, stateFile), err, container.ID)
|
||||
continue
|
||||
}
|
||||
return nil, errors.Wrapf(err, "error reading %q", filepath.Join(cdir, stateFile))
|
||||
}
|
||||
b := &Builder{}
|
||||
@@ -488,9 +492,12 @@ func OpenAllBuilders(store storage.Store) (builders []*Builder, err error) {
|
||||
return nil, err
|
||||
}
|
||||
buildstate, err := ioutil.ReadFile(filepath.Join(cdir, stateFile))
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
logrus.Debugf("error reading %q: %v", filepath.Join(cdir, stateFile), err)
|
||||
continue
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
logrus.Debugf("error reading %q: %v, ignoring container %q", filepath.Join(cdir, stateFile), err, container.ID)
|
||||
continue
|
||||
}
|
||||
return nil, errors.Wrapf(err, "error reading %q", filepath.Join(cdir, stateFile))
|
||||
}
|
||||
b := &Builder{}
|
||||
err = json.Unmarshal(buildstate, &b)
|
||||
|
||||
78
vendor/github.com/containers/buildah/commit.go
generated
vendored
78
vendor/github.com/containers/buildah/commit.go
generated
vendored
@@ -9,12 +9,15 @@ import (
|
||||
|
||||
"github.com/containers/buildah/util"
|
||||
cp "github.com/containers/image/copy"
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/image/manifest"
|
||||
"github.com/containers/image/signature"
|
||||
is "github.com/containers/image/storage"
|
||||
"github.com/containers/image/transports"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -88,26 +91,26 @@ type PushOptions struct {
|
||||
// configuration, to a new image in the specified location, and if we know how,
|
||||
// add any additional tags that were specified. Returns the ID of the new image
|
||||
// if commit was successful and the image destination was local
|
||||
func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options CommitOptions) (string, error) {
|
||||
func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options CommitOptions) (string, reference.Canonical, digest.Digest, error) {
|
||||
var imgID string
|
||||
|
||||
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
|
||||
|
||||
blocked, err := isReferenceBlocked(dest, systemContext)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "error checking if committing to registry for %q is blocked", transports.ImageName(dest))
|
||||
return "", nil, "", errors.Wrapf(err, "error checking if committing to registry for %q is blocked", transports.ImageName(dest))
|
||||
}
|
||||
if blocked {
|
||||
return "", errors.Errorf("commit access to registry for %q is blocked by configuration", transports.ImageName(dest))
|
||||
return "", nil, "", errors.Errorf("commit access to registry for %q is blocked by configuration", transports.ImageName(dest))
|
||||
}
|
||||
|
||||
policy, err := signature.DefaultPolicy(systemContext)
|
||||
if err != nil {
|
||||
return imgID, errors.Wrapf(err, "error obtaining default signature policy")
|
||||
return imgID, nil, "", errors.Wrapf(err, "error obtaining default signature policy")
|
||||
}
|
||||
policyContext, err := signature.NewPolicyContext(policy)
|
||||
if err != nil {
|
||||
return imgID, errors.Wrapf(err, "error creating new signature policy context")
|
||||
return imgID, nil, "", errors.Wrapf(err, "error creating new signature policy context")
|
||||
}
|
||||
defer func() {
|
||||
if err2 := policyContext.Destroy(); err2 != nil {
|
||||
@@ -127,21 +130,22 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
|
||||
}
|
||||
src, err := b.makeImageRef(options.PreferredManifestType, options.Parent, exportBaseLayers, options.Squash, options.Compression, options.HistoryTimestamp)
|
||||
if err != nil {
|
||||
return imgID, errors.Wrapf(err, "error computing layer digests and building metadata for container %q", b.ContainerID)
|
||||
return imgID, nil, "", errors.Wrapf(err, "error computing layer digests and building metadata for container %q", b.ContainerID)
|
||||
}
|
||||
// "Copy" our image to where it needs to be.
|
||||
if err = cp.Image(ctx, policyContext, dest, src, getCopyOptions(options.ReportWriter, src, nil, dest, systemContext, "")); err != nil {
|
||||
return imgID, errors.Wrapf(err, "error copying layers and metadata for container %q", b.ContainerID)
|
||||
var manifestBytes []byte
|
||||
if manifestBytes, err = cp.Image(ctx, policyContext, dest, src, getCopyOptions(options.ReportWriter, src, nil, dest, systemContext, "")); err != nil {
|
||||
return imgID, nil, "", errors.Wrapf(err, "error copying layers and metadata for container %q", b.ContainerID)
|
||||
}
|
||||
if len(options.AdditionalTags) > 0 {
|
||||
switch dest.Transport().Name() {
|
||||
case is.Transport.Name():
|
||||
img, err := is.Transport.GetStoreImage(b.store, dest)
|
||||
if err != nil {
|
||||
return imgID, errors.Wrapf(err, "error locating just-written image %q", transports.ImageName(dest))
|
||||
return imgID, nil, "", errors.Wrapf(err, "error locating just-written image %q", transports.ImageName(dest))
|
||||
}
|
||||
if err = util.AddImageNames(b.store, "", systemContext, img, options.AdditionalTags); err != nil {
|
||||
return imgID, errors.Wrapf(err, "error setting image names to %v", append(img.Names, options.AdditionalTags...))
|
||||
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)
|
||||
default:
|
||||
@@ -151,7 +155,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
|
||||
|
||||
img, err := is.Transport.GetStoreImage(b.store, dest)
|
||||
if err != nil && err != storage.ErrImageUnknown {
|
||||
return imgID, errors.Wrapf(err, "error locating image %q in local storage", transports.ImageName(dest))
|
||||
return imgID, nil, "", errors.Wrapf(err, "error locating image %q in local storage", transports.ImageName(dest))
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
@@ -159,47 +163,71 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
|
||||
|
||||
if options.IIDFile != "" {
|
||||
if err = ioutil.WriteFile(options.IIDFile, []byte(img.ID), 0644); err != nil {
|
||||
return imgID, errors.Wrapf(err, "failed to write image ID to file %q", options.IIDFile)
|
||||
return imgID, nil, "", errors.Wrapf(err, "failed to write image ID to file %q", options.IIDFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return imgID, nil
|
||||
manifestDigest, err := manifest.Digest(manifestBytes)
|
||||
if err != nil {
|
||||
return imgID, 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 imgID, ref, manifestDigest, nil
|
||||
}
|
||||
|
||||
// Push copies the contents of the image to a new location.
|
||||
func Push(ctx context.Context, image string, dest types.ImageReference, options PushOptions) error {
|
||||
func Push(ctx context.Context, image string, dest types.ImageReference, options PushOptions) (reference.Canonical, digest.Digest, error) {
|
||||
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
|
||||
|
||||
blocked, err := isReferenceBlocked(dest, systemContext)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error checking if pushing to registry for %q is blocked", transports.ImageName(dest))
|
||||
return nil, "", errors.Wrapf(err, "error checking if pushing to registry for %q is blocked", transports.ImageName(dest))
|
||||
}
|
||||
if blocked {
|
||||
return errors.Errorf("push access to registry for %q is blocked by configuration", transports.ImageName(dest))
|
||||
return nil, "", errors.Errorf("push access to registry for %q is blocked by configuration", transports.ImageName(dest))
|
||||
}
|
||||
|
||||
policy, err := signature.DefaultPolicy(systemContext)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error obtaining default signature policy")
|
||||
return nil, "", errors.Wrapf(err, "error obtaining default signature policy")
|
||||
}
|
||||
policyContext, err := signature.NewPolicyContext(policy)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating new signature policy context")
|
||||
return nil, "", errors.Wrapf(err, "error creating new signature policy context")
|
||||
}
|
||||
// Look up the image.
|
||||
src, img, err := util.FindImage(options.Store, "", systemContext, image)
|
||||
src, _, err := util.FindImage(options.Store, "", systemContext, image)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, "", err
|
||||
}
|
||||
// Copy everything.
|
||||
if err = cp.Image(ctx, policyContext, dest, src, getCopyOptions(options.ReportWriter, src, nil, dest, systemContext, options.ManifestType)); err != nil {
|
||||
return errors.Wrapf(err, "error copying layers and metadata from %q to %q", transports.ImageName(src), transports.ImageName(dest))
|
||||
var manifestBytes []byte
|
||||
if manifestBytes, err = cp.Image(ctx, policyContext, dest, src, getCopyOptions(options.ReportWriter, src, nil, dest, systemContext, options.ManifestType)); err != nil {
|
||||
return nil, "", errors.Wrapf(err, "error copying layers and metadata from %q to %q", transports.ImageName(src), transports.ImageName(dest))
|
||||
}
|
||||
if options.ReportWriter != nil {
|
||||
fmt.Fprintf(options.ReportWriter, "")
|
||||
}
|
||||
digest := "@" + img.Digest.Hex()
|
||||
fmt.Printf("Successfully pushed %s%s\n", dest.StringWithinTransport(), digest)
|
||||
return nil
|
||||
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)
|
||||
}
|
||||
}
|
||||
fmt.Printf("Successfully pushed %s@%s\n", dest.StringWithinTransport(), manifestDigest.String())
|
||||
return ref, manifestDigest, nil
|
||||
}
|
||||
|
||||
61
vendor/github.com/containers/buildah/imagebuildah/build.go
generated
vendored
61
vendor/github.com/containers/buildah/imagebuildah/build.go
generated
vendored
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/buildah/util"
|
||||
cp "github.com/containers/image/copy"
|
||||
"github.com/containers/image/docker/reference"
|
||||
is "github.com/containers/image/storage"
|
||||
"github.com/containers/image/transports"
|
||||
"github.com/containers/image/transports/alltransports"
|
||||
@@ -761,7 +762,7 @@ func (b *Executor) resolveNameToImageRef() (types.ImageReference, error) {
|
||||
if b.output != "" {
|
||||
imageRef, err = alltransports.ParseImageName(b.output)
|
||||
if err != nil {
|
||||
candidates, err := util.ResolveName(b.output, "", b.systemContext, b.store)
|
||||
candidates, _, err := util.ResolveName(b.output, "", b.systemContext, b.store)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing target image name %q: %v", b.output)
|
||||
}
|
||||
@@ -860,7 +861,7 @@ func (b *Executor) Execute(ctx context.Context, stage imagebuilder.Stage) error
|
||||
|
||||
// Commit if no cache is found
|
||||
if cacheID == "" {
|
||||
imgID, err = b.Commit(ctx, ib, getCreatedBy(node))
|
||||
imgID, _, err = b.Commit(ctx, ib, getCreatedBy(node))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error committing container for step %+v", *step)
|
||||
}
|
||||
@@ -903,7 +904,7 @@ func (b *Executor) copyExistingImage(ctx context.Context, cacheID string) error
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error getting source imageReference for %q", cacheID)
|
||||
}
|
||||
if err := cp.Image(ctx, policyContext, dest, src, nil); err != nil {
|
||||
if _, err := cp.Image(ctx, policyContext, dest, src, nil); err != nil {
|
||||
return errors.Wrapf(err, "error copying image %q", cacheID)
|
||||
}
|
||||
b.log("COMMIT %s", b.output)
|
||||
@@ -1083,10 +1084,10 @@ func urlContentModified(url string, historyTime *time.Time) (bool, error) {
|
||||
|
||||
// Commit writes the container's contents to an image, using a passed-in tag as
|
||||
// the name if there is one, generating a unique ID-based one otherwise.
|
||||
func (b *Executor) Commit(ctx context.Context, ib *imagebuilder.Builder, createdBy string) (string, error) {
|
||||
func (b *Executor) Commit(ctx context.Context, ib *imagebuilder.Builder, createdBy string) (string, reference.Canonical, error) {
|
||||
imageRef, err := b.resolveNameToImageRef()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if ib.Author != "" {
|
||||
@@ -1165,19 +1166,19 @@ func (b *Executor) Commit(ctx context.Context, ib *imagebuilder.Builder, created
|
||||
Squash: b.squash,
|
||||
Parent: b.builder.FromImageID,
|
||||
}
|
||||
imgID, err := b.builder.Commit(ctx, imageRef, options)
|
||||
imgID, ref, _, err := b.builder.Commit(ctx, imageRef, options)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", nil, err
|
||||
}
|
||||
if options.IIDFile == "" && imgID != "" {
|
||||
fmt.Fprintf(b.out, "--> %s\n", imgID)
|
||||
}
|
||||
return imgID, nil
|
||||
return imgID, ref, nil
|
||||
}
|
||||
|
||||
// Build takes care of the details of running Prepare/Execute/Commit/Delete
|
||||
// over each of the one or more parsed Dockerfiles and stages.
|
||||
func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) error {
|
||||
func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (string, reference.Canonical, error) {
|
||||
if len(stages) == 0 {
|
||||
errors.New("error building: no stages to build")
|
||||
}
|
||||
@@ -1190,7 +1191,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) error
|
||||
for _, stage := range stages {
|
||||
stageExecutor = b.withName(stage.Name, stage.Position)
|
||||
if err := stageExecutor.Prepare(ctx, stage, ""); err != nil {
|
||||
return err
|
||||
return "", nil, err
|
||||
}
|
||||
// Always remove the intermediate/build containers, even if the build was unsuccessful.
|
||||
// If building with layers, remove all intermediate/build containers if b.forceRmIntermediateCtrs
|
||||
@@ -1208,7 +1209,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) error
|
||||
if b.removeIntermediateCtrs {
|
||||
stageExecutor.deleteSuccessfulIntermediateCtrs()
|
||||
}
|
||||
return lastErr
|
||||
return "", nil, lastErr
|
||||
}
|
||||
b.containerIDs = append(b.containerIDs, stageExecutor.containerIDs...)
|
||||
// If we've a stage.Name with alpha and not numeric, we've an
|
||||
@@ -1216,20 +1217,24 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) error
|
||||
// stage to be used by other FROM statements that will want
|
||||
// to use it later in the Dockerfile. Note the id in our map.
|
||||
if _, err := strconv.Atoi(stage.Name); err != nil {
|
||||
imgID, err := stageExecutor.Commit(ctx, stages[stageCount].Builder, "")
|
||||
imgID, _, err := stageExecutor.Commit(ctx, stages[stageCount].Builder, "")
|
||||
if err != nil {
|
||||
return err
|
||||
return "", nil, err
|
||||
}
|
||||
b.imageMap[stage.Name] = imgID
|
||||
}
|
||||
stageCount++
|
||||
}
|
||||
|
||||
var imageRef reference.Canonical
|
||||
imageID := ""
|
||||
if !b.layers && !b.noCache {
|
||||
_, err := stageExecutor.Commit(ctx, stages[len(stages)-1].Builder, "")
|
||||
imgID, ref, err := stageExecutor.Commit(ctx, stages[len(stages)-1].Builder, "")
|
||||
if err != nil {
|
||||
return err
|
||||
return "", nil, err
|
||||
}
|
||||
imageID = imgID
|
||||
imageRef = ref
|
||||
}
|
||||
// If building with layers and b.removeIntermediateCtrs is true
|
||||
// only remove intermediate container for each step if an error
|
||||
@@ -1241,7 +1246,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) error
|
||||
// defer statement above.
|
||||
if b.removeIntermediateCtrs && (b.layers || b.noCache) {
|
||||
if err := b.deleteSuccessfulIntermediateCtrs(); err != nil {
|
||||
return errors.Errorf("Failed to cleanup intermediate containers")
|
||||
return "", nil, errors.Errorf("Failed to cleanup intermediate containers")
|
||||
}
|
||||
}
|
||||
// Remove intermediate images that we created for AS clause handling
|
||||
@@ -1250,15 +1255,15 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) error
|
||||
logrus.Debugf("unable to remove intermediate image %q: %v", value, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return imageID, imageRef, nil
|
||||
}
|
||||
|
||||
// BuildDockerfiles parses a set of one or more Dockerfiles (which may be
|
||||
// URLs), creates a new Executor, and then runs Prepare/Execute/Commit/Delete
|
||||
// over the entire set of instructions.
|
||||
func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOptions, paths ...string) error {
|
||||
func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOptions, paths ...string) (string, reference.Canonical, error) {
|
||||
if len(paths) == 0 {
|
||||
return errors.Errorf("error building: no dockerfiles specified")
|
||||
return "", nil, errors.Errorf("error building: no dockerfiles specified")
|
||||
}
|
||||
var dockerfiles []io.ReadCloser
|
||||
defer func(dockerfiles ...io.ReadCloser) {
|
||||
@@ -1274,11 +1279,11 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt
|
||||
logrus.Debugf("reading remote Dockerfile %q", dfile)
|
||||
resp, err := http.Get(dfile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error getting %q", dfile)
|
||||
return "", nil, errors.Wrapf(err, "error getting %q", dfile)
|
||||
}
|
||||
if resp.ContentLength == 0 {
|
||||
resp.Body.Close()
|
||||
return errors.Errorf("no contents in %q", dfile)
|
||||
return "", nil, errors.Errorf("no contents in %q", dfile)
|
||||
}
|
||||
data = resp.Body
|
||||
} else {
|
||||
@@ -1290,16 +1295,16 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt
|
||||
logrus.Debugf("reading local Dockerfile %q", dfile)
|
||||
contents, err := os.Open(dfile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error reading %q", dfile)
|
||||
return "", nil, errors.Wrapf(err, "error reading %q", dfile)
|
||||
}
|
||||
dinfo, err := contents.Stat()
|
||||
if err != nil {
|
||||
contents.Close()
|
||||
return errors.Wrapf(err, "error reading info about %q", dfile)
|
||||
return "", nil, errors.Wrapf(err, "error reading info about %q", dfile)
|
||||
}
|
||||
if dinfo.Mode().IsRegular() && dinfo.Size() == 0 {
|
||||
contents.Close()
|
||||
return errors.Wrapf(err, "no contents in %q", dfile)
|
||||
return "", nil, errors.Wrapf(err, "no contents in %q", dfile)
|
||||
}
|
||||
data = contents
|
||||
}
|
||||
@@ -1308,7 +1313,7 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt
|
||||
if strings.HasSuffix(dfile, ".in") {
|
||||
pData, err := preprocessDockerfileContents(data, options.ContextDirectory)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", nil, err
|
||||
}
|
||||
data = *pData
|
||||
}
|
||||
@@ -1317,18 +1322,18 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt
|
||||
}
|
||||
mainNode, err := imagebuilder.ParseDockerfile(dockerfiles[0])
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error parsing main Dockerfile")
|
||||
return "", nil, errors.Wrapf(err, "error parsing main Dockerfile")
|
||||
}
|
||||
for _, d := range dockerfiles[1:] {
|
||||
additionalNode, err := imagebuilder.ParseDockerfile(d)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error parsing additional Dockerfile")
|
||||
return "", nil, errors.Wrapf(err, "error parsing additional Dockerfile")
|
||||
}
|
||||
mainNode.Children = append(mainNode.Children, additionalNode.Children...)
|
||||
}
|
||||
exec, err := NewExecutor(store, options)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating build executor")
|
||||
return "", nil, errors.Wrapf(err, "error creating build executor")
|
||||
}
|
||||
b := imagebuilder.NewBuilder(options.Args)
|
||||
stages := imagebuilder.NewStages(mainNode, b)
|
||||
|
||||
116
vendor/github.com/containers/buildah/new.go
generated
vendored
116
vendor/github.com/containers/buildah/new.go
generated
vendored
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/containers/image/transports/alltransports"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/storage"
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
"github.com/openshift/imagebuilder"
|
||||
"github.com/pkg/errors"
|
||||
@@ -107,41 +106,46 @@ func newContainerIDMappingOptions(idmapOptions *IDMappingOptions) storage.IDMapp
|
||||
}
|
||||
|
||||
func resolveImage(ctx context.Context, systemContext *types.SystemContext, store storage.Store, options BuilderOptions) (types.ImageReference, *storage.Image, error) {
|
||||
var ref types.ImageReference
|
||||
var img *storage.Image
|
||||
images, err := util.ResolveName(options.FromImage, options.Registry, systemContext, store)
|
||||
type failure struct {
|
||||
resolvedImageName string
|
||||
err error
|
||||
}
|
||||
|
||||
candidates, searchRegistriesWereUsedButEmpty, err := util.ResolveName(options.FromImage, options.Registry, systemContext, store)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "error parsing reference to image %q", options.FromImage)
|
||||
}
|
||||
var pullErrors *multierror.Error
|
||||
for _, image := range images {
|
||||
failures := []failure{}
|
||||
for _, image := range candidates {
|
||||
var err error
|
||||
if len(image) >= minimumTruncatedIDLength {
|
||||
if img, err = store.Image(image); err == nil && img != nil && strings.HasPrefix(img.ID, image) {
|
||||
if ref, err = is.Transport.ParseStoreReference(store, img.ID); err != nil {
|
||||
if img, err := store.Image(image); err == nil && img != nil && strings.HasPrefix(img.ID, image) {
|
||||
ref, err := is.Transport.ParseStoreReference(store, img.ID)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "error parsing reference to image %q", img.ID)
|
||||
}
|
||||
break
|
||||
return ref, img, nil
|
||||
}
|
||||
}
|
||||
|
||||
if options.PullPolicy == PullAlways {
|
||||
pulledImg, pulledReference, err := pullAndFindImage(ctx, store, image, options, systemContext)
|
||||
if err != nil {
|
||||
pullErrors = multierror.Append(pullErrors, err)
|
||||
logrus.Debugf("unable to pull and read image %q: %v", image, err)
|
||||
failures = append(failures, failure{resolvedImageName: image, err: err})
|
||||
continue
|
||||
}
|
||||
ref = pulledReference
|
||||
img = pulledImg
|
||||
break
|
||||
return pulledReference, pulledImg, nil
|
||||
}
|
||||
|
||||
srcRef, err := alltransports.ParseImageName(image)
|
||||
if err != nil {
|
||||
if options.Transport == "" {
|
||||
pullErrors = multierror.Append(pullErrors, err)
|
||||
logrus.Debugf("error parsing image name %q: %v", image, err)
|
||||
failures = append(failures, failure{
|
||||
resolvedImageName: image,
|
||||
err: errors.Wrapf(err, "error parsing image name"),
|
||||
})
|
||||
continue
|
||||
}
|
||||
logrus.Debugf("error parsing image name %q as given, trying with transport %q: %v", image, options.Transport, err)
|
||||
@@ -151,8 +155,11 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store
|
||||
}
|
||||
srcRef2, err := alltransports.ParseImageName(transport + image)
|
||||
if err != nil {
|
||||
pullErrors = multierror.Append(pullErrors, err)
|
||||
logrus.Debugf("error parsing image name %q: %v", transport+image, err)
|
||||
failures = append(failures, failure{
|
||||
resolvedImageName: image,
|
||||
err: errors.Wrapf(err, "error parsing attempted image name %q", transport+image),
|
||||
})
|
||||
continue
|
||||
}
|
||||
srcRef = srcRef2
|
||||
@@ -166,34 +173,63 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store
|
||||
return nil, nil, errors.Errorf("error computing local image name for %q", transports.ImageName(srcRef))
|
||||
}
|
||||
|
||||
ref, err = is.Transport.ParseStoreReference(store, destImage)
|
||||
ref, err := is.Transport.ParseStoreReference(store, destImage)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "error parsing reference to image %q", destImage)
|
||||
}
|
||||
img, err = is.Transport.GetStoreImage(store, ref)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == storage.ErrImageUnknown && options.PullPolicy != PullIfMissing {
|
||||
pullErrors = multierror.Append(pullErrors, err)
|
||||
logrus.Debugf("no such image %q: %v", transports.ImageName(ref), err)
|
||||
continue
|
||||
}
|
||||
pulledImg, pulledReference, err := pullAndFindImage(ctx, store, image, options, systemContext)
|
||||
if err != nil {
|
||||
pullErrors = multierror.Append(pullErrors, err)
|
||||
logrus.Debugf("unable to pull and read image %q: %v", image, err)
|
||||
continue
|
||||
}
|
||||
ref = pulledReference
|
||||
img = pulledImg
|
||||
img, err := is.Transport.GetStoreImage(store, ref)
|
||||
if err == nil {
|
||||
return ref, img, nil
|
||||
}
|
||||
break
|
||||
|
||||
if errors.Cause(err) == storage.ErrImageUnknown && options.PullPolicy != PullIfMissing {
|
||||
logrus.Debugf("no such image %q: %v", transports.ImageName(ref), err)
|
||||
failures = append(failures, failure{
|
||||
resolvedImageName: image,
|
||||
err: fmt.Errorf("no such image %q", transports.ImageName(ref)),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
pulledImg, pulledReference, err := pullAndFindImage(ctx, store, image, options, systemContext)
|
||||
if err != nil {
|
||||
logrus.Debugf("unable to pull and read image %q: %v", image, err)
|
||||
failures = append(failures, failure{resolvedImageName: image, err: err})
|
||||
continue
|
||||
}
|
||||
return pulledReference, pulledImg, nil
|
||||
}
|
||||
|
||||
if img == nil && pullErrors != nil {
|
||||
return nil, nil, pullErrors
|
||||
if len(failures) != len(candidates) {
|
||||
return nil, nil, fmt.Errorf("internal error: %d candidates (%#v) vs. %d failures (%#v)", len(candidates), candidates, len(failures), failures)
|
||||
}
|
||||
|
||||
return ref, img, nil
|
||||
registriesConfPath := sysregistries.RegistriesConfPath(systemContext)
|
||||
switch len(failures) {
|
||||
case 0:
|
||||
if searchRegistriesWereUsedButEmpty {
|
||||
return nil, nil, errors.Errorf("image name %q is a short name and no search registries are defined in %s.", options.FromImage, registriesConfPath)
|
||||
}
|
||||
return nil, nil, fmt.Errorf("internal error: no pull candidates were available for %q for an unknown reason", options.FromImage)
|
||||
|
||||
case 1:
|
||||
err := failures[0].err
|
||||
if failures[0].resolvedImageName != options.FromImage {
|
||||
err = errors.Wrapf(err, "while pulling %q as %q", options.FromImage, failures[0].resolvedImageName)
|
||||
}
|
||||
if searchRegistriesWereUsedButEmpty {
|
||||
err = errors.Wrapf(err, "(image name %q is a short name and no search registries are defined in %s)", options.FromImage, registriesConfPath)
|
||||
}
|
||||
return nil, nil, err
|
||||
|
||||
default:
|
||||
// NOTE: a multi-line error string:
|
||||
e := fmt.Sprintf("The following failures happened while trying to pull image specified by %q based on search registries in %s:", options.FromImage, registriesConfPath)
|
||||
for _, f := range failures {
|
||||
e = e + fmt.Sprintf("\n* %q: %s", f.resolvedImageName, f.err.Error())
|
||||
}
|
||||
return nil, nil, errors.New(e)
|
||||
}
|
||||
}
|
||||
|
||||
func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions) (*Builder, error) {
|
||||
@@ -210,17 +246,11 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
|
||||
|
||||
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
|
||||
|
||||
if options.FromImage != "scratch" {
|
||||
if options.FromImage != "" && options.FromImage != "scratch" {
|
||||
ref, img, err = resolveImage(ctx, systemContext, store, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if options.FromImage != "" && (ref == nil || img == nil) {
|
||||
// If options.FromImage is set but we ended up
|
||||
// with nil in ref or in img then there was an error that
|
||||
// we should return.
|
||||
return nil, errors.Wrapf(storage.ErrImageUnknown, "image %q not found in %s registries", options.FromImage, sysregistries.RegistriesConfPath(systemContext))
|
||||
}
|
||||
}
|
||||
image := options.FromImage
|
||||
imageID := ""
|
||||
@@ -266,7 +296,7 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err2 := store.DeleteContainer(container.ID); err != nil {
|
||||
if err2 := store.DeleteContainer(container.ID); err2 != nil {
|
||||
logrus.Errorf("error deleting container %q: %v", container.ID, err2)
|
||||
}
|
||||
}
|
||||
|
||||
25
vendor/github.com/containers/buildah/pull.go
generated
vendored
25
vendor/github.com/containers/buildah/pull.go
generated
vendored
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/containers/image/docker/reference"
|
||||
tarfile "github.com/containers/image/docker/tarfile"
|
||||
ociarchive "github.com/containers/image/oci/archive"
|
||||
"github.com/containers/image/pkg/sysregistries"
|
||||
"github.com/containers/image/signature"
|
||||
is "github.com/containers/image/storage"
|
||||
"github.com/containers/image/transports"
|
||||
@@ -201,28 +200,10 @@ func pullImage(ctx context.Context, store storage.Store, imageName string, optio
|
||||
}()
|
||||
|
||||
logrus.Debugf("copying %q to %q", spec, destName)
|
||||
pullError := cp.Image(ctx, policyContext, destRef, srcRef, getCopyOptions(options.ReportWriter, srcRef, sc, destRef, nil, ""))
|
||||
if pullError == nil {
|
||||
return destRef, nil
|
||||
if _, err := cp.Image(ctx, policyContext, destRef, srcRef, getCopyOptions(options.ReportWriter, srcRef, sc, destRef, nil, "")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If no image was found, we should handle. Lets be nicer to the user and see if we can figure out why.
|
||||
registryPath := sysregistries.RegistriesConfPath(sc)
|
||||
searchRegistries, err := getRegistries(sc)
|
||||
if err != nil {
|
||||
logrus.Debugf("error getting list of registries: %v", err)
|
||||
return nil, errors.Wrapf(pullError, "error copying image from %q to %q", transports.ImageName(srcRef), transports.ImageName(destRef))
|
||||
}
|
||||
hasRegistryInName, err := hasRegistry(imageName)
|
||||
if err != nil {
|
||||
logrus.Debugf("error checking if image name %q includes a registry component: %v", imageName, err)
|
||||
return nil, errors.Wrapf(pullError, "error copying image from %q to %q", transports.ImageName(srcRef), transports.ImageName(destRef))
|
||||
}
|
||||
if !hasRegistryInName && len(searchRegistries) == 0 {
|
||||
logrus.Debugf("copying %q to %q failed: %v", pullError)
|
||||
return nil, errors.Errorf("image name provided does not include a registry name and no search registries are defined in %s: %s", registryPath, pullError)
|
||||
}
|
||||
return nil, pullError
|
||||
return destRef, nil
|
||||
}
|
||||
|
||||
// getImageDigest creates an image object and uses the hex value of the digest as the image ID
|
||||
|
||||
18
vendor/github.com/containers/buildah/run.go
generated
vendored
18
vendor/github.com/containers/buildah/run.go
generated
vendored
@@ -38,8 +38,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultWorkingDir is used if none was specified.
|
||||
DefaultWorkingDir = "/"
|
||||
// runUsingRuntimeCommand is a command we use as a key for reexec
|
||||
runUsingRuntimeCommand = Package + "-oci-runtime"
|
||||
)
|
||||
@@ -146,6 +144,8 @@ type RunOptions struct {
|
||||
Runtime string
|
||||
// Args adds global arguments for the runtime.
|
||||
Args []string
|
||||
// NoPivot adds the --no-pivot runtime flag.
|
||||
NoPivot bool
|
||||
// Mounts are additional mount points which we want to provide.
|
||||
Mounts []specs.Mount
|
||||
// Env is additional environment variables to set.
|
||||
@@ -520,7 +520,7 @@ func runSetupBuiltinVolumes(mountLabel, mountPoint, containerDir string, copyWit
|
||||
if err = os.Chown(volumePath, int(stat.Sys().(*syscall.Stat_t).Uid), int(stat.Sys().(*syscall.Stat_t).Gid)); err != nil {
|
||||
return nil, errors.Wrapf(err, "error chowning directory %q for volume %q", volumePath, volume)
|
||||
}
|
||||
if err = copyWithTar(srcPath, volumePath); err != nil && !os.IsNotExist(err) {
|
||||
if err = copyWithTar(srcPath, volumePath); err != nil && !os.IsNotExist(errors.Cause(err)) {
|
||||
return nil, errors.Wrapf(err, "error populating directory %q for volume %q using contents of %q", volumePath, volume, srcPath)
|
||||
}
|
||||
}
|
||||
@@ -1025,10 +1025,6 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
||||
spec := g.Spec()
|
||||
g = nil
|
||||
|
||||
// Set the working directory, creating it if we must.
|
||||
if spec.Process.Cwd == "" {
|
||||
spec.Process.Cwd = DefaultWorkingDir
|
||||
}
|
||||
logrus.Debugf("ensuring working directory %q exists", filepath.Join(mountPoint, spec.Process.Cwd))
|
||||
if err = os.MkdirAll(filepath.Join(mountPoint, spec.Process.Cwd), 0755); err != nil {
|
||||
return errors.Wrapf(err, "error ensuring working directory %q exists", spec.Process.Cwd)
|
||||
@@ -1093,7 +1089,13 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
||||
// }
|
||||
// }
|
||||
// options.Args = append(options.Args, rootlessFlag...)
|
||||
err = b.runUsingRuntimeSubproc(options, configureNetwork, configureNetworks, nil, spec, mountPoint, path, Package+"-"+filepath.Base(path))
|
||||
var moreCreateArgs []string
|
||||
if options.NoPivot {
|
||||
moreCreateArgs = []string{"--no-pivot"}
|
||||
} else {
|
||||
moreCreateArgs = nil
|
||||
}
|
||||
err = b.runUsingRuntimeSubproc(options, configureNetwork, configureNetworks, moreCreateArgs, spec, mountPoint, path, Package+"-"+filepath.Base(path))
|
||||
case IsolationChroot:
|
||||
err = chroot.RunUsingChroot(spec, path, options.Stdin, options.Stdout, options.Stderr)
|
||||
case IsolationOCIRootless:
|
||||
|
||||
31
vendor/github.com/containers/buildah/util.go
generated
vendored
31
vendor/github.com/containers/buildah/util.go
generated
vendored
@@ -173,21 +173,6 @@ func (b *Builder) tarPath() func(path string) (io.ReadCloser, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// getRegistries obtains the list of search registries defined in the global registries file.
|
||||
func getRegistries(sc *types.SystemContext) ([]string, error) {
|
||||
var searchRegistries []string
|
||||
registries, err := sysregistriesv2.GetRegistries(sc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to parse the registries.conf file")
|
||||
}
|
||||
for _, registry := range sysregistriesv2.FindUnqualifiedSearchRegistries(registries) {
|
||||
if !registry.Blocked {
|
||||
searchRegistries = append(searchRegistries, registry.URL)
|
||||
}
|
||||
}
|
||||
return searchRegistries, nil
|
||||
}
|
||||
|
||||
// isRegistryInsecure checks if the named registry is marked as not secure
|
||||
func isRegistryInsecure(registry string, sc *types.SystemContext) (bool, error) {
|
||||
registries, err := sysregistriesv2.GetRegistries(sc)
|
||||
@@ -252,20 +237,6 @@ func isReferenceBlocked(ref types.ImageReference, sc *types.SystemContext) (bool
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// hasRegistry returns a bool/err response if the image has a registry in its
|
||||
// name
|
||||
func hasRegistry(imageName string) (bool, error) {
|
||||
imgRef, err := reference.Parse(imageName)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "error parsing image name %q", imageName)
|
||||
}
|
||||
registry := reference.Domain(imgRef.(reference.Named))
|
||||
if registry != "" {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// ReserveSELinuxLabels reads containers storage and reserves SELinux containers
|
||||
// fall all existing buildah containers
|
||||
func ReserveSELinuxLabels(store storage.Store, id string) error {
|
||||
@@ -281,7 +252,7 @@ func ReserveSELinuxLabels(store storage.Store, id string) error {
|
||||
} else {
|
||||
b, err := OpenBuilder(store, c.ID)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if os.IsNotExist(errors.Cause(err)) {
|
||||
// Ignore not exist errors since containers probably created by other tool
|
||||
// TODO, we need to read other containers json data to reserve their SELinux labels
|
||||
continue
|
||||
|
||||
26
vendor/github.com/containers/buildah/util/util.go
generated
vendored
26
vendor/github.com/containers/buildah/util/util.go
generated
vendored
@@ -63,10 +63,13 @@ var (
|
||||
|
||||
// ResolveName checks if name is a valid image name, and if that name doesn't
|
||||
// include a domain portion, returns a list of the names which it might
|
||||
// correspond to in the set of configured registries.
|
||||
func ResolveName(name string, firstRegistry string, sc *types.SystemContext, store storage.Store) ([]string, error) {
|
||||
// correspond to in the set of configured registries,
|
||||
// and a boolean which is true iff 1) the list of search registries was used, and 2) it was empty.
|
||||
// NOTE: The "list of search registries is empty" check does not count blocked registries,
|
||||
// and neither the implied "localhost" nor a possible firstRegistry are counted
|
||||
func ResolveName(name string, firstRegistry string, sc *types.SystemContext, store storage.Store) ([]string, bool, error) {
|
||||
if name == "" {
|
||||
return nil, nil
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
// Maybe it's a truncated image ID. Don't prepend a registry name, then.
|
||||
@@ -74,7 +77,7 @@ func ResolveName(name string, firstRegistry string, sc *types.SystemContext, sto
|
||||
if img, err := store.Image(name); err == nil && img != nil && strings.HasPrefix(img.ID, name) {
|
||||
// It's a truncated version of the ID of an image that's present in local storage;
|
||||
// we need only expand the ID.
|
||||
return []string{img.ID}, nil
|
||||
return []string{img.ID}, false, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,18 +85,18 @@ func ResolveName(name string, firstRegistry string, sc *types.SystemContext, sto
|
||||
split := strings.SplitN(name, ":", 2)
|
||||
if len(split) == 2 {
|
||||
if _, ok := Transports[split[0]]; ok {
|
||||
return []string{split[1]}, nil
|
||||
return []string{split[1]}, false, nil
|
||||
}
|
||||
}
|
||||
|
||||
// If the image name already included a domain component, we're done.
|
||||
named, err := reference.ParseNormalizedNamed(name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing image name %q", name)
|
||||
return nil, false, errors.Wrapf(err, "error parsing image name %q", name)
|
||||
}
|
||||
if named.String() == name {
|
||||
// Parsing produced the same result, so there was a domain name in there to begin with.
|
||||
return []string{name}, nil
|
||||
return []string{name}, false, nil
|
||||
}
|
||||
if reference.Domain(named) != "" && RegistryDefaultPathPrefix[reference.Domain(named)] != "" {
|
||||
// If this domain can cause us to insert something in the middle, check if that happened.
|
||||
@@ -110,7 +113,7 @@ func ResolveName(name string, firstRegistry string, sc *types.SystemContext, sto
|
||||
defaultPrefix := RegistryDefaultPathPrefix[reference.Domain(named)] + "/"
|
||||
if strings.HasPrefix(repoPath, defaultPrefix) && path.Join(domain, repoPath[len(defaultPrefix):])+tag+digest == name {
|
||||
// Yup, parsing just inserted a bit in the middle, so there was a domain name there to begin with.
|
||||
return []string{name}, nil
|
||||
return []string{name}, false, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +129,7 @@ func ResolveName(name string, firstRegistry string, sc *types.SystemContext, sto
|
||||
registries = append(registries, registry.URL)
|
||||
}
|
||||
}
|
||||
searchRegistriesAreEmpty := len(registries) == 0
|
||||
|
||||
// Create all of the combinations. Some registries need an additional component added, so
|
||||
// use our lookaside map to keep track of them. If there are no configured registries, we'll
|
||||
@@ -146,7 +150,7 @@ func ResolveName(name string, firstRegistry string, sc *types.SystemContext, sto
|
||||
candidate := path.Join(registry, middle, name)
|
||||
candidates = append(candidates, candidate)
|
||||
}
|
||||
return candidates, nil
|
||||
return candidates, searchRegistriesAreEmpty, nil
|
||||
}
|
||||
|
||||
// ExpandNames takes unqualified names, parses them as image names, and returns
|
||||
@@ -157,7 +161,7 @@ func ExpandNames(names []string, firstRegistry string, systemContext *types.Syst
|
||||
expanded := make([]string, 0, len(names))
|
||||
for _, n := range names {
|
||||
var name reference.Named
|
||||
nameList, err := ResolveName(n, firstRegistry, systemContext, store)
|
||||
nameList, _, err := ResolveName(n, firstRegistry, systemContext, store)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing name %q", n)
|
||||
}
|
||||
@@ -193,7 +197,7 @@ func FindImage(store storage.Store, firstRegistry string, systemContext *types.S
|
||||
var ref types.ImageReference
|
||||
var img *storage.Image
|
||||
var err error
|
||||
names, err := ResolveName(image, firstRegistry, systemContext, store)
|
||||
names, _, err := ResolveName(image, firstRegistry, systemContext, store)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "error parsing name %q", image)
|
||||
}
|
||||
|
||||
2
vendor/github.com/containers/buildah/vendor.conf
generated
vendored
2
vendor/github.com/containers/buildah/vendor.conf
generated
vendored
@@ -3,7 +3,7 @@ github.com/blang/semver master
|
||||
github.com/BurntSushi/toml master
|
||||
github.com/containerd/continuity master
|
||||
github.com/containernetworking/cni v0.7.0-alpha1
|
||||
github.com/containers/image 918dbb93e6e099b196b498c38d079f6bb924d0c8
|
||||
github.com/containers/image 5e5b67d6b1cf43cc349128ec3ed7d5283a6cc0d1
|
||||
github.com/containers/libpod 2afadeec6696fefac468a49c8ba24b0bc275aa75
|
||||
github.com/containers/storage 41294c85d97bef688e18f710402895dbecde3308
|
||||
github.com/docker/distribution 5f6282db7d65e6d72ad7c2cc66310724a57be716
|
||||
|
||||
Reference in New Issue
Block a user