Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --restart flag to pod create #17627

Merged
merged 4 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions cmd/podman/common/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,14 +386,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
_ = cmd.RegisterFlagCompletionFunc(requiresFlagName, AutocompleteContainers)

restartFlagName := "restart"
createFlags.StringVar(
&cf.Restart,
restartFlagName, "",
`Restart policy to apply when a container exits ("always"|"no"|"on-failure"|"unless-stopped")`,
)
_ = cmd.RegisterFlagCompletionFunc(restartFlagName, AutocompleteRestartOption)

createFlags.BoolVar(
&cf.Rm,
"rm", false,
Expand Down Expand Up @@ -635,6 +627,14 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
}
if mode == entities.InfraMode || (mode == entities.CreateMode) { // infra container flags, create should also pick these up
restartFlagName := "restart"
createFlags.StringVar(
&cf.Restart,
restartFlagName, "",
`Restart policy to apply when a container exits ("always"|"no"|"never"|"on-failure"|"unless-stopped")`,
)
_ = cmd.RegisterFlagCompletionFunc(restartFlagName, AutocompleteRestartOption)

shmSizeFlagName := "shm-size"
createFlags.String(
shmSizeFlagName, shmSize(),
Expand Down
2 changes: 2 additions & 0 deletions cmd/podman/containers/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ func create(cmd *cobra.Command, args []string) error {
}
cliVals.InitContainerType = initctr
}
// TODO: v5.0 block users from setting restart policy for a container if the container is in a pod
umohnani8 marked this conversation as resolved.
Show resolved Hide resolved

cliVals, err := CreateInit(cmd, cliVals, false)
if err != nil {
Expand Down Expand Up @@ -405,6 +406,7 @@ func createPodIfNecessary(cmd *cobra.Command, s *specgen.SpecGenerator, netOpts
CpusetCpus: cliVals.CPUSetCPUs,
Pid: cliVals.PID,
Userns: uns,
Restart: cliVals.Restart,
}
// Unset config values we passed to the pod to prevent them being used twice for the container and pod.
s.ContainerBasicConfig.Hostname = ""
Expand Down
6 changes: 6 additions & 0 deletions cmd/podman/containers/ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"os"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -300,6 +301,7 @@ func createPsOut() ([]map[string]string, string) {
"PIDNS": "pidns",
"Pod": "pod id",
"PodName": "podname", // undo camelcase space break
"Restarts": "restarts",
"RunningFor": "running for",
"UTS": "uts",
"User": "userns",
Expand Down Expand Up @@ -377,6 +379,10 @@ func (l psReporter) Status() string {
return state
}

func (l psReporter) Restarts() string {
return strconv.Itoa(int(l.ListContainer.Restarts))
}

func (l psReporter) RunningFor() string {
return l.CreatedHuman()
}
Expand Down
1 change: 1 addition & 0 deletions cmd/podman/pods/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ func create(cmd *cobra.Command, args []string) error {
podSpec.InfraContainerSpec = specgen.NewSpecGenerator(imageName, false)
podSpec.InfraContainerSpec.RawImageName = rawImageName
podSpec.InfraContainerSpec.NetworkOptions = podSpec.NetworkOptions
podSpec.InfraContainerSpec.RestartPolicy = podSpec.RestartPolicy
err = specgenutil.FillOutSpecGen(podSpec.InfraContainerSpec, &infraOptions, []string{})
if err != nil {
return err
Expand Down
12 changes: 12 additions & 0 deletions cmd/podman/pods/ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"os"
"sort"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -147,6 +148,7 @@ func pods(cmd *cobra.Command, _ []string) error {
"ContainerStatuses": "STATUS",
"Cgroup": "CGROUP",
"Namespace": "NAMESPACES",
"Restarts": "RESTARTS",
})

if err := rpt.Execute(headers); err != nil {
Expand Down Expand Up @@ -178,6 +180,7 @@ func podPsFormat() string {
if !psInput.CtrStatus && !psInput.CtrNames && !psInput.CtrIds {
row = append(row, "{{.NumberOfContainers}}")
}

return "{{range . }}" + strings.Join(row, "\t") + "\n" + "{{end -}}"
}

Expand Down Expand Up @@ -265,6 +268,15 @@ func (l ListPodReporter) ContainerStatuses() string {
return strings.Join(statuses, ",")
}

// Restarts returns the total number of restarts for all the containers in the pod
func (l ListPodReporter) Restarts() string {
restarts := 0
for _, c := range l.Containers {
restarts += int(c.RestartCount)
}
return strconv.Itoa(restarts)
}

func sortPodPsOutput(sortBy string, lprs []*entities.ListPodsReport) error {
switch sortBy {
case "created":
Expand Down
3 changes: 2 additions & 1 deletion docs/source/markdown/options/restart.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
####> This option file is used in:
####> podman create, run
####> podman create, pod clone, pod create, run
####> If file is edited, make sure the changes
####> are applicable to all of those.
#### **--restart**=*policy*
Expand All @@ -10,6 +10,7 @@ Restart policy will not take effect if a container is stopped via the **podman k
Valid _policy_ values are:

- `no` : Do not restart containers on exit
- `never` : Synonym for **no**; do not restart containers on exit
- `on-failure[:max_retries]` : Restart containers when they exit with a non-zero exit code, retrying indefinitely or until the optional *max_retries* count is hit
- `always` : Restart containers when they exit, regardless of status, retrying indefinitely
- `unless-stopped` : Identical to **always**
Expand Down
4 changes: 4 additions & 0 deletions docs/source/markdown/podman-pod-clone.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ Set a custom name for the cloned pod. The default if not specified is of the syn

@@option pid.pod

@@option restart

Default restart policy for all the containers in a pod.

@@option security-opt

@@option shm-size
Expand Down
4 changes: 4 additions & 0 deletions docs/source/markdown/podman-pod-create.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ but only by the pod itself.

@@option replace

@@option restart

Default restart policy for all the containers in a pod.

@@option security-opt

#### **--share**=*namespace*
Expand Down
1 change: 1 addition & 0 deletions docs/source/markdown/podman-pod-inspect.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Valid placeholders for the Go template are listed below:
| .Name | Pod name |
| .Namespace | Namespace |
| .NumContainers | Number of containers in the pod |
| .RestartPolicy | Restart policy of the pod |
| .SecurityOpts | Security options |
| .SharedNamespaces | Pod shared namespaces |
| .State | Pod state |
Expand Down
29 changes: 15 additions & 14 deletions docs/source/markdown/podman-pod-ps.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,21 @@ Pretty-print containers to JSON or using a Go template

Valid placeholders for the Go template are listed below:

| **Placeholder** | **Description** |
|---------------------|----------------------------------------------------|
| .Cgroup | Cgroup path of pod |
| .ContainerIds | Comma-separated list of container IDs in the pod |
| .ContainerNames | Comma-separated list of container names in the pod |
| .ContainerStatuses | Comma-separated list of container statuses |
| .Created | Creation time of pod |
| .ID | Container ID |
| .InfraID | Pod infra container ID |
| .Labels | All the labels assigned to the pod |
| .Name | Name of pod |
| .Networks | Show all networks connected to the infra container |
| .NumberOfContainers | Show the number of containers attached to pod |
| .Status | Status of pod |
| **Placeholder** | **Description** |
|---------------------|------------------------------------------------------|
| .Cgroup | Cgroup path of pod |
| .ContainerIds | Comma-separated list of container IDs in the pod |
| .ContainerNames | Comma-separated list of container names in the pod |
| .ContainerStatuses | Comma-separated list of container statuses |
| .Created | Creation time of pod |
| .ID | Container ID |
| .InfraID | Pod infra container ID |
| .Labels | All the labels assigned to the pod |
| .Name | Name of pod |
| .Networks | Show all networks connected to the infra container |
| .NumberOfContainers | Show the number of containers attached to pod |
| .Restarts | Show the total number of container restarts in a pod |
| .Status | Status of pod |

#### **--help**, **-h**

Expand Down
1 change: 1 addition & 0 deletions docs/source/markdown/podman-ps.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Valid placeholders for the Go template are listed below:
| .Pod | Pod the container is associated with (SHA) |
| .PodName | Seems to be empty no matter what |
| .Ports | Exposed ports |
| .Restarts | Display the container restart count |
| .RunningFor | Time elapsed since container was started |
| .Size | Size of container |
| .StartedAt | Time (epoch seconds) the container started |
Expand Down
13 changes: 12 additions & 1 deletion libpod/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@ type ContainerState struct {
// restart policy. This is NOT incremented by normal container restarts
// (only by restart policy).
RestartCount uint `json:"restartCount,omitempty"`

// StartupHCPassed indicates that the startup healthcheck has
// succeeded and the main healthcheck can begin.
StartupHCPassed bool `json:"startupHCPassed,omitempty"`
Expand Down Expand Up @@ -730,6 +729,18 @@ func (c *Container) State() (define.ContainerStatus, error) {
return c.state.State, nil
}

func (c *Container) RestartCount() (uint, error) {
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()

if err := c.syncContainer(); err != nil {
return 0, err
}
}
return c.state.RestartCount, nil
}

// Mounted returns whether the container is mounted and the path it is mounted
// at (if it is mounted).
// If the container is not mounted, no error is returned, and the mountpoint
Expand Down
2 changes: 2 additions & 0 deletions libpod/define/pod_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ type InspectPodData struct {
BlkioWeight uint64 `json:"blkio_weight,omitempty"`
// BlkioWeightDevice contains the blkio weight device limits for the pod
BlkioWeightDevice []InspectBlkioWeightDevice `json:"blkio_weight_device,omitempty"`
// RestartPolicy of the pod.
RestartPolicy string `json:"RestartPolicy,omitempty"`
}

// InspectPodInfraConfig contains the configuration of the pod's infra
Expand Down
54 changes: 34 additions & 20 deletions libpod/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,23 +97,8 @@ func (p *Pod) GenerateForKube(ctx context.Context, getService bool) (*v1.Pod, []
}
pod.Spec.HostAliases = extraHost

// vendor/k8s.io/api/core/v1/types.go: v1.Container cannot save restartPolicy
// so set it at here
for _, ctr := range allContainers {
if !ctr.IsInfra() {
switch ctr.config.RestartPolicy {
case define.RestartPolicyAlways:
pod.Spec.RestartPolicy = v1.RestartPolicyAlways
case define.RestartPolicyOnFailure:
pod.Spec.RestartPolicy = v1.RestartPolicyOnFailure
case define.RestartPolicyNo:
pod.Spec.RestartPolicy = v1.RestartPolicyNever
default: // some pod create from cmdline, such as "", so set it to "" as k8s automatically defaults to always
pod.Spec.RestartPolicy = ""
}
break
}
}
// Set the pod's restart policy
pod.Spec.RestartPolicy = getPodRestartPolicy(p.config.RestartPolicy)

if p.SharesPID() {
// unfortunately, go doesn't have a nice way to specify a pointer to a bool
Expand All @@ -136,7 +121,7 @@ func (p *Pod) getInfraContainer() (*Container, error) {
// kind YAML.
func GenerateForKubeDeployment(ctx context.Context, pod *YAMLPod, options entities.GenerateKubeOptions) (*YAMLDeployment, error) {
// Restart policy for Deployments can only be set to Always
if options.Type == define.K8sKindDeployment && !(pod.Spec.RestartPolicy == "" || pod.Spec.RestartPolicy == define.RestartPolicyAlways) {
if options.Type == define.K8sKindDeployment && !(pod.Spec.RestartPolicy == "" || pod.Spec.RestartPolicy == v1.RestartPolicyAlways) {
return nil, fmt.Errorf("k8s Deployments can only have restartPolicy set to Always")
}

Expand Down Expand Up @@ -599,6 +584,7 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getServic
kubeAnnotations := make(map[string]string)
ctrNames := make([]string, 0, len(ctrs))
var hostname string
var restartPolicy *string
for _, ctr := range ctrs {
ctrNames = append(ctrNames, removeUnderscores(ctr.Name()))
for k, v := range ctr.config.Spec.Annotations {
Expand All @@ -623,6 +609,11 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getServic
}
}

// Use the restart policy of the first non-init container
if !isInit && restartPolicy == nil {
restartPolicy = &ctr.config.RestartPolicy
}

if ctr.config.Spec.Process != nil {
var ulimitArr []string
defaultUlimits := util.DefaultContainerConfig().Ulimits()
Expand Down Expand Up @@ -700,7 +691,7 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getServic
podName += "-pod"
}

return newPodObject(
pod := newPodObject(
podName,
kubeAnnotations,
kubeInitCtrs,
Expand All @@ -709,7 +700,30 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getServic
&podDNS,
hostNetwork,
hostUsers,
hostname), nil
hostname)

// Set the pod's restart policy
policy := ""
if restartPolicy != nil {
policy = *restartPolicy
}
pod.Spec.RestartPolicy = getPodRestartPolicy(policy)

return pod, nil
}

// getPodRestartPolicy returns the pod restart policy to be set in the generated kube yaml
func getPodRestartPolicy(policy string) v1.RestartPolicy {
switch policy {
case define.RestartPolicyNo:
return v1.RestartPolicyNever
case define.RestartPolicyAlways:
return v1.RestartPolicyAlways
case define.RestartPolicyOnFailure:
return v1.RestartPolicyOnFailure
default: // some pod/ctr create from cmdline, such as "" - set it to "" and let k8s handle the defaults
return ""
}
}

// containerToV1Container converts information we know about a libpod container
Expand Down
34 changes: 34 additions & 0 deletions libpod/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2020,6 +2020,40 @@ func WithPodExitPolicy(policy string) PodCreateOption {
}
}

// WithPodRestartPolicy sets the restart policy of the pod.
func WithPodRestartPolicy(policy string) PodCreateOption {
return func(pod *Pod) error {
if pod.valid {
return define.ErrPodFinalized
}

switch policy {
//TODO: v5.0 if no restart policy is set, follow k8s convention and default to Always
case define.RestartPolicyNone, define.RestartPolicyNo, define.RestartPolicyOnFailure, define.RestartPolicyAlways, define.RestartPolicyUnlessStopped:
pod.config.RestartPolicy = policy
default:
return fmt.Errorf("%q is not a valid restart policy: %w", policy, define.ErrInvalidArg)
}

return nil
}
}

// WithPodRestartRetries sets the number of retries to use when restarting a
// container with the "on-failure" restart policy.
// 0 is an allowed value, and indicates infinite retries.
func WithPodRestartRetries(tries uint) PodCreateOption {
return func(pod *Pod) error {
if pod.valid {
return define.ErrPodFinalized
}

pod.config.RestartRetries = &tries

return nil
}
}

// WithPodHostname sets the hostname of the pod.
func WithPodHostname(hostname string) PodCreateOption {
return func(pod *Pod) error {
Expand Down
Loading