diff options
59 files changed, 385 insertions, 129 deletions
@@ -808,7 +808,7 @@ ifneq (,$(findstring systemd,$(BUILDTAGS))) PODMAN_UNIT_FILES = contrib/systemd/auto-update/podman-auto-update.service \ contrib/systemd/system/podman.service \ contrib/systemd/system/podman-restart.service \ - contrib/systemd/system/podman-play-kube@.service + contrib/systemd/system/podman-kube@.service %.service: %.service.in sed -e 's;@@PODMAN@@;$(BINDIR)/podman;g' $< >$@.tmp.$$ \ @@ -822,14 +822,14 @@ install.systemd: $(PODMAN_UNIT_FILES) install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.socket ${DESTDIR}${USERSYSTEMDDIR}/podman.socket install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.service ${DESTDIR}${USERSYSTEMDDIR}/podman.service install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-restart.service ${DESTDIR}${USERSYSTEMDDIR}/podman-restart.service - install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-play-kube@.service ${DESTDIR}${USERSYSTEMDDIR}/podman-play-kube@.service + install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-kube@.service ${DESTDIR}${USERSYSTEMDDIR}/podman-kube@.service # System services install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.service ${DESTDIR}${SYSTEMDDIR}/podman-auto-update.service install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.timer ${DESTDIR}${SYSTEMDDIR}/podman-auto-update.timer install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.socket ${DESTDIR}${SYSTEMDDIR}/podman.socket install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.service ${DESTDIR}${SYSTEMDDIR}/podman.service install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-restart.service ${DESTDIR}${SYSTEMDDIR}/podman-restart.service - install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-play-kube@.service ${DESTDIR}${SYSTEMDDIR}/podman-play-kube@.service + install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-kube@.service ${DESTDIR}${SYSTEMDDIR}/podman-kube@.service rm -f $(PODMAN_UNIT_FILES) else install.systemd: diff --git a/cmd/podman-mac-helper/install.go b/cmd/podman-mac-helper/install.go index 7b8753820..713bdfcdf 100644 --- a/cmd/podman-mac-helper/install.go +++ b/cmd/podman-mac-helper/install.go @@ -193,7 +193,7 @@ func verifyRootDeep(path string) error { func installExecutable(user string) (string, error) { // Since the installed executable runs as root, as a precaution verify root ownership of - // the entire installation path, and utilize sticky + read only perms for the helper path + // the entire installation path, and utilize sticky + read-only perms for the helper path // suffix. The goal is to help users harden against privilege escalation from loose // filesystem permissions. // diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index e25bdd241..f05549a8d 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -863,14 +863,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(cpusetMemsFlagName, completion.AutocompleteNone) - memoryFlagName := "memory" - createFlags.StringVarP( - &cf.Memory, - memoryFlagName, "m", "", - "Memory limit "+sizeWithUnitFormat, - ) - _ = cmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone) - memoryReservationFlagName := "memory-reservation" createFlags.StringVar( &cf.MemoryReservation, @@ -912,4 +904,12 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, "CPUs in which to allow execution (0-3, 0,1)", ) _ = cmd.RegisterFlagCompletionFunc(cpusetCpusFlagName, completion.AutocompleteNone) + + memoryFlagName := "memory" + createFlags.StringVarP( + &cf.Memory, + memoryFlagName, "m", "", + "Memory limit "+sizeWithUnitFormat, + ) + _ = cmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone) } diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go index b736b3477..edddf026e 100644 --- a/cmd/podman/inspect/inspect.go +++ b/cmd/podman/inspect/inspect.go @@ -41,7 +41,7 @@ func AddInspectFlagSet(cmd *cobra.Command) *entities.InspectOptions { return &opts } -// Inspect inspects the specified container/image names or IDs. +// Inspect inspects the specified container/image/pod/volume names or IDs. func Inspect(namesOrIDs []string, options entities.InspectOptions) error { inspector, err := newInspector(options) if err != nil { diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index d3d44b45e..5a8a06b9d 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -5,7 +5,6 @@ package machine import ( "errors" - "fmt" "net" "os" "path/filepath" @@ -18,7 +17,6 @@ import ( "github.com/containers/podman/v4/cmd/podman/validate" "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/pkg/machine" - "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/util" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -164,10 +162,3 @@ func closeMachineEvents(cmd *cobra.Command, _ []string) error { } return nil } - -func rootlessOnly(cmd *cobra.Command, args []string) error { - if !rootless.IsRootless() { - return fmt.Errorf("cannot run command %q as root", cmd.CommandPath()) - } - return nil -} diff --git a/cmd/podman/machine/machine_unix.go b/cmd/podman/machine/machine_unix.go index b56d081ec..a2d9b9d8e 100644 --- a/cmd/podman/machine/machine_unix.go +++ b/cmd/podman/machine/machine_unix.go @@ -4,9 +4,20 @@ package machine import ( + "fmt" "os" + + "github.com/containers/podman/v4/pkg/rootless" + "github.com/spf13/cobra" ) func isUnixSocket(file os.DirEntry) bool { return file.Type()&os.ModeSocket != 0 } + +func rootlessOnly(cmd *cobra.Command, args []string) error { + if !rootless.IsRootless() { + return fmt.Errorf("cannot run command %q as root", cmd.CommandPath()) + } + return nil +} diff --git a/cmd/podman/machine/machine_windows.go b/cmd/podman/machine/machine_windows.go index ffd5d8827..bf1240868 100644 --- a/cmd/podman/machine/machine_windows.go +++ b/cmd/podman/machine/machine_windows.go @@ -3,9 +3,18 @@ package machine import ( "os" "strings" + + "github.com/spf13/cobra" ) func isUnixSocket(file os.DirEntry) bool { // Assume a socket on Windows, since sock mode is not supported yet https://github.com/golang/go/issues/33357 return !file.Type().IsDir() && strings.HasSuffix(file.Name(), ".sock") } + +func rootlessOnly(cmd *cobra.Command, args []string) error { + // Rootless is not relevant on Windows. In the future rootless.IsRootless + // could be switched to return true on Windows, and other codepaths migrated + + return nil +} diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go index e2163a6aa..6823d77ba 100644 --- a/cmd/podman/system/service_abi.go +++ b/cmd/podman/system/service_abi.go @@ -11,17 +11,39 @@ import ( "os" "path/filepath" + "github.com/containers/common/pkg/cgroups" "github.com/containers/podman/v4/cmd/podman/registry" api "github.com/containers/podman/v4/pkg/api/server" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/infra" "github.com/containers/podman/v4/pkg/servicereaper" + "github.com/containers/podman/v4/utils" "github.com/coreos/go-systemd/v22/activation" "github.com/sirupsen/logrus" "github.com/spf13/pflag" "golang.org/x/sys/unix" ) +// maybeMoveToSubCgroup moves the current process in a sub cgroup when +// it is running in the root cgroup on a system that uses cgroupv2. +func maybeMoveToSubCgroup() error { + unifiedMode, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + return err + } + if !unifiedMode { + return nil + } + cgroup, err := utils.GetOwnCgroup() + if err != nil { + return err + } + if cgroup == "/" { + return utils.MoveUnderCgroupSubtree("init") + } + return nil +} + func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities.ServiceOptions) error { var ( listener net.Listener @@ -103,6 +125,10 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities return err } + if err := maybeMoveToSubCgroup(); err != nil { + return err + } + servicereaper.Start() infra.StartWatcher(libpodRuntime) server, err := api.NewServerWithSettings(libpodRuntime, listener, opts) diff --git a/contrib/systemd/system/podman-play-kube@.service.in b/contrib/systemd/system/podman-kube@.service.in index 824f71eb0..824f71eb0 100644 --- a/contrib/systemd/system/podman-play-kube@.service.in +++ b/contrib/systemd/system/podman-kube@.service.in diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 425ce7bcc..403327d82 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -881,11 +881,11 @@ Suppress output information when pulling images #### **--read-only** -Mount the container's root filesystem as read only. +Mount the container's root filesystem as read-only. By default a container will have its root filesystem writable allowing processes to write files anywhere. By specifying the `--read-only` flag the container will have -its root filesystem mounted as read only prohibiting any writes. +its root filesystem mounted as read-only prohibiting any writes. #### **--read-only-tmpfs** @@ -1006,8 +1006,8 @@ Note: Labeling can be disabled for all containers by setting label=false in the possible mount options are specified in the **proc(5)** man page. -- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read only by default. - The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. +- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read-only by default. + The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read-only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file. diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md index 8c3c32d04..56ad4e446 100644 --- a/docs/source/markdown/podman-generate-systemd.1.md +++ b/docs/source/markdown/podman-generate-systemd.1.md @@ -14,6 +14,17 @@ Generating unit files for a pod requires the pod to be created with an infra con _Note: If you use this command with the remote client, including Mac and Windows (excluding WSL2) machines, you would still have to place the generated units on the remote system. Moreover, please make sure that the XDG_RUNTIME_DIR environment variable is set. If unset, you may set it via `export XDG_RUNTIME_DIR=/run/user/$(id -u)`._ +### Kubernetes Integration + +A Kubernetes YAML can be executed in systemd via the `podman-kube@.service` systemd template. The template's argument is the path to the YAML file. Given a `workload.yaml` file in the home directory, it can be executed as follows: + +``` +$ escaped=$(systemd-escape ~/sysadmin.yaml) +$ systemctl --user start podman-kube@$escaped.service +$ systemctl --user is-active podman-kube@$escaped.service +active +``` + ## OPTIONS #### **--after**=*dependency_name* diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md index 1c7fc99a2..92cb694b0 100644 --- a/docs/source/markdown/podman-play-kube.1.md +++ b/docs/source/markdown/podman-play-kube.1.md @@ -103,6 +103,19 @@ spec: and as a result environment variable `FOO` will be set to `bar` for container `container-1`. +### Systemd Integration + +A Kubernetes YAML can be executed in systemd via the `podman-kube@.service` systemd template. The template's argument is the path to the YAML file. Given a `workload.yaml` file in the home directory, it can be executed as follows: + +``` +$ escaped=$(systemd-escape ~/sysadmin.yaml) +$ systemctl --user start podman-kube@$escaped.service +$ systemctl --user is-active podman-kube@$escaped.service +active +``` + +Note that the path to the YAML file must be escaped via `systemd-escape`. + ## OPTIONS #### **--annotation**=*key=value* diff --git a/docs/source/markdown/podman-pod-clone.1.md b/docs/source/markdown/podman-pod-clone.1.md index e44e9fa3c..a18f7dbfe 100644 --- a/docs/source/markdown/podman-pod-clone.1.md +++ b/docs/source/markdown/podman-pod-clone.1.md @@ -80,6 +80,16 @@ Add metadata to a pod (e.g., --label com.example.key=value). Read in a line delimited file of labels. +#### **--memory**, **-m**=*limit* + +Memory limit (format: `<number>[<unit>]`, where unit = b (bytes), k (kibibytes), m (mebibytes), or g (gibibytes)) + +Constrains the memory available to a container. If the host +supports swap memory, then the **-m** memory setting can be larger than physical +RAM. If a limit of 0 is specified (not using **-m**), the container's memory is +not limited. The actual limit may be rounded up to a multiple of the operating +system's page size (the value would be very large, that's millions of trillions). + #### **--name**, **-n** Set a custom name for the cloned pod. The default if not specified is of the syntax: **<ORIGINAL_NAME>-clone** @@ -119,8 +129,8 @@ Note: Labeling can be disabled for all pods/containers by setting label=false in - `proc-opts=OPTIONS` : Comma-separated list of options to use for the /proc mount. More details for the possible mount options are specified in the **proc(5)** man page. -- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read only by default. - The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. +- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read-only by default. + The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read-only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file. diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index e63623169..75d2bb611 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -164,6 +164,16 @@ according to RFC4862. To specify multiple static MAC addresses per pod, set multiple networks using the **--network** option with a static MAC address specified for each using the `mac` mode for that option. +#### **--memory**, **-m**=*limit* + +Memory limit (format: `<number>[<unit>]`, where unit = b (bytes), k (kibibytes), m (mebibytes), or g (gibibytes)) + +Constrains the memory available to a container. If the host +supports swap memory, then the **-m** memory setting can be larger than physical +RAM. If a limit of 0 is specified (not using **-m**), the container's memory is +not limited. The actual limit may be rounded up to a multiple of the operating +system's page size (the value would be very large, that's millions of trillions). + #### **--name**=*name*, **-n** @@ -283,8 +293,8 @@ Note: Labeling can be disabled for all pods/containers by setting label=false in - `proc-opts=OPTIONS` : Comma-separated list of options to use for the /proc mount. More details for the possible mount options are specified in the **proc(5)** man page. -- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read only by default. - The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. +- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read-only by default. + The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read-only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file. diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 5b45c3350..8f71c3706 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -919,11 +919,11 @@ Suppress output information when pulling images #### **--read-only** -Mount the container's root filesystem as read only. +Mount the container's root filesystem as read-only. By default a container will have its root filesystem writable allowing processes to write files anywhere. By specifying the **--read-only** flag, the container will have -its root filesystem mounted as read only prohibiting any writes. +its root filesystem mounted as read-only prohibiting any writes. #### **--read-only-tmpfs** @@ -1051,8 +1051,8 @@ Note: Labeling can be disabled for all containers by setting label=false in the - **proc-opts**=_OPTIONS_ : Comma-separated list of options to use for the /proc mount. More details for the possible mount options are specified in the **proc(5)** man page. -- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read only by default. - The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.**. The default paths that are read only are **/proc/asound**, **/proc/bus**, **/proc/fs**, **/proc/irq**, **/proc/sys**, **/proc/sysrq-trigger**, **/sys/fs/cgroup**. +- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read-only by default. + The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.**. The default paths that are read-only are **/proc/asound**, **/proc/bus**, **/proc/fs**, **/proc/irq**, **/proc/sys**, **/proc/sysrq-trigger**, **/sys/fs/cgroup**. Note: Labeling can be disabled for all containers by setting **label=false** in the **containers.conf**(5) file. @@ -1603,7 +1603,7 @@ content. Installing packages into _/usr_, for example. In production, applications seldom need to write to the image. Container applications write to volumes if they need to write to file systems at all. Applications can be made more secure by running them in read-only mode using the **--read-only** switch. -This protects the containers image from modification. Read only containers may +This protects the containers image from modification. Read-only containers may still need to write temporary data. The best way to handle this is to mount tmpfs directories on _/run_ and _/tmp_. diff --git a/docs/source/markdown/podman-volume-create.1.md b/docs/source/markdown/podman-volume-create.1.md index 32b10da84..f43e647bf 100644 --- a/docs/source/markdown/podman-volume-create.1.md +++ b/docs/source/markdown/podman-volume-create.1.md @@ -40,8 +40,8 @@ The `o` option sets options for the mount, and is equivalent to the `-o` flag to - The `o` option supports `uid` and `gid` options to set the UID and GID of the created volume that are not normally supported by **mount(8)**. - The `o` option supports the `size` option to set the maximum size of the created volume, the `inodes` option to set the maximum number of inodes for the volume and `noquota` to completely disable quota support even for tracking of disk usage. Currently these flags are only supported on "xfs" file system mounted with the `prjquota` flag described in the **xfs_quota(8)** man page. - - The `o` option supports . - - Using volume options other then the UID/GID options with the **local** driver requires root privileges. + - The `o` option supports using volume options other than the UID/GID options with the **local** driver and requires root privileges. + - The `o` options supports the `timeout` option which allows users to set a driver specific timeout in seconds before volume creation fails. For example, **--opts=o=timeout=10** sets a driver timeout of 10 seconds. When not using the **local** driver, the given options are passed directly to the volume plugin. In this case, supported options are dictated by the plugin in question, not Podman. diff --git a/docs/tutorials/remote_client.md b/docs/tutorials/remote_client.md index 27b97e6f5..5cd679193 100644 --- a/docs/tutorials/remote_client.md +++ b/docs/tutorials/remote_client.md @@ -54,7 +54,7 @@ host: In order for the Podman client to communicate with the server you need to enable and start the SSH daemon on your Linux machine, if it is not currently enabled. ``` -sudo systemctl enable --now -s sshd +sudo systemctl enable --now sshd ``` #### Setting up SSH @@ -12,7 +12,7 @@ require ( github.com/containernetworking/cni v1.1.1 github.com/containernetworking/plugins v1.1.1 github.com/containers/buildah v1.26.1-0.20220609225314-e66309ebde8c - github.com/containers/common v0.48.1-0.20220628131511-a8336c1613fe + github.com/containers/common v0.48.1-0.20220630172158-178929cf063e github.com/containers/conmon v2.0.20+incompatible github.com/containers/image/v5 v5.21.2-0.20220617075545-929f14a56f5c github.com/containers/ocicrypt v1.1.5 @@ -338,8 +338,8 @@ github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19 github.com/containers/buildah v1.26.1-0.20220609225314-e66309ebde8c h1:/fKyiLFFuceBPZGJ0Lig7ElURhfsslAOw1BOcItD+X8= github.com/containers/buildah v1.26.1-0.20220609225314-e66309ebde8c/go.mod h1:b0L+u2Dam7soWGn5sVTK31L++Xrf80AbGvK5z9D2+lw= github.com/containers/common v0.48.1-0.20220608111710-dbecabbe82c9/go.mod h1:WBLwq+i7bicCpH54V70HM6s7jqDAESTlYnd05XXp0ac= -github.com/containers/common v0.48.1-0.20220628131511-a8336c1613fe h1:H5YI9PXhDB974IkSCUaha+AF60TunRdHaGElZroYx7M= -github.com/containers/common v0.48.1-0.20220628131511-a8336c1613fe/go.mod h1:UDe7OTpNdtJA2T80Sp7yB0yTaj79f4kMNQbTsNxsqoY= +github.com/containers/common v0.48.1-0.20220630172158-178929cf063e h1:Vf5tsGrLC2B2omVBP3AdDA7YlE/VoMdNyQ5yPF8GRoY= +github.com/containers/common v0.48.1-0.20220630172158-178929cf063e/go.mod h1:Zt3D/IhgFyG1oaBrqsbn9NdH/4fkjsO2Y0ahP12ieu4= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/image/v5 v5.21.2-0.20220511203756-fe4fd4ed8be4/go.mod h1:OsX9sFexyGF0FCNAjfcVFv3IwMqDyLyV/WQY/roLPcE= @@ -1268,7 +1268,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index edba78d6d..11b4aa049 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -530,7 +530,7 @@ func (s *BoltState) getVolumeFromDB(name []byte, volume *Volume, volBkt *bolt.Bu // Retrieve volume driver if volume.UsesVolumeDriver() { - plugin, err := s.runtime.getVolumePlugin(volume.config.Driver) + plugin, err := s.runtime.getVolumePlugin(volume.config) if err != nil { // We want to fail gracefully here, to ensure that we // can still remove volumes even if their plugin is diff --git a/libpod/container.go b/libpod/container.go index 3a15cfbdb..0619471b4 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -1118,7 +1118,7 @@ func (c *Container) IsInitCtr() bool { return len(c.config.InitContainerType) > 0 } -// IsReadOnly returns whether the container is running in read only mode +// IsReadOnly returns whether the container is running in read-only mode func (c *Container) IsReadOnly() bool { return c.config.Spec.Root.Readonly } diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go index c387856e5..935e0f5f9 100644 --- a/libpod/define/pod_inspect.go +++ b/libpod/define/pod_inspect.go @@ -69,6 +69,8 @@ type InspectPodData struct { VolumesFrom []string `json:"volumes_from,omitempty"` // SecurityOpt contains the specified security labels and related SELinux information SecurityOpts []string `json:"security_opt,omitempty"` + // MemoryLimit contains the specified cgroup memory limit for the pod + MemoryLimit uint64 `json:"memory_limit,omitempty"` } // InspectPodInfraConfig contains the configuration of the pod's infra diff --git a/libpod/define/volume_inspect.go b/libpod/define/volume_inspect.go index aaa23b4fc..f731a8735 100644 --- a/libpod/define/volume_inspect.go +++ b/libpod/define/volume_inspect.go @@ -56,6 +56,8 @@ type InspectVolumeData struct { // a container, the container will chown the volume to the container process // UID/GID. NeedsChown bool `json:"NeedsChown,omitempty"` + // Timeout is the specified driver timeout if given + Timeout int `json:"Timeout,omitempty"` } type VolumeReload struct { diff --git a/libpod/options.go b/libpod/options.go index 9a29fb279..3f9a0424a 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1693,6 +1693,18 @@ func withSetAnon() VolumeCreateOption { } } +// WithVolumeDriverTimeout sets the volume creation timeout period +func WithVolumeDriverTimeout(timeout int) VolumeCreateOption { + return func(volume *Volume) error { + if volume.valid { + return define.ErrVolumeFinalized + } + + volume.config.Timeout = timeout + return nil + } +} + // WithTimezone sets the timezone in the container func WithTimezone(path string) CtrCreateOption { return func(ctr *Container) error { diff --git a/libpod/plugin/volume_api.go b/libpod/plugin/volume_api.go index 2de7db32c..332ab912b 100644 --- a/libpod/plugin/volume_api.go +++ b/libpod/plugin/volume_api.go @@ -127,7 +127,7 @@ func validatePlugin(newPlugin *VolumePlugin) error { // GetVolumePlugin gets a single volume plugin, with the given name, at the // given path. -func GetVolumePlugin(name string, path string) (*VolumePlugin, error) { +func GetVolumePlugin(name string, path string, timeout int) (*VolumePlugin, error) { pluginsLock.Lock() defer pluginsLock.Unlock() @@ -151,6 +151,13 @@ func GetVolumePlugin(name string, path string) (*VolumePlugin, error) { // And since we can reuse it, might as well cache it. client := new(http.Client) client.Timeout = defaultTimeout + // if the user specified a non-zero timeout, use their value. Else, keep the default. + if timeout != 0 { + if time.Duration(timeout)*time.Second < defaultTimeout { + logrus.Warnf("the default timeout for volume creation is %d seconds, setting a time less than that may break this feature.", defaultTimeout) + } + client.Timeout = time.Duration(timeout) * time.Second + } // This bit borrowed from pkg/bindings/connection.go client.Transport = &http.Transport{ DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { diff --git a/libpod/pod.go b/libpod/pod.go index 2502c41a9..c8c6790e8 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -169,6 +169,23 @@ func (p *Pod) CPUQuota() int64 { return 0 } +// MemoryLimit returns the pod Memory Limit +func (p *Pod) MemoryLimit() uint64 { + if p.state.InfraContainerID == "" { + return 0 + } + infra, err := p.runtime.GetContainer(p.state.InfraContainerID) + if err != nil { + return 0 + } + conf := infra.config.Spec + if conf != nil && conf.Linux != nil && conf.Linux.Resources != nil && conf.Linux.Resources.Memory != nil && conf.Linux.Resources.Memory.Limit != nil { + val := *conf.Linux.Resources.Memory.Limit + return uint64(val) + } + return 0 +} + // NetworkMode returns the Network mode given by the user ex: pod, private... func (p *Pod) NetworkMode() string { infra, err := p.runtime.GetContainer(p.state.InfraContainerID) diff --git a/libpod/pod_api.go b/libpod/pod_api.go index fefe0e329..f06e62007 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -751,6 +751,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) { CPUSetCPUs: p.ResourceLim().CPU.Cpus, CPUPeriod: p.CPUPeriod(), CPUQuota: p.CPUQuota(), + MemoryLimit: p.MemoryLimit(), Mounts: inspectMounts, Devices: devices, BlkioDeviceReadBps: deviceLimits, diff --git a/libpod/runtime.go b/libpod/runtime.go index 38944d3b6..ea4b34954 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -1194,9 +1194,11 @@ func (r *Runtime) reloadStorageConf() error { return nil } -// getVolumePlugin gets a specific volume plugin given its name. -func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) { +// getVolumePlugin gets a specific volume plugin. +func (r *Runtime) getVolumePlugin(volConfig *VolumeConfig) (*plugin.VolumePlugin, error) { // There is no plugin for local. + name := volConfig.Driver + timeout := volConfig.Timeout if name == define.VolumeDriverLocal || name == "" { return nil, nil } @@ -1206,7 +1208,7 @@ func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) { return nil, fmt.Errorf("no volume plugin with name %s available: %w", name, define.ErrMissingPlugin) } - return plugin.GetVolumePlugin(name, pluginPath) + return plugin.GetVolumePlugin(name, pluginPath, timeout) } // GetSecretsStorageDir returns the directory that the secrets manager should take diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index a10525f3a..a751d75d2 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -59,7 +59,7 @@ func (r *Runtime) newVolume(noCreatePluginVolume bool, options ...VolumeCreateOp // Plugin can be nil if driver is local, but that's OK - superfluous // assignment doesn't hurt much. - plugin, err := r.getVolumePlugin(volume.config.Driver) + plugin, err := r.getVolumePlugin(volume.config) if err != nil { return nil, fmt.Errorf("volume %s uses volume plugin %s but it could not be retrieved: %w", volume.config.Name, volume.config.Driver, err) } @@ -183,7 +183,7 @@ func (r *Runtime) UpdateVolumePlugins(ctx context.Context) *define.VolumeReload ) for driverName, socket := range r.config.Engine.VolumePlugins { - driver, err := volplugin.GetVolumePlugin(driverName, socket) + driver, err := volplugin.GetVolumePlugin(driverName, socket, 0) if err != nil { errs = append(errs, err) continue diff --git a/libpod/volume.go b/libpod/volume.go index ab461a37f..2e8cd77a5 100644 --- a/libpod/volume.go +++ b/libpod/volume.go @@ -55,6 +55,8 @@ type VolumeConfig struct { // DisableQuota indicates that the volume should completely disable using any // quota tracking. DisableQuota bool `json:"disableQuota,omitempty"` + // Timeout allows users to override the default driver timeout of 5 seconds + Timeout int } // VolumeState holds the volume's mutable state. diff --git a/libpod/volume_inspect.go b/libpod/volume_inspect.go index 3d721410b..2182f04e6 100644 --- a/libpod/volume_inspect.go +++ b/libpod/volume_inspect.go @@ -63,6 +63,7 @@ func (v *Volume) Inspect() (*define.InspectVolumeData, error) { data.MountCount = v.state.MountCount data.NeedsCopyUp = v.state.NeedsCopyUp data.NeedsChown = v.state.NeedsChown + data.Timeout = v.config.Timeout return data, nil } diff --git a/pkg/domain/infra/abi/parse/parse.go b/pkg/domain/infra/abi/parse/parse.go index 66794e592..4e8c2e508 100644 --- a/pkg/domain/infra/abi/parse/parse.go +++ b/pkg/domain/infra/abi/parse/parse.go @@ -78,6 +78,16 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) libpodOptions = append(libpodOptions, libpod.WithVolumeDisableQuota()) // set option "NOQUOTA": "true" volumeOptions["NOQUOTA"] = "true" + case "timeout": + if len(splitO) != 2 { + return nil, errors.Wrapf(define.ErrInvalidArg, "timeout option must provide a valid timeout in seconds") + } + intTimeout, err := strconv.Atoi(splitO[1]) + if err != nil { + return nil, errors.Wrapf(err, "cannot convert Timeout %s to an integer", splitO[1]) + } + logrus.Debugf("Removing timeout from options and adding WithTimeout for Timeout %d", intTimeout) + libpodOptions = append(libpodOptions, libpod.WithVolumeDriverTimeout(intTimeout)) default: finalVal = append(finalVal, o) } diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go b/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go index d05984dac..69613321f 100644 --- a/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go +++ b/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go @@ -48,7 +48,7 @@ const ( var ( Zero = int64Amount{} - // Used by quantity strings - treat as read only + // Used by quantity strings - treat as read-only zeroBytes = []byte("0") ) diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/math.go b/pkg/k8s.io/apimachinery/pkg/api/resource/math.go index 9d03f5c05..59a4c14de 100644 --- a/pkg/k8s.io/apimachinery/pkg/api/resource/math.go +++ b/pkg/k8s.io/apimachinery/pkg/api/resource/math.go @@ -29,13 +29,13 @@ const ( ) var ( - // Commonly needed big.Int values-- treat as read only! + // Commonly needed big.Int values-- treat as read-only! bigTen = big.NewInt(10) bigZero = big.NewInt(0) bigOne = big.NewInt(1) big1024 = big.NewInt(1024) - // Commonly needed inf.Dec values-- treat as read only! + // Commonly needed inf.Dec values-- treat as read-only! decZero = inf.NewDec(0, 0) decOne = inf.NewDec(1, 0) diff --git a/pkg/machine/keys.go b/pkg/machine/keys.go index 45d9801cc..463271427 100644 --- a/pkg/machine/keys.go +++ b/pkg/machine/keys.go @@ -4,14 +4,15 @@ package machine import ( - "errors" "fmt" + "io" "io/ioutil" "os" "os/exec" "path/filepath" "strings" + "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -51,7 +52,23 @@ func CreateSSHKeysPrefix(dir string, file string, passThru bool, skipExisting bo // generatekeys creates an ed25519 set of keys func generatekeys(writeLocation string) error { args := append(append([]string{}, sshCommand[1:]...), writeLocation) - return exec.Command(sshCommand[0], args...).Run() + cmd := exec.Command(sshCommand[0], args...) + stdErr, err := cmd.StderrPipe() + if err != nil { + return err + } + if err := cmd.Start(); err != nil { + return err + } + waitErr := cmd.Wait() + if waitErr == nil { + return nil + } + errMsg, err := io.ReadAll(stdErr) + if err != nil { + return fmt.Errorf("key generation failed, unable to read from stderr: %w", waitErr) + } + return fmt.Errorf("failed to generate keys: %s: %w", string(errMsg), waitErr) } // generatekeys creates an ed25519 set of keys diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 48ffb03a4..2fe0230cf 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -963,7 +963,12 @@ func (v *MachineVM) State(bypass bool) (machine.Status, error) { } monitor, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address.GetPath(), v.QMPMonitor.Timeout) if err != nil { - // FIXME: this error should probably be returned + // If an improper cleanup was done and the socketmonitor was not deleted, + // it can appear as though the machine state is not stopped. Check for ECONNREFUSED + // almost assures us that the vm is stopped. + if errors.Is(err, syscall.ECONNREFUSED) { + return machine.Stopped, nil + } return "", err } if err := monitor.Connect(); err != nil { diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go index f272a5c11..c9f944abf 100644 --- a/pkg/specgen/volumes.go +++ b/pkg/specgen/volumes.go @@ -37,7 +37,7 @@ type OverlayVolume struct { // ImageVolume is a volume based on a container image. The container image is // first mounted on the host and is then bind-mounted into the container. An -// ImageVolume is always mounted read only. +// ImageVolume is always mounted read-only. type ImageVolume struct { // Source is the source of the image volume. The image can be referred // to by name and by ID. @@ -139,7 +139,13 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na // This is a overlay volume newOverlayVol := new(OverlayVolume) newOverlayVol.Destination = dest - newOverlayVol.Source = src + // convert src to absolute path so we don't end up passing + // relative values as lowerdir for overlay mounts + source, err := filepath.Abs(src) + if err != nil { + return nil, nil, nil, errors.Wrapf(err, "failed while resolving absolute path for source %v for overlay mount", src) + } + newOverlayVol.Source = source newOverlayVol.Options = options if _, ok := overlayVolumes[newOverlayVol.Destination]; ok { diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index ab45a8d47..8ad0a92e7 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -1134,17 +1134,21 @@ func parseLinuxResourcesDeviceAccess(device string) (specs.LinuxDeviceCgroup, er } number := strings.SplitN(value[1], ":", 2) - i, err := strconv.ParseInt(number[0], 10, 64) - if err != nil { - return specs.LinuxDeviceCgroup{}, err + if number[0] != "*" { + i, err := strconv.ParseUint(number[0], 10, 64) + if err != nil { + return specs.LinuxDeviceCgroup{}, err + } + m := int64(i) + major = &m } - major = &i if len(number) == 2 && number[1] != "*" { - i, err := strconv.ParseInt(number[1], 10, 64) + i, err := strconv.ParseUint(number[1], 10, 64) if err != nil { return specs.LinuxDeviceCgroup{}, err } - minor = &i + m := int64(i) + minor = &m } access = value[2] for _, c := range strings.Split(access, "") { diff --git a/pkg/specgenutil/specgenutil_test.go b/pkg/specgenutil/specgenutil_test.go index 5867b0ae0..fb2743f17 100644 --- a/pkg/specgenutil/specgenutil_test.go +++ b/pkg/specgenutil/specgenutil_test.go @@ -75,3 +75,82 @@ func TestWinPath(t *testing.T) { } } } + +func TestParseLinuxResourcesDeviceAccess(t *testing.T) { + d, err := parseLinuxResourcesDeviceAccess("a *:* rwm") + assert.Nil(t, err, "err is nil") + assert.True(t, d.Allow, "allow is true") + assert.Equal(t, d.Type, "a", "type is 'a'") + assert.Nil(t, d.Minor, "minor is nil") + assert.Nil(t, d.Major, "major is nil") + + d, err = parseLinuxResourcesDeviceAccess("b 3:* rwm") + assert.Nil(t, err, "err is nil") + assert.True(t, d.Allow, "allow is true") + assert.Equal(t, d.Type, "b", "type is 'b'") + assert.Nil(t, d.Minor, "minor is nil") + assert.NotNil(t, d.Major, "major is not nil") + assert.Equal(t, *d.Major, int64(3), "major is 3") + + d, err = parseLinuxResourcesDeviceAccess("a *:3 rwm") + assert.Nil(t, err, "err is nil") + assert.True(t, d.Allow, "allow is true") + assert.Equal(t, d.Type, "a", "type is 'a'") + assert.Nil(t, d.Major, "major is nil") + assert.NotNil(t, d.Minor, "minor is not nil") + assert.Equal(t, *d.Minor, int64(3), "minor is 3") + + d, err = parseLinuxResourcesDeviceAccess("c 1:2 rwm") + assert.Nil(t, err, "err is nil") + assert.True(t, d.Allow, "allow is true") + assert.Equal(t, d.Type, "c", "type is 'c'") + assert.NotNil(t, d.Major, "minor is not nil") + assert.Equal(t, *d.Major, int64(1), "minor is 1") + assert.NotNil(t, d.Minor, "minor is not nil") + assert.Equal(t, *d.Minor, int64(2), "minor is 2") + + _, err = parseLinuxResourcesDeviceAccess("q *:* rwm") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a a:* rwm") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a *:a rwm") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a *:* abc") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("* *:* *") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("* *:a2 *") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("*") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("*:*") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a *:*") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a *:*") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a 12a:* r") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a a12:* r") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a 0x1:* r") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a -2:* r") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a *:-3 r") + assert.NotNil(t, err, "err is not nil") +} diff --git a/pkg/specgenutil/volumes.go b/pkg/specgenutil/volumes.go index 50d745380..016166a20 100644 --- a/pkg/specgenutil/volumes.go +++ b/pkg/specgenutil/volumes.go @@ -605,7 +605,7 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) { // Parse the arguments into an image volume. An image volume is a volume based // on a container image. The container image is first mounted on the host and // is then bind-mounted into the container. An ImageVolume is always mounted -// read only. +// read-only. func getImageVolume(args []string) (*specgen.ImageVolume, error) { newVolume := new(specgen.ImageVolume) diff --git a/podman.spec.rpkg b/podman.spec.rpkg index c9127c2d9..30653b658 100644 --- a/podman.spec.rpkg +++ b/podman.spec.rpkg @@ -226,13 +226,13 @@ done %{_unitdir}/%{name}.service %{_unitdir}/%{name}.socket %{_unitdir}/%{name}-restart.service -%{_unitdir}/%{name}-play-kube@.service +%{_unitdir}/%{name}-kube@.service %{_userunitdir}/%{name}-auto-update.service %{_userunitdir}/%{name}-auto-update.timer %{_userunitdir}/%{name}.service %{_userunitdir}/%{name}.socket %{_userunitdir}/%{name}-restart.service -%{_userunitdir}/%{name}-play-kube@.service +%{_userunitdir}/%{name}-kube@.service %{_tmpfilesdir}/%{name}.conf %if 0%{?fedora} >= 36 %{_modulesloaddir}/%{name}-iptables.conf diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 261db8a9a..68b35acf5 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -1042,18 +1042,15 @@ var IPRegex = `(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01 // digShort execs into the given container and does a dig lookup with a timeout // backoff. If it gets a response, it ensures that the output is in the correct // format and iterates a string array for match -func digShort(container, lookupName string, matchNames []string, p *PodmanTestIntegration) { +func digShort(container, lookupName, expectedIP string, p *PodmanTestIntegration) { digInterval := time.Millisecond * 250 for i := 0; i < 6; i++ { time.Sleep(digInterval * time.Duration(i)) dig := p.Podman([]string{"exec", container, "dig", "+short", lookupName}) dig.WaitWithDefaultTimeout() - if dig.ExitCode() == 0 { - output := dig.OutputToString() - Expect(output).To(MatchRegexp(IPRegex)) - for _, name := range matchNames { - Expect(output).To(Equal(name)) - } + output := dig.OutputToString() + if dig.ExitCode() == 0 && output != "" { + Expect(output).To(Equal(expectedIP)) // success return } diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index 61f2b3a1c..de4e4bfac 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -2507,7 +2507,7 @@ spec: Expect(kube).To(ExitWithError()) }) - It("podman play kube test with read only HostPath volume", func() { + It("podman play kube test with read-only HostPath volume", func() { hostPathLocation := filepath.Join(tempdir, "file") f, err := os.Create(hostPathLocation) Expect(err).To(BeNil()) diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index a48193e90..e463862f5 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -899,27 +899,6 @@ ENTRYPOINT ["sleep","99999"] }) - It("podman pod create --device-read-bps", func() { - SkipIfRootless("Cannot create devices in /dev in rootless mode") - SkipIfRootlessCgroupsV1("Setting device-read-bps not supported on cgroupv1 for rootless users") - - podName := "testPod" - session := podmanTest.Podman([]string{"pod", "create", "--device-read-bps", "/dev/zero:1mb", "--name", podName}) - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) - - if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--rm", "--pod", podName, ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) - } else { - session = podmanTest.Podman([]string{"run", "--rm", "--pod", podName, ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"}) - } - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) - if !CGROUPSV2 { - Expect(session.OutputToString()).To(ContainSubstring("1048576")) - } - }) - It("podman pod create --volumes-from", func() { volName := "testVol" volCreate := podmanTest.Podman([]string{"volume", "create", volName}) diff --git a/test/e2e/run_aardvark_test.go b/test/e2e/run_aardvark_test.go index 25eb8b538..4a5800d04 100644 --- a/test/e2e/run_aardvark_test.go +++ b/test/e2e/run_aardvark_test.go @@ -53,7 +53,7 @@ var _ = Describe("Podman run networking", func() { cip := ctrIP.OutputToString() Expect(cip).To(MatchRegexp(IPRegex)) - digShort(cid, "aone", []string{cip}, podmanTest) + digShort(cid, "aone", cip, podmanTest) reverseLookup := podmanTest.Podman([]string{"exec", cid, "dig", "+short", "-x", cip}) reverseLookup.WaitWithDefaultTimeout() @@ -94,9 +94,9 @@ var _ = Describe("Podman run networking", func() { cip2 := ctrIP2.OutputToString() Expect(cip2).To(MatchRegexp(IPRegex)) - digShort("aone", "atwo", []string{cip2}, podmanTest) + digShort("aone", "atwo", cip2, podmanTest) - digShort("atwo", "aone", []string{cip1}, podmanTest) + digShort("atwo", "aone", cip1, podmanTest) reverseLookup12 := podmanTest.Podman([]string{"exec", cid1, "dig", "+short", "-x", cip2}) reverseLookup12.WaitWithDefaultTimeout() @@ -143,17 +143,17 @@ var _ = Describe("Podman run networking", func() { cip2 := ctrIP2.OutputToString() Expect(cip2).To(MatchRegexp(IPRegex)) - digShort("aone", "atwo", []string{cip2}, podmanTest) + digShort("aone", "atwo", cip2, podmanTest) - digShort("aone", "alias_a2", []string{cip2}, podmanTest) + digShort("aone", "alias_a2", cip2, podmanTest) - digShort("aone", "alias_2a", []string{cip2}, podmanTest) + digShort("aone", "alias_2a", cip2, podmanTest) - digShort("atwo", "aone", []string{cip1}, podmanTest) + digShort("atwo", "aone", cip1, podmanTest) - digShort("atwo", "alias_a1", []string{cip1}, podmanTest) + digShort("atwo", "alias_a1", cip1, podmanTest) - digShort("atwo", "alias_1a", []string{cip1}, podmanTest) + digShort("atwo", "alias_1a", cip1, podmanTest) }) @@ -250,13 +250,13 @@ var _ = Describe("Podman run networking", func() { cipA2B22 := ctrIPA2B22.OutputToString() Expect(cipA2B22).To(MatchRegexp(IPRegex)) - digShort("aone", "atwobtwo", []string{cipA2B21}, podmanTest) + digShort("aone", "atwobtwo", cipA2B21, podmanTest) - digShort("bone", "atwobtwo", []string{cipA2B22}, podmanTest) + digShort("bone", "atwobtwo", cipA2B22, podmanTest) - digShort("atwobtwo", "aone", []string{cipA1}, podmanTest) + digShort("atwobtwo", "aone", cipA1, podmanTest) - digShort("atwobtwo", "bone", []string{cipB1}, podmanTest) + digShort("atwobtwo", "bone", cipB1, podmanTest) }) It("Aardvark Test 6: Three subnets, first container on 1/2 and second on 2/3, w/ network aliases", func() { @@ -304,10 +304,9 @@ var _ = Describe("Podman run networking", func() { Expect(ctrIPCB2).Should(Exit(0)) cipCB2 := ctrIPCB2.OutputToString() - digShort("aone", "testB2_nw", []string{cipCB2}, podmanTest) - - digShort("cone", "testB1_nw", []string{cipAB1}, podmanTest) + digShort("aone", "testB2_nw", cipCB2, podmanTest) + digShort("cone", "testB1_nw", cipAB1, podmanTest) }) }) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 828e92170..42b01bdcc 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1084,7 +1084,7 @@ USER mail`, BB) Expect(session).Should(Exit(0)) ctrID := session.OutputToString() - // check that the read only option works + // check that the read-only option works session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro", ALPINE, "touch", mountpoint + "abc.txt"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(1)) @@ -1108,13 +1108,13 @@ USER mail`, BB) Expect(session).Should(Exit(125)) Expect(session.ErrorToString()).To(ContainSubstring("cannot set :z more than once in mount options")) - // create new read only volume + // create new read-only volume session = podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint + ":ro", ALPINE, "cat", mountpoint + filename}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) ctrID = session.OutputToString() - // check if the original volume was mounted as read only that --volumes-from also mount it as read only + // check if the original volume was mounted as read-only that --volumes-from also mount it as read-only session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "touch", mountpoint + "abc.txt"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(1)) diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index 8cc2a68de..5fcf340d4 100644 --- a/test/e2e/run_volume_test.go +++ b/test/e2e/run_volume_test.go @@ -678,6 +678,15 @@ VOLUME /test/`, ALPINE) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + // Test overlay mount when lowerdir is relative path. + f, err = os.Create("hello") + Expect(err).To(BeNil(), "os.Create") + f.Close() + session = podmanTest.Podman([]string{"run", "--rm", "-v", ".:/app:O", ALPINE, "ls", "/app"}) + session.WaitWithDefaultTimeout() + Expect(session.OutputToString()).To(ContainSubstring("hello")) + Expect(session).Should(Exit(0)) + // Make sure modifications in container do not show up on host session = podmanTest.Podman([]string{"run", "--rm", "-v", volumeFlag, ALPINE, "touch", "/run/test/container"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/volume_create_test.go b/test/e2e/volume_create_test.go index 499283cab..7a975f6a5 100644 --- a/test/e2e/volume_create_test.go +++ b/test/e2e/volume_create_test.go @@ -162,4 +162,19 @@ var _ = Describe("Podman volume create", func() { Expect(inspectOpts).Should(Exit(0)) Expect(inspectOpts.OutputToString()).To(Equal(optionStrFormatExpect)) }) + + It("podman create volume with o=timeout", func() { + volName := "testVol" + timeout := 10 + timeoutStr := "10" + session := podmanTest.Podman([]string{"volume", "create", "--opt", fmt.Sprintf("o=timeout=%d", timeout), volName}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + inspectTimeout := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .Timeout }}", volName}) + inspectTimeout.WaitWithDefaultTimeout() + Expect(inspectTimeout).Should(Exit(0)) + Expect(inspectTimeout.OutputToString()).To(Equal(timeoutStr)) + + }) }) diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 56cf4f266..b3e3cef00 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -730,7 +730,7 @@ EOF run_podman 125 run --device-cgroup-rule="x 7:* rmw" --rm $IMAGE is "$output" "Error: invalid device type in device-access-add: x" run_podman 125 run --device-cgroup-rule="a a:* rmw" --rm $IMAGE - is "$output" "Error: strconv.ParseInt: parsing \"a\": invalid syntax" + is "$output" "Error: strconv.ParseUint: parsing \"a\": invalid syntax" } @test "podman run closes stdin" { diff --git a/test/system/060-mount.bats b/test/system/060-mount.bats index 2735d2afd..4498e675f 100644 --- a/test/system/060-mount.bats +++ b/test/system/060-mount.bats @@ -87,7 +87,7 @@ load helpers # Run a container with an image mount run_podman run --rm --mount type=image,src=$IMAGE,dst=/image-mount $IMAGE diff /etc/os-release /image-mount/etc/os-release - # Make sure the mount is read only + # Make sure the mount is read-only run_podman 1 run --rm --mount type=image,src=$IMAGE,dst=/image-mount $IMAGE touch /image-mount/read-only is "$output" "touch: /image-mount/read-only: Read-only file system" diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats index 92d3966be..0e522b34d 100644 --- a/test/system/200-pod.bats +++ b/test/system/200-pod.bats @@ -479,21 +479,25 @@ spec: fi local name1="resources1" - run_podman --cgroup-manager=systemd pod create --name=$name1 --cpus=5 - run_podman --cgroup-manager=systemd pod start $name1 + run_podman --cgroup-manager=systemd pod create --name=$name1 --cpus=5 --memory=10m + run_podman --cgroup-manager=systemd pod start $name1 run_podman pod inspect --format '{{.CgroupPath}}' $name1 local path1="$output" local actual1=$(< /sys/fs/cgroup/$path1/cpu.max) is "$actual1" "500000 100000" "resource limits set properly" + local actual2=$(< /sys/fs/cgroup/$path1/memory.max) + is "$actual2" "10485760" "resource limits set properly" run_podman pod --cgroup-manager=systemd rm -f $name1 local name2="resources2" - run_podman --cgroup-manager=cgroupfs pod create --cpus=5 --name=$name2 + run_podman --cgroup-manager=cgroupfs pod create --cpus=5 --memory=10m --name=$name2 run_podman --cgroup-manager=cgroupfs pod start $name2 run_podman pod inspect --format '{{.CgroupPath}}' $name2 local path2="$output" local actual2=$(< /sys/fs/cgroup/$path2/cpu.max) is "$actual2" "500000 100000" "resource limits set properly" + local actual2=$(< /sys/fs/cgroup/$path2/memory.max) + is "$actual2" "10485760" "resource limits set properly" run_podman --cgroup-manager=cgroupfs pod rm $name2 } diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats index e251e8a6d..fc3c33975 100644 --- a/test/system/250-systemd.bats +++ b/test/system/250-systemd.bats @@ -295,12 +295,12 @@ LISTEN_FDNAMES=listen_fdnames" | sort) run_podman network rm -f $netname } -@test "podman-play-kube@.service template" { +@test "podman-kube@.service template" { skip_if_remote "systemd units do not work with remote clients" # If running from a podman source directory, build and use the source # version of the play-kube-@ unit file - unit_name="podman-play-kube@.service" + unit_name="podman-kube@.service" unit_file="contrib/systemd/system/${unit_name}" if [[ -e ${unit_file}.in ]]; then echo "# [Building & using $unit_name from source]" >&3 @@ -329,7 +329,7 @@ spec: EOF # Dispatch the YAML file - service_name="podman-play-kube@$(systemd-escape $yaml_source).service" + service_name="podman-kube@$(systemd-escape $yaml_source).service" systemctl start $service_name systemctl is-active $service_name diff --git a/test/testvol/util.go b/test/testvol/util.go index 7a0aeba86..b50bb3afb 100644 --- a/test/testvol/util.go +++ b/test/testvol/util.go @@ -25,5 +25,5 @@ func getPluginName(pathOrName string) string { func getPlugin(sockNameOrPath string) (*plugin.VolumePlugin, error) { path := getSocketPath(sockNameOrPath) name := getPluginName(sockNameOrPath) - return plugin.GetVolumePlugin(name, path) + return plugin.GetVolumePlugin(name, path, 0) } diff --git a/troubleshooting.md b/troubleshooting.md index 05685c906..a383b83b9 100644 --- a/troubleshooting.md +++ b/troubleshooting.md @@ -663,7 +663,7 @@ $ podman run --rm --rootfs /path/to/rootfs true The command above will create all the missing directories needed to run the container. -After that, it can be used in read only mode, by multiple containers at the same time: +After that, it can be used in read-only mode, by multiple containers at the same time: ```console $ podman run --read-only --rootfs /path/to/rootfs .... diff --git a/utils/utils_supported.go b/utils/utils_supported.go index c2dcc4631..6378212b6 100644 --- a/utils/utils_supported.go +++ b/utils/utils_supported.go @@ -137,7 +137,7 @@ func moveUnderCgroup(cgroup, subtree string, processes []uint32) error { } // root cgroup, skip it - if parts[2] == "/" { + if parts[2] == "/" && !(unifiedMode && parts[1] == "") { continue } diff --git a/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go b/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go index a45358f9b..ee9f584de 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go @@ -152,10 +152,10 @@ func resourcesToProps(res *configs.Resources) (map[string]uint64, map[string]str // Mem if res.Memory != 0 { - iMap["MemoryMax"] = res.Memory + uMap["MemoryMax"] = uint64(res.Memory) } if res.MemorySwap != 0 { - iMap["MemorySwapMax"] = res.MemorySwap + uMap["MemorySwapMax"] = uint64(res.MemorySwap) } // Blkio diff --git a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go index 3712afc71..0db77879c 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go +++ b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go @@ -221,6 +221,9 @@ func DefaultProfile() *Seccomp { "ipc", "keyctl", "kill", + "landlock_add_rule", + "landlock_create_ruleset", + "landlock_restrict_self", "lchown", "lchown32", "lgetxattr", diff --git a/vendor/github.com/containers/common/pkg/seccomp/seccomp.json b/vendor/github.com/containers/common/pkg/seccomp/seccomp.json index 442632e7d..18674db4d 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/seccomp.json +++ b/vendor/github.com/containers/common/pkg/seccomp/seccomp.json @@ -228,6 +228,9 @@ "ipc", "keyctl", "kill", + "landlock_add_rule", + "landlock_create_ruleset", + "landlock_restrict_self", "lchown", "lchown32", "lgetxattr", diff --git a/vendor/modules.txt b/vendor/modules.txt index 3e8657bc4..aaddcaeb0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -111,7 +111,7 @@ github.com/containers/buildah/pkg/rusage github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/util -# github.com/containers/common v0.48.1-0.20220628131511-a8336c1613fe +# github.com/containers/common v0.48.1-0.20220630172158-178929cf063e ## explicit github.com/containers/common/libimage github.com/containers/common/libimage/define |