summaryrefslogtreecommitdiff
path: root/cmd/podman/shared
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2019-03-06 12:12:35 -0600
committerbaude <bbaude@redhat.com>2019-03-12 14:29:18 -0500
commit03716cf7f331fa5b5ffab23dcc863bedd66b5dfc (patch)
tree866b063270455a6cd0dc91d95e91cf1d3ca7b53d /cmd/podman/shared
parent7038cac53c4c93cd088fdbb097eee8d45494c3b8 (diff)
downloadpodman-03716cf7f331fa5b5ffab23dcc863bedd66b5dfc.tar.gz
podman-03716cf7f331fa5b5ffab23dcc863bedd66b5dfc.tar.bz2
podman-03716cf7f331fa5b5ffab23dcc863bedd66b5dfc.zip
healtcheck phase 2
integration of healthcheck into create and run as well as inspect. healthcheck enhancements are as follows: * add the following options to create|run so that non-docker images can define healthchecks at the container level. * --healthcheck-command * --healthcheck-retries * --healthcheck-interval * --healthcheck-start-period * podman create|run --healthcheck-command=none disables healthcheck as described by an image. * the healthcheck itself and the healthcheck "history" can now be observed in podman inspect * added the wiring for healthcheck history which logs the health history of the container, the current failed streak attempts, and log entries for the last five attempts which themselves have start and stop times, result, and a 500 character truncated (if needed) log of stderr/stdout. The timings themselves are not implemented in this PR but will be in future enablement (i.e. next). Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'cmd/podman/shared')
-rw-r--r--cmd/podman/shared/container.go1
-rw-r--r--cmd/podman/shared/create.go98
2 files changed, 84 insertions, 15 deletions
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
+}