archive: add ChownOpts support to TarWithOptions

Signed-off-by: Sébastien HOUZÉ <cto@verylastroom.com>
This commit is contained in:
Sébastien HOUZÉ 2017-08-22 02:17:46 +02:00
parent cdf870bd0b
commit 8a34c67a7e
No known key found for this signature in database
GPG Key ID: F81C9EA3F8C13DF0
3 changed files with 63 additions and 2 deletions

View File

@ -382,6 +382,7 @@ type tarAppender struct {
// for hardlink mapping
SeenFiles map[uint64]string
IDMappings *idtools.IDMappings
ChownOpts *idtools.IDPair
// For packing and unpacking whiteout files in the
// non standard format. The whiteout files defined
@ -390,12 +391,13 @@ type tarAppender struct {
WhiteoutConverter tarWhiteoutConverter
}
func newTarAppender(idMapping *idtools.IDMappings, writer io.Writer) *tarAppender {
func newTarAppender(idMapping *idtools.IDMappings, writer io.Writer, chownOpts *idtools.IDPair) *tarAppender {
return &tarAppender{
SeenFiles: make(map[uint64]string),
TarWriter: tar.NewWriter(writer),
Buffer: pools.BufioWriter32KPool.Get(nil),
IDMappings: idMapping,
ChownOpts: chownOpts,
}
}
@ -470,6 +472,12 @@ func (ta *tarAppender) addTarFile(path, name string) error {
}
}
// explicitly override with ChownOpts
if ta.ChownOpts != nil {
hdr.Uid = ta.ChownOpts.UID
hdr.Gid = ta.ChownOpts.GID
}
if ta.WhiteoutConverter != nil {
wo, err := ta.WhiteoutConverter.ConvertWrite(hdr, path, fi)
if err != nil {
@ -692,6 +700,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
ta := newTarAppender(
idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps),
compressWriter,
options.ChownOpts,
)
ta.WhiteoutConverter = getWhiteoutConverter(options.WhiteoutFormat)

View File

@ -14,6 +14,7 @@ import (
"testing"
"time"
"github.com/docker/docker/pkg/idtools"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -724,6 +725,57 @@ func TestTarUntar(t *testing.T) {
}
}
func TestTarWithOptionsChownOptsAlwaysOverridesIdPair(t *testing.T) {
origin, err := ioutil.TempDir("", "docker-test-tar-chown-opt")
require.NoError(t, err)
defer os.RemoveAll(origin)
filePath := filepath.Join(origin, "1")
err = ioutil.WriteFile(filePath, []byte("hello world"), 0700)
require.NoError(t, err)
idMaps := []idtools.IDMap{
0: {
ContainerID: 0,
HostID: 0,
Size: 65536,
},
1: {
ContainerID: 0,
HostID: 100000,
Size: 65536,
},
}
cases := []struct {
opts *TarOptions
expectedUID int
expectedGID int
}{
{&TarOptions{ChownOpts: &idtools.IDPair{UID: 1337, GID: 42}}, 1337, 42},
{&TarOptions{ChownOpts: &idtools.IDPair{UID: 100001, GID: 100001}, UIDMaps: idMaps, GIDMaps: idMaps}, 100001, 100001},
{&TarOptions{ChownOpts: &idtools.IDPair{UID: 0, GID: 0}, NoLchown: false}, 0, 0},
{&TarOptions{ChownOpts: &idtools.IDPair{UID: 1, GID: 1}, NoLchown: true}, 1, 1},
{&TarOptions{ChownOpts: &idtools.IDPair{UID: 1000, GID: 1000}, NoLchown: true}, 1000, 1000},
}
for _, testCase := range cases {
reader, err := TarWithOptions(filePath, testCase.opts)
require.NoError(t, err)
tr := tar.NewReader(reader)
defer reader.Close()
for {
hdr, err := tr.Next()
if err == io.EOF {
// end of tar archive
break
}
require.NoError(t, err)
assert.Equal(t, hdr.Uid, testCase.expectedUID, "Uid equals expected value")
assert.Equal(t, hdr.Gid, testCase.expectedGID, "Gid equals expected value")
}
}
}
func TestTarWithOptions(t *testing.T) {
// TODO Windows: Figure out how to fix this test.
if runtime.GOOS == "windows" {

View File

@ -394,7 +394,7 @@ func ChangesSize(newDir string, changes []Change) int64 {
func ExportChanges(dir string, changes []Change, uidMaps, gidMaps []idtools.IDMap) (io.ReadCloser, error) {
reader, writer := io.Pipe()
go func() {
ta := newTarAppender(idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), writer)
ta := newTarAppender(idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), writer, nil)
// this buffer is needed for the duration of this piped stream
defer pools.BufioWriter32KPool.Put(ta.Buffer)