Skip to content

Commit 4244440

Browse files
committed
image: support UID/GID mapping options in the storage transport
Add uidMap/gidMap fields to storageReference and storageImageDestination so that callers can specify ID mappings when pulling images. This is the first half of a fix to avoid the expensive post-pull chown that happens when creating containers with user namespace remapping (e.g., --userns=keep-id) when there is no idmapped mount support like in rootless Podman. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
1 parent 8af7873 commit 4244440

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

image/storage/storage_dest.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"go.podman.io/storage/pkg/archive"
3838
"go.podman.io/storage/pkg/chunked"
3939
"go.podman.io/storage/pkg/chunked/toc"
40+
"go.podman.io/storage/pkg/idtools"
4041
"go.podman.io/storage/pkg/ioutils"
4142
)
4243

@@ -58,6 +59,8 @@ type storageImageDestination struct {
5859
stubs.AlwaysSupportsSignatures
5960

6061
imageRef storageReference
62+
uidMap []idtools.IDMap
63+
gidMap []idtools.IDMap
6164
directory string // Temporary directory where we store blobs until Commit() time
6265
nextTempFileID atomic.Int32 // A counter that we use for computing filenames to assign to blobs
6366
manifest []byte // (Per-instance) manifest contents, or nil if not yet known.
@@ -164,6 +167,8 @@ func newImageDestination(sys *types.SystemContext, imageRef storageReference) (*
164167
}),
165168

166169
imageRef: imageRef,
170+
uidMap: imageRef.uidMap,
171+
gidMap: imageRef.gidMap,
167172
directory: directory,
168173
signatureses: make(map[digest.Digest][]byte),
169174
metadata: storageImageMetadata{
@@ -1274,12 +1279,17 @@ func (s *storageImageDestination) createNewLayer(index int, trusted trustedLayer
12741279
defer file.Close()
12751280
// Build the new layer using the diff, regardless of where it came from.
12761281
// TODO: This can take quite some time, and should ideally be cancellable using ctx.Done().
1277-
layer, _, err := s.imageRef.transport.store.PutLayer(newLayerID, parentLayer, nil, "", false, &storage.LayerOptions{
1282+
layerOptions := &storage.LayerOptions{
12781283
OriginalDigest: trustedOriginalDigest,
12791284
OriginalSize: trustedOriginalSize, // nil in many cases
12801285
// This might be "" if trusted.layerIdentifiedByTOC; in that case PutLayer will compute the value from the stream.
12811286
UncompressedDigest: trusted.diffID,
1282-
}, file)
1287+
}
1288+
if len(s.uidMap) > 0 || len(s.gidMap) > 0 {
1289+
layerOptions.UIDMap = s.uidMap
1290+
layerOptions.GIDMap = s.gidMap
1291+
}
1292+
layer, _, err := s.imageRef.transport.store.PutLayer(newLayerID, parentLayer, nil, "", false, layerOptions, file)
12831293
if err != nil && !errors.Is(err, storage.ErrDuplicateID) {
12841294
return nil, fmt.Errorf("adding layer with blob %s: %w", trusted.logString(), err)
12851295
}

image/storage/storage_reference.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"go.podman.io/image/v5/transports"
1616
"go.podman.io/image/v5/types"
1717
"go.podman.io/storage"
18+
"go.podman.io/storage/pkg/idtools"
1819
)
1920

2021
// A storageReference holds an arbitrary name and/or an ID, which is a 32-byte
@@ -25,6 +26,15 @@ type storageReference struct {
2526
transport storageTransport
2627
named reference.Named // may include a tag and/or a digest
2728
id string
29+
uidMap []idtools.IDMap
30+
gidMap []idtools.IDMap
31+
}
32+
33+
// SetIDMappingOptions sets the UID/GID mapping options for the image reference.
34+
// When set, layers created for this image will use these mappings.
35+
func (ref *storageReference) SetIDMappingOptions(uidMap, gidMap []idtools.IDMap) {
36+
ref.uidMap = uidMap
37+
ref.gidMap = gidMap
2838
}
2939

3040
func newReference(transport storageTransport, named reference.Named, id string) (*storageReference, error) {

0 commit comments

Comments
 (0)