diff options
137 files changed, 774 insertions, 557 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index dac41dc5f..da28bb597 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -215,7 +215,8 @@ build_each_commit_task: on_failure: failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' -build_without_cgo: + +build_without_cgo_task: depends_on: - "gating" @@ -475,17 +476,18 @@ verify_test_built_images_task: always: <<: *standardlogs - -# Post message to IRC if everything passed +# Post message to IRC if everything passed PR testing success_task: only_if: $CIRRUS_BRANCH != 'master' - depends_on: # ignores any dependent task conditions + # ignores any dependent task conditions, include everything except 'release' + depends_on: &alltasks - "gating" - "vendor" - "varlink_api" - "build_each_commit" + - "build_without_cgo" - "meta" - "testing" - "special_testing_rootless" @@ -493,7 +495,6 @@ success_task: - "special_testing_cross" - "test_build_cache_images" - "verify_test_built_images" - - "build_without_cgo" env: CIRRUS_WORKING_DIR: "/usr/src/libpod" @@ -514,8 +515,7 @@ release_task: # allow_failures: $CI == "true" # skip_notifications: $CI == "true" - depends_on: - - "success" + depends_on: *alltasks gce_instance: image_name: "${IMAGE_BUILDER_CACHE_IMAGE_NAME}" diff --git a/cmd/podman/attach.go b/cmd/podman/attach.go index 48a25a3e2..b78633ed6 100644 --- a/cmd/podman/attach.go +++ b/cmd/podman/attach.go @@ -51,6 +51,6 @@ func attachCmd(c *cliconfig.AttachValues) error { if err != nil { return errors.Wrapf(err, "error creating runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) return runtime.Attach(getContext(), c) } diff --git a/cmd/podman/build.go b/cmd/podman/build.go index 5e2b1aa82..bd7269390 100644 --- a/cmd/podman/build.go +++ b/cmd/podman/build.go @@ -57,14 +57,20 @@ func init() { budFlags := buildahcli.GetBudFlags(&budFlagsValues) flag := budFlags.Lookup("pull") - flag.Value.Set("true") + if err := flag.Value.Set("true"); err != nil { + logrus.Error("unable to set pull flag to true") + } flag.DefValue = "true" layerFlags := buildahcli.GetLayerFlags(&layerValues) flag = layerFlags.Lookup("layers") - flag.Value.Set(useLayers()) + if err := flag.Value.Set(useLayers()); err != nil { + logrus.Error("unable to set uselayers") + } flag.DefValue = useLayers() flag = layerFlags.Lookup("force-rm") - flag.Value.Set("true") + if err := flag.Value.Set("true"); err != nil { + logrus.Error("unable to set force-rm flag to true") + } flag.DefValue = "true" fromAndBugFlags := buildahcli.GetFromAndBudFlags(&fromAndBudValues, &userNSValues, &namespaceValues) @@ -72,7 +78,7 @@ func init() { flags.AddFlagSet(&budFlags) flags.AddFlagSet(&layerFlags) flags.AddFlagSet(&fromAndBugFlags) - flags.MarkHidden("signature-policy") + markFlagHidden(flags, "signature-policy") } func getDockerfiles(files []string) []string { @@ -177,7 +183,6 @@ func buildCmd(c *cliconfig.BuildValues) error { } contextDir = absDir } - cliArgs = Tail(cliArgs) } else { // No context directory or URL was specified. Try to use the // home of the first locally-available Dockerfile. @@ -218,7 +223,7 @@ func buildCmd(c *cliconfig.BuildValues) error { } // end from buildah - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) var stdout, stderr, reporter *os.File stdout = os.Stdout diff --git a/cmd/podman/checkpoint.go b/cmd/podman/checkpoint.go index bfb5b49d4..6755bb073 100644 --- a/cmd/podman/checkpoint.go +++ b/cmd/podman/checkpoint.go @@ -59,6 +59,6 @@ func checkpointCmd(c *cliconfig.CheckpointValues) error { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) return runtime.Checkpoint(c) } diff --git a/cmd/podman/cleanup.go b/cmd/podman/cleanup.go index 9544b75b0..c00654162 100644 --- a/cmd/podman/cleanup.go +++ b/cmd/podman/cleanup.go @@ -52,7 +52,7 @@ func cleanupCmd(c *cliconfig.CleanupValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) ok, failures, err := runtime.CleanupContainers(getContext(), c) if err != nil { diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go index c49645a1d..e98b71514 100644 --- a/cmd/podman/commit.go +++ b/cmd/podman/commit.go @@ -53,7 +53,7 @@ func commitCmd(c *cliconfig.CommitValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) args := c.InputArgs if len(args) != 2 { diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 9d7c52273..50f3d9a7b 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -11,7 +11,6 @@ import ( "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/rootless" - "github.com/containers/storage" "github.com/fatih/camelcase" jsoniter "github.com/json-iterator/go" "github.com/pkg/errors" @@ -19,8 +18,7 @@ import ( ) var ( - stores = make(map[storage.Store]struct{}) - json = jsoniter.ConfigCompatibleWithStandardLibrary + json = jsoniter.ConfigCompatibleWithStandardLibrary ) const ( diff --git a/cmd/podman/containers_prune.go b/cmd/podman/containers_prune.go index 97481fb35..b8a84a0e3 100644 --- a/cmd/podman/containers_prune.go +++ b/cmd/podman/containers_prune.go @@ -43,7 +43,7 @@ func pruneContainersCmd(c *cliconfig.PruneContainersValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) maxWorkers := shared.DefaultPoolSize("prune") if c.GlobalIsSet("max-workers") { diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go index f6ac5f8f7..7c28edd26 100644 --- a/cmd/podman/cp.go +++ b/cmd/podman/cp.go @@ -68,7 +68,7 @@ func cpCmd(c *cliconfig.CpValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) return copyBetweenHostAndContainer(runtime, args[0], args[1], c.Extract, c.Pause) } @@ -95,7 +95,11 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin if err != nil { return err } - defer ctr.Unmount(false) + defer func() { + if err := ctr.Unmount(false); err != nil { + logrus.Errorf("unable to umount container '%s': %q", ctr.ID(), err) + } + }() // We can't pause rootless containers. if pause && rootless.IsRootless() { diff --git a/cmd/podman/create.go b/cmd/podman/create.go index 2351f5860..93141a800 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -57,7 +57,7 @@ func createCmd(c *cliconfig.CreateValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) cid, err := runtime.CreateContainer(getContext(), c) if err != nil { diff --git a/cmd/podman/diff.go b/cmd/podman/diff.go index 032c0f2c0..2b0c1d398 100644 --- a/cmd/podman/diff.go +++ b/cmd/podman/diff.go @@ -61,8 +61,7 @@ func init() { flags.BoolVar(&diffCommand.Archive, "archive", true, "Save the diff as a tar archive") flags.StringVar(&diffCommand.Format, "format", "", "Change the output format") flags.BoolVarP(&diffCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - - flags.MarkHidden("archive") + markFlagHidden(flags, "archive") markFlagHiddenForRemoteClient("latest", flags) } @@ -93,7 +92,7 @@ func diffCmd(c *cliconfig.DiffValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) var to string if c.Latest { @@ -137,7 +136,5 @@ func diffCmd(c *cliconfig.DiffValues) error { } else { out = stdoutStruct{output: diffOutput} } - formats.Writer(out).Out() - - return nil + return formats.Writer(out).Out() } diff --git a/cmd/podman/events.go b/cmd/podman/events.go index 88c1010e3..18126e626 100644 --- a/cmd/podman/events.go +++ b/cmd/podman/events.go @@ -36,7 +36,7 @@ func init() { flags.BoolVar(&eventsCommand.Stream, "stream", true, "stream new events; for testing only") flags.StringVar(&eventsCommand.Since, "since", "", "show all events created since timestamp") flags.StringVar(&eventsCommand.Until, "until", "", "show all events until timestamp") - flags.MarkHidden("stream") + markFlagHidden(flags, "stream") } func eventsCmd(c *cliconfig.EventValues) error { @@ -44,7 +44,7 @@ func eventsCmd(c *cliconfig.EventValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) return runtime.Events(c) } diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go index bf8de69fc..799ed9f38 100644 --- a/cmd/podman/exec.go +++ b/cmd/podman/exec.go @@ -64,7 +64,7 @@ func execCmd(c *cliconfig.ExecValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) err = runtime.Exec(c, cmd) if errors.Cause(err) == define.ErrCtrStateInvalid { diff --git a/cmd/podman/exists.go b/cmd/podman/exists.go index 1e052e25f..f8b1f8e59 100644 --- a/cmd/podman/exists.go +++ b/cmd/podman/exists.go @@ -90,7 +90,7 @@ func imageExistsCmd(c *cliconfig.ImageExistsValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if _, err := runtime.NewImageFromLocal(args[0]); err != nil { //TODO we need to ask about having varlink defined errors exposed //so we can reuse them @@ -111,7 +111,7 @@ func containerExistsCmd(c *cliconfig.ContainerExistsValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if _, err := runtime.LookupContainer(args[0]); err != nil { if errors.Cause(err) == define.ErrNoSuchCtr || err.Error() == "io.podman.ContainerNotFound" { os.Exit(1) @@ -130,7 +130,7 @@ func podExistsCmd(c *cliconfig.PodExistsValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if _, err := runtime.LookupPod(args[0]); err != nil { if errors.Cause(err) == define.ErrNoSuchPod || err.Error() == "io.podman.PodNotFound" { diff --git a/cmd/podman/export.go b/cmd/podman/export.go index f2336167b..27948004c 100644 --- a/cmd/podman/export.go +++ b/cmd/podman/export.go @@ -45,7 +45,7 @@ func exportCmd(c *cliconfig.ExportValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) args := c.InputArgs if len(args) == 0 { diff --git a/cmd/podman/generate_kube.go b/cmd/podman/generate_kube.go index 3969e3132..6f04d6517 100644 --- a/cmd/podman/generate_kube.go +++ b/cmd/podman/generate_kube.go @@ -62,7 +62,7 @@ func generateKubeYAMLCmd(c *cliconfig.GenerateKubeValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) podYAML, serviceYAML, err := runtime.GenerateKube(c) if err != nil { diff --git a/cmd/podman/generate_systemd.go b/cmd/podman/generate_systemd.go index b4779e512..8be097c83 100644 --- a/cmd/podman/generate_systemd.go +++ b/cmd/podman/generate_systemd.go @@ -50,7 +50,7 @@ func generateSystemdCmd(c *cliconfig.GenerateSystemdValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) // User input stop timeout must be 0 or greater if c.Flag("timeout").Changed && c.StopTimeout < 0 { diff --git a/cmd/podman/healthcheck_run.go b/cmd/podman/healthcheck_run.go index aaeed93c6..66ca4580a 100644 --- a/cmd/podman/healthcheck_run.go +++ b/cmd/podman/healthcheck_run.go @@ -42,6 +42,7 @@ func healthCheckCmd(c *cliconfig.HealthCheckValues) error { if err != nil { return errors.Wrap(err, "could not get runtime") } + defer runtime.DeferredShutdown(false) status, err := runtime.HealthCheck(c) fmt.Println(status) return err diff --git a/cmd/podman/history.go b/cmd/podman/history.go index 0998a023c..fea2219bc 100644 --- a/cmd/podman/history.go +++ b/cmd/podman/history.go @@ -71,7 +71,7 @@ func historyCmd(c *cliconfig.HistoryValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) format := genHistoryFormat(c.Format, c.Quiet) diff --git a/cmd/podman/images.go b/cmd/podman/images.go index 33cf11ab7..f842573d9 100644 --- a/cmd/podman/images.go +++ b/cmd/podman/images.go @@ -138,7 +138,7 @@ func imagesCmd(c *cliconfig.ImagesValues) error { if err != nil { return errors.Wrapf(err, "Could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if len(c.InputArgs) == 1 { image = c.InputArgs[0] } diff --git a/cmd/podman/images_prune.go b/cmd/podman/images_prune.go index 1ac5bc65d..5745edd6b 100644 --- a/cmd/podman/images_prune.go +++ b/cmd/podman/images_prune.go @@ -41,7 +41,7 @@ func pruneImagesCmd(c *cliconfig.PruneImagesValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) // Call prune; if any cids are returned, print them and then // return err in case an error also came up diff --git a/cmd/podman/import.go b/cmd/podman/import.go index 167d9f2c9..70ea167cb 100644 --- a/cmd/podman/import.go +++ b/cmd/podman/import.go @@ -49,7 +49,7 @@ func importCmd(c *cliconfig.ImportValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) var ( source string diff --git a/cmd/podman/info.go b/cmd/podman/info.go index e24fe3c77..ed60970b6 100644 --- a/cmd/podman/info.go +++ b/cmd/podman/info.go @@ -55,7 +55,7 @@ func infoCmd(c *cliconfig.InfoValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) infoArr, err := runtime.Info() if err != nil { @@ -97,9 +97,7 @@ func infoCmd(c *cliconfig.InfoValues) error { out = formats.StdoutTemplate{Output: info, Template: infoOutputFormat} } - formats.Writer(out).Out() - - return nil + return formats.Writer(out).Out() } // top-level "debug" info diff --git a/cmd/podman/init.go b/cmd/podman/init.go index 68c80631d..3f97824fc 100644 --- a/cmd/podman/init.go +++ b/cmd/podman/init.go @@ -54,7 +54,7 @@ func initCmd(c *cliconfig.InitValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) ok, failures, err := runtime.InitContainers(ctx, c) if err != nil { diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go index 24edfcb68..df597c868 100644 --- a/cmd/podman/inspect.go +++ b/cmd/podman/inspect.go @@ -88,7 +88,7 @@ func inspectCmd(c *cliconfig.InspectValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if !util.StringInSlice(inspectType, []string{inspectTypeContainer, inspectTypeImage, inspectAll}) { return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll) @@ -193,8 +193,8 @@ func iterateInput(ctx context.Context, size bool, args []string, runtime *adapte inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID()) break } - artifact, inspectError := getArtifact(ctr) - if inspectError != nil { + artifact, err := getArtifact(ctr) + if err != nil { inspectError = err break } diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go index edf69ff2e..d5056d86d 100644 --- a/cmd/podman/kill.go +++ b/cmd/podman/kill.go @@ -63,7 +63,7 @@ func killCmd(c *cliconfig.KillValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) ok, failures, err := runtime.KillContainers(getContext(), c, killSignal) if err != nil { diff --git a/cmd/podman/load.go b/cmd/podman/load.go index 0c41eb792..ed6a4e5fa 100644 --- a/cmd/podman/load.go +++ b/cmd/podman/load.go @@ -43,7 +43,7 @@ func init() { // Disabled flags for the remote client if !remote { flags.StringVar(&loadCommand.SignaturePolicy, "signature-policy", "", "Pathname of signature policy file (not usually used)") - flags.MarkHidden("signature-policy") + markFlagHidden(flags, "signature-policy") } } @@ -65,7 +65,7 @@ func loadCmd(c *cliconfig.LoadValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if len(c.Input) > 0 { if err := parse.ValidateFileName(c.Input); err != nil { diff --git a/cmd/podman/logs.go b/cmd/podman/logs.go index 25248db21..32605389e 100644 --- a/cmd/podman/logs.go +++ b/cmd/podman/logs.go @@ -54,8 +54,7 @@ func init() { flags.StringVar(&logsCommand.Since, "since", "", "Show logs since TIMESTAMP") flags.Uint64Var(&logsCommand.Tail, "tail", 0, "Output the specified number of LINES at the end of the logs. Defaults to 0, which prints all lines") flags.BoolVarP(&logsCommand.Timestamps, "timestamps", "t", false, "Output the timestamps in the log") - flags.MarkHidden("details") - + markFlagHidden(flags, "details") flags.SetInterspersed(false) markFlagHiddenForRemoteClient("latest", flags) @@ -68,7 +67,7 @@ func logsCmd(c *cliconfig.LogsValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) sinceTime := time.Time{} if c.Flag("since").Changed { diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go index d5f70a28f..e4f521bc4 100644 --- a/cmd/podman/main_local.go +++ b/cmd/podman/main_local.go @@ -45,14 +45,18 @@ func init() { rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.NetworkCmdPath, "network-cmd-path", "", "Path to the command for configuring the network") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CniConfigDir, "cni-config-dir", "", "Path of the configuration directory for CNI networks") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.DefaultMountsFile, "default-mounts-file", "", "Path to default mounts file") - rootCmd.PersistentFlags().MarkHidden("defaults-mount-file") + if err := rootCmd.PersistentFlags().MarkHidden("default-mounts-file"); err != nil { + logrus.Error("unable to mark default-mounts-file flag as hidden") + } // Override default --help information of `--help` global flag var dummyHelp bool rootCmd.PersistentFlags().BoolVar(&dummyHelp, "help", false, "Help for podman") rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.HooksDir, "hooks-dir", []string{}, "Set the OCI hooks directory path (may be set multiple times)") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", "Log messages above specified level: debug, info, warn, error, fatal or panic") rootCmd.PersistentFlags().IntVar(&MainGlobalOpts.MaxWorks, "max-workers", 0, "The maximum number of workers for parallel operations") - rootCmd.PersistentFlags().MarkHidden("max-workers") + if err := rootCmd.PersistentFlags().MarkHidden("max-workers"); err != nil { + logrus.Error("unable to mark max-workers flag as hidden") + } rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Namespace, "namespace", "", "Set the libpod namespace, used to create separate views of the containers and pods on the system") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Root, "root", "", "Path to the root directory in which data, including images, is stored") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored") @@ -118,10 +122,10 @@ func setupRootless(cmd *cobra.Command, args []string) error { return nil } podmanCmd := cliconfig.PodmanCommand{ - cmd, - args, - MainGlobalOpts, - remoteclient, + Command: cmd, + InputArgs: args, + GlobalFlags: MainGlobalOpts, + Remote: remoteclient, } pausePidPath, err := util.GetRootlessPauseProcessPidPath() @@ -148,7 +152,7 @@ func setupRootless(cmd *cobra.Command, args []string) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) ctrs, err := runtime.GetRunningContainers() if err != nil { diff --git a/cmd/podman/mount.go b/cmd/podman/mount.go index 662fb0a28..b14827592 100644 --- a/cmd/podman/mount.go +++ b/cmd/podman/mount.go @@ -65,7 +65,7 @@ func mountCmd(c *cliconfig.MountValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if os.Geteuid() != 0 { rtc, err := runtime.GetConfig() diff --git a/cmd/podman/pause.go b/cmd/podman/pause.go index ee5fd352d..3a8f4edb5 100644 --- a/cmd/podman/pause.go +++ b/cmd/podman/pause.go @@ -46,7 +46,7 @@ func pauseCmd(c *cliconfig.PauseValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) args := c.InputArgs if len(args) < 1 && !c.All { diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go index afdb6cc9b..9a5cc3ec1 100644 --- a/cmd/podman/play_kube.go +++ b/cmd/podman/play_kube.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/pkg/adapter" @@ -45,7 +44,7 @@ func init() { flags.StringVar(&playKubeCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys") flags.StringVar(&playKubeCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") flags.BoolVar(&playKubeCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") - flags.MarkHidden("signature-policy") + markFlagHidden(flags, "signature-policy") } } @@ -63,7 +62,7 @@ func playKubeCmd(c *cliconfig.KubePlayValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) _, err = runtime.PlayKubeYAML(ctx, c, args[0]) return err diff --git a/cmd/podman/pod_create.go b/cmd/podman/pod_create.go index 0abf84756..b6154b4db 100644 --- a/cmd/podman/pod_create.go +++ b/cmd/podman/pod_create.go @@ -8,6 +8,7 @@ import ( "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" + "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -56,7 +57,6 @@ func init() { flags.StringVar(&podCreateCommand.Share, "share", shared.DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share") } - func podCreateCmd(c *cliconfig.PodCreateValues) error { var ( err error @@ -67,7 +67,7 @@ func podCreateCmd(c *cliconfig.PodCreateValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if len(c.Publish) > 0 { if !c.Infra { @@ -86,8 +86,8 @@ func podCreateCmd(c *cliconfig.PodCreateValues) error { if err != nil { return errors.Errorf("error opening pod-id-file %s", c.PodIDFile) } - defer podIdFile.Close() - defer podIdFile.Sync() + defer errorhandling.CloseQuiet(podIdFile) + defer errorhandling.SyncQuiet(podIdFile) } labels, err := shared.GetAllLabels(c.LabelFile, c.Labels) diff --git a/cmd/podman/pod_inspect.go b/cmd/podman/pod_inspect.go index a22624078..03b5a8cc4 100644 --- a/cmd/podman/pod_inspect.go +++ b/cmd/podman/pod_inspect.go @@ -53,7 +53,7 @@ func podInspectCmd(c *cliconfig.PodInspectValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if c.Latest { pod, err = runtime.GetLatestPod() diff --git a/cmd/podman/pod_kill.go b/cmd/podman/pod_kill.go index 6be79363a..9bda77471 100644 --- a/cmd/podman/pod_kill.go +++ b/cmd/podman/pod_kill.go @@ -53,7 +53,7 @@ func podKillCmd(c *cliconfig.PodKillValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) killSignal := uint(syscall.SIGTERM) diff --git a/cmd/podman/pod_pause.go b/cmd/podman/pod_pause.go index e8574bfdc..75d179f52 100644 --- a/cmd/podman/pod_pause.go +++ b/cmd/podman/pod_pause.go @@ -49,7 +49,7 @@ func podPauseCmd(c *cliconfig.PodPauseValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) pauseIDs, conErrors, pauseErrors := runtime.PausePods(c) diff --git a/cmd/podman/pod_ps.go b/cmd/podman/pod_ps.go index fbea5124e..fd8da53fb 100644 --- a/cmd/podman/pod_ps.go +++ b/cmd/podman/pod_ps.go @@ -20,7 +20,7 @@ import ( ) const ( - STOPPED = "Stopped" + STOPPED = "Stopped" //nolint RUNNING = "Running" PAUSED = "Paused" EXITED = "Exited" @@ -36,9 +36,9 @@ var ( ) type podPsCtrInfo struct { - Name string `"json:name,omitempty"` - Id string `"json:id,omitempty"` - Status string `"json:status,omitempty"` + Name string `json:"name,omitempty"` + Id string `json:"id,omitempty"` + Status string `json:"status,omitempty"` } type podPsOptions struct { @@ -161,7 +161,7 @@ func podPsCmd(c *cliconfig.PodPsValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) opts := podPsOptions{ NoTrunc: c.NoTrunc, @@ -552,9 +552,6 @@ func generatePodPsOutput(pods []*adapter.Pod, opts podPsOptions) error { switch opts.Format { case formats.JSONString: - if err != nil { - return errors.Wrapf(err, "unable to create JSON for output") - } out = formats.JSONStructArray{Output: podPsToGeneric([]podPsTemplateParams{}, psOutput)} default: psOutput, err := getPodTemplateOutput(psOutput, opts) diff --git a/cmd/podman/pod_restart.go b/cmd/podman/pod_restart.go index a1f4c8359..0b009e6c7 100644 --- a/cmd/podman/pod_restart.go +++ b/cmd/podman/pod_restart.go @@ -51,7 +51,7 @@ func podRestartCmd(c *cliconfig.PodRestartValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) restartIDs, conErrors, restartErrors := runtime.RestartPods(getContext(), c) diff --git a/cmd/podman/pod_rm.go b/cmd/podman/pod_rm.go index 218ed8154..82d0eb977 100644 --- a/cmd/podman/pod_rm.go +++ b/cmd/podman/pod_rm.go @@ -51,7 +51,7 @@ func podRmCmd(c *cliconfig.PodRmValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) podRmIds, podRmErrors := runtime.RemovePods(getContext(), c) for _, p := range podRmIds { diff --git a/cmd/podman/pod_start.go b/cmd/podman/pod_start.go index 5c9225428..64c951b43 100644 --- a/cmd/podman/pod_start.go +++ b/cmd/podman/pod_start.go @@ -49,7 +49,7 @@ func podStartCmd(c *cliconfig.PodStartValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) podStartIDs, podStartErrors := runtime.StartPods(getContext(), c) for _, p := range podStartIDs { diff --git a/cmd/podman/pod_stats.go b/cmd/podman/pod_stats.go index 97aa52f5d..7984f08ee 100644 --- a/cmd/podman/pod_stats.go +++ b/cmd/podman/pod_stats.go @@ -74,16 +74,13 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error { if ctr > 1 { return errors.Errorf("--all, --latest and containers cannot be used together") - } else if ctr == 0 { - // If user didn't specify, imply --all - all = true } runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) times := -1 if c.NoStream { @@ -173,7 +170,9 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error { tm.Flush() } if strings.ToLower(format) == formats.JSONString { - outputJson(newStats) + if err := outputJson(newStats); err != nil { + return err + } } else { results := podContainerStatsToPodStatOut(newStats) @@ -300,17 +299,3 @@ func outputJson(stats []*adapter.PodContainerStats) error { fmt.Println(string(b)) return nil } - -func getPodsByList(podList []string, r *libpod.Runtime) ([]*libpod.Pod, error) { - var ( - pods []*libpod.Pod - ) - for _, p := range podList { - pod, err := r.LookupPod(p) - if err != nil { - return nil, err - } - pods = append(pods, pod) - } - return pods, nil -} diff --git a/cmd/podman/pod_stop.go b/cmd/podman/pod_stop.go index b4b1718d9..edda99550 100644 --- a/cmd/podman/pod_stop.go +++ b/cmd/podman/pod_stop.go @@ -51,7 +51,7 @@ func podStopCmd(c *cliconfig.PodStopValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) podStopIds, podStopErrors := runtime.StopPods(getContext(), c) for _, p := range podStopIds { diff --git a/cmd/podman/pod_top.go b/cmd/podman/pod_top.go index 72137b5a7..fcd9c4f3c 100644 --- a/cmd/podman/pod_top.go +++ b/cmd/podman/pod_top.go @@ -44,8 +44,7 @@ func init() { flags := podTopCommand.Flags() flags.BoolVarP(&podTopCommand.Latest, "latest,", "l", false, "Act on the latest pod podman is aware of") flags.BoolVar(&podTopCommand.ListDescriptors, "list-descriptors", false, "") - flags.MarkHidden("list-descriptors") - + markFlagHidden(flags, "list-descriptors") } func podTopCmd(c *cliconfig.PodTopValues) error { @@ -71,7 +70,7 @@ func podTopCmd(c *cliconfig.PodTopValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if c.Latest { descriptors = args @@ -85,8 +84,9 @@ func podTopCmd(c *cliconfig.PodTopValues) error { return err } for _, proc := range psOutput { - fmt.Fprintln(w, proc) + if _, err := fmt.Fprintln(w, proc); err != nil { + return err + } } - w.Flush() - return nil + return w.Flush() } diff --git a/cmd/podman/pod_unpause.go b/cmd/podman/pod_unpause.go index c5b7e6a18..91c3bfdf8 100644 --- a/cmd/podman/pod_unpause.go +++ b/cmd/podman/pod_unpause.go @@ -50,7 +50,7 @@ func podUnpauseCmd(c *cliconfig.PodUnpauseValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) unpauseIDs, conErrors, unpauseErrors := runtime.UnpausePods(c) diff --git a/cmd/podman/pods_prune.go b/cmd/podman/pods_prune.go index bdd75f9de..d40e37bdb 100644 --- a/cmd/podman/pods_prune.go +++ b/cmd/podman/pods_prune.go @@ -40,8 +40,11 @@ func podPruneCmd(c *cliconfig.PodPruneValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) ok, failures, err := runtime.PrunePods(getContext(), c) + if err != nil { + return err + } return printCmdResults(ok, failures) } diff --git a/cmd/podman/port.go b/cmd/podman/port.go index 1bd2d623e..5753c8e56 100644 --- a/cmd/podman/port.go +++ b/cmd/podman/port.go @@ -95,9 +95,12 @@ func portCmd(c *cliconfig.PortValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) containers, err := runtime.Port(c) + if err != nil { + return err + } for _, con := range containers { portmappings, err := con.PortMappings() if err != nil { diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index 75e07d325..9fad0ea65 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -15,87 +15,32 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/pkg/adapter" - "github.com/cri-o/ocicni/pkg/ocicni" "github.com/docker/go-units" "github.com/pkg/errors" "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/fields" ) const ( - mountTruncLength = 12 - hid = "CONTAINER ID" - himage = "IMAGE" - hcommand = "COMMAND" - hcreated = "CREATED" - hstatus = "STATUS" - hports = "PORTS" - hnames = "NAMES" - hsize = "SIZE" - hinfra = "IS INFRA" - hpod = "POD" - nspid = "PID" - nscgroup = "CGROUPNS" - nsipc = "IPC" - nsmnt = "MNT" - nsnet = "NET" - nspidns = "PIDNS" - nsuserns = "USERNS" - nsuts = "UTS" + hid = "CONTAINER ID" + himage = "IMAGE" + hcommand = "COMMAND" + hcreated = "CREATED" + hstatus = "STATUS" + hports = "PORTS" + hnames = "NAMES" + hsize = "SIZE" + hinfra = "IS INFRA" //nolint + hpod = "POD" + nspid = "PID" + nscgroup = "CGROUPNS" + nsipc = "IPC" + nsmnt = "MNT" + nsnet = "NET" + nspidns = "PIDNS" + nsuserns = "USERNS" + nsuts = "UTS" ) -type psTemplateParams struct { - ID string - Image string - Command string - CreatedAtTime time.Time - Created string - Status string - Ports string - Size string - Names string - Labels string - Mounts string - PID int - CGROUPNS string - IPC string - MNT string - NET string - PIDNS string - USERNS string - UTS string - Pod string - IsInfra bool -} - -// psJSONParams is used as a base structure for the psParams -// If template output is requested, psJSONParams will be converted to -// psTemplateParams. -// psJSONParams will be populated by data from libpod.Container, -// the members of the struct are the sama data types as their sources. -type psJSONParams struct { - ID string `json:"id"` - Image string `json:"image"` - ImageID string `json:"image_id"` - Command []string `json:"command"` - ExitCode int32 `json:"exitCode"` - Exited bool `json:"exited"` - CreatedAt time.Time `json:"createdAt"` - StartedAt time.Time `json:"startedAt"` - ExitedAt time.Time `json:"exitedAt"` - Status string `json:"status"` - PID int `json:"PID"` - Ports []ocicni.PortMapping `json:"ports"` - Size *shared.ContainerSize `json:"size,omitempty"` - Names string `json:"names"` - Labels fields.Set `json:"labels"` - Mounts []string `json:"mounts"` - ContainerRunning bool `json:"ctrRunning"` - Namespaces *shared.Namespace `json:"namespace,omitempty"` - Pod string `json:"pod,omitempty"` - IsInfra bool `json:"infra"` -} - // Type declaration and functions for sorting the PS output type psSorted []shared.PsContainerOutput @@ -223,7 +168,7 @@ func psCmd(c *cliconfig.PsValues) error { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if !watch { if err := psDisplay(c, runtime); err != nil { @@ -273,22 +218,6 @@ func checkFlagsPassed(c *cliconfig.PsValues) error { return nil } -// generate the accurate header based on template given -func (p *psTemplateParams) headerMap() map[string]string { - v := reflect.Indirect(reflect.ValueOf(p)) - values := make(map[string]string) - - for i := 0; i < v.NumField(); i++ { - key := v.Type().Field(i).Name - value := key - if value == "ID" { - value = "Container" + value - } - values[key] = strings.ToUpper(splitCamelCase(value)) - } - return values -} - func sortPsOutput(sortBy string, psOutput psSorted) (psSorted, error) { switch sortBy { case "id": @@ -390,6 +319,9 @@ func psDisplay(c *cliconfig.PsValues, runtime *adapter.LocalRuntime) error { } pss, err := runtime.Ps(c, opts) + if err != nil { + return err + } // Here and down if opts.Sort != "" { pss, err = sortPsOutput(opts.Sort, pss) @@ -447,8 +379,8 @@ func psDisplay(c *cliconfig.PsValues, runtime *adapter.LocalRuntime) error { size = units.HumanSizeWithPrecision(0, 0) } else { size = units.HumanSizeWithPrecision(float64(container.Size.RwSize), 3) + " (virtual " + units.HumanSizeWithPrecision(float64(container.Size.RootFsSize), 3) + ")" - fmt.Fprintf(w, "\t%s", size) } + fmt.Fprintf(w, "\t%s", size) } } else { diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go index 61cf1fd4d..0eee51e79 100644 --- a/cmd/podman/pull.go +++ b/cmd/podman/pull.go @@ -60,7 +60,7 @@ func init() { flags.StringVar(&pullCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys") flags.StringVar(&pullCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") flags.BoolVar(&pullCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") - flags.MarkHidden("signature-policy") + markFlagHidden(flags, "signature-policy") } } @@ -82,7 +82,7 @@ func pullCmd(c *cliconfig.PullValues) (retError error) { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) args := c.InputArgs if len(args) == 0 { diff --git a/cmd/podman/push.go b/cmd/podman/push.go index a15d8e699..43df8c2de 100644 --- a/cmd/podman/push.go +++ b/cmd/podman/push.go @@ -63,7 +63,7 @@ func init() { flags.BoolVar(&pushCommand.Compress, "compress", false, "Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type as source)") flags.StringVar(&pushCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") flags.BoolVar(&pushCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") - flags.MarkHidden("signature-policy") + markFlagHidden(flags, "signature-policy") } } @@ -109,7 +109,7 @@ func pushCmd(c *cliconfig.PushValues) error { if err != nil { return errors.Wrapf(err, "could not create runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) var writer io.Writer if !c.Quiet { diff --git a/cmd/podman/refresh.go b/cmd/podman/refresh.go index 9f9cbf908..b21a4ff79 100644 --- a/cmd/podman/refresh.go +++ b/cmd/podman/refresh.go @@ -42,7 +42,7 @@ func refreshCmd(c *cliconfig.RefreshValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) allCtrs, err := runtime.GetAllContainers() if err != nil { diff --git a/cmd/podman/restart.go b/cmd/podman/restart.go index 89bda7d6c..494a9ec06 100644 --- a/cmd/podman/restart.go +++ b/cmd/podman/restart.go @@ -55,7 +55,7 @@ func restartCmd(c *cliconfig.RestartValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) ok, failures, err := runtime.Restart(getContext(), c) if err != nil { diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go index fcac9855d..c4146eff0 100644 --- a/cmd/podman/restore.go +++ b/cmd/podman/restore.go @@ -58,7 +58,7 @@ func restoreCmd(c *cliconfig.RestoreValues, cmd *cobra.Command) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if c.Import == "" && c.Name != "" { return errors.Errorf("--name can only used with --import") diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go index 0f81a0d63..958ca1c60 100644 --- a/cmd/podman/rm.go +++ b/cmd/podman/rm.go @@ -54,7 +54,7 @@ func rmCmd(c *cliconfig.RmValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) // Storage conflicts with --all/--latest/--volumes if c.Storage { diff --git a/cmd/podman/rmi.go b/cmd/podman/rmi.go index 4c41a3ad5..9229d497e 100644 --- a/cmd/podman/rmi.go +++ b/cmd/podman/rmi.go @@ -55,7 +55,7 @@ func rmiCmd(c *cliconfig.RmiValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) args := c.InputArgs if len(args) == 0 && !removeAll { diff --git a/cmd/podman/run.go b/cmd/podman/run.go index 6f089e5a4..76ab3d944 100644 --- a/cmd/podman/run.go +++ b/cmd/podman/run.go @@ -37,7 +37,6 @@ func init() { flags.Bool("sig-proxy", true, "Proxy received signals to the process") getCreateFlags(&runCommand.PodmanCommand) markFlagHiddenForRemoteClient("authfile", flags) - flags.MarkHidden("signature-policy") } func runCmd(c *cliconfig.RunValues) error { @@ -54,7 +53,7 @@ func runCmd(c *cliconfig.RunValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) exitCode, err = runtime.Run(getContext(), c, exitCode) return err diff --git a/cmd/podman/runlabel.go b/cmd/podman/runlabel.go index fdbf7fa8f..db6d390d5 100644 --- a/cmd/podman/runlabel.go +++ b/cmd/podman/runlabel.go @@ -53,10 +53,9 @@ func init() { flags.StringVar(&runlabelCommand.Opt1, "opt1", "", "Optional parameter to pass for install") flags.StringVar(&runlabelCommand.Opt2, "opt2", "", "Optional parameter to pass for install") flags.StringVar(&runlabelCommand.Opt3, "opt3", "", "Optional parameter to pass for install") - flags.MarkHidden("opt1") - flags.MarkHidden("opt2") - flags.MarkHidden("opt3") - + markFlagHidden(flags, "opt1") + markFlagHidden(flags, "opt2") + markFlagHidden(flags, "opt3") flags.BoolP("pull", "p", false, "Pull the image if it does not exist locally prior to executing the label contents") flags.BoolVarP(&runlabelCommand.Quiet, "quiet", "q", false, "Suppress output information when installing images") // Disabled flags for the remote client @@ -66,10 +65,11 @@ func init() { flags.StringVar(&runlabelCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") flags.BoolVar(&runlabelCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") - flags.MarkDeprecated("pull", "podman will pull if not found in local storage") - flags.MarkHidden("signature-policy") + if err := flags.MarkDeprecated("pull", "podman will pull if not found in local storage"); err != nil { + logrus.Error("unable to mark pull flag deprecated") + } + markFlagHidden(flags, "signature-policy") } - markFlagHiddenForRemoteClient("authfile", flags) } // installCmd gets the data from the command line and calls installImage @@ -95,7 +95,7 @@ func runlabelCmd(c *cliconfig.RunlabelValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) args := c.InputArgs if len(args) < 2 { diff --git a/cmd/podman/save.go b/cmd/podman/save.go index e59c9df5f..237ebde03 100644 --- a/cmd/podman/save.go +++ b/cmd/podman/save.go @@ -74,7 +74,7 @@ func saveCmd(c *cliconfig.SaveValues) error { if err != nil { return errors.Wrapf(err, "could not create runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if c.Flag("compress").Changed && (c.Format != ociManifestDir && c.Format != v2s2ManifestDir && c.Format == "") { return errors.Errorf("--compress can only be set when --format is either 'oci-dir' or 'docker-dir'") diff --git a/cmd/podman/search.go b/cmd/podman/search.go index f1c625ee1..be75b6e37 100644 --- a/cmd/podman/search.go +++ b/cmd/podman/search.go @@ -13,11 +13,6 @@ import ( "github.com/spf13/cobra" ) -const ( - descriptionTruncLength = 44 - maxQueries = 25 -) - var ( searchCommand cliconfig.SearchValues searchDescription = `Search registries for a given image. Can search all the default registries or a specific registry. @@ -89,8 +84,7 @@ func searchCmd(c *cliconfig.SearchValues) error { return nil } out := formats.StdoutTemplateArray{Output: searchToGeneric(results), Template: format, Fields: searchHeaderMap()} - formats.Writer(out).Out() - return nil + return formats.Writer(out).Out() } // searchHeaderMap returns the headers of a SearchResult. diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go index df4583be6..3c68a29b4 100644 --- a/cmd/podman/shared/container.go +++ b/cmd/podman/shared/container.go @@ -305,7 +305,7 @@ func generateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) } return func(c *libpod.Container) bool { ec, exited, err := c.ExitCode() - if ec == int32(exitCode) && err == nil && exited == true { + if ec == int32(exitCode) && err == nil && exited { return true } return false @@ -611,7 +611,7 @@ func getNamespaceInfo(path string) (string, error) { // getStrFromSquareBrackets gets the string inside [] from a string func getStrFromSquareBrackets(cmd string) string { - reg, err := regexp.Compile(".*\\[|\\].*") + reg, err := regexp.Compile(`.*\[|\].*`) if err != nil { return "" } diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index 64cef1e89..60a01ff6d 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/containers/libpod/pkg/errorhandling" "io" "os" "path/filepath" @@ -63,8 +64,8 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. if err != nil { return nil, nil, errors.Errorf("error opening cidfile %s", c.String("cidfile")) } - defer cidFile.Close() - defer cidFile.Sync() + defer errorhandling.CloseQuiet(cidFile) + defer errorhandling.SyncQuiet(cidFile) } imageName := "" @@ -82,6 +83,9 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. return nil, nil, err } data, err = newImage.Inspect(ctx) + if err != nil { + return nil, nil, err + } names := newImage.Names() if len(names) > 0 { imageName = names[0] @@ -89,9 +93,8 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. imageName = newImage.ID() } - var healthCheckCommandInput string // if the user disabled the healthcheck with "none", we skip adding it - healthCheckCommandInput = c.String("healthcheck-command") + 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 diff --git a/cmd/podman/shared/create_cli.go b/cmd/podman/shared/create_cli.go index 4bfef8b62..08a40b206 100644 --- a/cmd/podman/shared/create_cli.go +++ b/cmd/podman/shared/create_cli.go @@ -133,7 +133,7 @@ func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, e if config.Resources.KernelMemory > 0 && config.Resources.KernelMemory < linuxMinMemory { return warnings, fmt.Errorf("minimum kernel memory limit allowed is 4MB") } - if config.Resources.DisableOomKiller == true && !sysInfo.OomKillDisable { + if config.Resources.DisableOomKiller && !sysInfo.OomKillDisable { // only produce warnings if the setting wasn't to *disable* the OOM Kill; no point // warning the caller if they already wanted the feature to be off warnings = addWarning(warnings, "Your kernel does not support OomKillDisable. OomKillDisable discarded.") diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go index 0c25eec62..1333cf441 100644 --- a/cmd/podman/sign.go +++ b/cmd/podman/sign.go @@ -60,7 +60,7 @@ func signCmd(c *cliconfig.SignValues) error { if err != nil { return errors.Wrapf(err, "could not create runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) signby := c.SignBy if signby == "" { diff --git a/cmd/podman/start.go b/cmd/podman/start.go index 165273114..737a6d9f1 100644 --- a/cmd/podman/start.go +++ b/cmd/podman/start.go @@ -69,7 +69,7 @@ func startCmd(c *cliconfig.StartValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) exitCode, err = runtime.Start(getContext(), c, sigProxy) return err } diff --git a/cmd/podman/stats.go b/cmd/podman/stats.go index d79eebc3d..05e30f95f 100644 --- a/cmd/podman/stats.go +++ b/cmd/podman/stats.go @@ -93,7 +93,7 @@ func statsCmd(c *cliconfig.StatsValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) times := -1 if c.NoStream { @@ -101,9 +101,8 @@ func statsCmd(c *cliconfig.StatsValues) error { } var ctrs []*libpod.Container - var containerFunc func() ([]*libpod.Container, error) - containerFunc = runtime.GetRunningContainers + containerFunc := runtime.GetRunningContainers if len(c.InputArgs) > 0 { containerFunc = func() ([]*libpod.Container, error) { return runtime.GetContainersByList(c.InputArgs) } } else if latest { @@ -175,7 +174,9 @@ func statsCmd(c *cliconfig.StatsValues) error { tm.MoveCursor(1, 1) tm.Flush() } - outputStats(reportStats, format) + if err := outputStats(reportStats, format); err != nil { + return err + } time.Sleep(time.Second) } return nil diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go index 5c93904ef..e04d8a12b 100644 --- a/cmd/podman/stop.go +++ b/cmd/podman/stop.go @@ -60,7 +60,7 @@ func stopCmd(c *cliconfig.StopValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) ok, failures, err := runtime.StopContainers(getContext(), c) if err != nil { diff --git a/cmd/podman/system_df.go b/cmd/podman/system_df.go index ab67e4f07..85554bf05 100644 --- a/cmd/podman/system_df.go +++ b/cmd/podman/system_df.go @@ -106,7 +106,7 @@ func dfSystemCmd(c *cliconfig.SystemDfValues) error { if err != nil { return errors.Wrapf(err, "Could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) ctx := getContext() @@ -131,11 +131,10 @@ func dfSystemCmd(c *cliconfig.SystemDfValues) error { if c.Format != "" { format = strings.Replace(c.Format, `\t`, "\t", -1) } - generateSysDfOutput(systemDfDiskUsages, format) - return nil + return generateSysDfOutput(systemDfDiskUsages, format) } -func generateSysDfOutput(systemDfDiskUsages []systemDfDiskUsage, format string) { +func generateSysDfOutput(systemDfDiskUsages []systemDfDiskUsage, format string) error { var systemDfHeader = map[string]string{ "Type": "TYPE", "Total": "TOTAL", @@ -144,7 +143,7 @@ func generateSysDfOutput(systemDfDiskUsages []systemDfDiskUsage, format string) "Reclaimable": "RECLAIMABLE", } out := formats.StdoutTemplateArray{Output: systemDfDiskUsageToGeneric(systemDfDiskUsages), Template: format, Fields: systemDfHeader} - formats.Writer(out).Out() + return formats.Writer(out).Out() } func getDiskUsage(ctx context.Context, runtime *libpod.Runtime, metaData dfMetaData) ([]systemDfDiskUsage, error) { @@ -554,10 +553,11 @@ func imagesVerboseOutput(ctx context.Context, metaData dfMetaData) error { if err != nil { return errors.Wrapf(err, "error getting verbose output of images") } - os.Stderr.WriteString("Images space usage:\n\n") + if _, err := os.Stderr.WriteString("Images space usage:\n\n"); err != nil { + return err + } out := formats.StdoutTemplateArray{Output: systemDfImageVerboseDiskUsageToGeneric(imagesVerboseDiskUsage), Template: imageVerboseFormat, Fields: imageVerboseHeader} - formats.Writer(out).Out() - return nil + return formats.Writer(out).Out() } func containersVerboseOutput(ctx context.Context, metaData dfMetaData) error { @@ -575,10 +575,12 @@ func containersVerboseOutput(ctx context.Context, metaData dfMetaData) error { if err != nil { return errors.Wrapf(err, "error getting verbose output of containers") } - os.Stderr.WriteString("\nContainers space usage:\n\n") + if _, err := os.Stderr.WriteString("\nContainers space usage:\n\n"); err != nil { + return err + } out := formats.StdoutTemplateArray{Output: systemDfContainerVerboseDiskUsageToGeneric(containersVerboseDiskUsage), Template: containerVerboseFormat, Fields: containerVerboseHeader} - formats.Writer(out).Out() - return nil + return formats.Writer(out).Out() + } func volumesVerboseOutput(ctx context.Context, metaData dfMetaData) error { @@ -591,10 +593,11 @@ func volumesVerboseOutput(ctx context.Context, metaData dfMetaData) error { if err != nil { return errors.Wrapf(err, "error getting verbose output of volumes") } - os.Stderr.WriteString("\nLocal Volumes space usage:\n\n") + if _, err := os.Stderr.WriteString("\nLocal Volumes space usage:\n\n"); err != nil { + return err + } out := formats.StdoutTemplateArray{Output: systemDfVolumeVerboseDiskUsageToGeneric(volumesVerboseDiskUsage), Template: volumeVerboseFormat, Fields: volumeVerboseHeader} - formats.Writer(out).Out() - return nil + return formats.Writer(out).Out() } func verboseOutput(ctx context.Context, metaData dfMetaData) error { diff --git a/cmd/podman/system_prune.go b/cmd/podman/system_prune.go index d5b218cd8..b499d8dd2 100644 --- a/cmd/podman/system_prune.go +++ b/cmd/podman/system_prune.go @@ -76,27 +76,33 @@ Are you sure you want to continue? [y/N] `, volumeString) if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) - - rmWorkers := shared.Parallelize("rm") - ctx := getContext() - fmt.Println("Deleted Containers") - ok, failures, lasterr := runtime.Prune(ctx, rmWorkers, false) - printCmdResults(ok, failures) + defer runtime.DeferredShutdown(false) + // We must clean out pods first because if they may have infra containers fmt.Println("Deleted Pods") pruneValues := cliconfig.PodPruneValues{ PodmanCommand: c.PodmanCommand, Force: c.Force, } - ok, failures, err = runtime.PrunePods(ctx, &pruneValues) + ctx := getContext() + ok, failures, lasterr := runtime.PrunePods(ctx, &pruneValues) + + if err := printCmdResults(ok, failures); err != nil { + return err + } + + rmWorkers := shared.Parallelize("rm") + fmt.Println("Deleted Containers") + ok, failures, err = runtime.Prune(ctx, rmWorkers, false) if err != nil { if lasterr != nil { - logrus.Errorf("%q", lasterr) + logrus.Errorf("%q", err) } lasterr = err } - printCmdResults(ok, failures) + if err := printCmdResults(ok, failures); err != nil { + return err + } if c.Bool("volumes") { fmt.Println("Deleted Volumes") diff --git a/cmd/podman/tag.go b/cmd/podman/tag.go index 58f221e26..eb43d695c 100644 --- a/cmd/podman/tag.go +++ b/cmd/podman/tag.go @@ -42,7 +42,7 @@ func tagCmd(c *cliconfig.TagValues) error { if err != nil { return errors.Wrapf(err, "could not create runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) newImage, err := runtime.NewImageFromLocal(args[0]) if err != nil { diff --git a/cmd/podman/top.go b/cmd/podman/top.go index ba6cbe72d..bfba90fc0 100644 --- a/cmd/podman/top.go +++ b/cmd/podman/top.go @@ -57,7 +57,7 @@ func init() { flags := topCommand.Flags() flags.SetInterspersed(false) flags.BoolVar(&topCommand.ListDescriptors, "list-descriptors", false, "") - flags.MarkHidden("list-descriptors") + markFlagHidden(flags, "list-descriptors") flags.BoolVarP(&topCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") markFlagHiddenForRemoteClient("latest", flags) } @@ -83,7 +83,7 @@ func topCmd(c *cliconfig.TopValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) psOutput, err := runtime.Top(c) if err != nil { @@ -91,8 +91,9 @@ func topCmd(c *cliconfig.TopValues) error { } w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0) for _, proc := range psOutput { - fmt.Fprintln(w, proc) + if _, err := fmt.Fprintln(w, proc); err != nil { + return err + } } - w.Flush() - return nil + return w.Flush() } diff --git a/cmd/podman/tree.go b/cmd/podman/tree.go index 48e192990..904a0d375 100644 --- a/cmd/podman/tree.go +++ b/cmd/podman/tree.go @@ -55,7 +55,7 @@ func treeCmd(c *cliconfig.TreeValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) imageInfo, layerInfoMap, img, err := runtime.Tree(c) if err != nil { return err @@ -107,7 +107,7 @@ func printImageChildren(layerMap map[string]*image.LayerInfo, layerID string, pr if !ok { return fmt.Errorf("lookup error: layerid %s, not found", layerID) } - fmt.Printf(prefix) + fmt.Print(prefix) //initialize intend with middleItem to reduce middleItem checks. intend := middleItem diff --git a/cmd/podman/trust_set_show.go b/cmd/podman/trust_set_show.go index b615f6266..d6f0eabd8 100644 --- a/cmd/podman/trust_set_show.go +++ b/cmd/podman/trust_set_show.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/containers/buildah/pkg/formats" - "github.com/containers/image/types" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/libpod/image" @@ -57,7 +56,7 @@ func init() { showTrustCommand.SetUsageTemplate(UsageTemplate()) setFlags := setTrustCommand.Flags() setFlags.StringVar(&setTrustCommand.PolicyPath, "policypath", "", "") - setFlags.MarkHidden("policypath") + markFlagHidden(setFlags, "policypath") setFlags.StringSliceVarP(&setTrustCommand.PubKeysFile, "pubkeysfile", "f", []string{}, `Path of installed public key(s) to trust for TARGET. Absolute path to keys is added to policy.json. May used multiple times to define multiple public keys. @@ -68,9 +67,9 @@ File(s) must exist before using this command`) showFlags.BoolVarP(&showTrustCommand.Json, "json", "j", false, "Output as json") showFlags.StringVar(&showTrustCommand.PolicyPath, "policypath", "", "") showFlags.BoolVar(&showTrustCommand.Raw, "raw", false, "Output raw policy file") - showFlags.MarkHidden("policypath") + markFlagHidden(showFlags, "policypath") showFlags.StringVar(&showTrustCommand.RegistryPath, "registrypath", "", "") - showFlags.MarkHidden("registrypath") + markFlagHidden(showFlags, "registrypath") } func showTrustCmd(c *cliconfig.ShowTrustValues) error { @@ -238,10 +237,6 @@ func isValidTrustType(t string) bool { return false } -func getDefaultPolicyPath() string { - return trust.DefaultPolicyPath(&types.SystemContext{}) -} - func getPolicyJSON(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) (map[string]map[string]interface{}, error) { registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath) if err != nil { diff --git a/cmd/podman/umount.go b/cmd/podman/umount.go index ddbd00bd5..c3d81d3a8 100644 --- a/cmd/podman/umount.go +++ b/cmd/podman/umount.go @@ -52,7 +52,7 @@ func umountCmd(c *cliconfig.UmountValues) error { if err != nil { return errors.Wrapf(err, "error creating runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) ok, failures, err := runtime.UmountRootFilesystems(getContext(), c) if err != nil { diff --git a/cmd/podman/unpause.go b/cmd/podman/unpause.go index 8126ebfbd..382b64e97 100644 --- a/cmd/podman/unpause.go +++ b/cmd/podman/unpause.go @@ -45,7 +45,7 @@ func unpauseCmd(c *cliconfig.UnpauseValues) error { if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) args := c.InputArgs if len(args) < 1 && !c.All { diff --git a/cmd/podman/utils.go b/cmd/podman/utils.go index 986db469e..0790f673a 100644 --- a/cmd/podman/utils.go +++ b/cmd/podman/utils.go @@ -3,27 +3,12 @@ package main import ( "fmt" "reflect" + "runtime/debug" + "github.com/sirupsen/logrus" "github.com/spf13/pflag" ) -// printParallelOutput takes the map of parallel worker results and outputs them -// to stdout -func printParallelOutput(m map[string]error, errCount int) error { - var lastError error - for cid, result := range m { - if result != nil { - if errCount > 1 { - fmt.Println(result.Error()) - } - lastError = result - continue - } - fmt.Println(cid) - } - return lastError -} - // print results from CLI command func printCmdResults(ok []string, failures map[string]error) error { for _, id := range ok { @@ -48,6 +33,17 @@ func printCmdResults(ok []string, failures map[string]error) error { // on the remote-client func markFlagHiddenForRemoteClient(flagName string, flags *pflag.FlagSet) { if remoteclient { - flags.MarkHidden(flagName) + if err := flags.MarkHidden(flagName); err != nil { + debug.PrintStack() + logrus.Errorf("unable to mark %s as hidden in the remote-client", flagName) + } + } +} + +// markFlagHidden is a helper function to log an error if marking +// a flag as hidden happens to fail +func markFlagHidden(flags *pflag.FlagSet, flag string) { + if err := flags.MarkHidden(flag); err != nil { + logrus.Errorf("unable to mark flag '%s' as hidden: %q", flag, err) } } diff --git a/cmd/podman/varlink.go b/cmd/podman/varlink.go index 698a30d84..92315cd6b 100644 --- a/cmd/podman/varlink.go +++ b/cmd/podman/varlink.go @@ -83,7 +83,7 @@ func varlinkCmd(c *cliconfig.VarlinkValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(&c.PodmanCommand, runtime)} // Register varlink service. The metadata can be retrieved with: diff --git a/cmd/podman/version.go b/cmd/podman/version.go index a078ba2fe..6a88993c1 100644 --- a/cmd/podman/version.go +++ b/cmd/podman/version.go @@ -42,7 +42,7 @@ func init() { func versionCmd(c *cliconfig.VersionValues) error { clientVersion, err := define.GetVersion() if err != nil { - errors.Wrapf(err, "unable to determine version") + return errors.Wrapf(err, "unable to determine version") } versionOutputFormat := c.Format @@ -63,18 +63,22 @@ func versionCmd(c *cliconfig.VersionValues) error { defer w.Flush() if remote { - fmt.Fprintf(w, "Client:\n") + if _, err := fmt.Fprintf(w, "Client:\n"); err != nil { + return err + } } formatVersion(w, clientVersion) if remote { - fmt.Fprintf(w, "\nService:\n") + if _, err := fmt.Fprintf(w, "\nService:\n"); err != nil { + return err + } runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) serviceVersion, err := runtime.GetVersion() if err != nil { diff --git a/cmd/podman/volume_create.go b/cmd/podman/volume_create.go index 84f6bba94..0897ab705 100644 --- a/cmd/podman/volume_create.go +++ b/cmd/podman/volume_create.go @@ -46,7 +46,7 @@ func volumeCreateCmd(c *cliconfig.VolumeCreateValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) if len(c.InputArgs) > 1 { return errors.Errorf("too many arguments, create takes at most 1 argument") diff --git a/cmd/podman/volume_inspect.go b/cmd/podman/volume_inspect.go index e4b05f96a..1ebc5ce60 100644 --- a/cmd/podman/volume_inspect.go +++ b/cmd/podman/volume_inspect.go @@ -47,7 +47,7 @@ func volumeInspectCmd(c *cliconfig.VolumeInspectValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) vols, err := runtime.InspectVolumes(getContext(), c) if err != nil { diff --git a/cmd/podman/volume_ls.go b/cmd/podman/volume_ls.go index 581e595cb..7248caf0c 100644 --- a/cmd/podman/volume_ls.go +++ b/cmd/podman/volume_ls.go @@ -76,7 +76,7 @@ func volumeLsCmd(c *cliconfig.VolumeLsValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) opts := volumeLsOptions{ Quiet: c.Quiet, diff --git a/cmd/podman/volume_prune.go b/cmd/podman/volume_prune.go index 6dc9e2403..daea5a4d2 100644 --- a/cmd/podman/volume_prune.go +++ b/cmd/podman/volume_prune.go @@ -67,7 +67,7 @@ func volumePruneCmd(c *cliconfig.VolumePruneValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) // Prompt for confirmation if --force is not set if !c.Force { diff --git a/cmd/podman/volume_rm.go b/cmd/podman/volume_rm.go index 77137eb7a..0141d06da 100644 --- a/cmd/podman/volume_rm.go +++ b/cmd/podman/volume_rm.go @@ -51,7 +51,7 @@ func volumeRmCmd(c *cliconfig.VolumeRmValues) error { if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) deletedVolumeNames, err := runtime.RemoveVolumes(getContext(), c) if err != nil { if len(deletedVolumeNames) > 0 { diff --git a/cmd/podman/wait.go b/cmd/podman/wait.go index 380e861ed..d6a707bb8 100644 --- a/cmd/podman/wait.go +++ b/cmd/podman/wait.go @@ -55,7 +55,7 @@ func waitCmd(c *cliconfig.WaitValues) error { if err != nil { return errors.Wrapf(err, "error creating runtime") } - defer runtime.Shutdown(false) + defer runtime.DeferredShutdown(false) ok, failures, err := runtime.WaitOnContainers(getContext(), c, interval) if err != nil { diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md index 9cf3e038d..a34111a03 100644 --- a/docs/podman-create.1.md +++ b/docs/podman-create.1.md @@ -723,6 +723,8 @@ The following example maps uids 0-2000 in the container to the uids 30000-31999 Ulimit options +You can pass `host` to copy the current configuration from the host. + **--user**, **-u**=*user* Sets the username or UID used and optionally the groupname or GID for the specified command. diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index 4889e5755..86cc2125c 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -759,6 +759,8 @@ The example maps uids 0-2000 in the container to the uids 30000-31999 on the hos Ulimit options +You can pass `host` to copy the current configuration from the host. + **--user**, **-u**=*user* Sets the username or UID used and optionally the groupname or GID for the specified command. diff --git a/docs/podman-stats.1.md b/docs/podman-stats.1.md index b817662a8..b71d435fa 100644 --- a/docs/podman-stats.1.md +++ b/docs/podman-stats.1.md @@ -39,7 +39,7 @@ Valid placeholders for the Go template are listed below: | **Placeholder** | **Description** | | --------------- | --------------- | | .Pod | Pod ID | -| .CID | Container ID | +| .ID | Container ID | | .Name | Container Name | | .CPU | CPU percentage | | .MemUsage | Memory usage | diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index 4dda3a7f0..176781f07 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -66,7 +66,7 @@ func NewBoltState(path string, runtime *Runtime) (State, error) { if err != nil { return nil, errors.Wrapf(err, "error opening database %s", path) } - // Everywhere else, we use s.closeDBCon(db) to ensure the state's DB + // Everywhere else, we use s.deferredCloseDBCon(db) to ensure the state's DB // mutex is also unlocked. // However, here, the mutex has not been locked, since we just created // the DB connection, and it hasn't left this function yet - no risk of @@ -141,7 +141,7 @@ func (s *BoltState) Refresh() error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { idBucket, err := getIDBucket(tx) @@ -253,7 +253,7 @@ func (s *BoltState) GetDBConfig() (*DBConfig, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { configBucket, err := getRuntimeConfigBucket(tx) @@ -298,7 +298,7 @@ func (s *BoltState) ValidateDBConfig(runtime *Runtime) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) // Check runtime configuration if err := checkRuntimeConfig(db, runtime); err != nil { @@ -342,7 +342,7 @@ func (s *BoltState) Container(id string) (*Container, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { ctrBucket, err := getCtrBucket(tx) @@ -378,7 +378,7 @@ func (s *BoltState) LookupContainer(idOrName string) (*Container, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { ctrBucket, err := getCtrBucket(tx) @@ -484,7 +484,7 @@ func (s *BoltState) HasContainer(id string) (bool, error) { if err != nil { return false, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) exists := false @@ -549,7 +549,7 @@ func (s *BoltState) RemoveContainer(ctr *Container) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { return s.removeContainer(ctr, nil, tx) @@ -580,7 +580,7 @@ func (s *BoltState) UpdateContainer(ctr *Container) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { ctrBucket, err := getCtrBucket(tx) @@ -651,7 +651,7 @@ func (s *BoltState) SaveContainer(ctr *Container) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { ctrBucket, err := getCtrBucket(tx) @@ -708,7 +708,7 @@ func (s *BoltState) ContainerInUse(ctr *Container) ([]string, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { ctrBucket, err := getCtrBucket(tx) @@ -759,7 +759,7 @@ func (s *BoltState) AllContainers() ([]*Container, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { allCtrsBucket, err := getAllCtrsBucket(tx) @@ -833,7 +833,7 @@ func (s *BoltState) RewriteContainerConfig(ctr *Container, newCfg *ContainerConf if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { ctrBkt, err := getCtrBucket(tx) @@ -877,7 +877,7 @@ func (s *BoltState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { podBkt, err := getPodBucket(tx) @@ -920,7 +920,7 @@ func (s *BoltState) Pod(id string) (*Pod, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { podBkt, err := getPodBucket(tx) @@ -955,7 +955,7 @@ func (s *BoltState) LookupPod(idOrName string) (*Pod, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { podBkt, err := getPodBucket(tx) @@ -1062,7 +1062,7 @@ func (s *BoltState) HasPod(id string) (bool, error) { if err != nil { return false, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { podBkt, err := getPodBucket(tx) @@ -1118,7 +1118,7 @@ func (s *BoltState) PodHasContainer(pod *Pod, id string) (bool, error) { if err != nil { return false, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { podBkt, err := getPodBucket(tx) @@ -1180,7 +1180,7 @@ func (s *BoltState) PodContainersByID(pod *Pod) ([]string, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { podBkt, err := getPodBucket(tx) @@ -1242,7 +1242,7 @@ func (s *BoltState) PodContainers(pod *Pod) ([]*Container, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { podBkt, err := getPodBucket(tx) @@ -1312,7 +1312,7 @@ func (s *BoltState) AddVolume(volume *Volume) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { volBkt, err := getVolBucket(tx) @@ -1369,7 +1369,7 @@ func (s *BoltState) RemoveVolume(volume *Volume) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { volBkt, err := getVolBucket(tx) @@ -1451,7 +1451,7 @@ func (s *BoltState) AllVolumes() ([]*Volume, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { allVolsBucket, err := getAllVolsBucket(tx) @@ -1512,7 +1512,7 @@ func (s *BoltState) Volume(name string) (*Volume, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { volBkt, err := getVolBucket(tx) @@ -1547,7 +1547,7 @@ func (s *BoltState) HasVolume(name string) (bool, error) { if err != nil { return false, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { volBkt, err := getVolBucket(tx) @@ -1587,7 +1587,7 @@ func (s *BoltState) VolumeInUse(volume *Volume) ([]string, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { volBucket, err := getVolBucket(tx) @@ -1673,7 +1673,7 @@ func (s *BoltState) AddPod(pod *Pod) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { podBkt, err := getPodBucket(tx) @@ -1782,7 +1782,7 @@ func (s *BoltState) RemovePod(pod *Pod) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { podBkt, err := getPodBucket(tx) @@ -1877,7 +1877,7 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { podBkt, err := getPodBucket(tx) @@ -2038,7 +2038,7 @@ func (s *BoltState) RemoveContainerFromPod(pod *Pod, ctr *Container) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { return s.removeContainer(ctr, pod, tx) @@ -2066,7 +2066,7 @@ func (s *BoltState) UpdatePod(pod *Pod) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) podID := []byte(pod.ID()) @@ -2126,7 +2126,7 @@ func (s *BoltState) SavePod(pod *Pod) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) podID := []byte(pod.ID()) @@ -2168,7 +2168,7 @@ func (s *BoltState) AllPods() ([]*Pod, error) { if err != nil { return nil, err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.View(func(tx *bolt.Tx) error { allPodsBucket, err := getAllPodsBucket(tx) diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index ee2784cdd..408ef7224 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -247,6 +247,15 @@ func (s *BoltState) getDBCon() (*bolt.DB, error) { return db, nil } +// deferredCloseDBCon closes the bolt db but instead of returning an +// error it logs the error. it is meant to be used within the confines +// of a defer statement only +func (s *BoltState) deferredCloseDBCon(db *bolt.DB) { + if err := s.closeDBCon(db); err != nil { + logrus.Errorf("failed to close libpod db: %q", err) + } +} + // Close a connection to the database. // MUST be used in place of `db.Close()` to ensure proper unlocking of the // state. @@ -479,7 +488,7 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error { if err != nil { return err } - defer s.closeDBCon(db) + defer s.deferredCloseDBCon(db) err = db.Update(func(tx *bolt.Tx) error { idsBucket, err := getIDBucket(tx) diff --git a/libpod/container.go b/libpod/container.go index a9b512de9..b71c0b2be 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -639,10 +639,7 @@ func (c *Container) HostsAdd() []string { // trigger some OCI hooks. func (c *Container) UserVolumes() []string { volumes := make([]string, 0, len(c.config.UserVolumes)) - for _, vol := range c.config.UserVolumes { - volumes = append(volumes, vol) - } - + volumes = append(volumes, c.config.UserVolumes...) return volumes } @@ -650,10 +647,7 @@ func (c *Container) UserVolumes() []string { // This is not added to the spec, but is instead used during image commit. func (c *Container) Entrypoint() []string { entrypoint := make([]string, 0, len(c.config.Entrypoint)) - for _, str := range c.config.Entrypoint { - entrypoint = append(entrypoint, str) - } - + entrypoint = append(entrypoint, c.config.Entrypoint...) return entrypoint } @@ -661,10 +655,7 @@ func (c *Container) Entrypoint() []string { // This is not added to the spec, but is instead used during image commit func (c *Container) Command() []string { command := make([]string, 0, len(c.config.Command)) - for _, str := range c.config.Command { - command = append(command, str) - } - + command = append(command, c.config.Command...) return command } diff --git a/libpod/container_api.go b/libpod/container_api.go index 3dd84b02c..3577b8e8c 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -277,7 +277,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir break } } - if found == true { + if found { sessionID = stringid.GenerateNonCryptoID() } } diff --git a/libpod/container_attach_linux.go b/libpod/container_attach_linux.go index 17b09fccc..43dd7d579 100644 --- a/libpod/container_attach_linux.go +++ b/libpod/container_attach_linux.go @@ -10,6 +10,7 @@ import ( "path/filepath" "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/kubeutils" "github.com/containers/libpod/utils" "github.com/docker/docker/pkg/term" @@ -66,7 +67,7 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi logrus.Debugf("Could not open ctl file: %v", err) return } - defer controlFile.Close() + defer errorhandling.CloseQuiet(controlFile) logrus.Debugf("Received a resize event: %+v", size) if _, err = fmt.Fprintf(controlFile, "%d %d %d\n", 1, size.Height, size.Width); err != nil { @@ -108,7 +109,9 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi var err error if streams.AttachInput { _, err = utils.CopyDetachable(conn, streams.InputStream, detachKeys) - conn.CloseWrite() + if err := conn.CloseWrite(); err != nil { + logrus.Error("failed to close write in attach") + } } stdinDone <- err }() diff --git a/libpod/container_graph.go b/libpod/container_graph.go index 50dbdfbe4..5aa51bc2f 100644 --- a/libpod/container_graph.go +++ b/libpod/container_graph.go @@ -264,6 +264,4 @@ func startNode(ctx context.Context, node *containerNode, setError bool, ctrError for _, successor := range node.dependedOn { startNode(ctx, successor, ctrErrored, ctrErrors, ctrsVisited, restart) } - - return } diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 2de78254c..de0027414 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -454,9 +454,7 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) (*InspectCon if spec.Process != nil { ctrConfig.Tty = spec.Process.Terminal ctrConfig.Env = []string{} - for _, val := range spec.Process.Env { - ctrConfig.Env = append(ctrConfig.Env, val) - } + ctrConfig.Env = append(ctrConfig.Env, spec.Process.Env...) ctrConfig.WorkingDir = spec.Process.Cwd } @@ -466,9 +464,7 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) (*InspectCon // Leave empty is not explicitly overwritten by user if len(c.config.Command) != 0 { ctrConfig.Cmd = []string{} - for _, val := range c.config.Command { - ctrConfig.Cmd = append(ctrConfig.Cmd, val) - } + ctrConfig.Cmd = append(ctrConfig.Cmd, c.config.Command...) } // Leave empty if not explicitly overwritten by user diff --git a/libpod/container_internal.go b/libpod/container_internal.go index c409da96a..47b425c0a 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -815,34 +815,6 @@ func (c *Container) checkDependenciesRunning() ([]string, error) { return notRunning, nil } -// Check if a container's dependencies are running -// Returns a []string containing the IDs of dependencies that are not running -// Assumes depencies are already locked, and will be passed in -// Accepts a map[string]*Container containing, at a minimum, the locked -// dependency containers -// (This must be a map from container ID to container) -func (c *Container) checkDependenciesRunningLocked(depCtrs map[string]*Container) ([]string, error) { - deps := c.Dependencies() - notRunning := []string{} - - for _, dep := range deps { - depCtr, ok := depCtrs[dep] - if !ok { - return nil, errors.Wrapf(define.ErrNoSuchCtr, "container %s depends on container %s but it is not on containers passed to checkDependenciesRunning", c.ID(), dep) - } - - if err := c.syncContainer(); err != nil { - return nil, err - } - - if depCtr.state.State != define.ContainerStateRunning { - notRunning = append(notRunning, dep) - } - } - - return notRunning, nil -} - func (c *Container) completeNetworkSetup() error { netDisabled, err := c.NetworkDisabled() if err != nil { diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 686a595de..aa477611f 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -636,6 +636,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO } } + c.state.FinishedTime = time.Now() return c.save() } diff --git a/libpod/events/filters.go b/libpod/events/filters.go index 9a64082d1..b3c5eda6e 100644 --- a/libpod/events/filters.go +++ b/libpod/events/filters.go @@ -1,7 +1,6 @@ package events import ( - "fmt" "strings" "time" @@ -23,7 +22,7 @@ func generateEventFilter(filter, filterValue string) (func(e *Event) bool, error }, nil case "EVENT", "STATUS": return func(e *Event) bool { - return fmt.Sprintf("%s", e.Status) == filterValue + return string(e.Status) == filterValue }, nil case "IMAGE": return func(e *Event) bool { @@ -54,7 +53,7 @@ func generateEventFilter(filter, filterValue string) (func(e *Event) bool, error }, nil case "TYPE": return func(e *Event) bool { - return fmt.Sprintf("%s", e.Type) == filterValue + return string(e.Type) == filterValue }, nil } return nil, errors.Errorf("%s is an invalid filter", filter) diff --git a/libpod/events/nullout.go b/libpod/events/nullout.go index 7d811a9c7..b11afcf80 100644 --- a/libpod/events/nullout.go +++ b/libpod/events/nullout.go @@ -17,7 +17,6 @@ func (e EventToNull) Read(options ReadOptions) error { // NewNullEventer returns a new null eventer. You should only do this for // the purposes on internal libpod testing. func NewNullEventer() Eventer { - var e Eventer - e = EventToNull{} + e := EventToNull{} return e } diff --git a/libpod/healthcheck_linux.go b/libpod/healthcheck_linux.go index 53fb271d1..dca72430d 100644 --- a/libpod/healthcheck_linux.go +++ b/libpod/healthcheck_linux.go @@ -62,7 +62,7 @@ func (c *Container) createTimer() error { if rootless.IsRootless() { cmd = append(cmd, "--user") } - cmd = append(cmd, "--unit", fmt.Sprintf("%s", c.ID()), fmt.Sprintf("--on-unit-inactive=%s", c.HealthCheckConfig().Interval.String()), "--timer-property=AccuracySec=1s", podman, "healthcheck", "run", c.ID()) + cmd = append(cmd, "--unit", c.ID(), fmt.Sprintf("--on-unit-inactive=%s", c.HealthCheckConfig().Interval.String()), "--timer-property=AccuracySec=1s", podman, "healthcheck", "run", c.ID()) conn, err := getConnection() if err != nil { diff --git a/libpod/image/image.go b/libpod/image/image.go index 76e46f74f..f9879b85b 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -323,7 +323,7 @@ func (i *Image) Names() []string { // RepoDigests returns a string array of repodigests associated with the image func (i *Image) RepoDigests() ([]string, error) { var repoDigests []string - digest := i.Digest() + imageDigest := i.Digest() for _, name := range i.Names() { named, err := reference.ParseNormalizedNamed(name) @@ -331,7 +331,7 @@ func (i *Image) RepoDigests() ([]string, error) { return nil, err } - canonical, err := reference.WithDigest(reference.TrimNamed(named), digest) + canonical, err := reference.WithDigest(reference.TrimNamed(named), imageDigest) if err != nil { return nil, err } @@ -461,12 +461,16 @@ func getImageDigest(ctx context.Context, src types.ImageReference, sc *types.Sys if err != nil { return "", err } - defer newImg.Close() - digest := newImg.ConfigInfo().Digest - if err = digest.Validate(); err != nil { + defer func() { + if err := newImg.Close(); err != nil { + logrus.Errorf("failed to close image: %q", err) + } + }() + imageDigest := newImg.ConfigInfo().Digest + if err = imageDigest.Validate(); err != nil { return "", errors.Wrapf(err, "error getting config info") } - return "@" + digest.Hex(), nil + return "@" + imageDigest.Hex(), nil } // normalizedTag returns the canonical version of tag for use in Image.Names() @@ -495,7 +499,9 @@ func normalizedTag(tag string) (reference.Named, error) { // TagImage adds a tag to the given image func (i *Image) TagImage(tag string) error { - i.reloadImage() + if err := i.reloadImage(); err != nil { + return err + } ref, err := normalizedTag(tag) if err != nil { return err @@ -508,14 +514,18 @@ func (i *Image) TagImage(tag string) error { if err := i.imageruntime.store.SetNames(i.ID(), tags); err != nil { return err } - i.reloadImage() - defer i.newImageEvent(events.Tag) + if err := i.reloadImage(); err != nil { + return err + } + i.newImageEvent(events.Tag) return nil } // UntagImage removes a tag from the given image func (i *Image) UntagImage(tag string) error { - i.reloadImage() + if err := i.reloadImage(); err != nil { + return err + } var newTags []string tags := i.Names() if !util.StringInSlice(tag, tags) { @@ -529,8 +539,10 @@ func (i *Image) UntagImage(tag string) error { if err := i.imageruntime.store.SetNames(i.ID(), newTags); err != nil { return err } - i.reloadImage() - defer i.newImageEvent(events.Untag) + if err := i.reloadImage(); err != nil { + return err + } + i.newImageEvent(events.Untag) return nil } @@ -566,7 +578,11 @@ func (i *Image) PushImageToReference(ctx context.Context, dest types.ImageRefere if err != nil { return err } - defer policyContext.Destroy() + defer func() { + if err := policyContext.Destroy(); err != nil { + logrus.Errorf("failed to destroy policy context: %q", err) + } + }() // Look up the source image, expecting it to be in local storage src, err := is.Transport.ParseStoreReference(i.imageruntime.store, i.ID()) @@ -580,7 +596,7 @@ func (i *Image) PushImageToReference(ctx context.Context, dest types.ImageRefere if err != nil { return errors.Wrapf(err, "Error copying image to the remote destination") } - defer i.newImageEvent(events.Push) + i.newImageEvent(events.Push) return nil } @@ -825,7 +841,7 @@ func (i *Image) GetLabel(ctx context.Context, label string) (string, error) { // Annotations returns the annotations of an image func (i *Image) Annotations(ctx context.Context) (map[string]string, error) { - manifest, manifestType, err := i.Manifest(ctx) + imageManifest, manifestType, err := i.Manifest(ctx) if err != nil { return nil, err } @@ -833,7 +849,7 @@ func (i *Image) Annotations(ctx context.Context) (map[string]string, error) { switch manifestType { case ociv1.MediaTypeImageManifest: var m ociv1.Manifest - if err := json.Unmarshal(manifest, &m); err == nil { + if err := json.Unmarshal(imageManifest, &m); err == nil { for k, v := range m.Annotations { annotations[k] = v } @@ -976,11 +992,15 @@ func (ir *Runtime) Import(ctx context.Context, path, reference string, writer io if err != nil { return nil, err } - defer policyContext.Destroy() + defer func() { + if err := policyContext.Destroy(); err != nil { + logrus.Errorf("failed to destroy policy context: %q", err) + } + }() copyOptions := getCopyOptions(sc, writer, nil, nil, signingOptions, "", nil) dest, err := is.Transport.ParseStoreReference(ir.store, reference) if err != nil { - errors.Wrapf(err, "error getting image reference for %q", reference) + return nil, errors.Wrapf(err, "error getting image reference for %q", reference) } _, err = cp.Image(ctx, policyContext, dest, src, copyOptions) if err != nil { @@ -988,7 +1008,7 @@ func (ir *Runtime) Import(ctx context.Context, path, reference string, writer io } newImage, err := ir.NewFromLocal(reference) if err == nil { - defer newImage.newImageEvent(events.Import) + newImage.newImageEvent(events.Import) } return newImage, err } @@ -1331,7 +1351,7 @@ func (i *Image) Save(ctx context.Context, source, format, output string, moreTag if err := i.PushImageToReference(ctx, destRef, manifestType, "", "", writer, compress, SigningOptions{}, &DockerRegistryOptions{}, additionaltags); err != nil { return errors.Wrapf(err, "unable to save %q", source) } - defer i.newImageEvent(events.Save) + i.newImageEvent(events.Save) return nil } diff --git a/libpod/image/pull.go b/libpod/image/pull.go index e5765febc..581beb538 100644 --- a/libpod/image/pull.go +++ b/libpod/image/pull.go @@ -249,7 +249,11 @@ func (ir *Runtime) doPullImage(ctx context.Context, sc *types.SystemContext, goa if err != nil { return nil, err } - defer policyContext.Destroy() + defer func() { + if err := policyContext.Destroy(); err != nil { + logrus.Errorf("failed to destroy policy context: %q", err) + } + }() systemRegistriesConfPath := registries.SystemRegistriesConfPath() @@ -263,7 +267,9 @@ func (ir *Runtime) doPullImage(ctx context.Context, sc *types.SystemContext, goa copyOptions.SourceCtx.SystemRegistriesConfPath = systemRegistriesConfPath // FIXME: Set this more globally. Probably no reason not to have it in every types.SystemContext, and to compute the value just once in one place. // Print the following statement only when pulling from a docker or atomic registry if writer != nil && (imageInfo.srcRef.Transport().Name() == DockerTransport || imageInfo.srcRef.Transport().Name() == AtomicTransport) { - io.WriteString(writer, fmt.Sprintf("Trying to pull %s...", imageInfo.image)) + if _, err := io.WriteString(writer, fmt.Sprintf("Trying to pull %s...", imageInfo.image)); err != nil { + return nil, err + } } // If the label is not nil, check if the label exists and if not, return err if label != nil { @@ -277,7 +283,7 @@ func (ir *Runtime) doPullImage(ctx context.Context, sc *types.SystemContext, goa pullErrors = multierror.Append(pullErrors, err) logrus.Errorf("Error pulling image ref %s: %v", imageInfo.srcRef.StringWithinTransport(), err) if writer != nil { - io.WriteString(writer, "Failed\n") + _, _ = io.WriteString(writer, "Failed\n") } } else { if !goal.pullAllPairs { @@ -302,7 +308,7 @@ func (ir *Runtime) doPullImage(ctx context.Context, sc *types.SystemContext, goa return nil, pullErrors } if len(images) > 0 { - defer ir.newImageEvent(events.Pull, images[0]) + ir.newImageEvent(events.Pull, images[0]) } return images, nil } diff --git a/libpod/image/search.go b/libpod/image/search.go index 03a67636b..9984e5234 100644 --- a/libpod/image/search.go +++ b/libpod/image/search.go @@ -99,7 +99,9 @@ func SearchImages(term string, options SearchOptions) ([]SearchResult, error) { ctx := context.Background() for i := range registries { - sem.Acquire(ctx, 1) + if err := sem.Acquire(ctx, 1); err != nil { + return nil, err + } go searchImageInRegistryHelper(i, registries[i]) } diff --git a/libpod/kube.go b/libpod/kube.go index 409937010..b114cda72 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -1,7 +1,6 @@ package libpod import ( - "fmt" "math/rand" "os" "strconv" @@ -179,7 +178,7 @@ func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1. labels["app"] = removeUnderscores(podName) om := v12.ObjectMeta{ // The name of the pod is container_name-libpod - Name: fmt.Sprintf("%s", removeUnderscores(podName)), + Name: removeUnderscores(podName), Labels: labels, // CreationTimestamp seems to be required, so adding it; in doing so, the timestamp // will reflect time this is run (not container create time) because the conversion diff --git a/libpod/logs/log.go b/libpod/logs/log.go index 488291cfe..0b1703567 100644 --- a/libpod/logs/log.go +++ b/libpod/logs/log.go @@ -156,8 +156,5 @@ func NewLogLine(line string) (*LogLine, error) { // Partial returns a bool if the log line is a partial log type func (l *LogLine) Partial() bool { - if l.ParseLogType == PartialLogType { - return true - } - return false + return l.ParseLogType == PartialLogType } diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index d978bceed..bef3f7739 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -16,6 +16,7 @@ import ( cnitypes "github.com/containernetworking/cni/pkg/types/current" "github.com/containernetworking/plugins/pkg/ns" + "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/firewall" "github.com/containers/libpod/pkg/netns" "github.com/containers/libpod/pkg/rootless" @@ -150,8 +151,8 @@ func checkSlirpFlags(path string) (bool, bool, error) { // Configure the network namespace for a rootless container func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { - defer ctr.rootlessSlirpSyncR.Close() - defer ctr.rootlessSlirpSyncW.Close() + defer errorhandling.CloseQuiet(ctr.rootlessSlirpSyncR) + defer errorhandling.CloseQuiet(ctr.rootlessSlirpSyncW) path := r.config.NetworkCmdPath @@ -168,8 +169,8 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { if err != nil { return errors.Wrapf(err, "failed to open pipe") } - defer syncR.Close() - defer syncW.Close() + defer errorhandling.CloseQuiet(syncR) + defer errorhandling.CloseQuiet(syncW) havePortMapping := len(ctr.Config().PortMappings) > 0 apiSocket := filepath.Join(ctr.ociRuntime.tmpDir, fmt.Sprintf("%s.net", ctr.config.ID)) @@ -200,7 +201,11 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { if err := cmd.Start(); err != nil { return errors.Wrapf(err, "failed to start slirp4netns process") } - defer cmd.Process.Release() + defer func() { + if err := cmd.Process.Release(); err != nil { + logrus.Errorf("unable to release comman process: %q", err) + } + }() b := make([]byte, 16) for { @@ -267,7 +272,11 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { if err != nil { return errors.Wrapf(err, "cannot open connection to %s", apiSocket) } - defer conn.Close() + defer func() { + if err := conn.Close(); err != nil { + logrus.Errorf("unable to close connection: %q", err) + } + }() hostIP := i.HostIP if hostIP == "" { hostIP = "0.0.0.0" diff --git a/libpod/oci.go b/libpod/oci.go index 6aad79cdf..566cbd821 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -273,7 +273,9 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container, useRuntime bool) erro } return errors.Wrapf(err, "error getting container %s state. stderr/out: %s", ctr.ID(), out) } - defer cmd.Wait() + defer func() { + _ = cmd.Wait() + }() if err := errPipe.Close(); err != nil { return err diff --git a/libpod/oci_linux.go b/libpod/oci_linux.go index 802f4311b..044373ec5 100644 --- a/libpod/oci_linux.go +++ b/libpod/oci_linux.go @@ -17,6 +17,7 @@ import ( "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/cgroups" + "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/util" "github.com/containers/libpod/utils" @@ -117,13 +118,17 @@ func (r *OCIRuntime) createContainer(ctr *Container, cgroupParent string, restor if err != nil { return err } - defer fd.Close() + defer errorhandling.CloseQuiet(fd) // create a new mountns on the current thread if err = unix.Unshare(unix.CLONE_NEWNS); err != nil { return err } - defer unix.Setns(int(fd.Fd()), unix.CLONE_NEWNS) + defer func() { + if err := unix.Setns(int(fd.Fd()), unix.CLONE_NEWNS); err != nil { + logrus.Errorf("unable to clone new namespace: %q", err) + } + }() // don't spread our mounts around. We are setting only /sys to be slave // so that the cleanup process is still able to umount the storage and the @@ -207,8 +212,8 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res return errors.Wrapf(err, "error creating socket pair for start pipe") } - defer parentPipe.Close() - defer parentStartPipe.Close() + defer errorhandling.CloseQuiet(parentPipe) + defer errorhandling.CloseQuiet(parentStartPipe) ociLog := filepath.Join(ctr.state.RunDir, "oci-log") logLevel := logrus.GetLevel() @@ -364,20 +369,28 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res err = cmd.Start() // Ignore error returned from SetProcessLabel("") call, // can't recover. - label.SetProcessLabel("") + if err := label.SetProcessLabel(""); err != nil { + _ = err + } runtime.UnlockOSThread() } else { err = cmd.Start() } if err != nil { - childPipe.Close() + errorhandling.CloseQuiet(childPipe) return err } - defer cmd.Wait() + defer func() { + _ = cmd.Wait() + }() // We don't need childPipe on the parent side - childPipe.Close() - childStartPipe.Close() + if err := childPipe.Close(); err != nil { + return err + } + if err := childStartPipe.Close(); err != nil { + return err + } // Move conmon to specified cgroup if err := r.moveConmonToCgroup(ctr, cgroupParent, cmd); err != nil { diff --git a/libpod/options.go b/libpod/options.go index 4f8bb42df..8d41764a9 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1152,10 +1152,7 @@ func WithUserVolumes(volumes []string) CtrCreateOption { } ctr.config.UserVolumes = make([]string, 0, len(volumes)) - for _, vol := range volumes { - ctr.config.UserVolumes = append(ctr.config.UserVolumes, vol) - } - + ctr.config.UserVolumes = append(ctr.config.UserVolumes, volumes...) return nil } } @@ -1172,10 +1169,7 @@ func WithEntrypoint(entrypoint []string) CtrCreateOption { } ctr.config.Entrypoint = make([]string, 0, len(entrypoint)) - for _, str := range entrypoint { - ctr.config.Entrypoint = append(ctr.config.Entrypoint, str) - } - + ctr.config.Entrypoint = append(ctr.config.Entrypoint, entrypoint...) return nil } } @@ -1192,10 +1186,7 @@ func WithCommand(command []string) CtrCreateOption { } ctr.config.Command = make([]string, 0, len(command)) - for _, str := range command { - ctr.config.Command = append(ctr.config.Command, str) - } - + ctr.config.Command = append(ctr.config.Command, command...) return nil } } diff --git a/libpod/runtime.go b/libpod/runtime.go index 53c9a1209..9196547a2 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -1162,6 +1162,13 @@ func (r *Runtime) GetConfig() (*RuntimeConfig, error) { return config, nil } +// DeferredShutdown shuts down the runtime without exposing any +// errors. This is only meant to be used when the runtime is being +// shutdown within a defer statement; else use Shutdown +func (r *Runtime) DeferredShutdown(force bool) { + _ = r.Shutdown(force) +} + // Shutdown shuts down the runtime and associated containers and storage // If force is true, containers and mounted storage will be shut down before // cleaning up; if force is false, an error will be returned if there are diff --git a/pkg/adapter/checkpoint_restore.go b/pkg/adapter/checkpoint_restore.go index 97ba5ecf7..ec1464fb1 100644 --- a/pkg/adapter/checkpoint_restore.go +++ b/pkg/adapter/checkpoint_restore.go @@ -4,16 +4,19 @@ package adapter import ( "context" + "io" + "io/ioutil" + "os" + "path/filepath" + "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/storage/pkg/archive" jsoniter "github.com/json-iterator/go" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" - "io" - "io/ioutil" - "os" - "path/filepath" + "github.com/sirupsen/logrus" ) // Prefixing the checkpoint/restore related functions with 'cr' @@ -25,7 +28,7 @@ func crImportFromJSON(filePath string, v interface{}) error { if err != nil { return errors.Wrapf(err, "Failed to open container definition %s for restore", filePath) } - defer jsonFile.Close() + defer errorhandling.CloseQuiet(jsonFile) content, err := ioutil.ReadAll(jsonFile) if err != nil { @@ -48,7 +51,7 @@ func crImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input stri if err != nil { return nil, errors.Wrapf(err, "Failed to open checkpoint archive %s for import", input) } - defer archiveFile.Close() + defer errorhandling.CloseQuiet(archiveFile) options := &archive.TarOptions{ // Here we only need the files config.dump and spec.dump ExcludePatterns: []string{ @@ -62,15 +65,19 @@ func crImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input stri if err != nil { return nil, err } - defer os.RemoveAll(dir) + defer func() { + if err := os.RemoveAll(dir); err != nil { + logrus.Errorf("could not recursively remove %s: %q", dir, err) + } + }() err = archive.Untar(archiveFile, dir, options) if err != nil { return nil, errors.Wrapf(err, "Unpacking of checkpoint archive %s failed", input) } // Load spec.dump from temporary directory - spec := new(spec.Spec) - if err := crImportFromJSON(filepath.Join(dir, "spec.dump"), spec); err != nil { + dumpSpec := new(spec.Spec) + if err := crImportFromJSON(filepath.Join(dir, "spec.dump"), dumpSpec); err != nil { return nil, err } @@ -112,7 +119,7 @@ func crImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input stri } // Now create a new container from the just loaded information - container, err := runtime.RestoreContainer(ctx, spec, config) + container, err := runtime.RestoreContainer(ctx, dumpSpec, config) if err != nil { return nil, err } @@ -127,7 +134,7 @@ func crImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input stri return nil, errors.Errorf("Name of restored container (%s) does not match requested name (%s)", containerConfig.Name, ctrName) } - if newName == false { + if !newName { // Only check ID for a restore with the same name. // Using -n to request a new name for the restored container, will also create a new ID if containerConfig.ID != ctrID { diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 0ea89a72c..86e9c0266 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -95,8 +95,8 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa } pool.Add(shared.Job{ - c.ID(), - func() error { + ID: c.ID(), + Fn: func() error { err := c.StopWithTimeout(*timeout) if err != nil { if errors.Cause(err) == define.ErrCtrStopped { @@ -134,8 +134,8 @@ func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillVa c := c pool.Add(shared.Job{ - c.ID(), - func() error { + ID: c.ID(), + Fn: func() error { return c.Kill(uint(signal)) }, }) @@ -163,8 +163,8 @@ func (r *LocalRuntime) InitContainers(ctx context.Context, cli *cliconfig.InitVa ctr := c pool.Add(shared.Job{ - ctr.ID(), - func() error { + ID: ctr.ID(), + Fn: func() error { err := ctr.Init(ctx) if err != nil { // If we're initializing all containers, ignore invalid state errors @@ -213,8 +213,8 @@ func (r *LocalRuntime) RemoveContainers(ctx context.Context, cli *cliconfig.RmVa c := c pool.Add(shared.Job{ - c.ID(), - func() error { + ID: c.ID(), + Fn: func() error { err := r.RemoveContainer(ctx, c, cli.Force, cli.Volumes) if err != nil { logrus.Debugf("Failed to remove container %s: %s", c.ID(), err.Error()) diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go index a28e1ab4b..b45b02d09 100644 --- a/pkg/adapter/pods.go +++ b/pkg/adapter/pods.go @@ -70,8 +70,9 @@ func (r *LocalRuntime) PrunePods(ctx context.Context, cli *cliconfig.PodPruneVal for _, p := range pods { p := p - pool.Add(shared.Job{p.ID(), - func() error { + pool.Add(shared.Job{ + ID: p.ID(), + Fn: func() error { err := r.Runtime.RemovePod(ctx, p, cli.Force, cli.Force) if err != nil { logrus.Debugf("Failed to remove pod %s: %s", p.ID(), err.Error()) diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go index 8ef88f36b..e65f07898 100644 --- a/pkg/adapter/runtime.go +++ b/pkg/adapter/runtime.go @@ -359,9 +359,6 @@ func (r *LocalRuntime) Events(c *cliconfig.EventValues) error { if eventsError != nil { return eventsError } - if err != nil { - return errors.Wrapf(err, "unable to tail the events log") - } w := bufio.NewWriter(os.Stdout) for event := range eventChannel { if len(c.Format) > 0 { diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go index 800ed7569..db3f23629 100644 --- a/pkg/adapter/runtime_remote.go +++ b/pkg/adapter/runtime_remote.go @@ -97,6 +97,14 @@ func GetRuntime(ctx context.Context, c *cliconfig.PodmanCommand) (*LocalRuntime, }, nil } +// DeferredShutdown is a bogus wrapper for compaat with the libpod +// runtime and should only be run when a defer is being used +func (r RemoteRuntime) DeferredShutdown(force bool) { + if err := r.Shutdown(force); err != nil { + logrus.Error("unable to shutdown runtime") + } +} + // Shutdown is a bogus wrapper for compat with the libpod runtime func (r RemoteRuntime) Shutdown(force bool) error { return nil diff --git a/pkg/adapter/sigproxy_linux.go b/pkg/adapter/sigproxy_linux.go index af968cb89..efa6afa7b 100644 --- a/pkg/adapter/sigproxy_linux.go +++ b/pkg/adapter/sigproxy_linux.go @@ -27,7 +27,9 @@ func ProxySignals(ctr *libpod.Container) { if err := ctr.Kill(uint(s.(syscall.Signal))); err != nil { logrus.Errorf("Error forwarding signal %d to container %s: %v", s, ctr.ID(), err) signal.StopCatch(sigBuffer) - syscall.Kill(syscall.Getpid(), s.(syscall.Signal)) + if err := syscall.Kill(syscall.Getpid(), s.(syscall.Signal)); err != nil { + logrus.Errorf("failed to kill pid %d", syscall.Getpid()) + } } } }() diff --git a/pkg/adapter/terminal_linux.go b/pkg/adapter/terminal_linux.go index 3c4c3bd38..e3255ecb6 100644 --- a/pkg/adapter/terminal_linux.go +++ b/pkg/adapter/terminal_linux.go @@ -35,9 +35,15 @@ func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, } logrus.SetFormatter(&RawTtyFormatter{}) - term.SetRawTerminal(os.Stdin.Fd()) + if _, err := term.SetRawTerminal(os.Stdin.Fd()); err != nil { + return err + } - defer restoreTerminal(oldTermState) + defer func() { + if err := restoreTerminal(oldTermState); err != nil { + logrus.Errorf("unable to restore terminal: %q", err) + } + }() } streams := new(libpod.AttachStreams) diff --git a/pkg/cgroups/blkio.go b/pkg/cgroups/blkio.go index 9c2a811d9..bacd4eb93 100644 --- a/pkg/cgroups/blkio.go +++ b/pkg/cgroups/blkio.go @@ -37,7 +37,7 @@ func (c *blkioHandler) Create(ctr *CgroupControl) (bool, error) { // Destroy the cgroup func (c *blkioHandler) Destroy(ctr *CgroupControl) error { - return os.Remove(ctr.getCgroupv1Path(Blkio)) + return rmDirRecursively(ctr.getCgroupv1Path(Blkio)) } // Stat fills a metrics structure with usage stats for the controller diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go index 1dad45d7f..081db772f 100644 --- a/pkg/cgroups/cgroups.go +++ b/pkg/cgroups/cgroups.go @@ -328,6 +328,13 @@ func Load(path string) (*CgroupControl, error) { systemd: false, } if !cgroup2 { + controllers, err := getAvailableControllers(handlers, false) + if err != nil { + return nil, err + } + control.additionalControllers = controllers + } + if !cgroup2 { for name := range handlers { p := control.getCgroupv1Path(name) if _, err := os.Stat(p); err != nil { @@ -355,11 +362,40 @@ func (c *CgroupControl) Delete() error { return c.DeleteByPath(c.path) } +// rmDirRecursively delete recursively a cgroup directory. +// It differs from os.RemoveAll as it doesn't attempt to unlink files. +// On cgroupfs we are allowed only to rmdir empty directories. +func rmDirRecursively(path string) error { + if err := os.Remove(path); err == nil || os.IsNotExist(err) { + return nil + } + entries, err := ioutil.ReadDir(path) + if err != nil { + return errors.Wrapf(err, "read %s", path) + } + for _, i := range entries { + if i.IsDir() { + if err := rmDirRecursively(filepath.Join(path, i.Name())); err != nil { + return err + } + } + } + if os.Remove(path); err != nil { + if !os.IsNotExist(err) { + return errors.Wrapf(err, "remove %s", path) + } + } + return nil +} + // DeleteByPath deletes the specified cgroup path func (c *CgroupControl) DeleteByPath(path string) error { if c.systemd { return systemdDestroy(path) } + if c.cgroup2 { + return rmDirRecursively(filepath.Join(cgroupRoot, c.path)) + } var lastError error for _, h := range handlers { if err := h.Destroy(c); err != nil { @@ -368,8 +404,11 @@ func (c *CgroupControl) DeleteByPath(path string) error { } for _, ctr := range c.additionalControllers { + if ctr.symlink { + continue + } p := c.getCgroupv1Path(ctr.name) - if err := os.Remove(p); err != nil { + if err := rmDirRecursively(p); err != nil { lastError = errors.Wrapf(err, "remove %s", p) } } diff --git a/pkg/cgroups/cpu.go b/pkg/cgroups/cpu.go index 1c8610cc4..03677f1ef 100644 --- a/pkg/cgroups/cpu.go +++ b/pkg/cgroups/cpu.go @@ -68,7 +68,7 @@ func (c *cpuHandler) Create(ctr *CgroupControl) (bool, error) { // Destroy the cgroup func (c *cpuHandler) Destroy(ctr *CgroupControl) error { - return os.Remove(ctr.getCgroupv1Path(CPU)) + return rmDirRecursively(ctr.getCgroupv1Path(CPU)) } // Stat fills a metrics structure with usage stats for the controller diff --git a/pkg/cgroups/cpuset.go b/pkg/cgroups/cpuset.go index 25d2f7f76..46d0484f2 100644 --- a/pkg/cgroups/cpuset.go +++ b/pkg/cgroups/cpuset.go @@ -3,7 +3,6 @@ package cgroups import ( "fmt" "io/ioutil" - "os" "path/filepath" "strings" @@ -77,7 +76,7 @@ func (c *cpusetHandler) Create(ctr *CgroupControl) (bool, error) { // Destroy the cgroup func (c *cpusetHandler) Destroy(ctr *CgroupControl) error { - return os.Remove(ctr.getCgroupv1Path(CPUset)) + return rmDirRecursively(ctr.getCgroupv1Path(CPUset)) } // Stat fills a metrics structure with usage stats for the controller diff --git a/pkg/cgroups/memory.go b/pkg/cgroups/memory.go index 80e88d17c..b3991f7e3 100644 --- a/pkg/cgroups/memory.go +++ b/pkg/cgroups/memory.go @@ -2,7 +2,6 @@ package cgroups import ( "fmt" - "os" "path/filepath" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -33,7 +32,7 @@ func (c *memHandler) Create(ctr *CgroupControl) (bool, error) { // Destroy the cgroup func (c *memHandler) Destroy(ctr *CgroupControl) error { - return os.Remove(ctr.getCgroupv1Path(Memory)) + return rmDirRecursively(ctr.getCgroupv1Path(Memory)) } // Stat fills a metrics structure with usage stats for the controller diff --git a/pkg/cgroups/pids.go b/pkg/cgroups/pids.go index ffbde100d..65b9b5b34 100644 --- a/pkg/cgroups/pids.go +++ b/pkg/cgroups/pids.go @@ -3,7 +3,6 @@ package cgroups import ( "fmt" "io/ioutil" - "os" "path/filepath" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -40,7 +39,7 @@ func (c *pidHandler) Create(ctr *CgroupControl) (bool, error) { // Destroy the cgroup func (c *pidHandler) Destroy(ctr *CgroupControl) error { - return os.Remove(ctr.getCgroupv1Path(Pids)) + return rmDirRecursively(ctr.getCgroupv1Path(Pids)) } // Stat fills a metrics structure with usage stats for the controller diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go new file mode 100644 index 000000000..970d47636 --- /dev/null +++ b/pkg/errorhandling/errorhandling.go @@ -0,0 +1,23 @@ +package errorhandling + +import ( + "os" + + "github.com/sirupsen/logrus" +) + +// SyncQuiet syncs a file and logs any error. Should only be used within +// a defer. +func SyncQuiet(f *os.File) { + if err := f.Sync(); err != nil { + logrus.Errorf("unable to sync file %s: %q", f.Name(), err) + } +} + +// CloseQuiet closes a file and logs any error. Should only be used within +// a defer. +func CloseQuiet(f *os.File) { + if err := f.Close(); err != nil { + logrus.Errorf("unable to close file %s: %q", f.Name(), err) + } +} diff --git a/pkg/firewall/firewalld.go b/pkg/firewall/firewalld.go index 32c2337a0..15e845cb7 100644 --- a/pkg/firewall/firewalld.go +++ b/pkg/firewall/firewalld.go @@ -18,6 +18,7 @@ package firewall import ( "fmt" + "github.com/sirupsen/logrus" "strings" "github.com/godbus/dbus" @@ -113,7 +114,9 @@ func (fb *fwdBackend) Del(conf *FirewallNetConf) error { // Remove firewalld rules which assigned the given source IP to the given zone firewalldObj := fb.conn.Object(firewalldName, firewalldPath) var res string - firewalldObj.Call(firewalldZoneInterface+"."+firewalldRemoveSourceMethod, 0, getFirewalldZone(conf), ipStr).Store(&res) + if err := firewalldObj.Call(firewalldZoneInterface+"."+firewalldRemoveSourceMethod, 0, getFirewalldZone(conf), ipStr).Store(&res); err != nil { + logrus.Errorf("unable to store firewallobj") + } } return nil } diff --git a/pkg/firewall/iptables.go b/pkg/firewall/iptables.go index 59d81b287..92d249f7b 100644 --- a/pkg/firewall/iptables.go +++ b/pkg/firewall/iptables.go @@ -21,6 +21,7 @@ package firewall import ( "fmt" + "github.com/sirupsen/logrus" "net" "github.com/coreos/go-iptables/iptables" @@ -53,7 +54,9 @@ func generateFilterRule(privChainName string) []string { func cleanupRules(ipt *iptables.IPTables, privChainName string, rules [][]string) { for _, rule := range rules { - ipt.Delete("filter", privChainName, rule...) + if err := ipt.Delete("filter", privChainName, rule...); err != nil { + logrus.Errorf("failed to delete iptables rule %s", privChainName) + } } } @@ -185,7 +188,9 @@ func (ib *iptablesBackend) Add(conf *FirewallNetConf) error { func (ib *iptablesBackend) Del(conf *FirewallNetConf) error { for proto, ipt := range ib.protos { - ib.delRules(conf, ipt, proto) + if err := ib.delRules(conf, ipt, proto); err != nil { + logrus.Errorf("failed to delete iptables backend rule %s", conf.IptablesAdminChainName) + } } return nil } diff --git a/pkg/hooks/exec/exec.go b/pkg/hooks/exec/exec.go index 0dd091561..4038e3d94 100644 --- a/pkg/hooks/exec/exec.go +++ b/pkg/hooks/exec/exec.go @@ -5,6 +5,7 @@ import ( "bytes" "context" "fmt" + "github.com/sirupsen/logrus" "io" osexec "os/exec" "time" @@ -54,7 +55,9 @@ func Run(ctx context.Context, hook *rspec.Hook, state []byte, stdout io.Writer, case err = <-exit: return err, err case <-ctx.Done(): - cmd.Process.Kill() + if err := cmd.Process.Kill(); err != nil { + logrus.Errorf("failed to kill pid %v", cmd.Process) + } timer := time.NewTimer(postKillTimeout) defer timer.Stop() select { diff --git a/pkg/logs/logs.go b/pkg/logs/logs.go index 0f684750e..89e4e5686 100644 --- a/pkg/logs/logs.go +++ b/pkg/logs/logs.go @@ -30,6 +30,7 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/errorhandling" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -153,7 +154,7 @@ func ReadLogs(logPath string, ctr *libpod.Container, opts *LogOptions) error { if err != nil { return errors.Wrapf(err, "failed to open log file %q", logPath) } - defer file.Close() + defer errorhandling.CloseQuiet(file) msg := &logMessage{} opts.bytes = -1 @@ -161,9 +162,9 @@ func ReadLogs(logPath string, ctr *libpod.Container, opts *LogOptions) error { reader := bufio.NewReader(file) if opts.Follow { - followLog(reader, writer, opts, ctr, msg, logPath) + err = followLog(reader, writer, opts, ctr, msg, logPath) } else { - dumpLog(reader, writer, opts, msg, logPath) + err = dumpLog(reader, writer, opts, msg, logPath) } return err } diff --git a/pkg/netns/netns_linux.go b/pkg/netns/netns_linux.go index a72a2d098..1d6fb873c 100644 --- a/pkg/netns/netns_linux.go +++ b/pkg/netns/netns_linux.go @@ -28,6 +28,7 @@ import ( "sync" "github.com/containernetworking/plugins/pkg/ns" + "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -83,12 +84,16 @@ func NewNS() (ns.NetNS, error) { if err != nil { return nil, err } - mountPointFd.Close() + if err := mountPointFd.Close(); err != nil { + return nil, err + } // Ensure the mount point is cleaned up on errors; if the namespace // was successfully mounted this will have no effect because the file // is in-use - defer os.RemoveAll(nsPath) + defer func() { + _ = os.RemoveAll(nsPath) + }() var wg sync.WaitGroup wg.Add(1) @@ -107,7 +112,11 @@ func NewNS() (ns.NetNS, error) { if err != nil { return } - defer origNS.Close() + defer func() { + if err := origNS.Close(); err != nil { + logrus.Errorf("unable to close namespace: %q", err) + } + }() // create a new netns on the current thread err = unix.Unshare(unix.CLONE_NEWNET) @@ -116,7 +125,11 @@ func NewNS() (ns.NetNS, error) { } // Put this thread back to the orig ns, since it might get reused (pre go1.10) - defer origNS.Set() + defer func() { + if err := origNS.Set(); err != nil { + logrus.Errorf("unable to set namespace: %q", err) + } + }() // bind mount the netns from the current thread (from /proc) onto the // mount point. This causes the namespace to persist, even when there diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index 8028a359c..99a0eb729 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -17,6 +17,7 @@ import ( "syscall" "unsafe" + "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/storage/pkg/idtools" "github.com/docker/docker/pkg/signal" "github.com/godbus/dbus" @@ -41,8 +42,7 @@ const ( ) func runInUser() error { - os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done") - return nil + return os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done") } var ( @@ -57,9 +57,15 @@ func IsRootless() bool { rootlessGIDInit := int(C.rootless_gid()) if rootlessUIDInit != 0 { // This happens if we joined the user+mount namespace as part of - os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done") - os.Setenv("_CONTAINERS_ROOTLESS_UID", fmt.Sprintf("%d", rootlessUIDInit)) - os.Setenv("_CONTAINERS_ROOTLESS_GID", fmt.Sprintf("%d", rootlessGIDInit)) + if err := os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done"); err != nil { + logrus.Errorf("failed to set environment variable %s as %s", "_CONTAINERS_USERNS_CONFIGURED", "done") + } + if err := os.Setenv("_CONTAINERS_ROOTLESS_UID", fmt.Sprintf("%d", rootlessUIDInit)); err != nil { + logrus.Errorf("failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_UID", rootlessUIDInit) + } + if err := os.Setenv("_CONTAINERS_ROOTLESS_GID", fmt.Sprintf("%d", rootlessGIDInit)); err != nil { + logrus.Errorf("failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_GID", rootlessGIDInit) + } } isRootless = os.Geteuid() != 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" }) @@ -185,18 +191,24 @@ func getUserNSFirstChild(fd uintptr) (*os.File, error) { } if ns == currentNS { - syscall.Close(int(nextFd)) + if err := syscall.Close(int(nextFd)); err != nil { + return nil, err + } // Drop O_CLOEXEC for the fd. _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, fd, syscall.F_SETFD, 0) if errno != 0 { - syscall.Close(int(fd)) + if err := syscall.Close(int(fd)); err != nil { + logrus.Errorf("failed to close file descriptor %d", fd) + } return nil, errno } return os.NewFile(fd, "userns child"), nil } - syscall.Close(int(fd)) + if err := syscall.Close(int(fd)); err != nil { + return nil, err + } fd = nextFd } } @@ -208,7 +220,11 @@ func EnableLinger() (string, error) { conn, err := dbus.SystemBus() if err == nil { - defer conn.Close() + defer func() { + if err := conn.Close(); err != nil { + logrus.Errorf("unable to close dbus connection: %q", err) + } + }() } lingerEnabled := false @@ -252,7 +268,9 @@ func EnableLinger() (string, error) { if lingerEnabled && lingerFile != "" { f, err := os.Create(lingerFile) if err == nil { - f.Close() + if err := f.Close(); err != nil { + logrus.Errorf("failed to close %s", f.Name()) + } } else { logrus.Debugf("could not create linger file: %v", err) } @@ -296,13 +314,21 @@ func joinUserAndMountNS(pid uint, pausePid string) (bool, int, error) { if err != nil { return false, -1, err } - defer userNS.Close() + defer func() { + if err := userNS.Close(); err != nil { + logrus.Errorf("unable to close namespace: %q", err) + } + }() mountNS, err := os.Open(fmt.Sprintf("/proc/%d/ns/mnt", pid)) if err != nil { return false, -1, err } - defer userNS.Close() + defer func() { + if err := mountNS.Close(); err != nil { + logrus.Errorf("unable to close namespace: %q", err) + } + }() fd, err := getUserNSFirstChild(userNS.Fd()) if err != nil { @@ -348,9 +374,13 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool, } r, w := os.NewFile(uintptr(fds[0]), "sync host"), os.NewFile(uintptr(fds[1]), "sync child") - defer r.Close() - defer w.Close() - defer w.Write([]byte("0")) + defer errorhandling.CloseQuiet(r) + defer errorhandling.CloseQuiet(w) + defer func() { + if _, err := w.Write([]byte("0")); err != nil { + logrus.Errorf("failed to write byte 0: %q", err) + } + }() pidC := C.reexec_in_user_namespace(C.int(r.Fd()), cPausePid, cFileToRead, fileOutputFD) pid := int(pidC) @@ -361,9 +391,9 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool, var uids, gids []idtools.IDMap username := os.Getenv("USER") if username == "" { - user, err := user.LookupId(fmt.Sprintf("%d", os.Getuid())) + userID, err := user.LookupId(fmt.Sprintf("%d", os.Getuid())) if err == nil { - username = user.Username + username = userID.Username } } mappings, err := idtools.NewIDMappings(username, username) @@ -458,7 +488,9 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool, continue } - syscall.Kill(int(pidC), s.(syscall.Signal)) + if err := syscall.Kill(int(pidC), s.(syscall.Signal)); err != nil { + logrus.Errorf("failed to kill %d", int(pidC)) + } } }() @@ -519,17 +551,19 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st r, w := os.NewFile(uintptr(fds[0]), "read file"), os.NewFile(uintptr(fds[1]), "write file") - defer w.Close() - defer r.Close() + defer errorhandling.CloseQuiet(w) + defer errorhandling.CloseQuiet(r) if _, _, err := becomeRootInUserNS("", path, w); err != nil { lastErr = err continue } - w.Close() + if err := w.Close(); err != nil { + return false, 0, err + } defer func() { - r.Close() + errorhandling.CloseQuiet(r) C.reexec_in_user_namespace_wait(-1, 0) }() diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 06d1ac12d..d44beb3e4 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -20,6 +20,12 @@ import ( const cpuPeriod = 100000 +type systemUlimit struct { + name string + max uint64 + cur uint64 +} + func getAvailableGids() (int64, error) { idMap, err := user.ParseIDMapFile("/proc/self/gid_map") if err != nil { @@ -475,7 +481,9 @@ func addPidNS(config *CreateConfig, g *generate.Generator) error { func addUserNS(config *CreateConfig, g *generate.Generator) error { if IsNS(string(config.UsernsMode)) { - g.AddOrReplaceLinuxNamespace(spec.UserNamespace, NS(string(config.UsernsMode))) + if err := g.AddOrReplaceLinuxNamespace(spec.UserNamespace, NS(string(config.UsernsMode))); err != nil { + return err + } // runc complains if no mapping is specified, even if we join another ns. So provide a dummy mapping g.AddLinuxUIDMapping(uint32(0), uint32(0), uint32(1)) @@ -483,7 +491,9 @@ func addUserNS(config *CreateConfig, g *generate.Generator) error { } if (len(config.IDMappings.UIDMap) > 0 || len(config.IDMappings.GIDMap) > 0) && !config.UsernsMode.IsHost() { - g.AddOrReplaceLinuxNamespace(spec.UserNamespace, "") + if err := g.AddOrReplaceLinuxNamespace(spec.UserNamespace, ""); err != nil { + return err + } } return nil } @@ -553,6 +563,20 @@ func addRlimits(config *CreateConfig, g *generate.Generator) error { ) for _, u := range config.Resources.Ulimit { + if u == "host" { + if len(config.Resources.Ulimit) != 1 { + return errors.New("ulimit can use host only once") + } + hostLimits, err := getHostRlimits() + if err != nil { + return err + } + for _, i := range hostLimits { + g.AddProcessRlimits(i.name, i.max, i.cur) + } + break + } + ul, err := units.ParseUlimit(u) if err != nil { return errors.Wrapf(err, "ulimit option %q requires name=SOFT:HARD, failed to be parsed", u) diff --git a/pkg/spec/spec_linux.go b/pkg/spec/spec_linux.go new file mode 100644 index 000000000..fcdfc5c4e --- /dev/null +++ b/pkg/spec/spec_linux.go @@ -0,0 +1,42 @@ +//+build linux + +package createconfig + +import ( + "syscall" + + "github.com/pkg/errors" +) + +type systemRlimit struct { + name string + value int +} + +var systemLimits = []systemRlimit{ + {"RLIMIT_AS", syscall.RLIMIT_AS}, + {"RLIMIT_CORE", syscall.RLIMIT_CORE}, + {"RLIMIT_CPU", syscall.RLIMIT_CPU}, + {"RLIMIT_DATA", syscall.RLIMIT_DATA}, + {"RLIMIT_FSIZE", syscall.RLIMIT_FSIZE}, + {"RLIMIT_NOFILE", syscall.RLIMIT_NOFILE}, + {"RLIMIT_STACK", syscall.RLIMIT_STACK}, +} + +func getHostRlimits() ([]systemUlimit, error) { + ret := []systemUlimit{} + for _, i := range systemLimits { + var l syscall.Rlimit + if err := syscall.Getrlimit(i.value, &l); err != nil { + return nil, errors.Wrapf(err, "cannot read limits for %s", i.name) + } + s := systemUlimit{ + name: i.name, + max: l.Max, + cur: l.Cur, + } + ret = append(ret, s) + } + return ret, nil + +} diff --git a/pkg/spec/spec_unsupported.go b/pkg/spec/spec_unsupported.go new file mode 100644 index 000000000..0f6a9acdc --- /dev/null +++ b/pkg/spec/spec_unsupported.go @@ -0,0 +1,7 @@ +//+build !linux + +package createconfig + +func getHostRlimits() ([]systemUlimit, error) { + return nil, nil +} diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 9e49f08a0..fba34a337 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -12,12 +12,14 @@ import ( "github.com/BurntSushi/toml" "github.com/containers/image/types" "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/namespaces" "github.com/containers/libpod/pkg/rootless" "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/spf13/pflag" "golang.org/x/crypto/ssh/terminal" ) @@ -272,16 +274,20 @@ func getTomlStorage(storeOptions *storage.StoreOptions) *tomlConfig { // WriteStorageConfigFile writes the configuration to a file func WriteStorageConfigFile(storageOpts *storage.StoreOptions, storageConf string) error { - os.MkdirAll(filepath.Dir(storageConf), 0755) - file, err := os.OpenFile(storageConf, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) + if err := os.MkdirAll(filepath.Dir(storageConf), 0755); err != nil { + return err + } + storageFile, err := os.OpenFile(storageConf, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) if err != nil { return errors.Wrapf(err, "cannot open %s", storageConf) } tomlConfiguration := getTomlStorage(storageOpts) - defer file.Close() - enc := toml.NewEncoder(file) + defer errorhandling.CloseQuiet(storageFile) + enc := toml.NewEncoder(storageFile) if err := enc.Encode(tomlConfiguration); err != nil { - os.Remove(storageConf) + if err := os.Remove(storageConf); err != nil { + logrus.Errorf("unable to remove file %s", storageConf) + } return err } return nil diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go index 99c9e4f1e..af55689a6 100644 --- a/pkg/util/utils_supported.go +++ b/pkg/util/utils_supported.go @@ -13,6 +13,7 @@ import ( "github.com/containers/libpod/pkg/rootless" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) // GetRootlessRuntimeDir returns the runtime directory when running as non root @@ -24,7 +25,9 @@ func GetRootlessRuntimeDir() (string, error) { uid := fmt.Sprintf("%d", rootless.GetRootlessUID()) if runtimeDir == "" { tmpDir := filepath.Join("/run", "user", uid) - os.MkdirAll(tmpDir, 0700) + if err := os.MkdirAll(tmpDir, 0700); err != nil { + logrus.Errorf("unable to make temp dir %s", tmpDir) + } st, err := os.Stat(tmpDir) if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { runtimeDir = tmpDir @@ -32,7 +35,9 @@ func GetRootlessRuntimeDir() (string, error) { } if runtimeDir == "" { tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("run-%s", uid)) - os.MkdirAll(tmpDir, 0700) + if err := os.MkdirAll(tmpDir, 0700); err != nil { + logrus.Errorf("unable to make temp dir %s", tmpDir) + } st, err := os.Stat(tmpDir) if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { runtimeDir = tmpDir diff --git a/test/README.md b/test/README.md index 4e61a0774..9bea679dc 100644 --- a/test/README.md +++ b/test/README.md @@ -110,19 +110,30 @@ make shell This will run a container and give you a shell and you can follow the instructions above. -# System test +# System tests System tests are used for testing the *podman* CLI in the context of a complete system. It requires that *podman*, all dependencies, and configurations are in place. The intention of system testing is to match as closely as possible with real-world user/developer use-cases and environments. The orchestration of the environments and tests is left to external tooling. -* `PodmanTestSystem`: System test *struct* as a composite of `PodmanTest`. It will not add any -options to the command by default. When you run system test, you can set GLOBALOPTIONS, -PODMAN_SUBCMD_OPTIONS or PODMAN_BINARY in ENV to run the test suite for different test matrices. +System tests use Bash Automated Testing System (`bats`) as a testing framework. +Install it via your package manager or get latest stable version +[directly from the repository](https://github.com/bats-core/bats-core), e.g.: -## Run system test -You can run the test with following command: +``` +mkdir -p ~/tools/bats +git clone --single-branch --branch v1.1.0 https://github.com/bats-core/bats-core.git ~/tools/bats +``` + +Make sure that `bats` binary (`bin/bats` in the repository) is in your `PATH`, if not - add it: + +``` +PATH=$PATH:~/tools/bats/bin +``` + +## Running system tests +When `bats` is installed and is in your `PATH`, you can run the test suite with following command: ``` make localsystem diff --git a/test/e2e/pod_rm_test.go b/test/e2e/pod_rm_test.go index 0d3f47f30..f0689f152 100644 --- a/test/e2e/pod_rm_test.go +++ b/test/e2e/pod_rm_test.go @@ -3,6 +3,8 @@ package integration import ( "fmt" "os" + "path/filepath" + "strings" . "github.com/containers/libpod/test/utils" . "github.com/onsi/ginkgo" @@ -40,6 +42,21 @@ var _ = Describe("Podman pod rm", func() { result := podmanTest.Podman([]string{"pod", "rm", podid}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) + + // Also check that we don't leak cgroups + err := filepath.Walk("/sys/fs/cgroup", func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() { + Expect(err).To(BeNil()) + } + if strings.Contains(info.Name(), podid) { + return fmt.Errorf("leaking cgroup path %s", path) + } + return nil + }) + Expect(err).To(BeNil()) }) It("podman pod rm latest pod", func() { diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 3fc628589..f95c5298d 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -8,7 +8,9 @@ import ( "net" "os" "path/filepath" + "strconv" "strings" + "syscall" "time" . "github.com/containers/libpod/test/utils" @@ -250,6 +252,25 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).To(ContainSubstring("100")) }) + It("podman run limits host test", func() { + SkipIfRemote() + + var l syscall.Rlimit + + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "host", fedoraMinimal, "ulimit", "-Hn"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + ulimitCtrStr := strings.TrimSpace(session.OutputToString()) + ulimitCtr, err := strconv.ParseUint(ulimitCtrStr, 10, 0) + Expect(err).To(BeNil()) + + Expect(ulimitCtr).Should(BeNumerically(">=", l.Max)) + }) + It("podman run with cidfile", func() { session := podmanTest.Podman([]string{"run", "--cidfile", tempdir + "cidfile", ALPINE, "ls"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/stats_test.go b/test/e2e/stats_test.go index 45511edb8..4000ab33a 100644 --- a/test/e2e/stats_test.go +++ b/test/e2e/stats_test.go @@ -65,7 +65,7 @@ var _ = Describe("Podman stats", func() { session := podmanTest.RunTopContainer("") session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - session = podmanTest.Podman([]string{"stats", "--all", "--no-stream", "--format", "\"{{.Container}}\""}) + session = podmanTest.Podman([]string{"stats", "--all", "--no-stream", "--format", "\"{{.ID}}\""}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) }) diff --git a/vendor/modules.txt b/vendor/modules.txt index 62d2ebc9d..ad2f69976 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -537,18 +537,18 @@ gopkg.in/yaml.v2 # k8s.io/api v0.0.0-20190624085159-95846d7ef82a k8s.io/api/core/v1 # k8s.io/apimachinery v0.0.0-20190624085041-961b39a1baa0 -k8s.io/apimachinery/pkg/fields k8s.io/apimachinery/pkg/apis/meta/v1 k8s.io/apimachinery/pkg/util/wait k8s.io/apimachinery/pkg/util/runtime -k8s.io/apimachinery/pkg/selection k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/runtime k8s.io/apimachinery/pkg/runtime/schema k8s.io/apimachinery/pkg/types k8s.io/apimachinery/pkg/util/intstr k8s.io/apimachinery/pkg/conversion +k8s.io/apimachinery/pkg/fields k8s.io/apimachinery/pkg/labels +k8s.io/apimachinery/pkg/selection k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/pkg/util/httpstream k8s.io/apimachinery/pkg/util/remotecommand |