Allow rootless users to use the cache directory in homedir

Currently rootless podman attempts to write to /var/lib/containers/cache
and fails. This causes us to repeatedly push images that have already been
pushed.  This cache directory should be relative to the location of containers/storage
and not always stored in the same directory.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1411
Approved by: TomSweeneyRedHat
This commit is contained in:
Daniel J Walsh 2019-03-13 16:03:13 -04:00 committed by Atomic Bot
parent 26bc8fb769
commit 939de6f4d9
10 changed files with 54 additions and 39 deletions

View File

@ -336,10 +336,10 @@ type BuilderOptions struct {
// needs to be pulled and the image name alone can not be resolved to a
// reference to a source image. No separator is implicitly added.
Registry string
// PullBlobDirectory is the name of a directory in which we'll attempt
// BlobDirectory is the name of a directory in which we'll attempt
// to store copies of layer blobs that we pull down, if any. It should
// already exist.
PullBlobDirectory string
BlobDirectory string
// Mount signals to NewBuilder() that the container should be mounted
// immediately.
Mount bool

View File

@ -183,6 +183,11 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budResults) error {
if err != nil {
return errors.Wrapf(err, "error building system context")
}
if iopts.BlobCache != "" {
systemContext.BlobInfoCacheDir = iopts.BlobCache
} else {
systemContext.BlobInfoCacheDir = filepath.Join(store.GraphRoot(), "cache")
}
isolation, err := parse.IsolationOption(c)
if err != nil {

View File

@ -156,6 +156,7 @@ func commitCmd(c *cobra.Command, args []string, iopts commitInputOptions) error
Squash: iopts.squash,
BlobDirectory: iopts.blobCache,
OmitTimestamp: iopts.omitTimestamp,
Store: store,
}
if !iopts.quiet {
options.ReportWriter = os.Stderr

View File

@ -226,7 +226,7 @@ func fromCmd(c *cobra.Command, args []string, iopts fromReply) error {
DropCapabilities: iopts.CapDrop,
CommonBuildOpts: commonOpts,
Format: format,
PullBlobDirectory: iopts.BlobCache,
BlobDirectory: iopts.BlobCache,
}
if !iopts.quiet {

View File

@ -71,6 +71,9 @@ type CommitOptions struct {
// OmitTimestamp forces epoch 0 as created timestamp to allow for
// deterministic, content-addressable builds.
OmitTimestamp bool
// Store is the local storage store which holds the source image.
Store storage.Store
}
// PushOptions can be used to alter how an image is copied somewhere.
@ -114,7 +117,7 @@ type PushOptions struct {
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)
systemContext := getSystemContext(options.Store, options.SystemContext, options.SignaturePolicyPath)
blocked, err := isReferenceBlocked(dest, systemContext)
if err != nil {
@ -178,7 +181,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
systemContext.DirForceCompress = true
}
var manifestBytes []byte
if manifestBytes, err = cp.Image(ctx, policyContext, maybeCachedDest, maybeCachedSrc, getCopyOptions(options.ReportWriter, maybeCachedSrc, nil, maybeCachedDest, systemContext, "")); err != nil {
if manifestBytes, err = cp.Image(ctx, policyContext, maybeCachedDest, maybeCachedSrc, getCopyOptions(options.Store, options.ReportWriter, maybeCachedSrc, nil, maybeCachedDest, systemContext, "")); err != nil {
return imgID, nil, "", errors.Wrapf(err, "error copying layers and metadata for container %q", b.ContainerID)
}
if len(options.AdditionalTags) > 0 {
@ -230,7 +233,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
// Push copies the contents of the image to a new location.
func Push(ctx context.Context, image string, dest types.ImageReference, options PushOptions) (reference.Canonical, digest.Digest, error) {
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
systemContext := getSystemContext(options.Store, options.SystemContext, options.SignaturePolicyPath)
if options.Quiet {
options.ReportWriter = nil // Turns off logging output
@ -266,6 +269,7 @@ func Push(ctx context.Context, image string, dest types.ImageReference, options
if err != nil {
return nil, "", errors.Wrapf(err, "error wrapping image reference %q in blob cache at %q", transports.ImageName(src), options.BlobDirectory)
}
systemContext.BlobInfoCacheDir = options.BlobDirectory
maybeCachedSrc = cache
}
// Copy everything.
@ -276,7 +280,7 @@ func Push(ctx context.Context, image string, dest types.ImageReference, options
systemContext.DirForceCompress = true
}
var manifestBytes []byte
if manifestBytes, err = cp.Image(ctx, policyContext, dest, maybeCachedSrc, getCopyOptions(options.ReportWriter, maybeCachedSrc, nil, dest, systemContext, options.ManifestType)); err != nil {
if manifestBytes, err = cp.Image(ctx, policyContext, dest, maybeCachedSrc, getCopyOptions(options.Store, options.ReportWriter, maybeCachedSrc, nil, dest, systemContext, options.ManifestType)); err != nil {
return nil, "", errors.Wrapf(err, "error copying layers and metadata from %q to %q", transports.ImageName(maybeCachedSrc), transports.ImageName(dest))
}
if options.ReportWriter != nil {

View File

@ -8,6 +8,7 @@ import (
cp "github.com/containers/image/copy"
"github.com/containers/image/types"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage"
)
const (
@ -17,31 +18,15 @@ const (
DOCKER = "docker"
)
// userRegistriesFile is the path to the per user registry configuration file.
var userRegistriesFile = filepath.Join(os.Getenv("HOME"), ".config/containers/registries.conf")
func getCopyOptions(reportWriter io.Writer, sourceReference types.ImageReference, sourceSystemContext *types.SystemContext, destinationReference types.ImageReference, destinationSystemContext *types.SystemContext, manifestType string) *cp.Options {
sourceCtx := &types.SystemContext{}
func getCopyOptions(store storage.Store, reportWriter io.Writer, sourceReference types.ImageReference, sourceSystemContext *types.SystemContext, destinationReference types.ImageReference, destinationSystemContext *types.SystemContext, manifestType string) *cp.Options {
sourceCtx := getSystemContext(store, nil, "")
if sourceSystemContext != nil {
*sourceCtx = *sourceSystemContext
} else {
if rootless.IsRootless() {
if _, err := os.Stat(userRegistriesFile); err == nil {
sourceCtx.SystemRegistriesConfPath = userRegistriesFile
}
}
}
destinationCtx := &types.SystemContext{}
destinationCtx := getSystemContext(store, nil, "")
if destinationSystemContext != nil {
*destinationCtx = *destinationSystemContext
} else {
if rootless.IsRootless() {
if _, err := os.Stat(userRegistriesFile); err == nil {
destinationCtx.SystemRegistriesConfPath = userRegistriesFile
}
}
}
return &cp.Options{
@ -52,7 +37,7 @@ func getCopyOptions(reportWriter io.Writer, sourceReference types.ImageReference
}
}
func getSystemContext(defaults *types.SystemContext, signaturePolicyPath string) *types.SystemContext {
func getSystemContext(store storage.Store, defaults *types.SystemContext, signaturePolicyPath string) *types.SystemContext {
sc := &types.SystemContext{}
if defaults != nil {
*sc = *defaults
@ -60,11 +45,16 @@ func getSystemContext(defaults *types.SystemContext, signaturePolicyPath string)
if signaturePolicyPath != "" {
sc.SignaturePolicyPath = signaturePolicyPath
}
if sc.SystemRegistriesConfPath == "" && rootless.IsRootless() {
if _, err := os.Stat(userRegistriesFile); err == nil {
sc.SystemRegistriesConfPath = userRegistriesFile
if store != nil {
if sc.BlobInfoCacheDir == "" {
sc.BlobInfoCacheDir = filepath.Join(store.GraphRoot(), "cache")
}
if sc.SystemRegistriesConfPath == "" && rootless.IsRootless() {
userRegistriesFile := filepath.Join(store.GraphRoot(), "registries.conf")
if _, err := os.Stat(userRegistriesFile); err == nil {
sc.SystemRegistriesConfPath = userRegistriesFile
}
}
}
return sc
}

View File

@ -666,7 +666,7 @@ func (b *Executor) Prepare(ctx context.Context, stage imagebuilder.Stage, from s
FromImage: from,
PullPolicy: b.pullPolicy,
Registry: b.registry,
PullBlobDirectory: b.blobDirectory,
BlobDirectory: b.blobDirectory,
SignaturePolicyPath: b.signaturePolicyPath,
ReportWriter: b.reportWriter,
SystemContext: b.systemContext,

View File

@ -83,7 +83,7 @@ func importBuilder(ctx context.Context, store storage.Store, options ImportOptio
return nil, err
}
systemContext := getSystemContext(&types.SystemContext{}, options.SignaturePolicyPath)
systemContext := getSystemContext(store, &types.SystemContext{}, options.SignaturePolicyPath)
builder, err := importBuilderDataFromImage(ctx, store, systemContext, c.ImageID, options.Container, c.ID)
if err != nil {
@ -115,7 +115,7 @@ func importBuilderFromImage(ctx context.Context, store storage.Store, options Im
return nil, errors.Errorf("image name must be specified")
}
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
systemContext := getSystemContext(store, options.SystemContext, options.SignaturePolicyPath)
_, img, err := util.FindImage(store, "", systemContext, options.Image)
if err != nil {

10
new.go
View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"math/rand"
"path/filepath"
"strings"
"github.com/containers/buildah/util"
@ -29,7 +30,7 @@ func pullAndFindImage(ctx context.Context, store storage.Store, srcRef types.Ima
ReportWriter: options.ReportWriter,
Store: store,
SystemContext: options.SystemContext,
BlobDirectory: options.PullBlobDirectory,
BlobDirectory: options.BlobDirectory,
}
ref, err := pullImage(ctx, store, srcRef, pullOptions, sc)
if err != nil {
@ -244,7 +245,12 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
options.FromImage = ""
}
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
systemContext := getSystemContext(store, options.SystemContext, options.SignaturePolicyPath)
if options.BlobDirectory != "" {
systemContext.BlobInfoCacheDir = options.BlobDirectory
} else {
systemContext.BlobInfoCacheDir = filepath.Join(store.GraphRoot(), "cache")
}
if options.FromImage != "" && options.FromImage != "scratch" {
ref, _, img, err = resolveImage(ctx, systemContext, store, options)

15
pull.go
View File

@ -4,6 +4,8 @@ import (
"context"
"fmt"
"io"
"path/filepath"
"strings"
"github.com/containers/buildah/pkg/blobcache"
@ -153,15 +155,22 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef
// Pull copies the contents of the image from somewhere else to local storage.
func Pull(ctx context.Context, imageName string, options PullOptions) error {
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
systemContext := getSystemContext(options.Store, options.SystemContext, options.SignaturePolicyPath)
boptions := BuilderOptions{
FromImage: imageName,
SignaturePolicyPath: options.SignaturePolicyPath,
SystemContext: systemContext,
PullBlobDirectory: options.BlobDirectory,
BlobDirectory: options.BlobDirectory,
ReportWriter: options.ReportWriter,
}
if options.BlobDirectory != "" {
systemContext.BlobInfoCacheDir = options.BlobDirectory
} else {
if systemContext.BlobInfoCacheDir != "" {
systemContext.BlobInfoCacheDir = filepath.Join(options.Store.GraphRoot(), "cache")
}
}
storageRef, transport, img, err := resolveImage(ctx, systemContext, options.Store, boptions)
if err != nil {
@ -262,7 +271,7 @@ func pullImage(ctx context.Context, store storage.Store, srcRef types.ImageRefer
}()
logrus.Debugf("copying %q to %q", transports.ImageName(srcRef), destName)
if _, err := cp.Image(ctx, policyContext, maybeCachedDestRef, srcRef, getCopyOptions(options.ReportWriter, srcRef, sc, maybeCachedDestRef, nil, "")); err != nil {
if _, err := cp.Image(ctx, policyContext, maybeCachedDestRef, srcRef, getCopyOptions(store, options.ReportWriter, srcRef, sc, maybeCachedDestRef, nil, "")); err != nil {
logrus.Debugf("error copying src image [%q] to dest image [%q] err: %v", transports.ImageName(srcRef), destName, err)
return nil, err
}