diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2022-02-22 10:10:49 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-22 10:10:49 -0500 |
commit | fab82a7c9ca3821c2b4496f9e9f6bfc8b2aff53d (patch) | |
tree | 7bafc1608557fd8f98970eaece2225b0d4820edb /pkg/domain | |
parent | 948dfc6f02b7b15547a42e39760b04eca20b193d (diff) | |
parent | 94df7015121759ce69f35f7e7735aa2e4a2dc71a (diff) | |
download | podman-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.go | 10 | ||||
-rw-r--r-- | pkg/domain/entities/engine_container.go | 1 | ||||
-rw-r--r-- | pkg/domain/entities/pods.go | 1 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 91 | ||||
-rw-r--r-- | pkg/domain/infra/abi/play.go | 4 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 4 |
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") +} |