diff options
author | Matej Vasek <mvasek@redhat.com> | 2021-06-28 21:17:13 +0200 |
---|---|---|
committer | Matej Vasek <mvasek@redhat.com> | 2021-07-01 12:01:46 +0200 |
commit | 86c6014145d5b8d4ea51f338beb9bddaa8b5a334 (patch) | |
tree | 056769253cf35f00bdd46389bddd9c076c31a00e /pkg | |
parent | fd1715568b7c14451dcf2581c385c8d3e307d30e (diff) | |
download | podman-86c6014145d5b8d4ea51f338beb9bddaa8b5a334.tar.gz podman-86c6014145d5b8d4ea51f338beb9bddaa8b5a334.tar.bz2 podman-86c6014145d5b8d4ea51f338beb9bddaa8b5a334.zip |
Implement --archive flag for podman cp
Signed-off-by: Matej Vasek <mvasek@redhat.com>
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/api/handlers/compat/containers_archive.go | 11 | ||||
-rw-r--r-- | pkg/bindings/containers/archive.go | 12 | ||||
-rw-r--r-- | pkg/bindings/containers/types.go | 8 | ||||
-rw-r--r-- | pkg/bindings/containers/types_copy_options.go | 37 | ||||
-rw-r--r-- | pkg/bindings/internal/util/util.go | 10 | ||||
-rw-r--r-- | pkg/domain/entities/containers.go | 7 | ||||
-rw-r--r-- | pkg/domain/entities/engine_container.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/archive.go | 4 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 4 |
9 files changed, 82 insertions, 13 deletions
diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go index e119dc7cb..a9d74e5f4 100644 --- a/pkg/api/handlers/compat/containers_archive.go +++ b/pkg/api/handlers/compat/containers_archive.go @@ -9,6 +9,7 @@ import ( "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/api/handlers/utils" "github.com/containers/podman/v3/pkg/copy" + "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/infra/abi" "github.com/gorilla/schema" "github.com/pkg/errors" @@ -92,11 +93,13 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) { query := struct { - Path string `schema:"path"` + Path string `schema:"path"` + Chown bool `schema:"copyUIDGID"` // TODO handle params below NoOverwriteDirNonDir bool `schema:"noOverwriteDirNonDir"` - CopyUIDGID bool `schema:"copyUIDGID"` - }{} + }{ + Chown: utils.IsLibpodRequest(r), // backward compatibility + } err := decoder.Decode(&query, r.URL.Query()) if err != nil { @@ -107,7 +110,7 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, containerName := utils.GetName(r) containerEngine := abi.ContainerEngine{Libpod: runtime} - copyFunc, err := containerEngine.ContainerCopyFromArchive(r.Context(), containerName, query.Path, r.Body) + copyFunc, err := containerEngine.ContainerCopyFromArchive(r.Context(), containerName, query.Path, r.Body, entities.CopyOptions{Chown: query.Chown}) if errors.Cause(err) == define.ErrNoSuchCtr || os.IsNotExist(err) { // 404 is returned for an absent container and path. The // clients must deal with it accordingly. diff --git a/pkg/bindings/containers/archive.go b/pkg/bindings/containers/archive.go index 0178f63c3..52b73662b 100644 --- a/pkg/bindings/containers/archive.go +++ b/pkg/bindings/containers/archive.go @@ -50,11 +50,21 @@ func Stat(ctx context.Context, nameOrID string, path string) (*entities.Containe } func CopyFromArchive(ctx context.Context, nameOrID string, path string, reader io.Reader) (entities.ContainerCopyFunc, error) { + return CopyFromArchiveWithOptions(ctx, nameOrID, path, reader, nil) +} + +// CopyFromArchiveWithOptions FIXME: remove this function and make CopyFromArchive accept the option as the last parameter in podman 4.0 +func CopyFromArchiveWithOptions(ctx context.Context, nameOrID string, path string, reader io.Reader, options *CopyOptions) (entities.ContainerCopyFunc, error) { conn, err := bindings.GetClient(ctx) if err != nil { return nil, err } - params := url.Values{} + + params, err := options.ToParams() + if err != nil { + return nil, err + } + params.Set("path", path) return func() error { diff --git a/pkg/bindings/containers/types.go b/pkg/bindings/containers/types.go index 0d22c32f8..db710d3da 100644 --- a/pkg/bindings/containers/types.go +++ b/pkg/bindings/containers/types.go @@ -251,3 +251,11 @@ type ExistsOptions struct { // External checks for containers created outside of Podman External *bool } + +//go:generate go run ../generator/generator.go CopyOptions +// CopyOptions are options for copying to containers. +type CopyOptions struct { + // If used with CopyFromArchive and set to true it will change ownership of files from the source tar archive + // to the primary uid/gid of the target container. + Chown *bool `schema:"copyUIDGID"` +} diff --git a/pkg/bindings/containers/types_copy_options.go b/pkg/bindings/containers/types_copy_options.go new file mode 100644 index 000000000..12ad085fd --- /dev/null +++ b/pkg/bindings/containers/types_copy_options.go @@ -0,0 +1,37 @@ +package containers + +import ( + "net/url" + + "github.com/containers/podman/v3/pkg/bindings/internal/util" +) + +/* +This file is generated automatically by go generate. Do not edit. +*/ + +// Changed +func (o *CopyOptions) Changed(fieldName string) bool { + return util.Changed(o, fieldName) +} + +// ToParams +func (o *CopyOptions) ToParams() (url.Values, error) { + return util.ToParams(o) +} + +// WithChown +func (o *CopyOptions) WithChown(value bool) *CopyOptions { + v := &value + o.Chown = v + return o +} + +// GetChown +func (o *CopyOptions) GetChown() bool { + var chown bool + if o.Chown == nil { + return chown + } + return *o.Chown +} diff --git a/pkg/bindings/internal/util/util.go b/pkg/bindings/internal/util/util.go index ef93d6e25..bcf6959f2 100644 --- a/pkg/bindings/internal/util/util.go +++ b/pkg/bindings/internal/util/util.go @@ -72,14 +72,18 @@ func ToParams(o interface{}) (url.Values, error) { if reflect.Ptr == f.Kind() { f = f.Elem() } + paramName := fieldName + if pn, ok := sType.Field(i).Tag.Lookup("schema"); ok { + paramName = pn + } switch { case IsSimpleType(f): - params.Set(fieldName, SimpleTypeToParam(f)) + params.Set(paramName, SimpleTypeToParam(f)) case f.Kind() == reflect.Slice: for i := 0; i < f.Len(); i++ { elem := f.Index(i) if IsSimpleType(elem) { - params.Add(fieldName, SimpleTypeToParam(elem)) + params.Add(paramName, SimpleTypeToParam(elem)) } else { return nil, errors.New("slices must contain only simple types") } @@ -95,7 +99,7 @@ func ToParams(o interface{}) (url.Values, error) { return nil, err } - params.Set(fieldName, s) + params.Set(paramName, s) } } return params, nil diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index 8ed9b9b61..302b35a47 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -160,6 +160,13 @@ type CommitOptions struct { Writer io.Writer } +type CopyOptions struct { + // If used with ContainerCopyFromArchive and set to true + // it will change ownership of files from the source tar archive + // to the primary uid/gid of the destination container. + Chown bool +} + type CommitReport struct { Id string //nolint } diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go index 4cd3cfd2a..1b35135d0 100644 --- a/pkg/domain/entities/engine_container.go +++ b/pkg/domain/entities/engine_container.go @@ -20,7 +20,7 @@ type ContainerEngine interface { ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error) ContainerCleanup(ctx context.Context, namesOrIds []string, options ContainerCleanupOptions) ([]*ContainerCleanupReport, error) ContainerCommit(ctx context.Context, nameOrID string, options CommitOptions) (*CommitReport, error) - ContainerCopyFromArchive(ctx context.Context, nameOrID string, path string, reader io.Reader) (ContainerCopyFunc, error) + ContainerCopyFromArchive(ctx context.Context, nameOrID, path string, reader io.Reader, options CopyOptions) (ContainerCopyFunc, error) ContainerCopyToArchive(ctx context.Context, nameOrID string, path string, writer io.Writer) (ContainerCopyFunc, error) ContainerCreate(ctx context.Context, s *specgen.SpecGenerator) (*ContainerCreateReport, error) ContainerDiff(ctx context.Context, nameOrID string, options DiffOptions) (*DiffReport, error) diff --git a/pkg/domain/infra/abi/archive.go b/pkg/domain/infra/abi/archive.go index 2ea63aa5e..1a5bb6dc4 100644 --- a/pkg/domain/infra/abi/archive.go +++ b/pkg/domain/infra/abi/archive.go @@ -7,12 +7,12 @@ import ( "github.com/containers/podman/v3/pkg/domain/entities" ) -func (ic *ContainerEngine) ContainerCopyFromArchive(ctx context.Context, nameOrID string, containerPath string, reader io.Reader) (entities.ContainerCopyFunc, error) { +func (ic *ContainerEngine) ContainerCopyFromArchive(ctx context.Context, nameOrID, containerPath string, reader io.Reader, options entities.CopyOptions) (entities.ContainerCopyFunc, error) { container, err := ic.Libpod.LookupContainer(nameOrID) if err != nil { return nil, err } - return container.CopyFromArchive(ctx, containerPath, reader) + return container.CopyFromArchive(ctx, containerPath, options.Chown, reader) } func (ic *ContainerEngine) ContainerCopyToArchive(ctx context.Context, nameOrID string, containerPath string, writer io.Writer) (entities.ContainerCopyFunc, error) { diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index ccebfffa4..c02e36804 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -833,8 +833,8 @@ func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrID string, o return reports, nil } -func (ic *ContainerEngine) ContainerCopyFromArchive(ctx context.Context, nameOrID string, path string, reader io.Reader) (entities.ContainerCopyFunc, error) { - return containers.CopyFromArchive(ic.ClientCtx, nameOrID, path, reader) +func (ic *ContainerEngine) ContainerCopyFromArchive(ctx context.Context, nameOrID, path string, reader io.Reader, options entities.CopyOptions) (entities.ContainerCopyFunc, error) { + return containers.CopyFromArchiveWithOptions(ic.ClientCtx, nameOrID, path, reader, new(containers.CopyOptions).WithChown(options.Chown)) } func (ic *ContainerEngine) ContainerCopyToArchive(ctx context.Context, nameOrID string, path string, writer io.Writer) (entities.ContainerCopyFunc, error) { |