From ebacfbd091f709d7ca0b811a9fe1fee57c6f0ad3 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 10 Jul 2019 15:09:33 -0400 Subject: podman: fix memleak caused by renaming and not deleting the exit file If the container exit code needs to be retained, it cannot be retained in tmpfs, because libpod runs in a memcg itself so it can't leave traces with a daemon-less design. This wasn't a memleak detectable by kmemleak for example. The kernel never lost track of the memory and there was no erroneous refcounting either. The reference count dependencies however are not easy to track because when a refcount is increased, there's no way to tell who's still holding the reference. In this case it was a single page of tmpfs pagecache holding a refcount that kept pinned a whole hierarchy of dying memcg, slab kmem, cgropups, unrechable kernfs nodes and the respective dentries and inodes. Such a problem wouldn't happen if the exit file was stored in a regular filesystem because the pagecache could be reclaimed in such case under memory pressure. The tmpfs page can be swapped out, but that's not enough to release the memcg with CONFIG_MEMCG_SWAP_ENABLED=y. No amount of more aggressive kernel slab shrinking could have solved this. Not even assigning slab kmem of dying cgroups to alive cgroup would fully solve this. The only way to free the memory of a dying cgroup when a struct page still references it, would be to loop over all "struct page" in the kernel to find which one is associated with the dying cgroup which is a O(N) operation (where N is the number of pages and can reach billions). Linking all the tmpfs pages to the memcg would cost less during memcg offlining, but it would waste lots of memory and CPU globally. So this can't be optimized in the kernel. A cronjob running this command can act as workaround and will allow all slab cache to be released, not just the single tmpfs pages. rm -f /run/libpod/exits/* This patch solved the memleak with a reproducer, booting with cgroup.memory=nokmem and with selinux disabled. The reason memcg kmem and selinux were disabled for testing of this fix, is because kmem greatly decreases the kernel effectiveness in reusing partial slab objects. cgroup.memory=nokmem is strongly recommended at least for workstation usage. selinux needs to be further analyzed because it causes further slab allocations. The upstream podman commit used for testing is 1fe2965e4f672674f7b66648e9973a0ed5434bb4 (v1.4.4). The upstream kernel commit used for testing is f16fea666898dbdd7812ce94068c76da3e3fcf1e (v5.2-rc6). Reported-by: Michele Baldessari Signed-off-by: Andrea Arcangeli Signed-off-by: Matthew Heon --- libpod/container_internal.go | 10 +++------ pkg/adapter/containers.go | 52 ++++---------------------------------------- 2 files changed, 7 insertions(+), 55 deletions(-) diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 83ee5640e..3114e00c0 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -634,19 +634,15 @@ func (c *Container) removeConmonFiles() error { return errors.Wrapf(err, "error removing container %s OOM file", c.ID()) } - // Instead of outright deleting the exit file, rename it (if it exists). - // We want to retain it so we can get the exit code of containers which - // are removed (at least until we have a workable events system) + // Remove the exit file so we don't leak memory in tmpfs exitFile := filepath.Join(c.ociRuntime.exitsDir, c.ID()) - oldExitFile := filepath.Join(c.ociRuntime.exitsDir, fmt.Sprintf("%s-old", c.ID())) if _, err := os.Stat(exitFile); err != nil { if !os.IsNotExist(err) { return errors.Wrapf(err, "error running stat on container %s exit file", c.ID()) } } else { - // Rename should replace the old exit file (if it exists) - if err := os.Rename(exitFile, oldExitFile); err != nil { - return errors.Wrapf(err, "error renaming container %s exit file", c.ID()) + if err := os.Remove(exitFile); err != nil { + return errors.Wrapf(err, "error removing container %s exit file", c.ID()) } } diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index faaef3e60..525b1f29b 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -9,7 +9,6 @@ import ( "io" "io/ioutil" "os" - "path/filepath" "strconv" "strings" "sync" @@ -418,15 +417,8 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode if ecode, err := ctr.Wait(); err != nil { if errors.Cause(err) == define.ErrNoSuchCtr { - // The container may have been removed - // Go looking for an exit file - ctrExitCode, err := ReadExitFile(config.TmpDir, ctr.ID()) - if err != nil { - logrus.Errorf("Cannot get exit code: %v", err) - exitCode = 127 - } else { - exitCode = ctrExitCode - } + logrus.Errorf("Cannot get exit code: %v", err) + exitCode = 127 } } else { exitCode = int(ecode) @@ -441,31 +433,6 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode return exitCode, nil } -// ReadExitFile reads a container's exit file -func ReadExitFile(runtimeTmp, ctrID string) (int, error) { - exitFile := filepath.Join(runtimeTmp, "exits", fmt.Sprintf("%s-old", ctrID)) - - logrus.Debugf("Attempting to read container %s exit code from file %s", ctrID, exitFile) - - // Check if it exists - if _, err := os.Stat(exitFile); err != nil { - return 0, errors.Wrapf(err, "error getting exit file for container %s", ctrID) - } - - // File exists, read it in and convert to int - statusStr, err := ioutil.ReadFile(exitFile) - if err != nil { - return 0, errors.Wrapf(err, "error reading exit file for container %s", ctrID) - } - - exitCode, err := strconv.Atoi(string(statusStr)) - if err != nil { - return 0, errors.Wrapf(err, "error parsing exit code for container %s", ctrID) - } - - return exitCode, nil -} - // Ps ... func (r *LocalRuntime) Ps(c *cliconfig.PsValues, opts shared.PsOptions) ([]shared.PsContainerOutput, error) { maxWorkers := shared.Parallelize("ps") @@ -655,19 +622,8 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP if ecode, err := ctr.Wait(); err != nil { if errors.Cause(err) == define.ErrNoSuchCtr { - // The container may have been removed - // Go looking for an exit file - rtc, err := r.GetConfig() - if err != nil { - return 0, err - } - ctrExitCode, err := ReadExitFile(rtc.TmpDir, ctr.ID()) - if err != nil { - logrus.Errorf("Cannot get exit code: %v", err) - exitCode = 127 - } else { - exitCode = ctrExitCode - } + logrus.Errorf("Cannot get exit code: %v", err) + exitCode = 127 } } else { exitCode = int(ecode) -- cgit v1.2.3-54-g00ecf From 7dd1df43231ba53e7d334c5272f93336a1ac32a5 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 10 Jul 2019 15:41:35 -0400 Subject: Retrieve exit codes for containers via events As we previously removed our exit code retrieval code to stop a memory leak, we need a new way of doing this. Fortunately, events is able to do the job for us. Signed-off-by: Matthew Heon --- pkg/adapter/containers.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 525b1f29b..155454e21 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -22,6 +22,7 @@ import ( "github.com/containers/libpod/cmd/podman/shared/parse" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/logs" "github.com/containers/libpod/pkg/adapter/shortcuts" @@ -417,8 +418,14 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode if ecode, err := ctr.Wait(); err != nil { if errors.Cause(err) == define.ErrNoSuchCtr { - logrus.Errorf("Cannot get exit code: %v", err) - exitCode = 127 + // Check events + event, err := r.Runtime.GetLastContainerEvent(ctr.ID(), events.Exited) + if err != nil { + logrus.Errorf("Cannot get exit code: %v", err) + exitCode = 127 + } else { + exitCode = event.ContainerExitCode + } } } else { exitCode = int(ecode) @@ -622,8 +629,14 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP if ecode, err := ctr.Wait(); err != nil { if errors.Cause(err) == define.ErrNoSuchCtr { - logrus.Errorf("Cannot get exit code: %v", err) - exitCode = 127 + // Check events + event, err := r.Runtime.GetLastContainerEvent(ctr.ID(), events.Exited) + if err != nil { + logrus.Errorf("Cannot get exit code: %v", err) + exitCode = 127 + } else { + exitCode = event.ContainerExitCode + } } } else { exitCode = int(ecode) -- cgit v1.2.3-54-g00ecf From 6619c073bda15ff828a49637b7330d01b7380e83 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Thu, 11 Jul 2019 13:32:42 -0400 Subject: Fix test suite Signed-off-by: Matthew Heon --- test/e2e/run_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 7b5ff2547..f66d1d2fa 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -789,9 +789,10 @@ USER mail` match, _ := session.GrepString("1.2.3.4") Expect(match).Should(BeTrue()) - session = podmanTest.Podman([]string{"run", "--rm", "--http-proxy=false", ALPINE, "printenv", "http_proxy"}) + session = podmanTest.Podman([]string{"run", "--http-proxy=false", ALPINE, "printenv", "http_proxy"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(1)) + Expect(session.OutputToString()).To(Equal("")) os.Unsetenv("http_proxy") }) -- cgit v1.2.3-54-g00ecf From 8e8d1ac1933e3891c597ea1b12e434d365b7d164 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 16 Jul 2019 15:56:24 -0400 Subject: Add a flag to set events logger type Signed-off-by: Matthew Heon --- cmd/podman/cliconfig/config.go | 1 + cmd/podman/libpodruntime/runtime.go | 4 + cmd/podman/main_local.go | 1 + docs/podman.1.md | 4 + libpod/events/events.go | 12 ++ libpod/options.go | 312 +++++++++++++++++++----------------- 6 files changed, 188 insertions(+), 146 deletions(-) diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go index 025f40cf6..37d6d3908 100644 --- a/cmd/podman/cliconfig/config.go +++ b/cmd/podman/cliconfig/config.go @@ -16,6 +16,7 @@ type MainFlags struct { CniConfigDir string ConmonPath string DefaultMountsFile string + EventsBackend string HooksDir []string MaxWorks int Namespace string diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go index 570288837..ee9e57966 100644 --- a/cmd/podman/libpodruntime/runtime.go +++ b/cmd/podman/libpodruntime/runtime.go @@ -118,6 +118,10 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra options = append(options, libpod.WithNetworkCmdPath(c.GlobalFlags.NetworkCmdPath)) } + if c.Flags().Changed("events-backend") { + options = append(options, libpod.WithEventsLogger(c.GlobalFlags.EventsBackend)) + } + if c.Flags().Changed("cgroup-manager") { options = append(options, libpod.WithCgroupManager(c.GlobalFlags.CGroupManager)) } else { diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go index e4f521bc4..5c8b2b1ff 100644 --- a/cmd/podman/main_local.go +++ b/cmd/podman/main_local.go @@ -48,6 +48,7 @@ func init() { if err := rootCmd.PersistentFlags().MarkHidden("default-mounts-file"); err != nil { logrus.Error("unable to mark default-mounts-file flag as hidden") } + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.EventsBackend, "events-backend", "", "Events backend to use") // Override default --help information of `--help` global flag var dummyHelp bool rootCmd.PersistentFlags().BoolVar(&dummyHelp, "help", false, "Help for podman") diff --git a/docs/podman.1.md b/docs/podman.1.md index 022514a80..02d15c197 100644 --- a/docs/podman.1.md +++ b/docs/podman.1.md @@ -36,6 +36,10 @@ Note: CGroup manager is not supported in rootless mode when using CGroups Versio Path to where the cpu performance results should be written +**--events-logger**=**type** + +Backend to use for storing events. Allowed values are **journald** and **file**. + **--hooks-dir**=*path* Each `*.json` file in the path configures a hook for Podman containers. For more details on the syntax of the JSON files and the semantics of hook injection, see `oci-hooks(5)`. Podman and libpod currently support both the 1.0.0 and 0.1.0 hook schemas, although the 0.1.0 schema is deprecated. diff --git a/libpod/events/events.go b/libpod/events/events.go index 2bebff162..a898171c1 100644 --- a/libpod/events/events.go +++ b/libpod/events/events.go @@ -23,6 +23,18 @@ func (et EventerType) String() string { return "journald" } +// IsValidEventer checks if the given string is a valid eventer type. +func IsValidEventer(eventer string) bool { + switch eventer { + case LogFile.String(): + return true + case Journald.String(): + return true + default: + return false + } +} + // NewEvent creates a event struct and populates with // the given status and time. func NewEvent(status Status) Event { diff --git a/libpod/options.go b/libpod/options.go index 81d3aa64f..7fbd0016a 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -8,7 +8,8 @@ import ( "syscall" "github.com/containers/image/manifest" - config2 "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/pkg/namespaces" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/util" @@ -20,7 +21,7 @@ import ( var ( nameRegex = regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9_.-]*$") - regexError = errors.Wrapf(config2.ErrInvalidArg, "names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*") + regexError = errors.Wrapf(define.ErrInvalidArg, "names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*") ) // Runtime Creation Options @@ -31,7 +32,7 @@ var ( func WithStorageConfig(config storage.StoreOptions) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } setField := false @@ -105,7 +106,7 @@ func WithStorageConfig(config storage.StoreOptions) RuntimeOption { func WithDefaultTransport(defaultTransport string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.ImageDefaultTransport = defaultTransport @@ -121,7 +122,7 @@ func WithDefaultTransport(defaultTransport string) RuntimeOption { func WithSignaturePolicy(path string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.SignaturePolicyPath = path @@ -137,11 +138,11 @@ func WithSignaturePolicy(path string) RuntimeOption { func WithStateType(storeType RuntimeStateStore) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } if storeType == InvalidStateStore { - return errors.Wrapf(config2.ErrInvalidArg, "must provide a valid state store type") + return errors.Wrapf(define.ErrInvalidArg, "must provide a valid state store type") } rt.config.StateType = storeType @@ -154,11 +155,11 @@ func WithStateType(storeType RuntimeStateStore) RuntimeOption { func WithOCIRuntime(runtime string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } if runtime == "" { - return errors.Wrapf(config2.ErrInvalidArg, "must provide a valid path") + return errors.Wrapf(define.ErrInvalidArg, "must provide a valid path") } rt.config.OCIRuntime = runtime @@ -173,11 +174,11 @@ func WithOCIRuntime(runtime string) RuntimeOption { func WithConmonPath(path string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } if path == "" { - return errors.Wrapf(config2.ErrInvalidArg, "must provide a valid path") + return errors.Wrapf(define.ErrInvalidArg, "must provide a valid path") } rt.config.ConmonPath = []string{path} @@ -190,7 +191,7 @@ func WithConmonPath(path string) RuntimeOption { func WithConmonEnv(environment []string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.ConmonEnvVars = make([]string, len(environment)) @@ -205,7 +206,7 @@ func WithConmonEnv(environment []string) RuntimeOption { func WithNetworkCmdPath(path string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.NetworkCmdPath = path @@ -220,11 +221,11 @@ func WithNetworkCmdPath(path string) RuntimeOption { func WithCgroupManager(manager string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } if manager != CgroupfsCgroupsManager && manager != SystemdCgroupsManager { - return errors.Wrapf(config2.ErrInvalidArg, "CGroup manager must be one of %s and %s", + return errors.Wrapf(define.ErrInvalidArg, "CGroup manager must be one of %s and %s", CgroupfsCgroupsManager, SystemdCgroupsManager) } @@ -239,7 +240,7 @@ func WithCgroupManager(manager string) RuntimeOption { func WithStaticDir(dir string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.StaticDir = dir @@ -253,12 +254,12 @@ func WithStaticDir(dir string) RuntimeOption { func WithHooksDir(hooksDirs ...string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } for _, hooksDir := range hooksDirs { if hooksDir == "" { - return errors.Wrap(config2.ErrInvalidArg, "empty-string hook directories are not supported") + return errors.Wrap(define.ErrInvalidArg, "empty-string hook directories are not supported") } } @@ -274,11 +275,11 @@ func WithHooksDir(hooksDirs ...string) RuntimeOption { func WithDefaultMountsFile(mountsFile string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } if mountsFile == "" { - return config2.ErrInvalidArg + return define.ErrInvalidArg } rt.config.DefaultMountsFile = mountsFile return nil @@ -291,7 +292,7 @@ func WithDefaultMountsFile(mountsFile string) RuntimeOption { func WithTmpDir(dir string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.TmpDir = dir rt.configuredFrom.libpodTmpDirSet = true @@ -314,7 +315,7 @@ func WithNoStore() RuntimeOption { func WithMaxLogSize(limit int64) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.MaxLogSize = limit @@ -328,7 +329,7 @@ func WithMaxLogSize(limit int64) RuntimeOption { func WithNoPivotRoot() RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.NoPivotRoot = true @@ -341,7 +342,7 @@ func WithNoPivotRoot() RuntimeOption { func WithCNIConfigDir(dir string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.CNIConfigDir = dir @@ -354,7 +355,7 @@ func WithCNIConfigDir(dir string) RuntimeOption { func WithCNIPluginDir(dir string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.CNIPluginDir = []string{dir} @@ -374,7 +375,7 @@ func WithCNIPluginDir(dir string) RuntimeOption { func WithNamespace(ns string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.Namespace = ns @@ -390,7 +391,7 @@ func WithNamespace(ns string) RuntimeOption { func WithVolumePath(volPath string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.VolumePath = volPath @@ -408,7 +409,7 @@ func WithVolumePath(volPath string) RuntimeOption { func WithDefaultInfraImage(img string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.InfraImage = img @@ -422,7 +423,7 @@ func WithDefaultInfraImage(img string) RuntimeOption { func WithDefaultInfraCommand(cmd string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.config.InfraCommand = cmd @@ -438,7 +439,7 @@ func WithDefaultInfraCommand(cmd string) RuntimeOption { func WithRenumber() RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.doRenumber = true @@ -453,7 +454,7 @@ func WithRenumber() RuntimeOption { func WithMigrate() RuntimeOption { return func(rt *Runtime) error { if rt.valid { - return config2.ErrRuntimeFinalized + return define.ErrRuntimeFinalized } rt.doMigrate = true @@ -462,13 +463,32 @@ func WithMigrate() RuntimeOption { } } +// WithEventsLogger sets the events backend to use. +// Currently supported values are "file" for file backend and "journald" for +// journald backend. +func WithEventsLogger(logger string) RuntimeOption { + return func(rt *Runtime) error { + if rt.valid { + return define.ErrRuntimeFinalized + } + + if !events.IsValidEventer(logger) { + return errors.Wrapf(define.ErrInvalidArg, "%q is not a valid events backend", logger) + } + + rt.config.EventsLogger = logger + + return nil + } +} + // Container Creation Options // WithShmDir sets the directory that should be mounted on /dev/shm. func WithShmDir(dir string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.ShmDir = dir @@ -480,7 +500,7 @@ func WithShmDir(dir string) CtrCreateOption { func WithSystemd() CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.Systemd = true @@ -492,7 +512,7 @@ func WithSystemd() CtrCreateOption { func WithShmSize(size int64) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.ShmSize = size @@ -504,7 +524,7 @@ func WithShmSize(size int64) CtrCreateOption { func WithPrivileged(privileged bool) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.Privileged = privileged @@ -516,7 +536,7 @@ func WithPrivileged(privileged bool) CtrCreateOption { func WithSecLabels(labelOpts []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.LabelOpts = labelOpts return nil @@ -528,7 +548,7 @@ func WithSecLabels(labelOpts []string) CtrCreateOption { func WithUser(user string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.User = user @@ -544,14 +564,14 @@ func WithUser(user string) CtrCreateOption { func WithRootFSFromImage(imageID string, imageName string, useImageVolumes bool) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if ctr.config.RootfsImageID != "" || ctr.config.RootfsImageName != "" { - return errors.Wrapf(config2.ErrInvalidArg, "container already configured with root filesystem") + return errors.Wrapf(define.ErrInvalidArg, "container already configured with root filesystem") } if ctr.config.Rootfs != "" { - return errors.Wrapf(config2.ErrInvalidArg, "cannot set both an image ID and a rootfs for a container") + return errors.Wrapf(define.ErrInvalidArg, "cannot set both an image ID and a rootfs for a container") } ctr.config.RootfsImageID = imageID @@ -566,7 +586,7 @@ func WithRootFSFromImage(imageID string, imageName string, useImageVolumes bool) func WithStdin() CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.Stdin = true @@ -582,11 +602,11 @@ func WithStdin() CtrCreateOption { func (r *Runtime) WithPod(pod *Pod) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if pod == nil { - return config2.ErrInvalidArg + return define.ErrInvalidArg } ctr.config.Pod = pod.ID() @@ -599,7 +619,7 @@ func (r *Runtime) WithPod(pod *Pod) CtrCreateOption { func WithLabels(labels map[string]string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.Labels = make(map[string]string) @@ -615,7 +635,7 @@ func WithLabels(labels map[string]string) CtrCreateOption { func WithName(name string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } // Check the name against a regex @@ -633,13 +653,13 @@ func WithName(name string) CtrCreateOption { func WithStopSignal(signal syscall.Signal) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if signal == 0 { - return errors.Wrapf(config2.ErrInvalidArg, "stop signal cannot be 0") + return errors.Wrapf(define.ErrInvalidArg, "stop signal cannot be 0") } else if signal > 64 { - return errors.Wrapf(config2.ErrInvalidArg, "stop signal cannot be greater than 64 (SIGRTMAX)") + return errors.Wrapf(define.ErrInvalidArg, "stop signal cannot be greater than 64 (SIGRTMAX)") } ctr.config.StopSignal = uint(signal) @@ -653,7 +673,7 @@ func WithStopSignal(signal syscall.Signal) CtrCreateOption { func WithStopTimeout(timeout uint) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.StopTimeout = timeout @@ -666,7 +686,7 @@ func WithStopTimeout(timeout uint) CtrCreateOption { func WithIDMappings(idmappings storage.IDMappingOptions) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.IDMappings = idmappings @@ -678,7 +698,7 @@ func WithIDMappings(idmappings storage.IDMappingOptions) CtrCreateOption { func WithExitCommand(exitCommand []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.ExitCommand = append(exitCommand, ctr.ID()) @@ -691,7 +711,7 @@ func WithExitCommand(exitCommand []string) CtrCreateOption { func WithUTSNSFromPod(p *Pod) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if err := validPodNSOption(p, ctr.config.Pod); err != nil { @@ -715,19 +735,19 @@ func WithUTSNSFromPod(p *Pod) CtrCreateOption { func WithIPCNSFrom(nsCtr *Container) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if !nsCtr.valid { - return config2.ErrCtrRemoved + return define.ErrCtrRemoved } if nsCtr.ID() == ctr.ID() { - return errors.Wrapf(config2.ErrInvalidArg, "must specify another container") + return errors.Wrapf(define.ErrInvalidArg, "must specify another container") } if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod { - return errors.Wrapf(config2.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) + return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) } ctr.config.IPCNsCtr = nsCtr.ID() @@ -743,19 +763,19 @@ func WithIPCNSFrom(nsCtr *Container) CtrCreateOption { func WithMountNSFrom(nsCtr *Container) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if !nsCtr.valid { - return config2.ErrCtrRemoved + return define.ErrCtrRemoved } if nsCtr.ID() == ctr.ID() { - return errors.Wrapf(config2.ErrInvalidArg, "must specify another container") + return errors.Wrapf(define.ErrInvalidArg, "must specify another container") } if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod { - return errors.Wrapf(config2.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) + return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) } ctr.config.MountNsCtr = nsCtr.ID() @@ -771,23 +791,23 @@ func WithMountNSFrom(nsCtr *Container) CtrCreateOption { func WithNetNSFrom(nsCtr *Container) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if !nsCtr.valid { - return config2.ErrCtrRemoved + return define.ErrCtrRemoved } if nsCtr.ID() == ctr.ID() { - return errors.Wrapf(config2.ErrInvalidArg, "must specify another container") + return errors.Wrapf(define.ErrInvalidArg, "must specify another container") } if ctr.config.CreateNetNS { - return errors.Wrapf(config2.ErrInvalidArg, "cannot join another container's net ns as we are making a new net ns") + return errors.Wrapf(define.ErrInvalidArg, "cannot join another container's net ns as we are making a new net ns") } if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod { - return errors.Wrapf(config2.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) + return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) } ctr.config.NetNsCtr = nsCtr.ID() @@ -803,19 +823,19 @@ func WithNetNSFrom(nsCtr *Container) CtrCreateOption { func WithPIDNSFrom(nsCtr *Container) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if !nsCtr.valid { - return config2.ErrCtrRemoved + return define.ErrCtrRemoved } if nsCtr.ID() == ctr.ID() { - return errors.Wrapf(config2.ErrInvalidArg, "must specify another container") + return errors.Wrapf(define.ErrInvalidArg, "must specify another container") } if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod { - return errors.Wrapf(config2.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) + return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) } ctr.config.PIDNsCtr = nsCtr.ID() @@ -831,19 +851,19 @@ func WithPIDNSFrom(nsCtr *Container) CtrCreateOption { func WithUserNSFrom(nsCtr *Container) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if !nsCtr.valid { - return config2.ErrCtrRemoved + return define.ErrCtrRemoved } if nsCtr.ID() == ctr.ID() { - return errors.Wrapf(config2.ErrInvalidArg, "must specify another container") + return errors.Wrapf(define.ErrInvalidArg, "must specify another container") } if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod { - return errors.Wrapf(config2.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) + return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) } ctr.config.UserNsCtr = nsCtr.ID() @@ -860,19 +880,19 @@ func WithUserNSFrom(nsCtr *Container) CtrCreateOption { func WithUTSNSFrom(nsCtr *Container) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if !nsCtr.valid { - return config2.ErrCtrRemoved + return define.ErrCtrRemoved } if nsCtr.ID() == ctr.ID() { - return errors.Wrapf(config2.ErrInvalidArg, "must specify another container") + return errors.Wrapf(define.ErrInvalidArg, "must specify another container") } if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod { - return errors.Wrapf(config2.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) + return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) } ctr.config.UTSNsCtr = nsCtr.ID() @@ -888,19 +908,19 @@ func WithUTSNSFrom(nsCtr *Container) CtrCreateOption { func WithCgroupNSFrom(nsCtr *Container) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if !nsCtr.valid { - return config2.ErrCtrRemoved + return define.ErrCtrRemoved } if nsCtr.ID() == ctr.ID() { - return errors.Wrapf(config2.ErrInvalidArg, "must specify another container") + return errors.Wrapf(define.ErrInvalidArg, "must specify another container") } if ctr.config.Pod != "" && nsCtr.config.Pod != ctr.config.Pod { - return errors.Wrapf(config2.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) + return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, nsCtr.ID()) } ctr.config.CgroupNsCtr = nsCtr.ID() @@ -914,22 +934,22 @@ func WithCgroupNSFrom(nsCtr *Container) CtrCreateOption { func WithDependencyCtrs(ctrs []*Container) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } deps := make([]string, 0, len(ctrs)) for _, dep := range ctrs { if !dep.valid { - return errors.Wrapf(config2.ErrCtrRemoved, "container %s is not valid", dep.ID()) + return errors.Wrapf(define.ErrCtrRemoved, "container %s is not valid", dep.ID()) } if dep.ID() == ctr.ID() { - return errors.Wrapf(config2.ErrInvalidArg, "must specify another container") + return errors.Wrapf(define.ErrInvalidArg, "must specify another container") } if ctr.config.Pod != "" && dep.config.Pod != ctr.config.Pod { - return errors.Wrapf(config2.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, dep.ID()) + return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, dep.ID()) } deps = append(deps, dep.ID()) @@ -948,11 +968,11 @@ func WithDependencyCtrs(ctrs []*Container) CtrCreateOption { func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netmode string, networks []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if ctr.config.NetNsCtr != "" { - return errors.Wrapf(config2.ErrInvalidArg, "container is already set to join another container's net ns, cannot create a new net ns") + return errors.Wrapf(define.ErrInvalidArg, "container is already set to join another container's net ns, cannot create a new net ns") } ctr.config.PostConfigureNetNS = postConfigureNetNS @@ -973,15 +993,15 @@ func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netmo func WithStaticIP(ip net.IP) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if !ctr.config.CreateNetNS { - return errors.Wrapf(config2.ErrInvalidArg, "cannot set a static IP if the container is not creating a network namespace") + return errors.Wrapf(define.ErrInvalidArg, "cannot set a static IP if the container is not creating a network namespace") } if len(ctr.config.Networks) != 0 { - return errors.Wrapf(config2.ErrInvalidArg, "cannot set a static IP if joining additional CNI networks") + return errors.Wrapf(define.ErrInvalidArg, "cannot set a static IP if joining additional CNI networks") } ctr.config.StaticIP = ip @@ -994,15 +1014,15 @@ func WithStaticIP(ip net.IP) CtrCreateOption { func WithLogDriver(driver string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } switch driver { case "": - return errors.Wrapf(config2.ErrInvalidArg, "log driver must be set") + return errors.Wrapf(define.ErrInvalidArg, "log driver must be set") case JournaldLogging, KubernetesLogging, JSONLogging: break default: - return errors.Wrapf(config2.ErrInvalidArg, "invalid log driver") + return errors.Wrapf(define.ErrInvalidArg, "invalid log driver") } ctr.config.LogDriver = driver @@ -1015,10 +1035,10 @@ func WithLogDriver(driver string) CtrCreateOption { func WithLogPath(path string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if path == "" { - return errors.Wrapf(config2.ErrInvalidArg, "log path must be set") + return errors.Wrapf(define.ErrInvalidArg, "log path must be set") } ctr.config.LogPath = path @@ -1031,11 +1051,11 @@ func WithLogPath(path string) CtrCreateOption { func WithCgroupParent(parent string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if parent == "" { - return errors.Wrapf(config2.ErrInvalidArg, "cgroup parent cannot be empty") + return errors.Wrapf(define.ErrInvalidArg, "cgroup parent cannot be empty") } ctr.config.CgroupParent = parent @@ -1048,10 +1068,10 @@ func WithCgroupParent(parent string) CtrCreateOption { func WithDNSSearch(searchDomains []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if ctr.config.UseImageResolvConf { - return errors.Wrapf(config2.ErrInvalidArg, "cannot add DNS search domains if container will not create /etc/resolv.conf") + return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS search domains if container will not create /etc/resolv.conf") } ctr.config.DNSSearch = searchDomains return nil @@ -1062,16 +1082,16 @@ func WithDNSSearch(searchDomains []string) CtrCreateOption { func WithDNS(dnsServers []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if ctr.config.UseImageResolvConf { - return errors.Wrapf(config2.ErrInvalidArg, "cannot add DNS servers if container will not create /etc/resolv.conf") + return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS servers if container will not create /etc/resolv.conf") } var dns []net.IP for _, i := range dnsServers { result := net.ParseIP(i) if result == nil { - return errors.Wrapf(config2.ErrInvalidArg, "invalid IP address %s", i) + return errors.Wrapf(define.ErrInvalidArg, "invalid IP address %s", i) } dns = append(dns, result) } @@ -1084,10 +1104,10 @@ func WithDNS(dnsServers []string) CtrCreateOption { func WithDNSOption(dnsOptions []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if ctr.config.UseImageResolvConf { - return errors.Wrapf(config2.ErrInvalidArg, "cannot add DNS options if container will not create /etc/resolv.conf") + return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS options if container will not create /etc/resolv.conf") } ctr.config.DNSOption = dnsOptions return nil @@ -1098,11 +1118,11 @@ func WithDNSOption(dnsOptions []string) CtrCreateOption { func WithHosts(hosts []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if ctr.config.UseImageHosts { - return errors.Wrapf(config2.ErrInvalidArg, "cannot add hosts if container will not create /etc/hosts") + return errors.Wrapf(define.ErrInvalidArg, "cannot add hosts if container will not create /etc/hosts") } ctr.config.HostAdd = hosts @@ -1115,7 +1135,7 @@ func WithHosts(hosts []string) CtrCreateOption { func WithConmonPidFile(path string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.ConmonPidFile = path return nil @@ -1127,7 +1147,7 @@ func WithConmonPidFile(path string) CtrCreateOption { func WithGroups(groups []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.Groups = groups return nil @@ -1145,11 +1165,11 @@ func WithGroups(groups []string) CtrCreateOption { func WithUserVolumes(volumes []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if volumes == nil { - return config2.ErrInvalidArg + return define.ErrInvalidArg } ctr.config.UserVolumes = make([]string, 0, len(volumes)) @@ -1166,7 +1186,7 @@ func WithUserVolumes(volumes []string) CtrCreateOption { func WithEntrypoint(entrypoint []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.Entrypoint = make([]string, 0, len(entrypoint)) @@ -1183,7 +1203,7 @@ func WithEntrypoint(entrypoint []string) CtrCreateOption { func WithCommand(command []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.Command = make([]string, 0, len(command)) @@ -1197,13 +1217,13 @@ func WithCommand(command []string) CtrCreateOption { func WithRootFS(rootfs string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if _, err := os.Stat(rootfs); err != nil { return errors.Wrapf(err, "error checking path %q", rootfs) } if ctr.config.RootfsImageID != "" { - return errors.Wrapf(config2.ErrInvalidArg, "cannot set both an image ID and a rootfs for a container") + return errors.Wrapf(define.ErrInvalidArg, "cannot set both an image ID and a rootfs for a container") } ctr.config.Rootfs = rootfs return nil @@ -1217,7 +1237,7 @@ func WithRootFS(rootfs string) CtrCreateOption { func WithCtrNamespace(ns string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.Namespace = ns @@ -1231,13 +1251,13 @@ func WithCtrNamespace(ns string) CtrCreateOption { func WithUseImageResolvConf() CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if len(ctr.config.DNSServer) != 0 || len(ctr.config.DNSSearch) != 0 || len(ctr.config.DNSOption) != 0 { - return errors.Wrapf(config2.ErrInvalidArg, "not creating resolv.conf conflicts with DNS options") + return errors.Wrapf(define.ErrInvalidArg, "not creating resolv.conf conflicts with DNS options") } ctr.config.UseImageResolvConf = true @@ -1251,11 +1271,11 @@ func WithUseImageResolvConf() CtrCreateOption { func WithUseImageHosts() CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } if len(ctr.config.HostAdd) != 0 { - return errors.Wrapf(config2.ErrInvalidArg, "not creating /etc/hosts conflicts with adding to the hosts file") + return errors.Wrapf(define.ErrInvalidArg, "not creating /etc/hosts conflicts with adding to the hosts file") } ctr.config.UseImageHosts = true @@ -1270,14 +1290,14 @@ func WithUseImageHosts() CtrCreateOption { func WithRestartPolicy(policy string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } switch policy { case RestartPolicyNone, RestartPolicyNo, RestartPolicyOnFailure, RestartPolicyAlways: ctr.config.RestartPolicy = policy default: - return errors.Wrapf(config2.ErrInvalidArg, "%q is not a valid restart policy", policy) + return errors.Wrapf(define.ErrInvalidArg, "%q is not a valid restart policy", policy) } return nil @@ -1290,7 +1310,7 @@ func WithRestartPolicy(policy string) CtrCreateOption { func WithRestartRetries(tries uint) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.RestartRetries = tries @@ -1304,7 +1324,7 @@ func WithRestartRetries(tries uint) CtrCreateOption { func withIsInfra() CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.IsInfra = true @@ -1317,7 +1337,7 @@ func withIsInfra() CtrCreateOption { func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } destinations := make(map[string]bool) @@ -1327,7 +1347,7 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { // If they don't we will automatically create them. if _, ok := destinations[vol.Dest]; ok { - return errors.Wrapf(config2.ErrInvalidArg, "two volumes found with destination %s", vol.Dest) + return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest) } destinations[vol.Dest] = true @@ -1348,7 +1368,7 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { func WithVolumeName(name string) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { - return config2.ErrVolumeFinalized + return define.ErrVolumeFinalized } // Check the name against a regex @@ -1365,7 +1385,7 @@ func WithVolumeName(name string) VolumeCreateOption { func WithVolumeLabels(labels map[string]string) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { - return config2.ErrVolumeFinalized + return define.ErrVolumeFinalized } volume.config.Labels = make(map[string]string) @@ -1381,7 +1401,7 @@ func WithVolumeLabels(labels map[string]string) VolumeCreateOption { func WithVolumeDriver(driver string) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { - return config2.ErrVolumeFinalized + return define.ErrVolumeFinalized } volume.config.Driver = driver @@ -1394,7 +1414,7 @@ func WithVolumeDriver(driver string) VolumeCreateOption { func WithVolumeOptions(options map[string]string) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { - return config2.ErrVolumeFinalized + return define.ErrVolumeFinalized } volume.config.Options = make(map[string]string) @@ -1410,7 +1430,7 @@ func WithVolumeOptions(options map[string]string) VolumeCreateOption { func WithVolumeUID(uid int) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { - return config2.ErrVolumeFinalized + return define.ErrVolumeFinalized } volume.config.UID = uid @@ -1423,7 +1443,7 @@ func WithVolumeUID(uid int) VolumeCreateOption { func WithVolumeGID(gid int) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { - return config2.ErrVolumeFinalized + return define.ErrVolumeFinalized } volume.config.GID = gid @@ -1439,7 +1459,7 @@ func WithVolumeGID(gid int) VolumeCreateOption { func withSetCtrSpecific() VolumeCreateOption { return func(volume *Volume) error { if volume.valid { - return config2.ErrVolumeFinalized + return define.ErrVolumeFinalized } volume.config.IsCtrSpecific = true @@ -1454,7 +1474,7 @@ func withSetCtrSpecific() VolumeCreateOption { func WithPodName(name string) PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } // Check the name against a regex @@ -1472,7 +1492,7 @@ func WithPodName(name string) PodCreateOption { func WithPodLabels(labels map[string]string) PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.Labels = make(map[string]string) @@ -1488,7 +1508,7 @@ func WithPodLabels(labels map[string]string) PodCreateOption { func WithPodCgroupParent(path string) PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.CgroupParent = path @@ -1504,7 +1524,7 @@ func WithPodCgroupParent(path string) PodCreateOption { func WithPodCgroups() PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.UsePodCgroup = true @@ -1521,7 +1541,7 @@ func WithPodCgroups() PodCreateOption { func WithPodNamespace(ns string) PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.Namespace = ns @@ -1537,7 +1557,7 @@ func WithPodNamespace(ns string) PodCreateOption { func WithPodIPC() PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.UsePodIPC = true @@ -1553,7 +1573,7 @@ func WithPodIPC() PodCreateOption { func WithPodNet() PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.UsePodNet = true @@ -1571,7 +1591,7 @@ func WithPodNet() PodCreateOption { func WithPodMount() PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.UsePodMount = true @@ -1589,7 +1609,7 @@ func WithPodMount() PodCreateOption { func WithPodUser() PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.UsePodUser = true @@ -1605,7 +1625,7 @@ func WithPodUser() PodCreateOption { func WithPodPID() PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.UsePodPID = true @@ -1621,7 +1641,7 @@ func WithPodPID() PodCreateOption { func WithPodUTS() PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.UsePodUTS = true @@ -1634,7 +1654,7 @@ func WithPodUTS() PodCreateOption { func WithInfraContainer() PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.InfraContainer.HasInfraContainer = true @@ -1647,7 +1667,7 @@ func WithInfraContainer() PodCreateOption { func WithInfraContainerPorts(bindings []ocicni.PortMapping) PodCreateOption { return func(pod *Pod) error { if pod.valid { - return config2.ErrPodFinalized + return define.ErrPodFinalized } pod.config.InfraContainer.PortBindings = bindings return nil @@ -1658,7 +1678,7 @@ func WithInfraContainerPorts(bindings []ocicni.PortMapping) PodCreateOption { func WithHealthCheck(healthCheck *manifest.Schema2HealthConfig) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { - return config2.ErrCtrFinalized + return define.ErrCtrFinalized } ctr.config.HealthCheckConfig = healthCheck return nil -- cgit v1.2.3-54-g00ecf From fd73075cbe91a4b38fe835b1f17bbabe0971bad9 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 16 Jul 2019 16:04:51 -0400 Subject: Force tests to use file backend for events Podman-in-podman (and possibly ubuntu) have "issues" with journald. Let's just use file instead to be safe. Signed-off-by: Matthew Heon --- test/e2e/libpod_suite_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index 8d993ee72..971911161 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -65,7 +65,7 @@ func (p *PodmanTestIntegration) makeOptions(args []string) []string { debug = "--log-level=debug --syslog=true " } - podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s --tmpdir %s", + podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend file", debug, p.CrioRoot, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager, p.TmpDir), " ") if os.Getenv("HOOK_OPTION") != "" { podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION")) -- cgit v1.2.3-54-g00ecf From cdd5639d564624a6fbca426421d47c840dac8556 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 17 Jul 2019 15:17:26 -0400 Subject: Expose Null eventer and allow its use in the Podman CLI We need this specifically for tests, but others may find it useful if they don't explicitly need events and don't want the performance implications of using them. Signed-off-by: Matthew Heon --- docs/libpod.conf.5.md | 2 +- docs/podman.1.md | 2 +- libpod/events/config.go | 2 ++ libpod/events/events.go | 13 ++++++++++--- libpod/events/events_linux.go | 4 +++- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/libpod.conf.5.md b/docs/libpod.conf.5.md index 097d0764a..0bdba4593 100644 --- a/docs/libpod.conf.5.md +++ b/docs/libpod.conf.5.md @@ -99,7 +99,7 @@ libpod to manage containers. a slirp4netns network. If "" is used then the binary is looked up using the $PATH environment variable. **events_logger**="" - Default method to use when logging events. Valid values are "journald" and "file". + Default method to use when logging events. Valid values are "file", "journald", and "null". **detach_keys**="" Keys sequence used for detaching a container diff --git a/docs/podman.1.md b/docs/podman.1.md index 02d15c197..7aa15019a 100644 --- a/docs/podman.1.md +++ b/docs/podman.1.md @@ -38,7 +38,7 @@ Path to where the cpu performance results should be written **--events-logger**=**type** -Backend to use for storing events. Allowed values are **journald** and **file**. +Backend to use for storing events. Allowed values are **file**, **journald**, and **null**. **--hooks-dir**=*path* diff --git a/libpod/events/config.go b/libpod/events/config.go index b9f01f3a5..96172d47b 100644 --- a/libpod/events/config.go +++ b/libpod/events/config.go @@ -14,6 +14,8 @@ const ( LogFile EventerType = iota // Journald indicates journald should be used to log events Journald EventerType = iota + // Null is a no-op events logger. It does not read or write events. + Null EventerType = iota ) // Event describes the attributes of a libpod event diff --git a/libpod/events/events.go b/libpod/events/events.go index a898171c1..a80e97e90 100644 --- a/libpod/events/events.go +++ b/libpod/events/events.go @@ -16,11 +16,16 @@ var ErrNoJournaldLogging = errors.New("No support for journald logging") // String returns a string representation of EventerType func (et EventerType) String() string { - if et == LogFile { + switch et { + case LogFile: return "file" - + case Journald: + return "journald" + case Null: + return "null" + default: + return "invalid" } - return "journald" } // IsValidEventer checks if the given string is a valid eventer type. @@ -30,6 +35,8 @@ func IsValidEventer(eventer string) bool { return true case Journald.String(): return true + case Null.String(): + return true default: return false } diff --git a/libpod/events/events_linux.go b/libpod/events/events_linux.go index 11f309574..ffb100be8 100644 --- a/libpod/events/events_linux.go +++ b/libpod/events/events_linux.go @@ -18,8 +18,10 @@ func NewEventer(options EventerOptions) (eventer Eventer, err error) { } case strings.ToUpper(LogFile.String()): eventer = EventLogFile{options} + case strings.ToUpper(Null.String()): + eventer = NewNullEventer() default: - return eventer, errors.Errorf("unknown event logger type: %s", strings.ToUpper(options.EventerType)) + return nil, errors.Errorf("unknown event logger type: %s", strings.ToUpper(options.EventerType)) } return eventer, nil } -- cgit v1.2.3-54-g00ecf From 318438fcb3ee2ac57498d06fdfd1c5300147a738 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 17 Jul 2019 15:28:40 -0400 Subject: Do not use an events backend when restoring images Signed-off-by: Matthew Heon --- test/e2e/common_test.go | 2 +- test/e2e/libpod_suite_remoteclient_test.go | 15 +++++++++++---- test/e2e/libpod_suite_test.go | 28 ++++++++++++++++++++-------- test/utils/podmantest_test.go | 2 +- test/utils/utils.go | 28 ++++++++++++++-------------- test/utils/utils_suite_test.go | 2 +- 6 files changed, 48 insertions(+), 29 deletions(-) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 22eb94972..88cecc325 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -413,7 +413,7 @@ func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers // PodmanPID execs podman and returns its PID func (p *PodmanTestIntegration) PodmanPID(args []string) (*PodmanSessionIntegration, int) { - podmanOptions := p.MakeOptions(args) + podmanOptions := p.MakeOptions(args, false) fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " ")) command := exec.Command(p.PodmanBinary, podmanOptions...) session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) diff --git a/test/e2e/libpod_suite_remoteclient_test.go b/test/e2e/libpod_suite_remoteclient_test.go index c8210f7d1..7f33fec87 100644 --- a/test/e2e/libpod_suite_remoteclient_test.go +++ b/test/e2e/libpod_suite_remoteclient_test.go @@ -30,13 +30,20 @@ func SkipIfRootless() { // Podman is the exec call to podman on the filesystem func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration { - podmanSession := p.PodmanBase(args, false) + podmanSession := p.PodmanBase(args, false, false) return &PodmanSessionIntegration{podmanSession} } // PodmanNoCache calls podman with out adding the imagecache func (p *PodmanTestIntegration) PodmanNoCache(args []string) *PodmanSessionIntegration { - podmanSession := p.PodmanBase(args, true) + podmanSession := p.PodmanBase(args, true, false) + return &PodmanSessionIntegration{podmanSession} +} + +// PodmanNoEvents calls the Podman command without an imagecache and without an +// events backend. It is used mostly for caching and uncaching images. +func (p *PodmanTestIntegration) PodmanNoEvents(args []string) *PodmanSessionIntegration { + podmanSession := p.PodmanBase(args, true, true) return &PodmanSessionIntegration{podmanSession} } @@ -135,7 +142,7 @@ func (p *PodmanTestIntegration) StopVarlink() { } //MakeOptions assembles all the podman main options -func (p *PodmanTestIntegration) makeOptions(args []string) []string { +func (p *PodmanTestIntegration) makeOptions(args []string, noEvents bool) []string { return args } @@ -156,7 +163,7 @@ func (p *PodmanTestIntegration) RestoreArtifactToCache(image string) error { dest := strings.Split(image, "/") destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1)) p.CrioRoot = p.ImageCacheDir - restore := p.PodmanNoCache([]string{"load", "-q", "-i", destName}) + restore := p.PodmanNoEvents([]string{"load", "-q", "-i", destName}) restore.WaitWithDefaultTimeout() return nil } diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index 971911161..841c8a9ca 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -23,19 +23,26 @@ func SkipIfRootless() { // Podman is the exec call to podman on the filesystem func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration { - podmanSession := p.PodmanBase(args, false) + podmanSession := p.PodmanBase(args, false, false) return &PodmanSessionIntegration{podmanSession} } // PodmanNoCache calls the podman command with no configured imagecache func (p *PodmanTestIntegration) PodmanNoCache(args []string) *PodmanSessionIntegration { - podmanSession := p.PodmanBase(args, true) + podmanSession := p.PodmanBase(args, true, false) + return &PodmanSessionIntegration{podmanSession} +} + +// PodmanNoEvents calls the Podman command without an imagecache and without an +// events backend. It is used mostly for caching and uncaching images. +func (p *PodmanTestIntegration) PodmanNoEvents(args []string) *PodmanSessionIntegration { + podmanSession := p.PodmanBase(args, true, true) return &PodmanSessionIntegration{podmanSession} } // PodmanAsUser is the exec call to podman on the filesystem with the specified uid/gid and environment func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, cwd string, env []string) *PodmanSessionIntegration { - podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env, false) + podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env, false, false) return &PodmanSessionIntegration{podmanSession} } @@ -59,14 +66,19 @@ func PodmanTestCreate(tempDir string) *PodmanTestIntegration { } // MakeOptions assembles all the podman main options -func (p *PodmanTestIntegration) makeOptions(args []string) []string { +func (p *PodmanTestIntegration) makeOptions(args []string, noEvents bool) []string { var debug string if _, ok := os.LookupEnv("DEBUG"); ok { debug = "--log-level=debug --syslog=true " } - podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend file", - debug, p.CrioRoot, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager, p.TmpDir), " ") + eventsType := "file" + if noEvents { + eventsType = "null" + } + + podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend %s", + debug, p.CrioRoot, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager, p.TmpDir, eventsType), " ") if os.Getenv("HOOK_OPTION") != "" { podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION")) } @@ -81,7 +93,7 @@ func (p *PodmanTestIntegration) RestoreArtifact(image string) error { fmt.Printf("Restoring %s...\n", image) dest := strings.Split(image, "/") destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1)) - restore := p.PodmanNoCache([]string{"load", "-q", "-i", destName}) + restore := p.PodmanNoEvents([]string{"load", "-q", "-i", destName}) restore.Wait(90) return nil } @@ -93,7 +105,7 @@ func (p *PodmanTestIntegration) RestoreArtifactToCache(image string) error { destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1)) p.CrioRoot = p.ImageCacheDir - restore := p.PodmanNoCache([]string{"load", "-q", "-i", destName}) + restore := p.PodmanNoEvents([]string{"load", "-q", "-i", destName}) restore.WaitWithDefaultTimeout() return nil } diff --git a/test/utils/podmantest_test.go b/test/utils/podmantest_test.go index cb31d5548..9620898af 100644 --- a/test/utils/podmantest_test.go +++ b/test/utils/podmantest_test.go @@ -23,7 +23,7 @@ var _ = Describe("PodmanTest test", func() { FakeOutputs["check"] = []string{"check"} os.Setenv("HOOK_OPTION", "hook_option") env := os.Environ() - session := podmanTest.PodmanAsUserBase([]string{"check"}, 1000, 1000, "", env, true) + session := podmanTest.PodmanAsUserBase([]string{"check"}, 1000, 1000, "", env, true, false) os.Unsetenv("HOOK_OPTION") session.WaitWithDefaultTimeout() Expect(session.Command.Process).ShouldNot(BeNil()) diff --git a/test/utils/utils.go b/test/utils/utils.go index 43819350c..028107d46 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -26,14 +26,14 @@ var ( // PodmanTestCommon contains common functions will be updated later in // the inheritance structs type PodmanTestCommon interface { - MakeOptions(args []string) []string + MakeOptions(args []string, noEvents bool) []string WaitForContainer() bool WaitContainerReady(id string, expStr string, timeout int, step int) bool } // PodmanTest struct for command line options type PodmanTest struct { - PodmanMakeOptions func(args []string) []string + PodmanMakeOptions func(args []string, noEvents bool) []string PodmanBinary string ArtifactPath string TempDir string @@ -59,15 +59,15 @@ type HostOS struct { } // MakeOptions assembles all podman options -func (p *PodmanTest) MakeOptions(args []string) []string { - return p.PodmanMakeOptions(args) +func (p *PodmanTest) MakeOptions(args []string, noEvents bool) []string { + return p.PodmanMakeOptions(args, noEvents) } // PodmanAsUserBase exec podman as user. uid and gid is set for credentials usage. env is used // to record the env for debugging -func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string, env []string, nocache bool) *PodmanSession { +func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string, env []string, nocache, noEvents bool) *PodmanSession { var command *exec.Cmd - podmanOptions := p.MakeOptions(args) + podmanOptions := p.MakeOptions(args, noEvents) podmanBinary := p.PodmanBinary if p.RemoteTest { podmanBinary = p.RemotePodmanBinary @@ -105,8 +105,8 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string } // PodmanBase exec podman with default env. -func (p *PodmanTest) PodmanBase(args []string, nocache bool) *PodmanSession { - return p.PodmanAsUserBase(args, 0, 0, "", nil, nocache) +func (p *PodmanTest) PodmanBase(args []string, nocache, noEvents bool) *PodmanSession { + return p.PodmanAsUserBase(args, 0, 0, "", nil, nocache, noEvents) } // WaitForContainer waits on a started container @@ -124,7 +124,7 @@ func (p *PodmanTest) WaitForContainer() bool { // containers are currently running. func (p *PodmanTest) NumberOfContainersRunning() int { var containers []string - ps := p.PodmanBase([]string{"ps", "-q"}, true) + ps := p.PodmanBase([]string{"ps", "-q"}, true, false) ps.WaitWithDefaultTimeout() Expect(ps.ExitCode()).To(Equal(0)) for _, i := range ps.OutputToStringArray() { @@ -139,7 +139,7 @@ func (p *PodmanTest) NumberOfContainersRunning() int { // containers are currently defined. func (p *PodmanTest) NumberOfContainers() int { var containers []string - ps := p.PodmanBase([]string{"ps", "-aq"}, true) + ps := p.PodmanBase([]string{"ps", "-aq"}, true, false) ps.WaitWithDefaultTimeout() Expect(ps.ExitCode()).To(Equal(0)) for _, i := range ps.OutputToStringArray() { @@ -154,7 +154,7 @@ func (p *PodmanTest) NumberOfContainers() int { // pods are currently defined. func (p *PodmanTest) NumberOfPods() int { var pods []string - ps := p.PodmanBase([]string{"pod", "ps", "-q"}, true) + ps := p.PodmanBase([]string{"pod", "ps", "-q"}, true, false) ps.WaitWithDefaultTimeout() Expect(ps.ExitCode()).To(Equal(0)) for _, i := range ps.OutputToStringArray() { @@ -170,7 +170,7 @@ func (p *PodmanTest) NumberOfPods() int { func (p *PodmanTest) GetContainerStatus() string { var podmanArgs = []string{"ps"} podmanArgs = append(podmanArgs, "--all", "--format={{.Status}}") - session := p.PodmanBase(podmanArgs, true) + session := p.PodmanBase(podmanArgs, true, false) session.WaitWithDefaultTimeout() return session.OutputToString() } @@ -178,7 +178,7 @@ func (p *PodmanTest) GetContainerStatus() string { // WaitContainerReady waits process or service inside container start, and ready to be used. func (p *PodmanTest) WaitContainerReady(id string, expStr string, timeout int, step int) bool { startTime := time.Now() - s := p.PodmanBase([]string{"logs", id}, true) + s := p.PodmanBase([]string{"logs", id}, true, false) s.WaitWithDefaultTimeout() for { @@ -191,7 +191,7 @@ func (p *PodmanTest) WaitContainerReady(id string, expStr string, timeout int, s return true } time.Sleep(time.Duration(step) * time.Second) - s = p.PodmanBase([]string{"logs", id}, true) + s = p.PodmanBase([]string{"logs", id}, true, false) s.WaitWithDefaultTimeout() } } diff --git a/test/utils/utils_suite_test.go b/test/utils/utils_suite_test.go index b1100892b..5904d37dc 100644 --- a/test/utils/utils_suite_test.go +++ b/test/utils/utils_suite_test.go @@ -32,7 +32,7 @@ func FakePodmanTestCreate() *FakePodmanTest { return p } -func (p *FakePodmanTest) makeOptions(args []string) []string { +func (p *FakePodmanTest) makeOptions(args []string, noEvents bool) []string { return FakeOutputs[strings.Join(args, " ")] } -- cgit v1.2.3-54-g00ecf From cc63aff571fd5ebf13a493fab923a829176c5108 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Thu, 18 Jul 2019 15:22:18 -0400 Subject: System events are valid, don't error on them The logfile driver was not aware that system events existed. Signed-off-by: Matthew Heon --- libpod/events/logfile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go index e5efc09bb..30d72b9fc 100644 --- a/libpod/events/logfile.go +++ b/libpod/events/logfile.go @@ -55,7 +55,7 @@ func (e EventLogFile) Read(options ReadOptions) error { return err } switch event.Type { - case Image, Volume, Pod, Container: + case Image, Volume, Pod, System, Container: // no-op default: return errors.Errorf("event type %s is not valid in %s", event.Type.String(), e.options.LogFilePath) -- cgit v1.2.3-54-g00ecf From ef2d96a7a84f1ad7567d6e6ead9e46f9459a530b Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 24 Jul 2019 22:28:28 -0400 Subject: Fix Dockerfile - a dependency's name was changed Signed-off-by: Matthew Heon --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ca7807fa1..3185586b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ RUN apt-get update && apt-get install -y \ libnl-3-dev \ libostree-dev \ libprotobuf-dev \ - libprotobuf-c0-dev \ + libprotobuf-c-dev \ libseccomp2 \ libseccomp-dev \ libtool \ -- cgit v1.2.3-54-g00ecf From 9dcd76e369fb163774f8f58a7da24a7899e95b60 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 31 Jul 2019 17:22:08 -0400 Subject: Ensure we generate a 'stopped' event on force-remove When forcibly removing a container, we are initiating an explicit stop of the container, which is not reflected in 'podman events'. Swap to using our standard 'stop()' function instead of a custom one for force-remove, and move the event into the internal stop function (so internal calls also register it). This does add one more database save() to `podman remove`. This should not be a terribly serious performance hit, and does have the desirable side effect of making things generally safer. Signed-off-by: Matthew Heon --- libpod/container_api.go | 2 +- libpod/container_internal.go | 8 +++++++- libpod/runtime_ctr.go | 7 +------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libpod/container_api.go b/libpod/container_api.go index cd020e429..ef9c3f006 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -187,7 +187,7 @@ func (c *Container) StopWithTimeout(timeout uint) error { c.state.State == define.ContainerStateExited { return define.ErrCtrStopped } - defer c.newContainerEvent(events.Stop) + return c.stop(timeout) } diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 3114e00c0..aba9c5b93 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1108,7 +1108,13 @@ func (c *Container) stop(timeout uint) error { } // Wait until we have an exit file, and sync once we do - return c.waitForExitFileAndSync() + if err := c.waitForExitFileAndSync(); err != nil { + return err + } + + c.newContainerEvent(events.Stop) + + return nil } // Internal, non-locking function to pause a container diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index e57ab4634..47d49f6aa 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -394,14 +394,9 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool, // Check that the container's in a good state to be removed if c.state.State == config2.ContainerStateRunning { - if err := c.ociRuntime.stopContainer(c, c.StopTimeout()); err != nil { + if err := c.stop(c.StopTimeout()); err != nil { return errors.Wrapf(err, "cannot remove container %s as it could not be stopped", c.ID()) } - - // Need to update container state to make sure we know it's stopped - if err := c.waitForExitFileAndSync(); err != nil { - return err - } } // Check that all of our exec sessions have finished -- cgit v1.2.3-54-g00ecf From 6bbeda6da5f1facef226125b2089d8f1712208c8 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Thu, 1 Aug 2019 12:37:24 -0400 Subject: Pass on events-backend config to cleanup processes Signed-off-by: Matthew Heon --- pkg/spec/createconfig.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 214a3c5ed..f21ae2831 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -168,6 +168,9 @@ func (c *CreateConfig) createExitCommand(runtime *libpod.Runtime) ([]string, err for _, opt := range config.StorageConfig.GraphDriverOptions { command = append(command, []string{"--storage-opt", opt}...) } + if config.EventsLogger != "" { + command = append(command, []string{"--events-backend", config.EventsLogger}...) + } if c.Syslog { command = append(command, "--syslog", "true") -- cgit v1.2.3-54-g00ecf From 8da24f2f7d3472d2be4ccde8e7b42790671d464f Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Thu, 1 Aug 2019 14:57:29 -0400 Subject: Use "none" instead of "null" for the null eventer Signed-off-by: Matthew Heon --- docs/libpod.conf.5.md | 2 +- docs/podman.1.md | 4 ++-- libpod/events/events.go | 2 +- test/e2e/libpod_suite_test.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/libpod.conf.5.md b/docs/libpod.conf.5.md index 0bdba4593..4240ae15a 100644 --- a/docs/libpod.conf.5.md +++ b/docs/libpod.conf.5.md @@ -99,7 +99,7 @@ libpod to manage containers. a slirp4netns network. If "" is used then the binary is looked up using the $PATH environment variable. **events_logger**="" - Default method to use when logging events. Valid values are "file", "journald", and "null". + Default method to use when logging events. Valid values are "file", "journald", and "none". **detach_keys**="" Keys sequence used for detaching a container diff --git a/docs/podman.1.md b/docs/podman.1.md index 7aa15019a..bfb5a9aec 100644 --- a/docs/podman.1.md +++ b/docs/podman.1.md @@ -36,9 +36,9 @@ Note: CGroup manager is not supported in rootless mode when using CGroups Versio Path to where the cpu performance results should be written -**--events-logger**=**type** +**--events-logger**=*type* -Backend to use for storing events. Allowed values are **file**, **journald**, and **null**. +Backend to use for storing events. Allowed values are **file**, **journald**, and **none**. **--hooks-dir**=*path* diff --git a/libpod/events/events.go b/libpod/events/events.go index a80e97e90..5e828bc8a 100644 --- a/libpod/events/events.go +++ b/libpod/events/events.go @@ -22,7 +22,7 @@ func (et EventerType) String() string { case Journald: return "journald" case Null: - return "null" + return "none" default: return "invalid" } diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index 841c8a9ca..1df59dbe3 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -74,7 +74,7 @@ func (p *PodmanTestIntegration) makeOptions(args []string, noEvents bool) []stri eventsType := "file" if noEvents { - eventsType = "null" + eventsType = "none" } podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend %s", -- cgit v1.2.3-54-g00ecf