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:
baude
2018-10-17 16:42:05 -05:00
parent 19c150bef1
commit bfc473f982
25 changed files with 260 additions and 317 deletions

View File

@ -14,4 +14,4 @@ fi
${CONTAINER_RUNTIME} build -t ${IMAGE} -f Dockerfile.${DIST} . 2>build.log
# Run the tests
${CONTAINER_RUNTIME} run --rm --cap-add all --security-opt seccomp:unconfined --security-opt label:disabled --net=host -v $PWD:/go/src/github.com/containers/libpod:Z --workdir /go/src/github.com/containers/libpod -e CGROUP_MANAGER=cgroupfs -e PYTHON=$PYTHON -e STORAGE_OPTIONS="--storage-driver=vfs" -e CRIO_ROOT="/go/src/github.com/containers/libpod" -e PODMAN_BINARY="/usr/bin/podman" -e CONMON_BINARY="/usr/libexec/podman/conmon" -e DIST=$DIST -e CONTAINER_RUNTIME=$CONTAINER_RUNTIME $IMAGE sh ./.papr.sh -b -i -t
${CONTAINER_RUNTIME} run --rm --cap-add all --security-opt seccomp=unconfined --security-opt label=disable --net=host -v $PWD:/go/src/github.com/containers/libpod:Z --workdir /go/src/github.com/containers/libpod -e CGROUP_MANAGER=cgroupfs -e PYTHON=$PYTHON -e STORAGE_OPTIONS="--storage-driver=vfs" -e CRIO_ROOT="/go/src/github.com/containers/libpod" -e PODMAN_BINARY="/usr/bin/podman" -e CONMON_BINARY="/usr/libexec/podman/conmon" -e DIST=$DIST -e CONTAINER_RUNTIME=$CONTAINER_RUNTIME $IMAGE sh ./.papr.sh -b -i -t

View File

@ -161,7 +161,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
importBuilder.SetWorkDir(splitChange[1])
}
}
candidates, err := util.ResolveName(destImage, "", sc, c.runtime.store)
candidates, _, err := util.ResolveName(destImage, "", sc, c.runtime.store)
if err != nil {
return nil, errors.Wrapf(err, "error resolving name %q", destImage)
}
@ -172,7 +172,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
if err != nil {
return nil, errors.Wrapf(err, "error parsing target image name %q", destImage)
}
id, err := importBuilder.Commit(ctx, imageRef, commitOptions)
id, _, _, err := importBuilder.Commit(ctx, imageRef, commitOptions)
if err != nil {
return nil, err
}

View File

