Skip to content

Commit

Permalink
pod create --replace
Browse files Browse the repository at this point in the history
Add a `--replace` flag to the `pod create` command.  If another pod with
the same name already exists, it will be replaced and removed.

Adding this flag is motivated by #5485 to make running Podman in systemd
units (or any other scripts/automation) more robust.  In case of a
crash, a pod may not be removed by a sytemd unit anymore.  The
`--replace` flag allows for supporting crashes.

Note that the `--replace` flag does not require the `--name` flag to be
set, so it can be set unconditionally in `podman generate systemd`.

Signed-off-by: Valentin Rothberg <[email protected]>
  • Loading branch information
vrothberg committed Jun 15, 2020
1 parent fa3b8a7 commit fe488b5
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 6 deletions.
19 changes: 19 additions & 0 deletions cmd/podman/pods/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ var (
createOptions entities.PodCreateOptions
labels, labelFile []string
podIDFile string
replace bool
share string
)

Expand All @@ -61,6 +62,7 @@ func init() {
flags.StringVarP(&createOptions.Name, "name", "n", "", "Assign a name to the pod")
flags.StringVarP(&createOptions.Hostname, "hostname", "", "", "Set a hostname to the pod")
flags.StringVar(&podIDFile, "pod-id-file", "", "Write the pod ID to the file")
flags.BoolVar(&replace, "replace", false, "If a pod with the same exists, replace it")
flags.StringVar(&share, "share", specgen.DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share")
flags.SetNormalizeFunc(aliasNetworkFlag)
}
Expand Down Expand Up @@ -147,6 +149,12 @@ func create(cmd *cobra.Command, args []string) error {
}
}

if replace {
if err := replacePod(createOptions.Name); err != nil {
return err
}
}

response, err := registry.ContainerEngine().PodCreate(context.Background(), createOptions)
if err != nil {
return err
Expand All @@ -159,3 +167,14 @@ func create(cmd *cobra.Command, args []string) error {
fmt.Println(response.Id)
return nil
}

func replacePod(name string) error {
if len(name) == 0 {
return errors.New("cannot replace pod without --name being set")
}
rmOptions := entities.PodRmOptions{
Force: true, // stop and remove pod
Ignore: true, // ignore if pod doesn't exist
}
return removePods([]string{name}, rmOptions, false)
}
18 changes: 12 additions & 6 deletions cmd/podman/pods/rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,24 +58,30 @@ func init() {
}

func rm(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)

ids, err := common.ReadPodIDFiles(rmOptions.PodIDFiles)
if err != nil {
return err
}
args = append(args, ids...)
return removePods(args, rmOptions.PodRmOptions, true)
}

responses, err := registry.ContainerEngine().PodRm(context.Background(), args, rmOptions.PodRmOptions)
// removePods removes the specified pods (names or IDs). Allows for sharing
// pod-removal logic across commands.
func removePods(namesOrIDs []string, rmOptions entities.PodRmOptions, printIDs bool) error {
var errs utils.OutputErrors

responses, err := registry.ContainerEngine().PodRm(context.Background(), namesOrIDs, rmOptions)
if err != nil {
return err
}

// in the cli, first we print out all the successful attempts
for _, r := range responses {
if r.Err == nil {
fmt.Println(r.Id)
if printIDs {
fmt.Println(r.Id)
}
} else {
errs = append(errs, r.Err)
}
Expand Down
1 change: 1 addition & 0 deletions completions/bash/podman
Original file line number Diff line number Diff line change
Expand Up @@ -3118,6 +3118,7 @@ _podman_pod_create() {
--help
-h
--infra
--replace
"
_complete_ "$options_with_args" "$boolean_options"
}
Expand Down
4 changes: 4 additions & 0 deletions docs/source/markdown/podman-pod-create.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ Use `podman port` to see the actual mapping: `podman port CONTAINER $CONTAINERPO

NOTE: This cannot be modified once the pod is created.

**--replace**=**true**|**false**

If another pod with the same name already exists, replace and remove it. The default is **false**.

**--share**=*namespace*

A comma delimited list of kernel namespaces to share. If none or "" is specified, no namespaces will be shared. The namespaces to choose from are ipc, net, pid, user, uts.
Expand Down
15 changes: 15 additions & 0 deletions test/e2e/pod_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,4 +305,19 @@ var _ = Describe("Podman pod create", func() {
data := check.InspectPodToJSON()
Expect(data.ID).To(Equal(string(id)))
})

It("podman pod create --replace", func() {
// Make sure we error out with --name.
session := podmanTest.Podman([]string{"pod", "create", "--replace", ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(125))

// Create and replace 5 times in a row the "same" pod.
podName := "testCtr"
for i := 0; i < 5; i++ {
session = podmanTest.Podman([]string{"pod", "create", "--replace", "--name", podName})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
}
})
})

0 comments on commit fe488b5

Please sign in to comment.