From 1cc1e893ecfb43da5d873c31adc5f170417777c6 Mon Sep 17 00:00:00 2001 From: zc Date: Thu, 23 Sep 2021 00:13:52 +0800 Subject: [PATCH] runtime CopyFrom/CopyTo support uid, gid, mode --- engine/docker/container.go | 20 +++++++++------- engine/docker/tarfile.go | 15 +++++------- engine/engine.go | 4 ++-- engine/mocks/API.go | 48 ++++++++++++++++++++++++-------------- engine/virt/virt.go | 13 ++++++----- 5 files changed, 58 insertions(+), 42 deletions(-) diff --git a/engine/docker/container.go b/engine/docker/container.go index b04767b7b..2f47f04f4 100644 --- a/engine/docker/container.go +++ b/engine/docker/container.go @@ -320,13 +320,13 @@ func (e *Engine) VirtualizationResourceRemap(ctx context.Context, opts *enginety } // VirtualizationCopyTo copy things to virtualization -func (e *Engine) VirtualizationCopyTo(ctx context.Context, ID, target string, content io.Reader, AllowOverwriteDirWithFile, CopyUIDGID bool) error { - return withTarfileDump(ctx, target, content, func(target, tarfile string) error { +func (e *Engine) VirtualizationCopyTo(ctx context.Context, ID, target string, content []byte, uid, gid int, mode int64) error { + return withTarfileDump(ctx, target, content, uid, gid, mode, func(target, tarfile string) error { content, err := os.Open(tarfile) if err != nil { return err } - return e.client.CopyToContainer(ctx, ID, filepath.Dir(target), content, dockertypes.CopyToContainerOptions{AllowOverwriteDirWithFile: AllowOverwriteDirWithFile, CopyUIDGID: CopyUIDGID}) + return e.client.CopyToContainer(ctx, ID, filepath.Dir(target), content, dockertypes.CopyToContainerOptions{AllowOverwriteDirWithFile: true, CopyUIDGID: false}) }) } @@ -487,12 +487,16 @@ func (e *Engine) VirtualizationUpdateResource(ctx context.Context, ID string, op } // VirtualizationCopyFrom copy thing from a virtualization -func (e *Engine) VirtualizationCopyFrom(ctx context.Context, ID, path string) (io.ReadCloser, string, error) { - resp, stat, err := e.client.CopyFromContainer(ctx, ID, path) +func (e *Engine) VirtualizationCopyFrom(ctx context.Context, ID, path string) (content []byte, uid, gid int, mode int64, err error) { + resp, _, err := e.client.CopyFromContainer(ctx, ID, path) if err != nil { - return nil, "", err + return } tarReader := tar.NewReader(resp) - _, err = tarReader.Next() - return ioutil.NopCloser(tarReader), stat.Name, errors.Wrapf(err, "read tarball from docker API failed: %s", path) + header, err := tarReader.Next() + if err != nil { + return + } + content, err = ioutil.ReadAll(tarReader) + return content, header.Uid, header.Gid, header.Mode, err } diff --git a/engine/docker/tarfile.go b/engine/docker/tarfile.go index 7e9c2363c..4d516bb31 100644 --- a/engine/docker/tarfile.go +++ b/engine/docker/tarfile.go @@ -3,7 +3,6 @@ package docker import ( "archive/tar" "context" - "io" "io/ioutil" "os" "path/filepath" @@ -11,12 +10,8 @@ import ( "github.com/projecteru2/core/log" ) -func withTarfileDump(ctx context.Context, target string, content io.Reader, f func(target, tarfile string) error) error { - bytes, err := ioutil.ReadAll(content) - if err != nil { - return err - } - tarfile, err := tempTarFile(target, bytes) +func withTarfileDump(ctx context.Context, target string, content []byte, uid, gid int, mode int64, f func(target, tarfile string) error) error { + tarfile, err := tempTarFile(target, content, uid, gid, mode) defer func(tarfile string) { if err := os.RemoveAll(tarfile); err != nil { @@ -30,7 +25,7 @@ func withTarfileDump(ctx context.Context, target string, content io.Reader, f fu return f(target, tarfile) } -func tempTarFile(path string, data []byte) (string, error) { +func tempTarFile(path string, data []byte, uid, gid int, mode int64) (string, error) { filename := filepath.Base(path) f, err := ioutil.TempFile(os.TempDir(), filename) if err != nil { @@ -43,8 +38,10 @@ func tempTarFile(path string, data []byte) (string, error) { defer tw.Close() hdr := &tar.Header{ Name: filename, - Mode: 0755, Size: int64(len(data)), + Mode: int64(mode), + Uid: int(uid), + Gid: int(gid), } if err := tw.WriteHeader(hdr); err != nil { return name, err diff --git a/engine/engine.go b/engine/engine.go index 68a79e6f4..22720692f 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -37,7 +37,7 @@ type API interface { VirtualizationCreate(ctx context.Context, opts *enginetypes.VirtualizationCreateOptions) (*enginetypes.VirtualizationCreated, error) VirtualizationResourceRemap(context.Context, *enginetypes.VirtualizationRemapOptions) (<-chan enginetypes.VirtualizationRemapMessage, error) - VirtualizationCopyTo(ctx context.Context, ID, target string, content io.Reader, AllowOverwriteDirWithFile, CopyUIDGID bool) error + VirtualizationCopyTo(ctx context.Context, ID, target string, content []byte, uid, gid int, mode int64) error VirtualizationStart(ctx context.Context, ID string) error VirtualizationStop(ctx context.Context, ID string, gracefulTimeout time.Duration) error VirtualizationRemove(ctx context.Context, ID string, volumes, force bool) error @@ -47,7 +47,7 @@ type API interface { VirtualizationResize(ctx context.Context, ID string, height, width uint) error VirtualizationWait(ctx context.Context, ID, state string) (*enginetypes.VirtualizationWaitResult, error) VirtualizationUpdateResource(ctx context.Context, ID string, opts *enginetypes.VirtualizationResource) error - VirtualizationCopyFrom(ctx context.Context, ID, path string) (io.ReadCloser, string, error) + VirtualizationCopyFrom(ctx context.Context, ID, path string) (content []byte, uid, gid int, mode int64, _ error) ResourceValidate(ctx context.Context, cpu float64, cpumap map[string]int64, memory, storage int64) error } diff --git a/engine/mocks/API.go b/engine/mocks/API.go index d06565d28..f2bd176ab 100644 --- a/engine/mocks/API.go +++ b/engine/mocks/API.go @@ -1,4 +1,4 @@ -// Code generated by mockery 2.9.0. DO NOT EDIT. +// Code generated by mockery v2.8.0. DO NOT EDIT. package mocks @@ -504,42 +504,56 @@ func (_m *API) VirtualizationAttach(ctx context.Context, ID string, stream bool, } // VirtualizationCopyFrom provides a mock function with given fields: ctx, ID, path -func (_m *API) VirtualizationCopyFrom(ctx context.Context, ID string, path string) (io.ReadCloser, string, error) { +func (_m *API) VirtualizationCopyFrom(ctx context.Context, ID string, path string) ([]byte, int, int, int64, error) { ret := _m.Called(ctx, ID, path) - var r0 io.ReadCloser - if rf, ok := ret.Get(0).(func(context.Context, string, string) io.ReadCloser); ok { + var r0 []byte + if rf, ok := ret.Get(0).(func(context.Context, string, string) []byte); ok { r0 = rf(ctx, ID, path) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(io.ReadCloser) + r0 = ret.Get(0).([]byte) } } - var r1 string - if rf, ok := ret.Get(1).(func(context.Context, string, string) string); ok { + var r1 int + if rf, ok := ret.Get(1).(func(context.Context, string, string) int); ok { r1 = rf(ctx, ID, path) } else { - r1 = ret.Get(1).(string) + r1 = ret.Get(1).(int) } - var r2 error - if rf, ok := ret.Get(2).(func(context.Context, string, string) error); ok { + var r2 int + if rf, ok := ret.Get(2).(func(context.Context, string, string) int); ok { r2 = rf(ctx, ID, path) } else { - r2 = ret.Error(2) + r2 = ret.Get(2).(int) } - return r0, r1, r2 + var r3 int64 + if rf, ok := ret.Get(3).(func(context.Context, string, string) int64); ok { + r3 = rf(ctx, ID, path) + } else { + r3 = ret.Get(3).(int64) + } + + var r4 error + if rf, ok := ret.Get(4).(func(context.Context, string, string) error); ok { + r4 = rf(ctx, ID, path) + } else { + r4 = ret.Error(4) + } + + return r0, r1, r2, r3, r4 } -// VirtualizationCopyTo provides a mock function with given fields: ctx, ID, target, content, AllowOverwriteDirWithFile, CopyUIDGID -func (_m *API) VirtualizationCopyTo(ctx context.Context, ID string, target string, content io.Reader, AllowOverwriteDirWithFile bool, CopyUIDGID bool) error { - ret := _m.Called(ctx, ID, target, content, AllowOverwriteDirWithFile, CopyUIDGID) +// VirtualizationCopyTo provides a mock function with given fields: ctx, ID, target, content, uid, gid, mode +func (_m *API) VirtualizationCopyTo(ctx context.Context, ID string, target string, content []byte, uid int, gid int, mode int64) error { + ret := _m.Called(ctx, ID, target, content, uid, gid, mode) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, bool, bool) error); ok { - r0 = rf(ctx, ID, target, content, AllowOverwriteDirWithFile, CopyUIDGID) + if rf, ok := ret.Get(0).(func(context.Context, string, string, []byte, int, int, int64) error); ok { + r0 = rf(ctx, ID, target, content, uid, gid, mode) } else { r0 = ret.Error(0) } diff --git a/engine/virt/virt.go b/engine/virt/virt.go index 97f2d12bb..cc5094fdb 100644 --- a/engine/virt/virt.go +++ b/engine/virt/virt.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "io/ioutil" - "path/filepath" "strings" "time" @@ -179,8 +178,8 @@ func (v *Virt) VirtualizationResourceRemap(ctx context.Context, opts *enginetype } // VirtualizationCopyTo copies one. -func (v *Virt) VirtualizationCopyTo(ctx context.Context, ID, dest string, content io.Reader, AllowOverwriteDirWithFile, CopyUIDGID bool) error { - return v.client.CopyToGuest(ctx, ID, dest, content, AllowOverwriteDirWithFile, CopyUIDGID) +func (v *Virt) VirtualizationCopyTo(ctx context.Context, ID, dest string, content []byte, uid, gid int, mode int64) error { + return v.client.CopyToGuest(ctx, ID, dest, bytes.NewReader(content), true, true) } // VirtualizationStart boots a guest. @@ -261,12 +260,14 @@ func (v *Virt) VirtualizationUpdateResource(ctx context.Context, ID string, opts } // VirtualizationCopyFrom copies file content from the container. -func (v *Virt) VirtualizationCopyFrom(ctx context.Context, ID, path string) (io.ReadCloser, string, error) { +func (v *Virt) VirtualizationCopyFrom(ctx context.Context, ID, path string) (content []byte, uid, gid int, mode int64, err error) { + // TODO@zc: virt shall return the properties too rd, err := v.client.Cat(ctx, ID, path) if err != nil { - return nil, "", err + return } - return ioutil.NopCloser(rd), filepath.Base(path), nil + content, err = ioutil.ReadAll(rd) + return } // VirtualizationExecute executes commands in running virtual unit