@ -552,7 +552,7 @@ func (i *Image) PushImageToReference(ctx context.Context, dest types.ImageRefere
}
}
// Copy the image to the remote destination
err = cp.Image(ctx, policyContext, dest, src, copyOptions)
_, err = cp.Image(ctx, policyContext, dest, src, copyOptions)
if err != nil {
return errors.Wrapf(err, "Error copying image to the remote destination")
}
@ -912,7 +912,8 @@ func (ir *Runtime) Import(ctx context.Context, path, reference string, writer io
if err != nil {
errors.Wrapf(err, "error getting image reference for %q", reference)
}
if err = cp.Image(ctx, policyContext, dest, src, copyOptions); err != nil {
_, err = cp.Image(ctx, policyContext, dest, src, copyOptions)
if err != nil {
return nil, err
}
return ir.NewFromLocal(reference)

View File

@ -255,7 +255,8 @@ func (ir *Runtime) doPullImage(ctx context.Context, sc *types.SystemContext, goa
if writer != nil && (imageInfo.srcRef.Transport().Name() == DockerTransport || imageInfo.srcRef.Transport().Name() == AtomicTransport) {
io.WriteString(writer, fmt.Sprintf("Trying to pull %s...", imageInfo.image))
}
if err = cp.Image(ctx, policyContext, imageInfo.dstRef, imageInfo.srcRef, copyOptions); err != nil {
_, err = cp.Image(ctx, policyContext, imageInfo.dstRef, imageInfo.srcRef, copyOptions)
if err != nil {
pullErrors = multierror.Append(pullErrors, err)
logrus.Debugf("Error pulling image ref %s: %v", imageInfo.srcRef.StringWithinTransport(), err)
if writer != nil {

View File

@ -164,5 +164,6 @@ func removeStorageContainers(ctrIDs []string, store storage.Store) error {
// Build adds the runtime to the imagebuildah call
func (r *Runtime) Build(ctx context.Context, options imagebuildah.BuildOptions, dockerfiles ...string) error {
return imagebuildah.BuildDockerfiles(ctx, r.store, options, dockerfiles...)
_, _, err := imagebuildah.BuildDockerfiles(ctx, r.store, options, dockerfiles...)
return err
}

View File

@ -160,7 +160,7 @@ func main() {
ctx := context.TODO()
if imageName != "" {
if importFrom != "" {
err = copy.Image(ctx, policyContext, ref, importRef, options)
_, err = copy.Image(ctx, policyContext, ref, importRef, options)
if err != nil {
logrus.Errorf("error importing %s: %v", importFrom, err)
os.Exit(1)
@ -180,7 +180,7 @@ func main() {
}
}
if exportTo != "" {
err = copy.Image(ctx, policyContext, exportRef, ref, options)
_, err = copy.Image(ctx, policyContext, exportRef, ref, options)
if err != nil {
logrus.Errorf("error exporting %s: %v", exportTo, err)
os.Exit(1)
@ -188,7 +188,7 @@ func main() {
}
} else {
if importFrom != "" && exportTo != "" {
err = copy.Image(ctx, policyContext, exportRef, importRef, options)
_, err = copy.Image(ctx, policyContext, exportRef, importRef, options)
if err != nil {
logrus.Errorf("error copying %s to %s: %v", importFrom, exportTo, err)
os.Exit(1)

View File

@ -10,7 +10,7 @@ github.com/containerd/cgroups 58556f5ad8448d99a6f7bea69ea4bdb7747cfeb0
github.com/containerd/continuity master
github.com/containernetworking/cni v0.7.0-alpha1
github.com/containernetworking/plugins 1562a1e60ed101aacc5e08ed9dbeba8e9f3d4ec1
github.com/containers/image 918dbb93e6e099b196b498c38d079f6bb924d0c8
github.com/containers/image bd10b1b53b2976f215b3f2f848fb8e7cad779aeb
github.com/containers/storage 41294c85d97bef688e18f710402895dbecde3308
github.com/containers/psgo 5dde6da0bc8831b35243a847625bcf18183bd1ee
github.com/coreos/go-systemd v14
@ -91,7 +91,7 @@ k8s.io/kube-openapi 275e2ce91dec4c05a4094a7b1daee5560b555ac9 https://github.com/
k8s.io/utils 258e2a2fa64568210fbd6267cf1d8fd87c3cb86e https://github.com/kubernetes/utils
github.com/mrunalp/fileutils master
github.com/varlink/go master
github.com/containers/buildah 9d50d04b9324a22bbb64df9e66b5d9d53ed3daae
github.com/containers/buildah 46c577c87d5a7ab30ef40cfa695cd2b96b32b117
github.com/Nvveen/Gotty master
github.com/fsouza/go-dockerclient master
github.com/openshift/imagebuilder master

View File

@ -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,10 +492,13 @@ 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)
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)
if err == nil && b.Type == containerType {

View File

@ -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
}

View File

@ -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)

View File

@ -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 {
img, err := is.Transport.GetStoreImage(store, ref)
if err == nil {
return ref, img, 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)
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 {
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
}
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)
}
}

View File

@ -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 {
if _, err := cp.Image(ctx, policyContext, destRef, srcRef, getCopyOptions(options.ReportWriter, srcRef, sc, destRef, nil, "")); err != nil {
return nil, err
}
return destRef, nil
}
// 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
}
// getImageDigest creates an image object and uses the hex value of the digest as the image ID

View File

@ -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:

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -53,7 +53,7 @@ are also available
This library, by default, also depends on the GpgME and libostree C libraries. Either install them:
```sh
Fedora$ dnf install gpgme-devel libassuan-devel libostree-devel
Fedora$ dnf install gpgme-devel libassuan-devel ostree-devel
macOS$ brew install gpgme
```
or use the build tags described below to avoid the dependencies (e.g. using `go build -tags …`)

View File

@ -102,8 +102,9 @@ type Options struct {
}
// Image copies image from srcRef to destRef, using policyContext to validate
// source image admissibility.
func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef, srcRef types.ImageReference, options *Options) (retErr error) {
// source image admissibility. It returns the manifest which was written to
// the new copy of the image.
func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef, srcRef types.ImageReference, options *Options) (manifest []byte, retErr error) {
// NOTE this function uses an output parameter for the error return value.
// Setting this and returning is the ideal way to return an error.
//
@ -121,7 +122,7 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef,
dest, err := destRef.NewImageDestination(ctx, options.DestinationCtx)
if err != nil {
return errors.Wrapf(err, "Error initializing destination %s", transports.ImageName(destRef))
return nil, errors.Wrapf(err, "Error initializing destination %s", transports.ImageName(destRef))
}
defer func() {
if err := dest.Close(); err != nil {
@ -131,7 +132,7 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef,
rawSource, err := srcRef.NewImageSource(ctx, options.SourceCtx)
if err != nil {
return errors.Wrapf(err, "Error initializing source %s", transports.ImageName(srcRef))
return nil, errors.Wrapf(err, "Error initializing source %s", transports.ImageName(srcRef))
}
defer func() {
if err := rawSource.Close(); err != nil {
@ -151,63 +152,63 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef,
unparsedToplevel := image.UnparsedInstance(rawSource, nil)
multiImage, err := isMultiImage(ctx, unparsedToplevel)
if err != nil {
return errors.Wrapf(err, "Error determining manifest MIME type for %s", transports.ImageName(srcRef))
return nil, errors.Wrapf(err, "Error determining manifest MIME type for %s", transports.ImageName(srcRef))
}
if !multiImage {
// The simple case: Just copy a single image.
if err := c.copyOneImage(ctx, policyContext, options, unparsedToplevel); err != nil {
return err
if manifest, err = c.copyOneImage(ctx, policyContext, options, unparsedToplevel); err != nil {
return nil, err
}
} else {
// This is a manifest list. Choose a single image and copy it.
// FIXME: Copy to destinations which support manifest lists, one image at a time.
instanceDigest, err := image.ChooseManifestInstanceFromManifestList(ctx, options.SourceCtx, unparsedToplevel)
if err != nil {
return errors.Wrapf(err, "Error choosing an image from manifest list %s", transports.ImageName(srcRef))
return nil, errors.Wrapf(err, "Error choosing an image from manifest list %s", transports.ImageName(srcRef))
}
logrus.Debugf("Source is a manifest list; copying (only) instance %s", instanceDigest)
unparsedInstance := image.UnparsedInstance(rawSource, &instanceDigest)
if err := c.copyOneImage(ctx, policyContext, options, unparsedInstance); err != nil {
return err
if manifest, err = c.copyOneImage(ctx, policyContext, options, unparsedInstance); err != nil {
return nil, err
}
}
if err := c.dest.Commit(ctx); err != nil {
return errors.Wrap(err, "Error committing the finished image")
return nil, errors.Wrap(err, "Error committing the finished image")
}
return nil
return manifest, nil
}
// Image copies a single (on-manifest-list) image unparsedImage, using policyContext to validate
// source image admissibility.
func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.PolicyContext, options *Options, unparsedImage *image.UnparsedImage) (retErr error) {
func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.PolicyContext, options *Options, unparsedImage *image.UnparsedImage) (manifest []byte, retErr error) {
// The caller is handling manifest lists; this could happen only if a manifest list contains a manifest list.
// Make sure we fail cleanly in such cases.
multiImage, err := isMultiImage(ctx, unparsedImage)
if err != nil {
// FIXME FIXME: How to name a reference for the sub-image?
return errors.Wrapf(err, "Error determining manifest MIME type for %s", transports.ImageName(unparsedImage.Reference()))
return nil, errors.Wrapf(err, "Error determining manifest MIME type for %s", transports.ImageName(unparsedImage.Reference()))
}
if multiImage {
return fmt.Errorf("Unexpectedly received a manifest list instead of a manifest for a single image")
return nil, fmt.Errorf("Unexpectedly received a manifest list instead of a manifest for a single image")
}
// Please keep this policy check BEFORE reading any other information about the image.
// (the multiImage check above only matches the MIME type, which we have received anyway.
// Actual parsing of anything should be deferred.)
if allowed, err := policyContext.IsRunningImageAllowed(ctx, unparsedImage); !allowed || err != nil { // Be paranoid and fail if either return value indicates so.
return errors.Wrap(err, "Source image rejected")
return nil, errors.Wrap(err, "Source image rejected")
}
src, err := image.FromUnparsedImage(ctx, options.SourceCtx, unparsedImage)
if err != nil {
return errors.Wrapf(err, "Error initializing image from source %s", transports.ImageName(c.rawSource.Reference()))
return nil, errors.Wrapf(err, "Error initializing image from source %s", transports.ImageName(c.rawSource.Reference()))
}
if err := checkImageDestinationForCurrentRuntimeOS(ctx, options.DestinationCtx, src, c.dest); err != nil {
return err
return nil, err
}
var sigs [][]byte
@ -217,14 +218,14 @@ func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.Poli
c.Printf("Getting image source signatures\n")
s, err := src.Signatures(ctx)
if err != nil {
return errors.Wrap(err, "Error reading signatures")
return nil, errors.Wrap(err, "Error reading signatures")
}
sigs = s
}
if len(sigs) != 0 {
c.Printf("Checking if image destination supports signatures\n")
if err := c.dest.SupportsSignatures(ctx); err != nil {
return errors.Wrap(err, "Can not copy signatures")
return nil, errors.Wrap(err, "Can not copy signatures")
}
}
@ -237,28 +238,28 @@ func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.Poli
}
if err := ic.updateEmbeddedDockerReference(); err != nil {
return err
return nil, err
}
// We compute preferredManifestMIMEType only to show it in error messages.
// Without having to add this context in an error message, we would be happy enough to know only that no conversion is needed.
preferredManifestMIMEType, otherManifestMIMETypeCandidates, err := ic.determineManifestConversion(ctx, c.dest.SupportedManifestMIMETypes(), options.ForceManifestMIMEType)
if err != nil {
return err
return nil, err
}
// If src.UpdatedImageNeedsLayerDiffIDs(ic.manifestUpdates) will be true, it needs to be true by the time we get here.
ic.diffIDsAreNeeded = src.UpdatedImageNeedsLayerDiffIDs(*ic.manifestUpdates)
if err := ic.copyLayers(ctx); err != nil {
return err
return nil, err
}
// With docker/distribution registries we do not know whether the registry accepts schema2 or schema1 only;
// and at least with the OpenShift registry "acceptschema2" option, there is no way to detect the support
// without actually trying to upload something and getting a types.ManifestTypeRejectedError.
// So, try the preferred manifest MIME type. If the process succeeds, fine…
manifest, err := ic.copyUpdatedConfigAndManifest(ctx)
manifest, err = ic.copyUpdatedConfigAndManifest(ctx)
if err != nil {
logrus.Debugf("Writing manifest using preferred type %s failed: %v", preferredManifestMIMEType, err)
// … if it fails, _and_ the failure is because the manifest is rejected, we may have other options.
@ -266,14 +267,14 @@ func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.Poli
// We dont have other options.
// In principle the code below would handle this as well, but the resulting error message is fairly ugly.
// Dont bother the user with MIME types if we have no choice.
return err
return nil, err
}
// If the original MIME type is acceptable, determineManifestConversion always uses it as preferredManifestMIMEType.
// So if we are here, we will definitely be trying to convert the manifest.
// With !ic.canModifyManifest, that would just be a string of repeated failures for the same reason,
// so lets bail out early and with a better error message.
if !ic.canModifyManifest {
return errors.Wrap(err, "Writing manifest failed (and converting it is not possible)")
return nil, errors.Wrap(err, "Writing manifest failed (and converting it is not possible)")
}
// errs is a list of errors when trying various manifest types. Also serves as an "upload succeeded" flag when set to nil.
@ -294,24 +295,24 @@ func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.Poli
break
}
if errs != nil {
return fmt.Errorf("Uploading manifest failed, attempted the following formats: %s", strings.Join(errs, ", "))
return nil, fmt.Errorf("Uploading manifest failed, attempted the following formats: %s", strings.Join(errs, ", "))
}
}
if options.SignBy != "" {
newSig, err := c.createSignature(manifest, options.SignBy)
if err != nil {
return err
return nil, err
}
sigs = append(sigs, newSig)
}
c.Printf("Storing signatures\n")
if err := c.dest.PutSignatures(ctx, sigs); err != nil {
return errors.Wrap(err, "Error writing signatures")
return nil, errors.Wrap(err, "Error writing signatures")
}
return nil
return manifest, nil
}
// Printf writes a formatted string to c.reportWriter.

View File

@ -275,7 +275,7 @@ func (m *Schema1) ToSchema2Config(diffIDs []digest.Digest) ([]byte, error) {
raw := make(map[string]*json.RawMessage)
err = json.Unmarshal(config, &raw)
if err != nil {
return nil, errors.Wrapf(err, "error re-decoding compat image config %#v: %v", s1)
return nil, errors.Wrapf(err, "error re-decoding compat image config %#v", s1)
}
// Drop some fields.
delete(raw, "id")

View File

@ -25,7 +25,7 @@ func newImageDestination(ctx context.Context, sys *types.SystemContext, ref ociA
unpackedDest, err := tempDirRef.ociRefExtracted.NewImageDestination(ctx, sys)
if err != nil {
if err := tempDirRef.deleteTempDir(); err != nil {
return nil, errors.Wrapf(err, "error deleting temp directory", tempDirRef.tempDirectory)
return nil, errors.Wrapf(err, "error deleting temp directory %q", tempDirRef.tempDirectory)
}
return nil, err
}

View File

@ -28,7 +28,7 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref ociArchiv
unpackedSrc, err := tempDirRef.ociRefExtracted.NewImageSource(ctx, sys)
if err != nil {
if err := tempDirRef.deleteTempDir(); err != nil {
return nil, errors.Wrapf(err, "error deleting temp directory", tempDirRef.tempDirectory)
return nil, errors.Wrapf(err, "error deleting temp directory %q", tempDirRef.tempDirectory)
}
return nil, err
}

View File

@ -96,7 +96,7 @@ func (c *openshiftClient) doRequest(ctx context.Context, method, path string, re
req.Header.Set("Content-Type", "application/json")
}
logrus.Debugf("%s %s", method, url)
logrus.Debugf("%s %s", method, url.String())
res, err := c.httpClient.Do(req)
if err != nil {
return nil, err

View File

@ -141,6 +141,10 @@ func parseURL(input string) (string, error) {
// registries of type Registry.
func getV1Registries(config *tomlConfig) ([]Registry, error) {
regMap := make(map[string]*Registry)
// We must preserve the order of config.V1Registries.Search.Registries at least. The order of the
// other registries is not really important, but make it deterministic (the same for the same config file)
// to minimize behavior inconsistency and not contribute to difficult-to-reproduce situations.
registryOrder := []string{}
getRegistry := func(url string) (*Registry, error) { // Note: _pointer_ to a long-lived object
var err error
@ -156,10 +160,13 @@ func getV1Registries(config *tomlConfig) ([]Registry, error) {
Prefix: url,
}
regMap[url] = reg
registryOrder = append(registryOrder, url)
}
return reg, nil
}
// Note: config.V1Registries.Search needs to be processed first to ensure registryOrder is populated in the right order
// if one of the search registries is also in one of the other lists.
for _, search := range config.V1Registries.Search.Registries {
reg, err := getRegistry(search)
if err != nil {
@ -183,7 +190,8 @@ func getV1Registries(config *tomlConfig) ([]Registry, error) {
}
registries := []Registry{}
for _, reg := range regMap {
for _, url := range registryOrder {
reg := regMap[url]
registries = append(registries, *reg)
}
return registries, nil

View File

@ -107,7 +107,7 @@ func (s *storageTransport) DefaultGIDMap() []idtools.IDMap {
// relative to the given store, and returns it in a reference object.
func (s storageTransport) ParseStoreReference(store storage.Store, ref string) (*storageReference, error) {
if ref == "" {
return nil, errors.Wrapf(ErrInvalidReference, "%q is an empty reference")
return nil, errors.Wrapf(ErrInvalidReference, "%q is an empty reference", ref)
}
if ref[0] == '[' {
// Ignore the store specifier.

View File

@ -1,97 +0,0 @@
// +build ignore
// Simple tool to create an archive stream from an old and new directory
//
// By default it will stream the comparison of two temporary directories with junk files
package main
import (
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"github.com/containers/storage/pkg/archive"
"github.com/sirupsen/logrus"
)
var (
flDebug = flag.Bool("D", false, "debugging output")
flNewDir = flag.String("newdir", "", "")
flOldDir = flag.String("olddir", "", "")
log = logrus.New()
)
func main() {
flag.Usage = func() {
fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)")
fmt.Printf("%s [OPTIONS]\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
log.Out = os.Stderr
if (len(os.Getenv("DEBUG")) > 0) || *flDebug {
logrus.SetLevel(logrus.DebugLevel)
}
var newDir, oldDir string
if len(*flNewDir) == 0 {
var err error
newDir, err = ioutil.TempDir("", "storage-test-newDir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(newDir)
if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil {
log.Fatal(err)
}
} else {
newDir = *flNewDir
}
if len(*flOldDir) == 0 {
oldDir, err := ioutil.TempDir("", "storage-test-oldDir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(oldDir)
} else {
oldDir = *flOldDir
}
changes, err := archive.ChangesDirs(newDir, oldDir)
if err != nil {
log.Fatal(err)
}
a, err := archive.ExportChanges(newDir, changes)
if err != nil {
log.Fatal(err)
}
defer a.Close()
i, err := io.Copy(os.Stdout, a)
if err != nil && err != io.EOF {
log.Fatal(err)
}
fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i)
}
func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) {
fileData := []byte("fooo")
for n := 0; n < numberOfFiles; n++ {
fileName := fmt.Sprintf("file-%d", n)
if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
return 0, err
}
if makeLinks {
if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil {
return 0, err
}
}
}
totalSize := numberOfFiles * len(fileData)
return totalSize, nil
}