summaryrefslogtreecommitdiff
path: root/cmd/podman
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman')
-rw-r--r--cmd/podman/common.go21
-rw-r--r--cmd/podman/healthcheck_run.go2
-rw-r--r--cmd/podman/shared/container.go1
-rw-r--r--cmd/podman/shared/create.go98
4 files changed, 105 insertions, 17 deletions
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 30eaa95d8..79b7495ab 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -287,7 +287,26 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
createFlags.Bool(
"help", false, "",
)
-
+ createFlags.String(
+ "healthcheck-command", "",
+ "set a healthcheck command for the container ('none' disables the existing healthcheck)",
+ )
+ createFlags.String(
+ "healthcheck-interval", "30s",
+ "set an interval for the healthchecks",
+ )
+ createFlags.Uint(
+ "healthcheck-retries", 3,
+ "the number of retries allowed before a healthcheck is considered to be unhealthy",
+ )
+ createFlags.String(
+ "healthcheck-start-period", "0s",
+ "the initialization time needed for a container to bootstrap",
+ )
+ createFlags.String(
+ "healthcheck-timeout", "30s",
+ "the maximum time allowed to complete the healthcheck before an interval is considered failed",
+ )
createFlags.StringP(
"hostname", "h", "",
"Set container hostname",
diff --git a/cmd/podman/healthcheck_run.go b/cmd/podman/healthcheck_run.go
index d92b2ac01..bd3a4ea15 100644
--- a/cmd/podman/healthcheck_run.go
+++ b/cmd/podman/healthcheck_run.go
@@ -48,6 +48,6 @@ func healthCheckCmd(c *cliconfig.HealthCheckValues) error {
}
return err
}
- fmt.Println("\nhealthy")
+ fmt.Println("healthy")
return nil
}
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index e191e8069..41950928e 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -523,6 +523,7 @@ func GetCtrInspectInfo(config *libpod.ContainerConfig, ctrInspectData *inspect.C
StopSignal: config.StopSignal,
Cmd: config.Spec.Process.Args,
Entrypoint: strings.Join(createArtifact.Entrypoint, " "),
+ Healthcheck: config.HealthCheckConfig,
},
}
return data, nil
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
index bfd05d53e..32a80e9f9 100644
--- a/cmd/podman/shared/create.go
+++ b/cmd/podman/shared/create.go
@@ -11,6 +11,7 @@ import (
"strconv"
"strings"
"syscall"
+ "time"
"github.com/containers/image/manifest"
"github.com/containers/libpod/cmd/podman/cliconfig"
@@ -26,6 +27,7 @@ import (
"github.com/docker/docker/pkg/signal"
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
+ "github.com/google/shlex"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/opentracing/opentracing-go"
@@ -40,8 +42,7 @@ func getContext() context.Context {
func CreateContainer(ctx context.Context, c *cliconfig.PodmanCommand, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) {
var (
- hasHealthCheck bool
- healthCheck *manifest.Schema2HealthConfig
+ healthCheck *manifest.Schema2HealthConfig
)
if c.Bool("trace") {
span, _ := opentracing.StartSpanFromContext(ctx, "createContainer")
@@ -89,18 +90,31 @@ func CreateContainer(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
imageName = newImage.ID()
}
- // add healthcheck if it exists AND is correct mediatype
- _, mediaType, err := newImage.Manifest(ctx)
- if err != nil {
- return nil, nil, errors.Wrapf(err, "unable to determine mediatype of image %s", newImage.ID())
- }
- if mediaType == manifest.DockerV2Schema2MediaType {
- healthCheck, err = newImage.GetHealthCheck(ctx)
- if err != nil {
- return nil, nil, errors.Wrapf(err, "unable to get healthcheck for %s", c.InputArgs[0])
- }
- if healthCheck != nil {
- hasHealthCheck = true
+ var healthCheckCommandInput string
+ // if the user disabled the healthcheck with "none", we skip adding it
+ healthCheckCommandInput = c.String("healthcheck-command")
+
+ // the user didnt disable the healthcheck but did pass in a healthcheck command
+ // now we need to make a healthcheck from the commandline input
+ if healthCheckCommandInput != "none" {
+ if len(healthCheckCommandInput) > 0 {
+ healthCheck, err = makeHealthCheckFromCli(c)
+ if err != nil {
+ return nil, nil, errors.Wrapf(err, "unable to create healthcheck")
+ }
+ } else {
+ // the user did not disable the health check and did not pass in a healthcheck
+ // command as input. so now we add healthcheck if it exists AND is correct mediatype
+ _, mediaType, err := newImage.Manifest(ctx)
+ if err != nil {
+ return nil, nil, errors.Wrapf(err, "unable to determine mediatype of image %s", newImage.ID())
+ }
+ if mediaType == manifest.DockerV2Schema2MediaType {
+ healthCheck, err = newImage.GetHealthCheck(ctx)
+ if err != nil {
+ return nil, nil, errors.Wrapf(err, "unable to get healthcheck for %s", c.InputArgs[0])
+ }
+ }
}
}
}
@@ -111,7 +125,6 @@ func CreateContainer(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
// Because parseCreateOpts does derive anything from the image, we add health check
// at this point. The rest is done by WithOptions.
- createConfig.HasHealthCheck = hasHealthCheck
createConfig.HealthCheck = healthCheck
ctr, err := CreateContainerFromCreateConfig(runtime, createConfig, ctx, nil)
@@ -835,3 +848,58 @@ var defaultEnvVariables = map[string]string{
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM": "xterm",
}
+
+func makeHealthCheckFromCli(c *cliconfig.PodmanCommand) (*manifest.Schema2HealthConfig, error) {
+ inCommand := c.String("healthcheck-command")
+ inInterval := c.String("healthcheck-interval")
+ inRetries := c.Uint("healthcheck-retries")
+ inTimeout := c.String("healthcheck-timeout")
+ inStartPeriod := c.String("healthcheck-start-period")
+
+ // Every healthcheck requires a command
+ if len(inCommand) == 0 {
+ return nil, errors.New("Must define a healthcheck command for all healthchecks")
+ }
+
+ cmd, err := shlex.Split(inCommand)
+ if err != nil {
+ return nil, errors.Wrap(err, "failed to parse healthcheck command")
+ }
+ hc := manifest.Schema2HealthConfig{
+ Test: cmd,
+ }
+ intervalDuration, err := time.ParseDuration(inInterval)
+ if err != nil {
+ return nil, errors.Wrapf(err, "invalid healthcheck-interval %s ", inInterval)
+ }
+
+ if intervalDuration < time.Duration(time.Second*1) {
+ return nil, errors.New("healthcheck-interval must be at least 1 second")
+ }
+
+ hc.Interval = intervalDuration
+
+ if inRetries < 1 {
+ return nil, errors.New("healthcheck-retries must be greater than 0.")
+ }
+
+ timeoutDuration, err := time.ParseDuration(inTimeout)
+ if err != nil {
+ return nil, errors.Wrapf(err, "invalid healthcheck-timeout %s", inTimeout)
+ }
+ if timeoutDuration < time.Duration(time.Second*1) {
+ return nil, errors.New("healthcheck-timeout must be at least 1 second")
+ }
+ hc.Timeout = timeoutDuration
+
+ startPeriodDuration, err := time.ParseDuration(inStartPeriod)
+ if err != nil {
+ return nil, errors.Wrapf(err, "invalid healthcheck-start-period %s", inStartPeriod)
+ }
+ if startPeriodDuration < time.Duration(0) {
+ return nil, errors.New("healthcheck-start-period must be a 0 seconds or greater")
+ }
+ hc.StartPeriod = startPeriodDuration
+
+ return &hc, nil
+}