mirror of https://github.com/containers/podman.git
pkg/copy: add parsing API
Add an API for parsing user input into a possibly specified container and path. This allows for sharing the parsing code between the local and the remote client (and bindings) in the future. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
parent
dd295f297b
commit
8472efdbd1
|
@ -0,0 +1,61 @@
|
|||
package copy
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ParseSourceAndDestination parses the source and destination input into a
|
||||
// possibly specified container and path. The input format is described in
|
||||
// podman-cp(1) as "[nameOrID:]path". Colons in paths are supported as long
|
||||
// they start with a dot or slash.
|
||||
//
|
||||
// It returns, in order, the source container and path, followed by the
|
||||
// destination container and path, and an error. Note that exactly one
|
||||
// container must be specified.
|
||||
func ParseSourceAndDestination(source, destination string) (string, string, string, string, error) {
|
||||
sourceContainer, sourcePath := parseUserInput(source)
|
||||
destContainer, destPath := parseUserInput(destination)
|
||||
|
||||
numContainers := 0
|
||||
if len(sourceContainer) > 0 {
|
||||
numContainers++
|
||||
}
|
||||
if len(destContainer) > 0 {
|
||||
numContainers++
|
||||
}
|
||||
|
||||
if numContainers != 1 {
|
||||
return "", "", "", "", errors.Errorf("invalid arguments %q, %q: exactly 1 container expected but %d specified", source, destination, numContainers)
|
||||
}
|
||||
|
||||
if len(sourcePath) == 0 || len(destPath) == 0 {
|
||||
return "", "", "", "", errors.Errorf("invalid arguments %q, %q: you must specify paths", source, destination)
|
||||
}
|
||||
|
||||
return sourceContainer, sourcePath, destContainer, destPath, nil
|
||||
}
|
||||
|
||||
// parseUserInput parses the input string and returns, if specified, the name
|
||||
// or ID of the container and the path. The input format is described in
|
||||
// podman-cp(1) as "[nameOrID:]path". Colons in paths are supported as long
|
||||
// they start with a dot or slash.
|
||||
func parseUserInput(input string) (container string, path string) {
|
||||
if len(input) == 0 {
|
||||
return
|
||||
}
|
||||
path = input
|
||||
|
||||
// If the input starts with a dot or slash, it cannot refer to a
|
||||
// container.
|
||||
if input[0] == '.' || input[0] == '/' {
|
||||
return
|
||||
}
|
||||
|
||||
if spl := strings.SplitN(path, ":", 2); len(spl) == 2 {
|
||||
container = spl[0]
|
||||
path = spl[1]
|
||||
}
|
||||
return
|
||||
}
|
|
@ -2,46 +2,53 @@ package abi
|
|||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/podman/v2/libpod"
|
||||
"github.com/containers/podman/v2/pkg/copy"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string, options entities.ContainerCpOptions) error {
|
||||
srcCtr, srcPath := parsePath(ic.Libpod, source)
|
||||
destCtr, destPath := parsePath(ic.Libpod, dest)
|
||||
// Parse user input.
|
||||
sourceContainerStr, sourcePath, destContainerStr, destPath, err := copy.ParseSourceAndDestination(source, dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if srcCtr != nil && destCtr != nil {
|
||||
return errors.Errorf("invalid arguments %q, %q: you must use just one container", source, dest)
|
||||
// Look up containers.
|
||||
var sourceContainer, destContainer *libpod.Container
|
||||
if len(sourceContainerStr) > 0 {
|
||||
sourceContainer, err = ic.Libpod.LookupContainer(sourceContainerStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if srcCtr == nil && destCtr == nil {
|
||||
return errors.Errorf("invalid arguments %q, %q: you must specify one container", source, dest)
|
||||
}
|
||||
if len(srcPath) == 0 || len(destPath) == 0 {
|
||||
return errors.Errorf("invalid arguments %q, %q: you must specify paths", source, dest)
|
||||
if len(destContainerStr) > 0 {
|
||||
destContainer, err = ic.Libpod.LookupContainer(destContainerStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var sourceItem, destinationItem copy.CopyItem
|
||||
var err error
|
||||
// Copy from the container to the host.
|
||||
if srcCtr != nil {
|
||||
sourceItem, err = copy.CopyItemForContainer(srcCtr, srcPath, options.Pause, true)
|
||||
|
||||
// Source ... container OR host.
|
||||
if sourceContainer != nil {
|
||||
sourceItem, err = copy.CopyItemForContainer(sourceContainer, sourcePath, options.Pause, true)
|
||||
defer sourceItem.CleanUp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
sourceItem, err = copy.CopyItemForHost(srcPath, true)
|
||||
sourceItem, err = copy.CopyItemForHost(sourcePath, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if destCtr != nil {
|
||||
destinationItem, err = copy.CopyItemForContainer(destCtr, destPath, options.Pause, false)
|
||||
// Destination ... container OR host.
|
||||
if destContainer != nil {
|
||||
destinationItem, err = copy.CopyItemForContainer(destContainer, destPath, options.Pause, false)
|
||||
defer destinationItem.CleanUp()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -57,20 +64,3 @@ func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string,
|
|||
// Copy from the host to the container.
|
||||
return copy.Copy(&sourceItem, &destinationItem, options.Extract)
|
||||
}
|
||||
|
||||
func parsePath(runtime *libpod.Runtime, path string) (*libpod.Container, string) {
|
||||
if len(path) == 0 {
|
||||
return nil, ""
|
||||
}
|
||||
if path[0] == '.' || path[0] == '/' { // A path cannot point to a container.
|
||||
return nil, path
|
||||
}
|
||||
pathArr := strings.SplitN(path, ":", 2)
|
||||
if len(pathArr) == 2 {
|
||||
ctr, err := runtime.LookupContainer(pathArr[0])
|
||||
if err == nil {
|
||||
return ctr, pathArr[1]
|
||||
}
|
||||
}
|
||||
return nil, path
|
||||
}
|
||||
|
|
|
@ -732,7 +732,8 @@ func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrID string, o
|
|||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string, options entities.ContainerCpOptions) error {
|
||||
return errors.New("not implemented")
|
||||
return nil
|
||||
// return containers.Copy(ic.ClientCxt, source, dest, options)
|
||||
}
|
||||
|
||||
// Shutdown Libpod engine
|
||||
|
|
Loading…
Reference in New Issue