aboutsummaryrefslogtreecommitdiff
path: root/pkg/domain
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2022-02-22 10:10:49 -0500
committerGitHub <noreply@github.com>2022-02-22 10:10:49 -0500
commitfab82a7c9ca3821c2b4496f9e9f6bfc8b2aff53d (patch)
tree7bafc1608557fd8f98970eaece2225b0d4820edb /pkg/domain
parent948dfc6f02b7b15547a42e39760b04eca20b193d (diff)
parent94df7015121759ce69f35f7e7735aa2e4a2dc71a (diff)
downloadpodman-fab82a7c9ca3821c2b4496f9e9f6bfc8b2aff53d.tar.gz
podman-fab82a7c9ca3821c2b4496f9e9f6bfc8b2aff53d.tar.bz2
podman-fab82a7c9ca3821c2b4496f9e9f6bfc8b2aff53d.zip
Merge pull request #13059 from cdoern/clone
Implement Podman Container Clone
Diffstat (limited to 'pkg/domain')
-rw-r--r--pkg/domain/entities/containers.go10
-rw-r--r--pkg/domain/entities/engine_container.go1
-rw-r--r--pkg/domain/entities/pods.go1
-rw-r--r--pkg/domain/infra/abi/containers.go91
-rw-r--r--pkg/domain/infra/abi/play.go4
-rw-r--r--pkg/domain/infra/tunnel/containers.go4
6 files changed, 107 insertions, 4 deletions
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index d39a70732..e9bce0eb7 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -463,3 +463,13 @@ type ContainerRenameOptions struct {
// NewName is the new name that will be given to the container.
NewName string
}
+
+// ContainerCloneOptions contains options for cloning an existing continer
+type ContainerCloneOptions struct {
+ ID string
+ Destroy bool
+ CreateOpts ContainerCreateOptions
+ Image string
+ RawImageName string
+ Run bool
+}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 5dedceacc..21272d33f 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -19,6 +19,7 @@ type ContainerEngine interface {
ContainerAttach(ctx context.Context, nameOrID string, options AttachOptions) error
ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error)
ContainerCleanup(ctx context.Context, namesOrIds []string, options ContainerCleanupOptions) ([]*ContainerCleanupReport, error)
+ ContainerClone(ctx context.Context, ctrClone ContainerCloneOptions) (*ContainerCreateReport, error)
ContainerCommit(ctx context.Context, nameOrID string, options CommitOptions) (*CommitReport, 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)
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index 7922db4e6..6fb3db1b5 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -264,6 +264,7 @@ type ContainerCreateOptions struct {
SeccompPolicy string
PidFile string
IsInfra bool
+ IsClone bool
Net *NetOptions `json:"net,omitempty"`
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index a5c4647d7..92f5b1a80 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -6,6 +6,7 @@ import (
"io/ioutil"
"os"
"strconv"
+ "strings"
"sync"
"time"
@@ -648,7 +649,7 @@ func (ic *ContainerEngine) ContainerCreate(ctx context.Context, s *specgen.SpecG
for _, w := range warn {
fmt.Fprintf(os.Stderr, "%s\n", w)
}
- rtSpec, spec, opts, err := generate.MakeContainer(context.Background(), ic.Libpod, s)
+ rtSpec, spec, opts, err := generate.MakeContainer(context.Background(), ic.Libpod, s, false, nil)
if err != nil {
return nil, err
}
@@ -971,7 +972,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
fmt.Fprintf(os.Stderr, "%s\n", w)
}
- rtSpec, spec, optsN, err := generate.MakeContainer(ctx, ic.Libpod, opts.Spec)
+ rtSpec, spec, optsN, err := generate.MakeContainer(ctx, ic.Libpod, opts.Spec, false, nil)
if err != nil {
return nil, err
}
@@ -1490,3 +1491,89 @@ func (ic *ContainerEngine) ContainerRename(ctx context.Context, nameOrID string,
return nil
}
+
+func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts entities.ContainerCloneOptions) (*entities.ContainerCreateReport, error) {
+ spec := specgen.NewSpecGenerator(ctrCloneOpts.Image, ctrCloneOpts.CreateOpts.RootFS)
+ var c *libpod.Container
+ c, err := generate.ConfigToSpec(ic.Libpod, spec, ctrCloneOpts.ID)
+ if err != nil {
+ return nil, err
+ }
+
+ err = specgenutil.FillOutSpecGen(spec, &ctrCloneOpts.CreateOpts, []string{})
+ if err != nil {
+ return nil, err
+ }
+ out, err := generate.CompleteSpec(ctx, ic.Libpod, spec)
+ if err != nil {
+ return nil, err
+ }
+
+ // Print warnings
+ if len(out) > 0 {
+ for _, w := range out {
+ fmt.Println("Could not properly complete the spec as expected:")
+ fmt.Fprintf(os.Stderr, "%s\n", w)
+ }
+ }
+
+ if len(ctrCloneOpts.CreateOpts.Name) > 0 {
+ spec.Name = ctrCloneOpts.CreateOpts.Name
+ } else {
+ n := c.Name()
+ _, err := ic.Libpod.LookupContainer(c.Name() + "-clone")
+ if err == nil {
+ n += "-clone"
+ }
+ switch {
+ case strings.Contains(n, "-clone"):
+ ind := strings.Index(n, "-clone") + 6
+ num, _ := strconv.Atoi(n[ind:])
+ if num == 0 { // clone1 is hard to get with this logic, just check for it here.
+ _, err = ic.Libpod.LookupContainer(n + "1")
+ if err != nil {
+ spec.Name = n + "1"
+ break
+ }
+ } else {
+ n = n[0:ind]
+ }
+ err = nil
+ count := num
+ for err == nil {
+ count++
+ tempN := n + strconv.Itoa(count)
+ _, err = ic.Libpod.LookupContainer(tempN)
+ }
+ n += strconv.Itoa(count)
+ spec.Name = n
+ default:
+ spec.Name = c.Name() + "-clone"
+ }
+ }
+
+ rtSpec, spec, opts, err := generate.MakeContainer(context.Background(), ic.Libpod, spec, true, c)
+ if err != nil {
+ return nil, err
+ }
+ ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ if ctrCloneOpts.Destroy {
+ var time *uint
+ err := ic.Libpod.RemoveContainer(context.Background(), c, false, false, time)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if ctrCloneOpts.Run {
+ if err := ctr.Start(ctx, true); err != nil {
+ return nil, err
+ }
+ }
+
+ return &entities.ContainerCreateReport{Id: ctr.ID()}, nil
+}
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index b8ca591bb..1cd80a6d2 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -392,7 +392,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
if err != nil {
return nil, err
}
- rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen)
+ rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen, false, nil)
if err != nil {
return nil, err
}
@@ -435,7 +435,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
if err != nil {
return nil, err
}
- rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen)
+ rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen, false, nil)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 67e709486..aa4baf846 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -958,3 +958,7 @@ func (ic *ContainerEngine) ShouldRestart(_ context.Context, id string) (bool, er
func (ic *ContainerEngine) ContainerRename(ctx context.Context, nameOrID string, opts entities.ContainerRenameOptions) error {
return containers.Rename(ic.ClientCtx, nameOrID, new(containers.RenameOptions).WithName(opts.NewName))
}
+
+func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts entities.ContainerCloneOptions) (*entities.ContainerCreateReport, error) {
+ return nil, errors.New("cloning a container is not supported on the remote client")
+}