diff options
-rw-r--r-- | cmd/podman/common/create.go | 19 | ||||
-rw-r--r-- | cmd/podman/images/scp.go | 13 | ||||
-rw-r--r-- | cmd/podman/root.go | 5 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-create.1.md | 22 | ||||
-rw-r--r-- | docs/source/markdown/podman.1.md | 5 | ||||
-rw-r--r-- | libpod/options.go | 2 | ||||
-rw-r--r-- | libpod/runtime.go | 7 | ||||
-rw-r--r-- | pkg/domain/entities/engine.go | 1 | ||||
-rw-r--r-- | pkg/domain/entities/events.go | 2 | ||||
-rw-r--r-- | pkg/domain/entities/pods.go | 12 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 50 | ||||
-rw-r--r-- | pkg/machine/config.go | 9 | ||||
-rw-r--r-- | pkg/machine/qemu/machine.go | 122 | ||||
-rw-r--r-- | pkg/specgen/podspecgen.go | 2 | ||||
-rw-r--r-- | test/e2e/events_test.go | 2 | ||||
-rw-r--r-- | test/e2e/pod_create_test.go | 39 | ||||
-rw-r--r-- | test/system/030-run.bats | 15 | ||||
-rw-r--r-- | test/system/050-stop.bats | 5 | ||||
-rw-r--r-- | test/system/080-pause.bats | 3 | ||||
-rw-r--r-- | test/system/090-events.bats | 13 | ||||
-rw-r--r-- | test/system/200-pod.bats | 6 | ||||
-rw-r--r-- | test/system/250-systemd.bats | 5 | ||||
-rw-r--r-- | test/system/500-networking.bats | 6 |
23 files changed, 302 insertions, 63 deletions
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index b60169990..e95e447e1 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -563,15 +563,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(stopTimeoutFlagName, completion.AutocompleteNone) - sysctlFlagName := "sysctl" - createFlags.StringSliceVar( - &cf.Sysctl, - sysctlFlagName, []string{}, - "Sysctl options", - ) - //TODO: Add function for sysctl completion. - _ = cmd.RegisterFlagCompletionFunc(sysctlFlagName, completion.AutocompleteNone) - systemdFlagName := "systemd" createFlags.StringVar( &cf.Systemd, @@ -712,6 +703,16 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, `If a container with the same name exists, replace it`, ) } + + sysctlFlagName := "sysctl" + createFlags.StringSliceVar( + &cf.Sysctl, + sysctlFlagName, []string{}, + "Sysctl options", + ) + //TODO: Add function for sysctl completion. + _ = cmd.RegisterFlagCompletionFunc(sysctlFlagName, completion.AutocompleteNone) + securityOptFlagName := "security-opt" createFlags.StringArrayVar( &cf.SecurityOpt, diff --git a/cmd/podman/images/scp.go b/cmd/podman/images/scp.go index f02a3c15e..fb20d9417 100644 --- a/cmd/podman/images/scp.go +++ b/cmd/podman/images/scp.go @@ -46,6 +46,7 @@ var ( var ( parentFlags []string + quiet bool source entities.ImageScpOptions dest entities.ImageScpOptions sshInfo entities.ImageScpConnections @@ -61,7 +62,7 @@ func init() { func scpFlags(cmd *cobra.Command) { flags := cmd.Flags() - flags.BoolVarP(&source.Quiet, "quiet", "q", false, "Suppress the output") + flags.BoolVarP(&quiet, "quiet", "q", false, "Suppress the output") } func scp(cmd *cobra.Command, args []string) (finalErr error) { @@ -139,6 +140,7 @@ func scp(cmd *cobra.Command, args []string) (finalErr error) { } } + source.Quiet = quiet source.File = f.Name() // after parsing the arguments, set the file for the save/load dest.File = source.File if err = os.Remove(source.File); err != nil { // remove the file and simply use its name so podman creates the file upon save. avoids umask errors @@ -203,15 +205,6 @@ func scp(cmd *cobra.Command, args []string) (finalErr error) { } } - src, err := json.MarshalIndent(source, "", " ") - if err != nil { - return err - } - dst, err := json.MarshalIndent(dest, "", " ") - if err != nil { - return err - } - fmt.Printf("SOURCE: %s\nDEST: %s\n", string(src), string(dst)) return nil } diff --git a/cmd/podman/root.go b/cmd/podman/root.go index b695443c2..1de937ca5 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -114,6 +114,10 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error { } cfg := registry.PodmanConfig() + if cfg.NoOut { + null, _ := os.Open(os.DevNull) + os.Stdout = null + } // Currently it is only possible to restore a container with the same runtime // as used for checkpointing. It should be possible to make crun and runc @@ -343,6 +347,7 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) { lFlags.StringVar(&opts.Identity, identityFlagName, ident, "path to SSH identity file, (CONTAINER_SSHKEY)") _ = cmd.RegisterFlagCompletionFunc(identityFlagName, completion.AutocompleteDefault) + lFlags.BoolVar(&opts.NoOut, "noout", false, "do not output to stdout") lFlags.BoolVarP(&opts.Remote, "remote", "r", registry.IsRemote(), "Access remote Podman service") pFlags := cmd.PersistentFlags() if registry.IsRemote() { diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index b2e16e051..c9255d37f 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -276,6 +276,28 @@ podman generates a UUID for each pod, and if a name is not assigned to the container with **--name** then a random string name will be generated for it. The name is useful any place you need to identify a pod. +#### **--sysctl**=_name_=_value_ + +Configure namespace kernel parameters for all containers in the pod. + +For the IPC namespace, the following sysctls are allowed: + +- kernel.msgmax +- kernel.msgmnb +- kernel.msgmni +- kernel.sem +- kernel.shmall +- kernel.shmmax +- kernel.shmmni +- kernel.shm_rmid_forced +- Sysctls beginning with fs.mqueue.\* + +Note: if the ipc namespace is not shared within the pod, these sysctls are not allowed. + +For the network namespace, only sysctls beginning with net.\* are allowed. + +Note: if the network namespace is not shared within the pod, these sysctls are not allowed. + #### **--userns**=*mode* Set the user namespace mode for all the containers in a pod. It defaults to the **PODMAN_USERNS** environment variable. An empty value ("") means user namespaces are disabled. diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md index daa8212c5..9f85ebda3 100644 --- a/docs/source/markdown/podman.1.md +++ b/docs/source/markdown/podman.1.md @@ -92,6 +92,11 @@ When namespace is set, created containers and pods will join the given namespace #### **--network-cmd-path**=*path* Path to the command binary to use for setting up a network. It is currently only used for setting up a slirp4netns network. If "" is used then the binary is looked up using the $PATH environment variable. +#### **--noout** + +Redirect stdout to /dev/null. This command will prevent all stdout from the Podman command. The **--noout** option will not block stderr or stdout from containers. + + #### **--remote**, **-r** When true, access to the Podman service will be remote. Defaults to false. Settings can be modified in the containers.conf file. If the CONTAINER_HOST diff --git a/libpod/options.go b/libpod/options.go index 1137d228f..5cf7609e9 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -500,8 +500,6 @@ func WithEventsLogger(logger string) RuntimeOption { } rt.config.Engine.EventsLogger = logger - rt.config.Engine.EventsLogFilePath = filepath.Join(rt.config.Engine.TmpDir, "events", "events.log") - return nil } } diff --git a/libpod/runtime.go b/libpod/runtime.go index 5a86cc993..077fce999 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -169,7 +169,6 @@ func NewRuntime(ctx context.Context, options ...RuntimeOption) (*Runtime, error) if err != nil { return nil, err } - conf.CheckCgroupsAndAdjustConfig() return newRuntimeFromConfig(ctx, conf, options...) } @@ -227,6 +226,8 @@ func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...R return nil, err } + runtime.config.CheckCgroupsAndAdjustConfig() + return runtime, nil } @@ -1078,7 +1079,9 @@ func (r *Runtime) mergeDBConfig(dbConfig *DBConfig) { logrus.Debugf("Overriding tmp dir %q with %q from database", c.TmpDir, dbConfig.LibpodTmp) } c.TmpDir = dbConfig.LibpodTmp - c.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log") + if c.EventsLogFilePath == "" { + c.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log") + } } if !r.storageSet.VolumePathSet && dbConfig.VolumePath != "" { diff --git a/pkg/domain/entities/engine.go b/pkg/domain/entities/engine.go index a8023f7cf..055af7ff9 100644 --- a/pkg/domain/entities/engine.go +++ b/pkg/domain/entities/engine.go @@ -40,6 +40,7 @@ type PodmanConfig struct { Identity string // ssh identity for connecting to server MaxWorks int // maximum number of parallel threads MemoryProfile string // Hidden: Should memory profile be taken + NoOut bool // Don't output to stdout RegistriesConf string // allows for specifying a custom registries.conf Remote bool // Connection to Podman API Service will use RESTful API RuntimePath string // --runtime flag will set Engine.RuntimePath diff --git a/pkg/domain/entities/events.go b/pkg/domain/entities/events.go index 73a375b94..fa815d7b9 100644 --- a/pkg/domain/entities/events.go +++ b/pkg/domain/entities/events.go @@ -42,7 +42,7 @@ func ConvertToLibpodEvent(e Event) *libpodEvents.Event { Image: image, Name: name, Status: status, - Time: time.Unix(e.Time, e.TimeNano), + Time: time.Unix(0, e.TimeNano), Type: t, Details: libpodEvents.Details{ Attributes: details, diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index 1b5a1be51..cc9476d79 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -139,6 +139,7 @@ type PodCreateOptions struct { Volume []string `json:"volume,omitempty"` VolumesFrom []string `json:"volumes_from,omitempty"` SecurityOpt []string `json:"security_opt,omitempty"` + Sysctl []string `json:"sysctl,omitempty"` } // PodLogsOptions describes the options to extract pod logs. @@ -240,7 +241,7 @@ type ContainerCreateOptions struct { StorageOpts []string SubUIDName string SubGIDName string - Sysctl []string + Sysctl []string `json:"sysctl,omitempty"` Systemd string Timeout uint TLSVerify commonFlag.OptionalBool @@ -360,6 +361,15 @@ func ToPodSpecGen(s specgen.PodSpecGenerator, p *PodCreateOptions) (*specgen.Pod } } s.Userns = p.Userns + sysctl := map[string]string{} + if ctl := p.Sysctl; len(ctl) > 0 { + sysctl, err = util.ValidateSysctls(ctl) + if err != nil { + return nil, err + } + } + s.Sysctl = sysctl + return &s, nil } diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 84c83ea8e..592e0f4e3 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -745,11 +745,17 @@ func putSignature(manifestBlob []byte, mech signature.SigningMechanism, sigStore // TransferRootless creates new podman processes using exec.Command and sudo, transferring images between the given source and destination users func transferRootless(source entities.ImageScpOptions, dest entities.ImageScpOptions, podman string, parentFlags []string) error { var cmdSave *exec.Cmd - saveCommand := parentFlags - saveCommand = append(saveCommand, []string{"save", "--output", source.File, source.Image}...) + saveCommand, loadCommand := parentFlags, parentFlags + saveCommand = append(saveCommand, []string{"save"}...) + loadCommand = append(loadCommand, []string{"load"}...) + if source.Quiet { + saveCommand = append(saveCommand, "-q") + loadCommand = append(loadCommand, "-q") + } + + saveCommand = append(saveCommand, []string{"--output", source.File, source.Image}...) - loadCommand := parentFlags - loadCommand = append(loadCommand, []string{"load", "--input", dest.File}...) + loadCommand = append(loadCommand, []string{"--input", dest.File}...) if source.User == "root" { cmdSave = exec.Command("sudo", podman) @@ -757,7 +763,7 @@ func transferRootless(source entities.ImageScpOptions, dest entities.ImageScpOpt cmdSave = exec.Command(podman) } cmdSave = utils.CreateSCPCommand(cmdSave, saveCommand) - logrus.Debug("Executing save command") + logrus.Debugf("Executing save command: %q", cmdSave) err := cmdSave.Run() if err != nil { return err @@ -770,20 +776,22 @@ func transferRootless(source entities.ImageScpOptions, dest entities.ImageScpOpt cmdLoad = exec.Command(podman) } cmdLoad = utils.CreateSCPCommand(cmdLoad, loadCommand) - logrus.Debug("Executing load command") - err = cmdLoad.Run() - if err != nil { - return err - } - return nil + logrus.Debugf("Executing load command: %q", cmdLoad) + return cmdLoad.Run() } -// TransferRootless creates new podman processes using exec.Command and su/machinectl, transferring images between the given source and destination users +// TransferRootful creates new podman processes using exec.Command and su/machinectl, transferring images between the given source and destination users func transferRootful(source entities.ImageScpOptions, dest entities.ImageScpOptions, podman string, parentFlags []string) error { basicCommand := []string{podman} basicCommand = append(basicCommand, parentFlags...) - saveCommand := append(basicCommand, []string{"save", "--output", source.File, source.Image}...) - loadCommand := append(basicCommand, []string{"load", "--input", dest.File}...) + saveCommand := append(basicCommand, "save") + loadCommand := append(basicCommand, "load") + if source.Quiet { + saveCommand = append(saveCommand, "-q") + loadCommand = append(loadCommand, "-q") + } + saveCommand = append(saveCommand, []string{"--output", source.File, source.Image}...) + loadCommand = append(loadCommand, []string{"--input", dest.File}...) save := []string{strings.Join(saveCommand, " ")} load := []string{strings.Join(loadCommand, " ")} @@ -846,18 +854,18 @@ func lookupUser(u string) (*user.User, error) { func execSu(execUser *user.User, command []string) error { cmd := exec.Command("su", "-l", execUser.Username, "--command") cmd = utils.CreateSCPCommand(cmd, command) - logrus.Debug("Executing command su") + logrus.Debugf("Executing via su: %q", cmd) return cmd.Run() } func execMachine(execUser *user.User, command []string, machinectl string) error { - var cmd *exec.Cmd + verb := machinectl + args := []string{"shell", "-q", execUser.Username + "@.host"} if execUser.Uid == "0" { - cmd = exec.Command("sudo", machinectl, "shell", "-q", execUser.Username+"@.host") - } else { - cmd = exec.Command(machinectl, "shell", "-q", execUser.Username+"@.host") + args = append([]string{verb}, args...) + verb = "sudo" } - cmd = utils.CreateSCPCommand(cmd, command) - logrus.Debug("Executing command machinectl") + cmd := utils.CreateSCPCommand(exec.Command(verb, args...), command) + logrus.Debugf("Executing via machinectl: %q", cmd) return cmd.Run() } diff --git a/pkg/machine/config.go b/pkg/machine/config.go index 27a7c1b1f..97237f5e5 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -29,6 +29,15 @@ type InitOptions struct { ReExec bool } +type QemuMachineStatus = string + +const ( + // Running indicates the qemu vm is running + Running QemuMachineStatus = "running" + // Stopped indicates the vm has stopped + Stopped QemuMachineStatus = "stopped" +) + type Provider interface { NewMachine(opts InitOptions) (VM, error) LoadVMByName(name string) (VM, error) diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index a43d78665..560037542 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -386,8 +386,16 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { } if len(v.Mounts) > 0 { - for !v.isRunning() || !v.isListening() { + running, err := v.isRunning() + if err != nil { + return err + } + for running || !v.isListening() { time.Sleep(100 * time.Millisecond) + running, err = v.isRunning() + if err != nil { + return err + } } } for _, mount := range v.Mounts { @@ -416,8 +424,48 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { return nil } +func (v *MachineVM) checkStatus(monitor *qmp.SocketMonitor) (machine.QemuMachineStatus, error) { + // this is the format returned from the monitor + // {"return": {"status": "running", "singlestep": false, "running": true}} + + type statusDetails struct { + Status string `json:"status"` + Step bool `json:"singlestep"` + Running bool `json:"running"` + } + type statusResponse struct { + Response statusDetails `json:"return"` + } + var response statusResponse + + checkCommand := struct { + Execute string `json:"execute"` + }{ + Execute: "query-status", + } + input, err := json.Marshal(checkCommand) + if err != nil { + return "", err + } + b, err := monitor.Run(input) + if err != nil { + if errors.Cause(err) == os.ErrNotExist { + return machine.Stopped, nil + } + return "", err + } + if err := json.Unmarshal(b, &response); err != nil { + return "", err + } + if response.Response.Status == machine.Running { + return machine.Running, nil + } + return machine.Stopped, nil +} + // Stop uses the qmp monitor to call a system_powerdown func (v *MachineVM) Stop(name string, _ machine.StopOptions) error { + var disconnected bool // check if the qmp socket is there. if not, qemu instance is gone if _, err := os.Stat(v.QMPMonitor.Address); os.IsNotExist(err) { // Right now it is NOT an error to stop a stopped machine @@ -442,19 +490,22 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error { return err } defer func() { - if err := qmpMonitor.Disconnect(); err != nil { - logrus.Error(err) + if !disconnected { + if err := qmpMonitor.Disconnect(); err != nil { + logrus.Error(err) + } } }() + if _, err = qmpMonitor.Run(input); err != nil { return err } + qemuSocketFile, pidFile, err := v.getSocketandPid() if err != nil { return err } if _, err := os.Stat(pidFile); os.IsNotExist(err) { - logrus.Info(err) return nil } pidString, err := ioutil.ReadFile(pidFile) @@ -483,6 +534,24 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error { return err } + if err := qmpMonitor.Disconnect(); err != nil { + return nil + } + + disconnected = true + waitInternal := 250 * time.Millisecond + for i := 0; i < 5; i++ { + running, err := v.isRunning() + if err != nil { + return err + } + if !running { + break + } + time.Sleep(waitInternal) + waitInternal = waitInternal * 2 + } + return nil } @@ -519,7 +588,11 @@ func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, fun ) // cannot remove a running vm - if v.isRunning() { + running, err := v.isRunning() + if err != nil { + return "", nil, err + } + if running { return "", nil, errors.Errorf("running vm %q cannot be destroyed", v.Name) } @@ -578,16 +651,33 @@ func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, fun }, nil } -func (v *MachineVM) isRunning() bool { +func (v *MachineVM) isRunning() (bool, error) { // Check if qmp socket path exists if _, err := os.Stat(v.QMPMonitor.Address); os.IsNotExist(err) { - return false + return false, nil } // Check if we can dial it - if _, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address, v.QMPMonitor.Timeout); err != nil { - return false + monitor, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address, v.QMPMonitor.Timeout) + if err != nil { + return false, nil } - return true + if err := monitor.Connect(); err != nil { + return false, err + } + defer func() { + if err := monitor.Disconnect(); err != nil { + logrus.Error(err) + } + }() + // If there is a monitor, lets see if we can query state + state, err := v.checkStatus(monitor) + if err != nil { + return false, err + } + if state == machine.Running { + return true, nil + } + return false, nil } func (v *MachineVM) isListening() bool { @@ -603,7 +693,11 @@ func (v *MachineVM) isListening() bool { // SSH opens an interactive SSH session to the vm specified. // Added ssh function to VM interface: pkg/machine/config/go : line 58 func (v *MachineVM) SSH(name string, opts machine.SSHOptions) error { - if !v.isRunning() { + running, err := v.isRunning() + if err != nil { + return err + } + if !running { return errors.Errorf("vm %q is not running.", v.Name) } @@ -710,7 +804,11 @@ func GetVMInfos() ([]*machine.ListResponse, error) { return err } listEntry.LastUp = fi.ModTime() - if vm.isRunning() { + running, err := vm.isRunning() + if err != nil { + return err + } + if running { listEntry.Running = true } diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go index ec4c66595..b6f2d6bf0 100644 --- a/pkg/specgen/podspecgen.go +++ b/pkg/specgen/podspecgen.go @@ -74,6 +74,8 @@ type PodBasicConfig struct { Userns Namespace `json:"userns,omitempty"` // Devices contains user specified Devices to be added to the Pod Devices []string `json:"pod_devices,omitempty"` + // Sysctl sets kernel parameters for the pod + Sysctl map[string]string `json:"sysctl,omitempty"` } // PodNetworkConfig contains networking configuration for a pod. diff --git a/test/e2e/events_test.go b/test/e2e/events_test.go index 39f495460..3b5b8ac6c 100644 --- a/test/e2e/events_test.go +++ b/test/e2e/events_test.go @@ -62,6 +62,8 @@ var _ = Describe("Podman events", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) Expect(len(result.OutputToStringArray())).To(BeNumerically(">=", 1), "Number of events") + date := time.Now().Format("2006-01-02") + Expect(result.OutputToStringArray()).To(ContainElement(HavePrefix(date)), "event log has correct timestamp") }) It("podman events with an event filter and container=cid", func() { diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index fab107af8..623377ea1 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -1029,4 +1029,43 @@ ENTRYPOINT ["sleep","99999"] Expect(inspect[0].AppArmorProfile).To(Equal(apparmor.Profile)) }) + + It("podman pod create --sysctl test", func() { + SkipIfRootless("Network sysctls are not available root rootless") + podCreate := podmanTest.Podman([]string{"pod", "create", "--sysctl", "net.core.somaxconn=65535"}) + podCreate.WaitWithDefaultTimeout() + Expect(podCreate).Should(Exit(0)) + session := podmanTest.Podman([]string{"run", "--pod", podCreate.OutputToString(), "--rm", ALPINE, "sysctl", "net.core.somaxconn"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("net.core.somaxconn = 65535")) + + // if not sharing the net NS, nothing should fail, but the sysctl should not be passed + podCreate = podmanTest.Podman([]string{"pod", "create", "--share", "pid", "--sysctl", "net.core.somaxconn=65535"}) + podCreate.WaitWithDefaultTimeout() + Expect(podCreate).Should(Exit(0)) + session = podmanTest.Podman([]string{"run", "--pod", podCreate.OutputToString(), "--rm", ALPINE, "sysctl", "net.core.somaxconn"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).NotTo(ContainSubstring("net.core.somaxconn = 65535")) + + // one other misc option + podCreate = podmanTest.Podman([]string{"pod", "create", "--sysctl", "kernel.msgmax=65535"}) + podCreate.WaitWithDefaultTimeout() + Expect(podCreate).Should(Exit(0)) + session = podmanTest.Podman([]string{"run", "--pod", podCreate.OutputToString(), "--rm", ALPINE, "sysctl", "kernel.msgmax"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("kernel.msgmax = 65535")) + + podCreate = podmanTest.Podman([]string{"pod", "create", "--share", "pid", "--sysctl", "kernel.msgmax=65535"}) + podCreate.WaitWithDefaultTimeout() + Expect(podCreate).Should(Exit(0)) + session = podmanTest.Podman([]string{"run", "--pod", podCreate.OutputToString(), "--rm", ALPINE, "sysctl", "kernel.msgmax"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).NotTo(ContainSubstring("kernel.msgmax = 65535")) + + }) + }) diff --git a/test/system/030-run.bats b/test/system/030-run.bats index feca5370b..afcda3d3c 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -509,6 +509,21 @@ json-file | f rm -f $new_runtime } +@test "podman --noout run should print output" { + run_podman --noout run -d --name test $IMAGE echo hi + is "$output" "" "output should be empty" + run_podman wait test + run_podman --noout rm test + is "$output" "" "output should be empty" +} + +@test "podman --noout create should print output" { + run_podman --noout create --name test $IMAGE echo hi + is "$output" "" "output should be empty" + run_podman --noout rm test + is "$output" "" "output should be empty" +} + # Regression test for issue #8082 @test "podman run : look up correct image name" { # Create a 2nd tag for the local image. Force to lower case, and apply it. diff --git a/test/system/050-stop.bats b/test/system/050-stop.bats index e049da518..7dd8f98e8 100644 --- a/test/system/050-stop.bats +++ b/test/system/050-stop.bats @@ -173,4 +173,9 @@ load helpers is "$output" ".*StopSignal SIGTERM failed to stop container stopme in 1 seconds, resorting to SIGKILL" "stopping container should print warning" } +@test "podman stop --noout" { + run_podman run --rm --name stopme -d $IMAGE top + run_podman --noout stop -t 0 stopme + is "$output" "" "output should be empty" +} # vim: filetype=sh diff --git a/test/system/080-pause.bats b/test/system/080-pause.bats index 857c8bbf4..57f390a74 100644 --- a/test/system/080-pause.bats +++ b/test/system/080-pause.bats @@ -21,7 +21,8 @@ load helpers # time to write a new post-restart time value. Pause by CID, unpause # by name, just to exercise code paths. While paused, check 'ps' # and 'inspect', then check again after restarting. - run_podman pause $cid + run_podman --noout pause $cid + is "$output" "" "output should be empty" run_podman inspect --format '{{.State.Status}}' $cid is "$output" "paused" "podman inspect .State.Status" sleep 3 diff --git a/test/system/090-events.bats b/test/system/090-events.bats index 5af6a3793..a0b0380a2 100644 --- a/test/system/090-events.bats +++ b/test/system/090-events.bats @@ -116,3 +116,16 @@ function _events_disjunctive_filters() { @test "events with disjunctive filters - default" { _events_disjunctive_filters "" } + +@test "events with events_logfile_path in containers.conf" { + skip_if_remote "remote does not support --events-backend" + events_file=$PODMAN_TMPDIR/events.log + containersconf=$PODMAN_TMPDIR/containers.conf + cat >$containersconf <<EOF +[engine] +events_logfile_path="$events_file" +EOF + CONTAINERS_CONF="$containersconf" run_podman --events-backend=file pull $IMAGE + run cat $events_file + is "$output" ".*\"Name\":\"$IMAGE" "test" +} diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats index 6abdf9779..4a3337e57 100644 --- a/test/system/200-pod.bats +++ b/test/system/200-pod.bats @@ -57,7 +57,8 @@ function teardown() { fi # Clean up - run_podman pod rm -f -t 0 $podid + run_podman --noout pod rm -f -t 0 $podid + is "$output" "" "output should be empty" } @@ -330,7 +331,8 @@ EOF # Note that the internal pause image is built even when --infra-image is # set to the K8s one. - run_podman pod create --name $pod_name --infra-name "$infra_name" --infra-image "k8s.gcr.io/pause:3.5" + run_podman --noout pod create --name $pod_name --infra-name "$infra_name" --infra-image "k8s.gcr.io/pause:3.5" + is "$output" "" "output should be empty" run_podman '?' pod create --infra-name "$infra_name" if [ $status -eq 0 ]; then die "Podman should fail when user try to create two pods with the same infra-name value" diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats index c49727cc9..c47679904 100644 --- a/test/system/250-systemd.bats +++ b/test/system/250-systemd.bats @@ -276,4 +276,9 @@ LISTEN_FDNAMES=listen_fdnames" | sort) is "$output" ".*--template cannot be set" "Error message should be '--template requires --new'" } +@test "podman --cgroup=cgroupfs doesn't show systemd warning" { + DBUS_SESSION_BUS_ADDRESS= run_podman --log-level warning --cgroup-manager=cgroupfs info -f '' + is "$output" "" "output should be empty" +} + # vim: filetype=sh diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index 2b5ad44dc..5a721c965 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -332,7 +332,8 @@ load helpers is_rootless || skip "only meaningful for rootless" local mynetname=testnet-$(random_string 10) - run_podman network create $mynetname + run_podman --noout network create $mynetname + is "$output" "" "output should be empty" # Test that rootless cni adds /usr/sbin to $PATH # iptables is located under /usr/sbin and is needed for the CNI plugins. @@ -340,7 +341,8 @@ load helpers PATH=/usr/local/bin:/usr/bin run_podman run --rm --network $mynetname $IMAGE ip addr is "$output" ".*eth0.*" "Interface eth0 not found in ip addr output" - run_podman network rm -t 0 -f $mynetname + run_podman --noout network rm -t 0 -f $mynetname + is "$output" "" "output should be empty" } @test "podman ipv6 in /etc/resolv.conf" { |