diff options
Diffstat (limited to 'cmd/podman')
-rw-r--r-- | cmd/podman/common.go | 21 | ||||
-rw-r--r-- | cmd/podman/healthcheck_run.go | 2 | ||||
-rw-r--r-- | cmd/podman/shared/container.go | 1 | ||||
-rw-r--r-- | cmd/podman/shared/create.go | 98 |
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 +} |