diff options
60 files changed, 766 insertions, 182 deletions
@@ -185,6 +185,10 @@ ifdef HOMEBREW_PREFIX endif endif +# For building pause/pause.c +GCC ?= gcc +PAUSE_CFLAGS = -Os -static -Wall -Werror -DVERSION=v$(RELEASE_VERSION) + ### ### Primary entry-point targets ### @@ -196,7 +200,7 @@ default: all all: binaries docs .PHONY: binaries -binaries: podman podman-remote rootlessport ## Build podman, podman-remote and rootlessport binaries +binaries: podman podman-remote rootlessport pause # Extract text following double-# for targets, as their description for # the `help` target. Otherwise These simple-substitutions are resolved @@ -374,6 +378,12 @@ bin/rootlessport: .gopathok $(SOURCES) go.mod go.sum .PHONY: rootlessport rootlessport: bin/rootlessport +bin/pause: pause/pause.c + $(GCC) $(PAUSE_CFLAGS) pause/pause.c -o bin/pause + +.PHONY: pause +pause: bin/pause + ### ### Secondary binary-build targets ### @@ -733,7 +743,7 @@ install.remote-nobuild: install.remote: podman-remote install.remote-nobuild .PHONY: install.bin-nobuild -install.bin-nobuild: +install.bin-nobuild: install.pause install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(BINDIR) install ${SELINUXOPT} -m 755 bin/podman $(DESTDIR)$(BINDIR)/podman test -z "${SELINUXOPT}" || chcon --verbose --reference=$(DESTDIR)$(BINDIR)/podman bin/podman @@ -787,8 +797,10 @@ install.docker-docs-nobuild: .PHONY: install.docker-docs install.docker-docs: docker-docs install.docker-docs-nobuild -.PHONY: install.docker-full -install.docker-full: install.docker install.docker-docs +.PHONY: install.pause +install.pause: pause + install ${SELINUXOPT} -m 755 -d $(DESTDIR)$(LIBEXECPODMAN)/pause + install ${SELINUXOPT} -m 755 bin/pause $(DESTDIR)$(LIBEXECPODMAN)/pause/pause .PHONY: install.systemd ifneq (,$(findstring systemd,$(BUILDTAGS))) @@ -819,6 +831,9 @@ else install.systemd: endif +.PHONY: install.pause +install.pause: pause + .PHONY: install.tools install.tools: .install.goimports .install.gitvalidation .install.md2man .install.ginkgo .install.golangci-lint .install.bats ## Install needed tools diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index 6270bad16..fbc8fb8ab 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -5,6 +5,7 @@ import ( "github.com/containers/common/pkg/auth" "github.com/containers/common/pkg/completion" + commonFlag "github.com/containers/common/pkg/flag" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/domain/entities" @@ -589,12 +590,9 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(timeoutFlagName, completion.AutocompleteNone) - // Flag for TLS verification, so that `run` and `create` commands can make use of it. - // Make sure to use `=` while using this flag i.e `--tls-verify=false/true` - tlsVerifyFlagName := "tls-verify" - createFlags.BoolVar( + commonFlag.OptionalBoolFlag(createFlags, &cf.TLSVerify, - tlsVerifyFlagName, true, + "tls-verify", "Require HTTPS and verify certificates when contacting registries for pulling images", ) diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index bfeeb7ebe..d35c1a192 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -303,6 +303,11 @@ func PullImage(imageName string, cliVals entities.ContainerCreateOptions) (strin } } + skipTLSVerify := types.OptionalBoolUndefined + if cliVals.TLSVerify.Present() { + skipTLSVerify = types.NewOptionalBool(!cliVals.TLSVerify.Value()) + } + pullReport, pullErr := registry.ImageEngine().Pull(registry.GetContext(), imageName, entities.ImagePullOptions{ Authfile: cliVals.Authfile, Quiet: cliVals.Quiet, @@ -311,7 +316,7 @@ func PullImage(imageName string, cliVals entities.ContainerCreateOptions) (strin Variant: cliVals.Variant, SignaturePolicy: cliVals.SignaturePolicy, PullPolicy: pullPolicy, - SkipTLSVerify: types.NewOptionalBool(!cliVals.TLSVerify), // If Flag changed for TLS Verification + SkipTLSVerify: skipTLSVerify, }) if pullErr != nil { return "", pullErr @@ -372,15 +377,10 @@ func createPodIfNecessary(s *specgen.SpecGenerator, netOpts *entities.NetOptions } infraOpts := entities.ContainerCreateOptions{ImageVolume: "bind", Net: netOpts, Quiet: true} - rawImageName := config.DefaultInfraImage - name, err := PullImage(rawImageName, infraOpts) - if err != nil { - fmt.Println(err) - } - imageName := name + imageName := config.DefaultInfraImage podGen.InfraImage = imageName podGen.InfraContainerSpec = specgen.NewSpecGenerator(imageName, false) - podGen.InfraContainerSpec.RawImageName = rawImageName + podGen.InfraContainerSpec.RawImageName = imageName podGen.InfraContainerSpec.NetworkOptions = podGen.NetworkOptions err = specgenutil.FillOutSpecGen(podGen.InfraContainerSpec, &infraOpts, []string{}) if err != nil { diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go index 7e5459e08..d569f4db0 100644 --- a/cmd/podman/machine/list.go +++ b/cmd/podman/machine/list.go @@ -48,6 +48,7 @@ type machineReporter struct { Created string Running bool LastUp string + Stream string VMType string CPUs uint64 Memory string @@ -153,6 +154,13 @@ func strUint(u uint64) string { return strconv.FormatUint(u, 10) } +func streamName(imageStream string) string { + if imageStream == "" { + return "default" + } + return imageStream +} + func toMachineFormat(vms []*machine.ListResponse) ([]*machineReporter, error) { cfg, err := config.ReadCustomConfig() if err != nil { @@ -167,6 +175,7 @@ func toMachineFormat(vms []*machine.ListResponse) ([]*machineReporter, error) { response.Running = vm.Running response.LastUp = strTime(vm.LastUp) response.Created = strTime(vm.CreatedAt) + response.Stream = streamName(vm.Stream) response.VMType = vm.VMType response.CPUs = vm.CPUs response.Memory = strUint(vm.Memory * units.MiB) diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go index 7c2c72171..0a0d43b53 100644 --- a/cmd/podman/pods/create.go +++ b/cmd/podman/pods/create.go @@ -242,16 +242,6 @@ func create(cmd *cobra.Command, args []string) error { } if createOptions.Infra { rawImageName = img - if !infraOptions.RootFS { - curr := infraOptions.Quiet - infraOptions.Quiet = true - name, err := containers.PullImage(imageName, infraOptions) - if err != nil { - fmt.Println(err) - } - imageName = name - infraOptions.Quiet = curr - } podSpec.InfraImage = imageName if infraOptions.Entrypoint != nil { createOptions.InfraCommand = infraOptions.Entrypoint diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go index 4502b156c..3443978d6 100644 --- a/cmd/podman/system/version.go +++ b/cmd/podman/system/version.go @@ -20,7 +20,7 @@ var ( versionCommand = &cobra.Command{ Use: "version [options]", Args: validate.NoArgs, - Short: "Display the Podman Version Information", + Short: "Display the Podman version information", RunE: version, ValidArgsFunction: completion.AutocompleteNone, } @@ -67,7 +67,7 @@ func version(cmd *cobra.Command, args []string) error { } if err := tmpl.Execute(w, versions); err != nil { // On Failure, assume user is using older version of podman version --format and check client - row = strings.Replace(row, ".Server.", ".", 1) + row = strings.ReplaceAll(row, ".Server.", ".") tmpl, err := report.NewTemplate("version 1.0.0").Parse(row) if err != nil { return err diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh index 9a7bfba8f..9b7c613f5 100644 --- a/contrib/cirrus/lib.sh +++ b/contrib/cirrus/lib.sh @@ -143,6 +143,8 @@ setup_rootless() { local rootless_uid local rootless_gid local env_var_val + local akfilepath + local sshcmd # Only do this once; established by setup_environment.sh # shellcheck disable=SC2154 @@ -169,24 +171,25 @@ setup_rootless() { ssh-keygen -P "" -f "$HOME/.ssh/id_rsa" msg "Allowing ssh key for $ROOTLESS_USER" + akfilepath="/home/$ROOTLESS_USER/.ssh/authorized_keys" (umask 077 && mkdir "/home/$ROOTLESS_USER/.ssh") chown -R $ROOTLESS_USER:$ROOTLESS_USER "/home/$ROOTLESS_USER/.ssh" install -o $ROOTLESS_USER -g $ROOTLESS_USER -m 0600 \ - "$HOME/.ssh/id_rsa.pub" "/home/$ROOTLESS_USER/.ssh/authorized_keys" + "$HOME/.ssh/id_rsa.pub" "$akfilepath" # Makes debugging easier - cat /root/.ssh/authorized_keys >> "/home/$ROOTLESS_USER/.ssh/authorized_keys" - - msg "Configuring subuid and subgid" - grep -q "${ROOTLESS_USER}" /etc/subuid || \ - echo "${ROOTLESS_USER}:$[rootless_uid * 100]:65536" | \ - tee -a /etc/subuid >> /etc/subgid + cat /root/.ssh/authorized_keys >> "$akfilepath" msg "Ensure the ssh daemon is up and running within 5 minutes" systemctl start sshd - lilto ssh $ROOTLESS_USER@localhost \ - -o UserKnownHostsFile=/dev/null \ - -o StrictHostKeyChecking=no \ - -o CheckHostIP=no true + sshcmd="ssh $ROOTLESS_USER@localhost + -o UserKnownHostsFile=/dev/null + -o StrictHostKeyChecking=no + -o CheckHostIP=no" + lilto $sshcmd true # retry until sshd is up + + msg "Configuring rootless user self-access to ssh to localhost" + $sshcmd ssh-keygen -P '""' -f "/home/$ROOTLESS_USER/.ssh/id_rsa" + cat "/home/$ROOTLESS_USER/.ssh/id_rsa" >> "$akfilepath" } install_test_configs() { diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh index 22a66dd08..8ef2a6e64 100755 --- a/contrib/cirrus/runner.sh +++ b/contrib/cirrus/runner.sh @@ -117,6 +117,7 @@ exec_container() { set -x # shellcheck disable=SC2154 exec podman run --rm --privileged --net=host --cgroupns=host \ + -v `mktemp -d -p /var/tmp`:/tmp:Z \ -v /dev/fuse:/dev/fuse \ -v "$GOPATH:$GOPATH:Z" \ --workdir "$GOSRC" \ diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in index 295a953ef..2db8f6e67 100644 --- a/contrib/spec/podman.spec.in +++ b/contrib/spec/podman.spec.in @@ -528,6 +528,7 @@ export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath} %{_usr}/lib/tmpfiles.d/podman.conf %dir %{_libexecdir}/%{name} %{_libexecdir}/%{name}/rootlessport +%{_libexecdir}/%{name}/pause/pause %if 0%{?with_devel} %files -n libpod-devel -f devel.file-list diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index ea9042861..3ff736adb 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -638,6 +638,16 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container. + Options specific to devpts: + + · uid: UID of the file owner (default 0). + + · gid: GID of the file owner (default 0). + + · mode: permission mask for the file (default 600). + + · max: maximum number of PTYs (default 1048576). + #### **--name**=*name* Assign a name to the container diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md index f1fbd56ee..45f798cd6 100644 --- a/docs/source/markdown/podman-machine-init.1.md +++ b/docs/source/markdown/podman-machine-init.1.md @@ -18,6 +18,10 @@ tied to the Linux kernel. SSH keys are automatically generated to access the VM, and system connections to the root account and a user account inside the VM are added. +By default, the VM distribution is [Fedora CoreOS](https://getfedora.org/en/coreos?stream=testing). +Fedora CoreOS upgrades come out every 14 days and are detected and installed automatically. The VM will be rebooted during the upgrade. +For more information on updates and advanced configuration, please see the FCOS update docs [here](https://docs.fedoraproject.org/en-US/fedora-coreos/auto-updates/) and [here](https://coreos.github.io/zincati/usage/updates-strategy/). + ## OPTIONS #### **--cpus**=*number* diff --git a/docs/source/markdown/podman-machine-ssh.1.md b/docs/source/markdown/podman-machine-ssh.1.md index c4c732819..dd592622f 100644 --- a/docs/source/markdown/podman-machine-ssh.1.md +++ b/docs/source/markdown/podman-machine-ssh.1.md @@ -9,7 +9,7 @@ podman\-machine\-ssh - SSH into a virtual machine ## DESCRIPTION SSH into a Podman-managed virtual machine and optionally execute a command -on the virtual machine. Unless using the default virtual machine, the +on the virtual machine. Unless using the default virtual machine, the first argument must be the virtual machine name. The optional command to execute can then follow. If no command is provided, an interactive session with the virtual machine is established. diff --git a/docs/source/markdown/podman-pause.1.md b/docs/source/markdown/podman-pause.1.md index 123362822..90ea1e32e 100644 --- a/docs/source/markdown/podman-pause.1.md +++ b/docs/source/markdown/podman-pause.1.md @@ -31,7 +31,7 @@ podman pause 860a4b23 Pause all **running** containers. ``` -podman stop -a +podman pause -a ``` ## SEE ALSO diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index 08ac19b8b..061727559 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -112,7 +112,7 @@ The command that will be run to start the infra container. Default: "/pause". #### **--infra-image**=*image* -The image that will be created for the infra container. Default: "k8s.gcr.io/pause:3.1". +The custom image that will be used for the infra container. Unless specified, Podman builds a custom local image which does not require pulling down an image. #### **--infra-name**=*name* diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index b5f3130fe..a1170253f 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -665,6 +665,16 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container. + Options specific to devpts: + + · uid: UID of the file owner (default 0). + + · gid: GID of the file owner (default 0). + + · mode: permission mask for the file (default 600). + + · max: maximum number of PTYs (default 1048576). + #### **--name**=*name* Assign a name to the container. @@ -12,7 +12,7 @@ require ( github.com/containernetworking/cni v1.0.1 github.com/containernetworking/plugins v1.0.1 github.com/containers/buildah v1.23.1 - github.com/containers/common v0.46.1-0.20211008123044-d846f5aaec0e + github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f github.com/containers/conmon v2.0.20+incompatible github.com/containers/image/v5 v5.16.1 github.com/containers/ocicrypt v1.1.2 @@ -31,7 +31,7 @@ require ( github.com/dtylman/scp v0.0.0-20181017070807-f3000a34aef4 github.com/fsnotify/fsnotify v1.5.1 github.com/ghodss/yaml v1.0.0 - github.com/godbus/dbus/v5 v5.0.5 + github.com/godbus/dbus/v5 v5.0.6 github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf github.com/google/uuid v1.3.0 github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 @@ -68,6 +68,6 @@ require ( golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b - k8s.io/api v0.22.2 - k8s.io/apimachinery v0.22.2 + k8s.io/api v0.22.3 + k8s.io/apimachinery v0.22.3 ) @@ -258,8 +258,8 @@ github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNB github.com/containers/buildah v1.23.1 h1:Tpc9DsRuU+0Oofewpxb6OJVNQjCu7yloN/obUqzfDTY= github.com/containers/buildah v1.23.1/go.mod h1:4WnrN0yrA7ab0ppgunixu2WM1rlD2rG8QLJAKbEkZlQ= github.com/containers/common v0.44.2/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo= -github.com/containers/common v0.46.1-0.20211008123044-d846f5aaec0e h1:lYazDued7KBcMq5IJzRIbX47SSLRg/yYxvM/P9LaVhE= -github.com/containers/common v0.46.1-0.20211008123044-d846f5aaec0e/go.mod h1:ggZks97KCmjBcHvNTCyLc17SqdjSYoeexW7rnRt9H9Y= +github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f h1:jFFIV8QvsPgwkJHh3tjfREFRwSeMq5M8lt8vklkZaOk= +github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f/go.mod h1:pVvmLTLCOZE300e4rex/QDmpnRmEM/5aZ/YfCkkjgZo= 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.16.0/go.mod h1:XgTpfAPLRGOd1XYyCU5cISFr777bLmOerCSpt/v7+Q4= @@ -336,7 +336,6 @@ github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BU github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.10+incompatible h1:GKkP0T7U4ks6X3lmmHKC2QDprnpRJor2Z5a8m62R9ZM= github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= @@ -425,8 +424,8 @@ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68Fp github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.5 h1:9Eg0XUhQxtkV8ykTMKtMMYY72g4NgxtRq4jgh4Ih5YM= -github.com/godbus/dbus/v5 v5.0.5/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= @@ -1506,13 +1505,13 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= -k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= +k8s.io/api v0.22.3 h1:wOoES2GoSkUsdped2RB4zYypPqWtvprGoKCENTOOjP4= +k8s.io/api v0.22.3/go.mod h1:azgiXFiXqiWyLCfI62/eYBOu19rj2LKmIhFPP4+33fs= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= -k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/apimachinery v0.22.3 h1:mrvBG5CZnEfwgpVqWcrRKvdsYECTrhAR6cApAgdsflk= +k8s.io/apimachinery v0.22.3/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= diff --git a/libpod/container_internal.go b/libpod/container_internal.go index d4384b791..b9805faa3 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1513,8 +1513,8 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { mountPoint := c.config.Rootfs // Check if overlay has to be created on top of Rootfs if c.config.RootfsOverlay { - overlayDest := c.runtime.store.GraphRoot() - contentDir, err := overlay.GenerateStructure(c.runtime.store.GraphRoot(), c.ID(), "rootfs", c.RootUID(), c.RootGID()) + overlayDest := c.runtime.RunRoot() + contentDir, err := overlay.GenerateStructure(overlayDest, c.ID(), "rootfs", c.RootUID(), c.RootGID()) if err != nil { return "", errors.Wrapf(err, "rootfs-overlay: failed to create TempDir in the %s directory", overlayDest) } @@ -1739,11 +1739,11 @@ func (c *Container) cleanupStorage() error { // umount rootfs overlay if it was created if c.config.RootfsOverlay { - overlayBasePath := filepath.Dir(c.config.StaticDir) - overlayBasePath = filepath.Join(overlayBasePath, "rootfs") + overlayBasePath := filepath.Dir(c.state.Mountpoint) if err := overlay.Unmount(overlayBasePath); err != nil { - // If the container can't remove content report the error - logrus.Errorf("Failed to cleanup overlay mounts for %s: %v", c.ID(), err) + if cleanupErr != nil { + logrus.Errorf("Failed to cleanup overlay mounts for %s: %v", c.ID(), err) + } cleanupErr = err } } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index d3151f7e0..2fd519990 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1546,6 +1546,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti logrus.Debugf("Restored container %s", c.ID()) c.state.State = define.ContainerStateRunning + c.state.Checkpointed = false if !options.Keep { // Delete all checkpoint related files. At this point, in theory, all files diff --git a/libpod/container_path_resolution.go b/libpod/container_path_resolution.go index bb2ef1a73..7db23b783 100644 --- a/libpod/container_path_resolution.go +++ b/libpod/container_path_resolution.go @@ -161,7 +161,7 @@ func isPathOnBindMount(c *Container, containerPath string) bool { if cleanedContainerPath == filepath.Clean(m.Destination) { return true } - for dest := m.Destination; dest != "/"; dest = filepath.Dir(dest) { + for dest := m.Destination; dest != "/" && dest != "."; dest = filepath.Dir(dest) { if cleanedContainerPath == dest { return true } diff --git a/libpod/kube.go b/libpod/kube.go index 02ac8ed98..ad5acea78 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/containers/common/pkg/config" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/libpod/network/types" "github.com/containers/podman/v3/pkg/env" @@ -468,11 +469,23 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, [] kubeContainer.Name = removeUnderscores(c.Name()) _, image := c.Image() + + // The infra container may have been created with an overlay root FS + // instead of an infra image. If so, set the imageto the default K8s + // pause one and make sure it's in the storage by pulling it down if + // missing. + if image == "" && c.IsInfra() { + image = config.DefaultInfraImage + if _, err := c.runtime.libimageRuntime.Pull(ctx, image, config.PullPolicyMissing, nil); err != nil { + return kubeContainer, nil, nil, nil, err + } + } + kubeContainer.Image = image kubeContainer.Stdin = c.Stdin() img, _, err := c.runtime.libimageRuntime.LookupImage(image, nil) if err != nil { - return kubeContainer, kubeVolumes, nil, annotations, err + return kubeContainer, kubeVolumes, nil, annotations, fmt.Errorf("looking up image %q of container %q: %w", image, c.ID(), err) } imgData, err := img.Inspect(ctx, nil) if err != nil { diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 1719b2dfa..db906fabb 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -1016,7 +1016,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co } if ctr.config.CgroupsMode == cgroupSplit { - if err := utils.MoveUnderCgroupSubtree("supervisor"); err != nil { + if err := utils.MoveUnderCgroupSubtree("runtime"); err != nil { return err } } diff --git a/libpod/runtime.go b/libpod/runtime.go index 855f3a9f9..b01f8dd13 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -543,6 +543,8 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { return err } if became { + // Check if the pause process was created. If it was created, then + // move it to its own systemd scope. utils.MovePauseProcessToScope(pausePid) os.Exit(ret) } diff --git a/pause/pause.c b/pause/pause.c new file mode 100644 index 000000000..1e363bd7a --- /dev/null +++ b/pause/pause.c @@ -0,0 +1,69 @@ +/* +Copyright 2016 The Kubernetes Authors. +Copyright 2021 The Podman Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#define STRINGIFY(x) #x +#define VERSION_STRING(x) STRINGIFY(x) + +#ifndef VERSION +#define VERSION HEAD +#endif + +static void sigdown(int signo) { + psignal(signo, "Shutting down, got signal"); + exit(0); +} + +static void sigreap(int signo) { + while (waitpid(-1, NULL, WNOHANG) > 0) + ; +} + +int main(int argc, char **argv) { + int i; + for (i = 1; i < argc; ++i) { + if (!strcasecmp(argv[i], "-v")) { + printf("pause.c %s\n", VERSION_STRING(VERSION)); + return 0; + } + } + + if (getpid() != 1) + /* Not an error because pause sees use outside of infra containers. */ + fprintf(stderr, "Warning: pause should be the first process\n"); + + if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0) + return 1; + if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0) + return 2; + if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap, + .sa_flags = SA_NOCLDSTOP}, + NULL) < 0) + return 3; + + for (;;) + pause(); + fprintf(stderr, "Error: infinite loop terminated\n"); + return 42; +} diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go index 77d026550..1e64de0ee 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -1,15 +1,12 @@ package libpod import ( - "context" "encoding/json" "fmt" "net/http" "strings" - "github.com/containers/common/libimage" "github.com/containers/common/pkg/config" - "github.com/containers/image/v5/transports/alltransports" "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/api/handlers" @@ -67,20 +64,6 @@ func PodCreate(w http.ResponseWriter, r *http.Request) { imageName = config.DefaultInfraImage rawImageName = config.DefaultInfraImage } - curr := infraOptions.Quiet - infraOptions.Quiet = true - pullOptions := &libimage.PullOptions{} - pulledImages, err := runtime.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, pullOptions) - if err != nil { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "could not pull image")) - return - } - if _, err := alltransports.ParseImageName(imageName); err == nil { - if len(pulledImages) != 0 { - imageName = pulledImages[0].ID() - } - } - infraOptions.Quiet = curr psg.InfraImage = imageName psg.InfraContainerSpec.Image = imageName psg.InfraContainerSpec.RawImageName = rawImageName diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go index 3ba39b860..ffdb30551 100644 --- a/pkg/api/handlers/libpod/volumes.go +++ b/pkg/api/handlers/libpod/volumes.go @@ -29,12 +29,13 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { }{ // override any golang type defaults } - input := entities.VolumeCreateOptions{} if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return } + + input := entities.VolumeCreateOptions{} // decode params from body if err := json.NewDecoder(r.Body).Decode(&input); err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()")) @@ -47,9 +48,19 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { if len(input.Driver) > 0 { volumeOptions = append(volumeOptions, libpod.WithVolumeDriver(input.Driver)) } - if len(input.Label) > 0 { - volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(input.Label)) + + // Label provided for compatibility. + labels := make(map[string]string, len(input.Label)+len(input.Labels)) + for k, v := range input.Label { + labels[k] = v } + for k, v := range input.Labels { + labels[k] = v + } + if len(labels) > 0 { + volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(labels)) + } + if len(input.Options) > 0 { parsedOptions, err := parse.VolumeOptions(input.Options) if err != nil { diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 95a8b4939..e21cc2a33 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -103,7 +103,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - application/json // responses: // 200: - // $ref: "#/responses/DockerImageSummary" + // $ref: "#/responses/DockerImageSummaryResponse" // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/json"), s.APIHandler(compat.GetImages)).Methods(http.MethodGet) @@ -837,7 +837,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - application/json // responses: // 200: - // $ref: "#/responses/DockerImageSummary" + // $ref: "#/responses/LibpodImageSummaryResponse" // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/json"), s.APIHandler(libpod.GetImages)).Methods(http.MethodGet) diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go index 0fd66652e..3f8f6f9c5 100644 --- a/pkg/api/server/swagger.go +++ b/pkg/api/server/swagger.go @@ -6,6 +6,7 @@ import ( "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/entities/reports" "github.com/containers/podman/v3/pkg/errorhandling" + docker "github.com/docker/docker/api/types" ) // No such image @@ -134,9 +135,16 @@ type swagPodAlreadyStopped struct { } } -// Image summary -// swagger:response DockerImageSummary -type swagImageSummary struct { +// Image summary for compat API +// swagger:response DockerImageSummaryResponse +type swagDockerImageSummaryResponse struct { + // in:body + Body []docker.ImageSummary +} + +// Image summary for libpod API +// swagger:response LibpodImageSummaryResponse +type swagLibpodImageSummaryResponse struct { // in:body Body []entities.ImageSummary } diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go index 1debc020c..d0c090012 100644 --- a/pkg/cgroups/cgroups.go +++ b/pkg/cgroups/cgroups.go @@ -464,7 +464,7 @@ func (c *CgroupControl) CreateSystemdUnit(path string) error { // GetUserConnection returns a user connection to D-BUS func GetUserConnection(uid int) (*systemdDbus.Conn, error) { return systemdDbus.NewConnection(func() (*dbus.Conn, error) { - return dbusAuthConnection(uid, dbus.SessionBusPrivate) + return dbusAuthConnection(uid, dbus.SessionBusPrivateNoAutoStartup) }) } diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index ac5e6f410..38cdc8f2f 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -50,6 +50,7 @@ func (i *Image) Id() string { // nolint return i.ID } +// swagger:model LibpodImageSummary type ImageSummary struct { ID string `json:"Id"` ParentId string // nolint diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index a2f36eaa6..3d8579acf 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -5,6 +5,7 @@ import ( "strings" "time" + commonFlag "github.com/containers/common/pkg/flag" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/specgen" "github.com/containers/podman/v3/pkg/util" @@ -241,7 +242,7 @@ type ContainerCreateOptions struct { Sysctl []string Systemd string Timeout uint - TLSVerify bool + TLSVerify commonFlag.OptionalBool TmpFS []string TTY bool Timezone string diff --git a/pkg/domain/entities/volumes.go b/pkg/domain/entities/volumes.go index 2ecfb4446..9b2a170e2 100644 --- a/pkg/domain/entities/volumes.go +++ b/pkg/domain/entities/volumes.go @@ -78,8 +78,10 @@ type VolumeCreateOptions struct { Name string `schema:"name"` // Volume driver to use Driver string `schema:"driver"` - // User-defined key/value metadata. + // User-defined key/value metadata. Provided for compatibility Label map[string]string `schema:"label"` + // User-defined key/value metadata. Preferred field, will override Label + Labels map[string]string `schema:"labels"` // Mapping of driver options and values. Options map[string]string `schema:"opts"` } diff --git a/pkg/machine/config.go b/pkg/machine/config.go index 3ff5c7fe7..55d5dd7b4 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -57,6 +57,7 @@ type ListResponse struct { CreatedAt time.Time LastUp time.Time Running bool + Stream string VMType string CPUs uint64 Memory uint64 diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go index e211f5ea6..42d729458 100644 --- a/pkg/machine/ignition.go +++ b/pkg/machine/ignition.go @@ -304,6 +304,24 @@ machine_enabled=true }, }) + setDockerHost := `export DOCKER_HOST="unix://$(podman info -f "{{.Host.RemoteSocket.Path}}")" +` + + files = append(files, File{ + Node: Node{ + Group: getNodeGrp("root"), + Path: "/etc/profile.d/docker-host.sh", + User: getNodeUsr("root"), + }, + FileEmbedded1: FileEmbedded1{ + Append: nil, + Contents: Resource{ + Source: encodeDataURLPtr(setDockerHost), + }, + Mode: intToPtr(0644), + }, + }) + return files } diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go index 9f5f45b58..c04773450 100644 --- a/pkg/machine/qemu/config.go +++ b/pkg/machine/qemu/config.go @@ -13,6 +13,8 @@ type MachineVM struct { IdentityPath string // IgnitionFilePath is the fq path to the .ign file IgnitionFilePath string + // ImageStream is the update stream for the image + ImageStream string // ImagePath is the fq path to ImagePath string // Memory in megabytes assigned to the vm diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 727b3cda4..4d8242e39 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -143,6 +143,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) error { switch opts.ImagePath { case "testing", "next", "stable", "": // Get image as usual + v.ImageStream = opts.ImagePath dd, err := machine.NewFcosDownloader(vmtype, v.Name, opts.ImagePath) if err != nil { return err @@ -154,6 +155,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) error { default: // The user has provided an alternate image which can be a file path // or URL. + v.ImageStream = "custom" g, err := machine.NewGenericDownloader(vmtype, v.Name, opts.ImagePath) if err != nil { return err @@ -595,6 +597,7 @@ func GetVMInfos() ([]*machine.ListResponse, error) { listEntry := new(machine.ListResponse) listEntry.Name = vm.Name + listEntry.Stream = vm.ImageStream listEntry.VMType = "qemu" listEntry.CPUs = vm.CPUs listEntry.Memory = vm.Memory diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index a4027eae7..88ebc7ae3 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -2,8 +2,12 @@ package generate import ( "context" + "fmt" + "io/ioutil" "net" + "os" + buildahDefine "github.com/containers/buildah/define" "github.com/containers/common/pkg/config" "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/libpod/define" @@ -14,10 +18,102 @@ import ( "github.com/sirupsen/logrus" ) +func buildPauseImage(rt *libpod.Runtime, rtConfig *config.Config) (string, error) { + version, err := define.GetVersion() + if err != nil { + return "", err + } + imageName := fmt.Sprintf("localhost/podman-pause:%s-%d", version.Version, version.Built) + + // First check if the image has already been built. + if _, _, err := rt.LibimageRuntime().LookupImage(imageName, nil); err == nil { + return imageName, nil + } + + // NOTE: Having the pause binary in its own directory keeps the door + // open for replacing the image building with using an overlay root FS. + // The latter turned out to be complex and error prone (see #11956) but + // we may be able to come up with a proper solution at a later point in + // time. + pausePath, err := rtConfig.FindHelperBinary("pause/pause", false) + if err != nil { + return "", fmt.Errorf("finding pause binary: %w", err) + } + + buildContent := fmt.Sprintf(`FROM scratch +COPY %s /pause +ENTRYPOINT ["/pause"]`, pausePath) + + tmpF, err := ioutil.TempFile("", "pause.containerfile") + if err != nil { + return "", err + } + if _, err := tmpF.WriteString(buildContent); err != nil { + return "", err + } + if err := tmpF.Close(); err != nil { + return "", err + } + defer os.Remove(tmpF.Name()) + + buildOptions := buildahDefine.BuildOptions{ + CommonBuildOpts: &buildahDefine.CommonBuildOptions{}, + Output: imageName, + Quiet: true, + IIDFile: "/dev/null", // prevents Buildah from writing the ID on stdout + } + if _, _, err := rt.Build(context.Background(), buildOptions, tmpF.Name()); err != nil { + return "", err + } + + return imageName, nil +} + +func pullOrBuildInfraImage(p *entities.PodSpec, rt *libpod.Runtime) error { + if p.PodSpecGen.NoInfra { + return nil + } + + rtConfig, err := rt.GetConfigNoCopy() + if err != nil { + return err + } + + // NOTE: we need pull down the infra image if it was explicitly set by + // the user (or containers.conf) to the non-default one. + imageName := p.PodSpecGen.InfraImage + if imageName == "" { + imageName = rtConfig.Engine.InfraImage + } + + if imageName != config.DefaultInfraImage { + _, err := rt.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, nil) + if err != nil { + return err + } + } else { + name, err := buildPauseImage(rt, rtConfig) + if err != nil { + return fmt.Errorf("building local pause image: %w", err) + } + imageName = name + } + + p.PodSpecGen.InfraImage = imageName + p.PodSpecGen.InfraContainerSpec.RawImageName = imageName + + return nil +} + func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) { if err := p.PodSpecGen.Validate(); err != nil { return nil, err } + + if err := pullOrBuildInfraImage(p, rt); err != nil { + return nil, err + } + if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil { var err error p.PodSpecGen.InfraContainerSpec, err = MapSpec(&p.PodSpecGen) @@ -35,7 +131,6 @@ func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) { return nil, err } if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil { - p.PodSpecGen.InfraContainerSpec.ContainerCreateCommand = []string{} // we do NOT want os.Args as the command, will display the pod create cmd if p.PodSpecGen.InfraContainerSpec.Name == "" { p.PodSpecGen.InfraContainerSpec.Name = pod.ID()[:12] + "-infra" } diff --git a/pkg/specgen/generate/storage.go b/pkg/specgen/generate/storage.go index 3fde1a1b4..30248a886 100644 --- a/pkg/specgen/generate/storage.go +++ b/pkg/specgen/generate/storage.go @@ -214,9 +214,6 @@ func getImageVolumes(ctx context.Context, img *libimage.Image, s *specgen.SpecGe } for volume := range inspect.Config.Volumes { logrus.Debugf("Image has volume at %q", volume) - if err = parse.ValidateVolumeCtrDir(volume); err != nil { - return nil, nil, err - } cleanDest := filepath.Clean(volume) switch mode { case "", "anonymous": diff --git a/pkg/specgenutil/volumes.go b/pkg/specgenutil/volumes.go index 3ce96164f..184bfadf8 100644 --- a/pkg/specgenutil/volumes.go +++ b/pkg/specgenutil/volumes.go @@ -360,7 +360,7 @@ func getBindMount(args []string) (spec.Mount, error) { // Since Docker ignores this option so shall we. continue default: - return newMount, errors.Wrapf(util.ErrBadMntOption, kv[0]) + return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) } } @@ -460,7 +460,7 @@ func getTmpfsMount(args []string) (spec.Mount, error) { // Since Docker ignores this option so shall we. continue default: - return newMount, errors.Wrapf(util.ErrBadMntOption, kv[0]) + return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) } } @@ -483,6 +483,8 @@ func getDevptsMount(args []string) (spec.Mount, error) { for _, val := range args { kv := strings.SplitN(val, "=", 2) switch kv[0] { + case "uid", "gid", "mode", "ptxmode", "newinstance", "max": + newMount.Options = append(newMount.Options, val) case "target", "dst", "destination": if len(kv) == 1 { return newMount, errors.Wrapf(optionArgError, kv[0]) @@ -493,7 +495,7 @@ func getDevptsMount(args []string) (spec.Mount, error) { newMount.Destination = filepath.Clean(kv[1]) setDest = true default: - return newMount, errors.Wrapf(util.ErrBadMntOption, kv[0]) + return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) } } @@ -573,7 +575,7 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) { // Since Docker ignores this option so shall we. continue default: - return nil, errors.Wrapf(util.ErrBadMntOption, kv[0]) + return nil, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) } } @@ -624,7 +626,7 @@ func getImageVolume(args []string) (*specgen.ImageVolume, error) { // Since Docker ignores this option so shall we. continue default: - return nil, errors.Wrapf(util.ErrBadMntOption, kv[0]) + return nil, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) } } diff --git a/test/apiv2/python/rest_api/test_v2_0_0_volume.py b/test/apiv2/python/rest_api/test_v2_0_0_volume.py index f5231e17c..2156318b0 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_volume.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_volume.py @@ -7,7 +7,7 @@ from .fixtures import APITestCase class VolumeTestCase(APITestCase): - def test_volume(self): + def test_volume_crud(self): name = f"Volume_{random.getrandbits(160):x}" ls = requests.get(self.podman_url + "/v1.40/volumes") @@ -70,6 +70,71 @@ class VolumeTestCase(APITestCase): self.assertIn(name, payload["VolumesDeleted"]) self.assertGreater(payload["SpaceReclaimed"], 0) + def test_volume_label(self): + name = f"Volume_{random.getrandbits(160):x}" + expected = { + "Production": "False", + "Database": "Foxbase", + } + + create = requests.post( + self.podman_url + "/v4.0.0/libpod/volumes/create", + json={"name": name, "label": expected}, + ) + self.assertEqual(create.status_code, 201, create.text) + + inspect = requests.get(self.podman_url + f"/v4.0.0/libpod/volumes/{name}/json") + self.assertEqual(inspect.status_code, 200, inspect.text) + + volume = inspect.json() + self.assertIn("Labels", volume) + self.assertNotIn("Label", volume) + self.assertDictEqual(expected, volume["Labels"]) + + def test_volume_labels(self): + name = f"Volume_{random.getrandbits(160):x}" + expected = { + "Production": "False", + "Database": "Foxbase", + } + + create = requests.post( + self.podman_url + "/v4.0.0/libpod/volumes/create", + json={"name": name, "labels": expected}, + ) + self.assertEqual(create.status_code, 201, create.text) + + inspect = requests.get(self.podman_url + f"/v4.0.0/libpod/volumes/{name}/json") + self.assertEqual(inspect.status_code, 200, inspect.text) + + volume = inspect.json() + self.assertIn("Labels", volume) + self.assertDictEqual(expected, volume["Labels"]) + + def test_volume_label_override(self): + name = f"Volume_{random.getrandbits(160):x}" + create = requests.post( + self.podman_url + "/v4.0.0/libpod/volumes/create", + json={ + "Name": name, + "Label": { + "Database": "dbase", + }, + "Labels": { + "Database": "sqlserver", + }, + }, + ) + self.assertEqual(create.status_code, 201, create.text) + + inspect = requests.get(self.podman_url + f"/v4.0.0/libpod/volumes/{name}/json") + self.assertEqual(inspect.status_code, 200, inspect.text) + + volume = inspect.json() + self.assertIn("Labels", volume) + self.assertNotIn("Label", volume) + self.assertDictEqual({"Database": "sqlserver"}, volume["Labels"]) + if __name__ == "__main__": unittest.main() diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index d5b913743..b0b927445 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -11,7 +11,6 @@ import ( "text/template" "time" - "github.com/containers/common/pkg/config" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/util" . "github.com/containers/podman/v3/test/utils" @@ -1120,24 +1119,6 @@ var _ = Describe("Podman play kube", func() { Expect(label).To(ContainSubstring("unconfined_u:system_r:spc_t:s0")) }) - It("podman play kube should use default infra_image", func() { - err := writeYaml(checkInfraImagePodYaml, kubeYaml) - Expect(err).To(BeNil()) - - kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) - kube.WaitWithDefaultTimeout() - Expect(kube).Should(Exit(0)) - - podInspect := podmanTest.Podman([]string{"inspect", "check-infra-image", "--format", "{{ .InfraContainerID }}"}) - podInspect.WaitWithDefaultTimeout() - infraContainerID := podInspect.OutputToString() - - conInspect := podmanTest.Podman([]string{"inspect", infraContainerID, "--format", "{{ .ImageName }}"}) - conInspect.WaitWithDefaultTimeout() - infraContainerImage := conInspect.OutputToString() - Expect(infraContainerImage).To(Equal(config.DefaultInfraImage)) - }) - It("podman play kube --no-host", func() { err := writeYaml(checkInfraImagePodYaml, kubeYaml) Expect(err).To(BeNil()) diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go index b7e8309fb..7b35acd35 100644 --- a/test/e2e/push_test.go +++ b/test/e2e/push_test.go @@ -146,7 +146,7 @@ var _ = Describe("Podman push", func() { session = podmanTest.Podman([]string{"logs", "registry"}) session.WaitWithDefaultTimeout() - push := podmanTest.Podman([]string{"push", "--format=v2s2", "--creds=podmantest:test", ALPINE, "localhost:5000/tlstest"}) + push := podmanTest.Podman([]string{"push", "--tls-verify=true", "--format=v2s2", "--creds=podmantest:test", ALPINE, "localhost:5000/tlstest"}) push.WaitWithDefaultTimeout() Expect(push).To(ExitWithError()) @@ -163,7 +163,7 @@ var _ = Describe("Podman push", func() { if !IsRemote() { // remote does not support --cert-dir - push = podmanTest.Podman([]string{"push", "--creds=podmantest:test", "--cert-dir=fakedir", ALPINE, "localhost:5000/certdirtest"}) + push = podmanTest.Podman([]string{"push", "--tls-verify=true", "--creds=podmantest:test", "--cert-dir=fakedir", ALPINE, "localhost:5000/certdirtest"}) push.WaitWithDefaultTimeout() Expect(push).To(ExitWithError()) } diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 8502879ff..95660bfc9 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -188,6 +188,12 @@ var _ = Describe("Podman run", func() { run.WaitWithDefaultTimeout() Expect(run).Should(Exit(0)) Expect(podmanTest.NumberOfContainers()).To(Equal(3)) + + // Now registries.conf will be consulted where localhost:5000 + // is set to be insecure. + run = podmanTest.Podman([]string{"run", ALPINE}) + run.WaitWithDefaultTimeout() + Expect(run).Should(Exit(0)) }) It("podman run a container with a --rootfs", func() { @@ -1192,6 +1198,14 @@ USER mail`, BB) Expect(session.OutputToString()).To(ContainSubstring("devpts")) }) + It("podman run --mount type=devpts,target=/dev/pts with uid, gid and mode", func() { + // runc doesn't seem to honor uid= so avoid testing it + session := podmanTest.Podman([]string{"run", "-t", "--mount", "type=devpts,target=/dev/pts,uid=1000,gid=1001,mode=123", fedoraMinimal, "stat", "-c%g-%a", "/dev/pts/0"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("1001-123")) + }) + It("podman run --pod automatically", func() { session := podmanTest.Podman([]string{"run", "-d", "--pod", "new:foobar", ALPINE, "nc", "-l", "-p", "8686"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/system_reset_test.go b/test/e2e/system_reset_test.go index 102526a46..93ab166cd 100644 --- a/test/e2e/system_reset_test.go +++ b/test/e2e/system_reset_test.go @@ -60,6 +60,8 @@ var _ = Describe("podman system reset", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + Expect(session.ErrorToString()).To(Not(ContainSubstring("Failed to add pause process"))) + // If remote then the API service should have exited // On local tests this is a noop podmanTest.StartRemoteService() diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index a1b25b723..98def3d8f 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -4,7 +4,6 @@ import ( "io/ioutil" "os" "strings" - "time" . "github.com/containers/podman/v3/test/utils" . "github.com/onsi/ginkgo" @@ -82,27 +81,13 @@ WantedBy=multi-user.target run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", ubi_init, "/sbin/init"}) run.WaitWithDefaultTimeout() Expect(run).Should(Exit(0)) - ctrID := run.OutputToString() logs := podmanTest.Podman([]string{"logs", ctrName}) logs.WaitWithDefaultTimeout() Expect(logs).Should(Exit(0)) // Give container 10 seconds to start - started := false - for i := 0; i < 10; i++ { - runningCtrs := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"}) - runningCtrs.WaitWithDefaultTimeout() - Expect(runningCtrs).Should(Exit(0)) - - if strings.Contains(runningCtrs.OutputToString(), ctrID) { - started = true - break - } - - time.Sleep(1 * time.Second) - } - + started := podmanTest.WaitContainerReady(ctrName, "Reached target Multi-User System.", 30, 1) Expect(started).To(BeTrue()) systemctl := podmanTest.Podman([]string{"exec", "-t", "-i", ctrName, "systemctl", "status", "--no-pager"}) diff --git a/test/e2e/version_test.go b/test/e2e/version_test.go index 75986e671..9398248b8 100644 --- a/test/e2e/version_test.go +++ b/test/e2e/version_test.go @@ -31,7 +31,6 @@ var _ = Describe("Podman version", func() { f := CurrentGinkgoTestDescription() processTestResult(f) podmanTest.SeedImages() - }) It("podman version", func() { @@ -96,4 +95,13 @@ var _ = Describe("Podman version", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) }) + + It("podman help", func() { + session := podmanTest.Podman([]string{"help"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.Out.Contents()).Should( + ContainSubstring("Display the Podman version information"), + ) + }) }) diff --git a/test/registries.conf b/test/registries.conf index 0559c9e52..8e4671760 100644 --- a/test/registries.conf +++ b/test/registries.conf @@ -15,3 +15,9 @@ location="mirror.gcr.io" [[registry]] prefix="docker.io/library" location="quay.io/libpod" + +# For testing #11933 to make sure that registries.conf is consulted unless +# --tls-verify is used during container creation. +[[registry]] +location="localhost:5000" +insecure=true diff --git a/test/system/070-build.bats b/test/system/070-build.bats index d3dc14d81..1d24eef15 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -39,6 +39,7 @@ EOF cat >$dockerfile <<EOF FROM $IMAGE RUN echo $rand_content > /$rand_filename +VOLUME ['/etc/foo', '/etc/bar'] EOF run_podman buildx build --load -t build_test --format=docker $tmpdir @@ -47,6 +48,14 @@ EOF run_podman run --rm build_test cat /$rand_filename is "$output" "$rand_content" "reading generated file in image" + # Make sure the volumes are created at surprising yet Docker-compatible + # destinations (see bugzilla.redhat.com/show_bug.cgi?id=2014149). + run_podman run --rm build_test find /[ /etc/bar\] -print + is "$output" "/\[ +/\[/etc +/\[/etc/foo, +/etc/bar]" "weird VOLUME gets converted to directories with brackets and comma" + run_podman rmi -f build_test } diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats index 86f3610ab..09a419914 100644 --- a/test/system/200-pod.bats +++ b/test/system/200-pod.bats @@ -60,6 +60,10 @@ function teardown() { run_podman pod rm -f -t 0 $podid } +function rm_podman_pause_image() { + run_podman version --format "{{.Server.Version}}-{{.Server.Built}}" + run_podman rmi -f "localhost/podman-pause:$output" +} @test "podman pod - communicating between pods" { podname=pod$(random_string) @@ -100,19 +104,14 @@ function teardown() { # Clean up. First the nc -l container... run_podman rm $cid1 - # ...then, from pause container, find the image ID of the pause image... - run_podman pod inspect --format '{{(index .Containers 0).ID}}' $podname - pause_cid="$output" - run_podman container inspect --format '{{.Image}}' $pause_cid - pause_iid="$output" - # ...then rm the pod, then rmi the pause image so we don't leave strays. run_podman pod rm $podname - run_podman rmi $pause_iid # Pod no longer exists run_podman 1 pod exists $podid run_podman 1 pod exists $podname + + rm_podman_pause_image } @test "podman pod - communicating via /dev/shm " { @@ -133,6 +132,10 @@ function teardown() { # Pod no longer exists run_podman 1 pod exists $podid run_podman 1 pod exists $podname + + # Pause image hasn't been pulled + run_podman 1 image exists k8s.gcr.io/pause:3.5 + rm_podman_pause_image } # Random byte @@ -303,16 +306,25 @@ EOF run_podman rm $cid run_podman pod rm -t 0 -f mypod run_podman rmi $infra_image - } @test "podman pod create should fail when infra-name is already in use" { local infra_name="infra_container_$(random_string 10 | tr A-Z a-z)" - run_podman pod create --infra-name "$infra_name" + local pod_name="$(random_string 10 | tr A-Z a-z)" + + # 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 '?' 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" fi + run_podman pod rm -f $pod_name + run_podman images -a + + # Pause image hasn't been pulled + run_podman 1 image exists k8s.gcr.io/pause:3.5 + rm_podman_pause_image } # vim: filetype=sh diff --git a/utils/utils.go b/utils/utils.go index b08630d2f..109ae088b 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -14,6 +14,7 @@ import ( "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/cgroups" "github.com/containers/storage/pkg/archive" + "github.com/godbus/dbus/v5" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -177,13 +178,26 @@ func RunsOnSystemd() bool { func moveProcessToScope(pidPath, slice, scope string) error { data, err := ioutil.ReadFile(pidPath) if err != nil { + // do not raise an error if the file doesn't exist + if os.IsNotExist(err) { + return nil + } return errors.Wrapf(err, "cannot read pid file %s", pidPath) } pid, err := strconv.ParseUint(string(data), 10, 0) if err != nil { return errors.Wrapf(err, "cannot parse pid file %s", pidPath) } - return RunUnderSystemdScope(int(pid), slice, scope) + err = RunUnderSystemdScope(int(pid), slice, scope) + + // If the PID is not valid anymore, do not return an error. + if dbusErr, ok := err.(dbus.Error); ok { + if dbusErr.Name == "org.freedesktop.DBus.Error.UnixProcessIdUnknown" { + return nil + } + } + + return err } // MovePauseProcessToScope moves the pause process used for rootless mode to keep the namespaces alive to @@ -191,8 +205,8 @@ func moveProcessToScope(pidPath, slice, scope string) error { func MovePauseProcessToScope(pausePidPath string) { err := moveProcessToScope(pausePidPath, "user.slice", "podman-pause.scope") if err != nil { - unified, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { + unified, err2 := cgroups.IsCgroup2UnifiedMode() + if err2 != nil { logrus.Warnf("Failed to detect if running with cgroup unified: %v", err) } if RunsOnSystemd() && unified { diff --git a/vendor/github.com/containers/common/libimage/filters.go b/vendor/github.com/containers/common/libimage/filters.go index 833f940cc..521af5d06 100644 --- a/vendor/github.com/containers/common/libimage/filters.go +++ b/vendor/github.com/containers/common/libimage/filters.go @@ -50,6 +50,18 @@ func filterImages(images []*Image, filters []filterFunc) ([]*Image, error) { func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOptions) ([]filterFunc, error) { logrus.Tracef("Parsing image filters %s", options.Filters) + var tree *layerTree + getTree := func() (*layerTree, error) { + if tree == nil { + t, err := r.layerTree() + if err != nil { + return nil, err + } + tree = t + } + return tree, nil + } + filterFuncs := []filterFunc{} for _, filter := range options.Filters { var key, value string @@ -93,7 +105,11 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp if err != nil { return nil, errors.Wrapf(err, "non-boolean value %q for dangling filter", value) } - filterFuncs = append(filterFuncs, filterDangling(ctx, dangling)) + t, err := getTree() + if err != nil { + return nil, err + } + filterFuncs = append(filterFuncs, filterDangling(ctx, dangling, t)) case "id": filterFuncs = append(filterFuncs, filterID(value)) @@ -103,7 +119,11 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp if err != nil { return nil, errors.Wrapf(err, "non-boolean value %q for intermediate filter", value) } - filterFuncs = append(filterFuncs, filterIntermediate(ctx, intermediate)) + t, err := getTree() + if err != nil { + return nil, err + } + filterFuncs = append(filterFuncs, filterIntermediate(ctx, intermediate, t)) case "label": filterFuncs = append(filterFuncs, filterLabel(ctx, value)) @@ -221,9 +241,9 @@ func filterContainers(value string, fn IsExternalContainerFunc) filterFunc { } // filterDangling creates a dangling filter for matching the specified value. -func filterDangling(ctx context.Context, value bool) filterFunc { +func filterDangling(ctx context.Context, value bool, tree *layerTree) filterFunc { return func(img *Image) (bool, error) { - isDangling, err := img.IsDangling(ctx) + isDangling, err := img.isDangling(ctx, tree) if err != nil { return false, err } @@ -241,9 +261,9 @@ func filterID(value string) filterFunc { // filterIntermediate creates an intermediate filter for images. An image is // considered to be an intermediate image if it is dangling (i.e., no tags) and // has no children (i.e., no other image depends on it). -func filterIntermediate(ctx context.Context, value bool) filterFunc { +func filterIntermediate(ctx context.Context, value bool, tree *layerTree) filterFunc { return func(img *Image) (bool, error) { - isIntermediate, err := img.IsIntermediate(ctx) + isIntermediate, err := img.isIntermediate(ctx, tree) if err != nil { return false, err } diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go index 00a2d620e..bf3310da2 100644 --- a/vendor/github.com/containers/common/libimage/image.go +++ b/vendor/github.com/containers/common/libimage/image.go @@ -128,10 +128,16 @@ func (i *Image) IsReadOnly() bool { // IsDangling returns true if the image is dangling, that is an untagged image // without children. func (i *Image) IsDangling(ctx context.Context) (bool, error) { + return i.isDangling(ctx, nil) +} + +// isDangling returns true if the image is dangling, that is an untagged image +// without children. If tree is nil, it will created for this invocation only. +func (i *Image) isDangling(ctx context.Context, tree *layerTree) (bool, error) { if len(i.Names()) > 0 { return false, nil } - children, err := i.getChildren(ctx, false) + children, err := i.getChildren(ctx, false, tree) if err != nil { return false, err } @@ -141,10 +147,17 @@ func (i *Image) IsDangling(ctx context.Context) (bool, error) { // IsIntermediate returns true if the image is an intermediate image, that is // an untagged image with children. func (i *Image) IsIntermediate(ctx context.Context) (bool, error) { + return i.isIntermediate(ctx, nil) +} + +// isIntermediate returns true if the image is an intermediate image, that is +// an untagged image with children. If tree is nil, it will created for this +// invocation only. +func (i *Image) isIntermediate(ctx context.Context, tree *layerTree) (bool, error) { if len(i.Names()) > 0 { return false, nil } - children, err := i.getChildren(ctx, false) + children, err := i.getChildren(ctx, false, tree) if err != nil { return false, err } @@ -189,7 +202,7 @@ func (i *Image) Parent(ctx context.Context) (*Image, error) { // HasChildren returns indicates if the image has children. func (i *Image) HasChildren(ctx context.Context) (bool, error) { - children, err := i.getChildren(ctx, false) + children, err := i.getChildren(ctx, false, nil) if err != nil { return false, err } @@ -198,7 +211,7 @@ func (i *Image) HasChildren(ctx context.Context) (bool, error) { // Children returns the image's children. func (i *Image) Children(ctx context.Context) ([]*Image, error) { - children, err := i.getChildren(ctx, true) + children, err := i.getChildren(ctx, true, nil) if err != nil { return nil, err } @@ -206,13 +219,16 @@ func (i *Image) Children(ctx context.Context) ([]*Image, error) { } // getChildren returns a list of imageIDs that depend on the image. If all is -// false, only the first child image is returned. -func (i *Image) getChildren(ctx context.Context, all bool) ([]*Image, error) { - tree, err := i.runtime.layerTree() - if err != nil { - return nil, err +// false, only the first child image is returned. If tree is nil, it will be +// created for this invocation only. +func (i *Image) getChildren(ctx context.Context, all bool, tree *layerTree) ([]*Image, error) { + if tree == nil { + t, err := i.runtime.layerTree() + if err != nil { + return nil, err + } + tree = t } - return tree.children(ctx, i, all) } diff --git a/vendor/github.com/containers/common/libimage/search.go b/vendor/github.com/containers/common/libimage/search.go index 7e20e4331..ece81531a 100644 --- a/vendor/github.com/containers/common/libimage/search.go +++ b/vendor/github.com/containers/common/libimage/search.go @@ -244,7 +244,7 @@ func (r *Runtime) searchImageInRegistry(ctx context.Context, term, registry stri name = index + "/library/" + results[i].Name } params := SearchResult{ - Index: index, + Index: registry, Name: name, Description: description, Official: official, diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index d5be77edd..45230703d 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -574,7 +574,7 @@ func readConfigFromFile(path string, config *Config) error { } keys := meta.Undecoded() if len(keys) > 0 { - logrus.Warningf("Failed to decode the keys %q from %q.", keys, path) + logrus.Debugf("Failed to decode the keys %q from %q.", keys, path) } return nil diff --git a/vendor/github.com/containers/common/pkg/flag/flag.go b/vendor/github.com/containers/common/pkg/flag/flag.go new file mode 100644 index 000000000..52eb50da0 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/flag/flag.go @@ -0,0 +1,174 @@ +package flag + +import ( + "strconv" + + "github.com/spf13/pflag" +) + +// OptionalBool is a boolean with a separate presence flag and value. +type OptionalBool struct { + present bool + value bool +} + +// Present returns the bool's presence flag. +func (ob *OptionalBool) Present() bool { + return ob.present +} + +// Present returns the bool's value. Should only be used if Present() is true. +func (ob *OptionalBool) Value() bool { + return ob.value +} + +// optionalBool is a cli.Generic == flag.Value implementation equivalent to +// the one underlying flag.Bool, except that it records whether the flag has been set. +// This is distinct from optionalBool to (pretend to) force callers to use +// optionalBoolFlag +type optionalBoolValue OptionalBool + +// OptionalBoolFlag creates new flag for an optional in the specified flag with +// the specified name and usage. +func OptionalBoolFlag(fs *pflag.FlagSet, p *OptionalBool, name, usage string) *pflag.Flag { + flag := fs.VarPF(internalNewOptionalBoolValue(p), name, "", usage) + flag.NoOptDefVal = "true" + flag.DefValue = "false" + return flag +} + +// WARNING: Do not directly use this method to define optionalBool flag. +// Caller should use optionalBoolFlag +func internalNewOptionalBoolValue(p *OptionalBool) pflag.Value { + p.present = false + return (*optionalBoolValue)(p) +} + +// Set parses the string to a bool and sets it. +func (ob *optionalBoolValue) Set(s string) error { + v, err := strconv.ParseBool(s) + if err != nil { + return err + } + ob.value = v + ob.present = true + return nil +} + +// String returns the string representation of the string. +func (ob *optionalBoolValue) String() string { + if !ob.present { + return "" // This is, sadly, not round-trip safe: --flag is interpreted as --flag=true + } + return strconv.FormatBool(ob.value) +} + +// Type returns the type. +func (ob *optionalBoolValue) Type() string { + return "bool" +} + +// IsBoolFlag indicates that it's a bool flag. +func (ob *optionalBoolValue) IsBoolFlag() bool { + return true +} + +// OptionalString is a string with a separate presence flag. +type OptionalString struct { + present bool + value string +} + +// Present returns the strings's presence flag. +func (os *OptionalString) Present() bool { + return os.present +} + +// Present returns the string's value. Should only be used if Present() is true. +func (os *OptionalString) Value() string { + return os.value +} + +// optionalString is a cli.Generic == flag.Value implementation equivalent to +// the one underlying flag.String, except that it records whether the flag has been set. +// This is distinct from optionalString to (pretend to) force callers to use +// newoptionalString +type optionalStringValue OptionalString + +// NewOptionalStringValue returns a pflag.Value fo the string. +func NewOptionalStringValue(p *OptionalString) pflag.Value { + p.present = false + return (*optionalStringValue)(p) +} + +// Set sets the string. +func (ob *optionalStringValue) Set(s string) error { + ob.value = s + ob.present = true + return nil +} + +// String returns the string if present. +func (ob *optionalStringValue) String() string { + if !ob.present { + return "" // This is, sadly, not round-trip safe: --flag= is interpreted as {present:true, value:""} + } + return ob.value +} + +// Type returns the string type. +func (ob *optionalStringValue) Type() string { + return "string" +} + +// OptionalInt is a int with a separate presence flag. +type OptionalInt struct { + present bool + value int +} + +// Present returns the int's presence flag. +func (oi *OptionalInt) Present() bool { + return oi.present +} + +// Present returns the int's value. Should only be used if Present() is true. +func (oi *OptionalInt) Value() int { + return oi.value +} + +// optionalInt is a cli.Generic == flag.Value implementation equivalent to +// the one underlying flag.Int, except that it records whether the flag has been set. +// This is distinct from optionalInt to (pretend to) force callers to use +// newoptionalIntValue +type optionalIntValue OptionalInt + +// NewOptionalIntValue returns the pflag.Value of the int. +func NewOptionalIntValue(p *OptionalInt) pflag.Value { + p.present = false + return (*optionalIntValue)(p) +} + +// Set parses the string to an int and sets it. +func (ob *optionalIntValue) Set(s string) error { + v, err := strconv.ParseInt(s, 0, strconv.IntSize) + if err != nil { + return err + } + ob.value = int(v) + ob.present = true + return nil +} + +// String returns the string representation of the int. +func (ob *optionalIntValue) String() string { + if !ob.present { + return "" // If the value is not present, just return an empty string, any other value wouldn't make sense. + } + return strconv.Itoa(int(ob.value)) +} + +// Type returns the int's type. +func (ob *optionalIntValue) Type() string { + return "int" +} diff --git a/vendor/github.com/godbus/dbus/v5/auth.go b/vendor/github.com/godbus/dbus/v5/auth.go index eb0b2f434..a59b4c0eb 100644 --- a/vendor/github.com/godbus/dbus/v5/auth.go +++ b/vendor/github.com/godbus/dbus/v5/auth.go @@ -53,7 +53,7 @@ type Auth interface { // bus. Auth must not be called on shared connections. func (conn *Conn) Auth(methods []Auth) error { if methods == nil { - uid := strconv.Itoa(os.Getuid()) + uid := strconv.Itoa(os.Geteuid()) methods = []Auth{AuthExternal(uid), AuthCookieSha1(uid, getHomeDir())} } in := bufio.NewReader(conn.transport) diff --git a/vendor/github.com/godbus/dbus/v5/conn.go b/vendor/github.com/godbus/dbus/v5/conn.go index cb8966a74..76fc5cde3 100644 --- a/vendor/github.com/godbus/dbus/v5/conn.go +++ b/vendor/github.com/godbus/dbus/v5/conn.go @@ -73,7 +73,7 @@ func SessionBus() (conn *Conn, err error) { return } -func getSessionBusAddress() (string, error) { +func getSessionBusAddress(autolaunch bool) (string, error) { if address := os.Getenv("DBUS_SESSION_BUS_ADDRESS"); address != "" && address != "autolaunch:" { return address, nil @@ -81,12 +81,26 @@ func getSessionBusAddress() (string, error) { os.Setenv("DBUS_SESSION_BUS_ADDRESS", address) return address, nil } + if !autolaunch { + return "", errors.New("dbus: couldn't determine address of session bus") + } return getSessionBusPlatformAddress() } // SessionBusPrivate returns a new private connection to the session bus. func SessionBusPrivate(opts ...ConnOption) (*Conn, error) { - address, err := getSessionBusAddress() + address, err := getSessionBusAddress(true) + if err != nil { + return nil, err + } + + return Dial(address, opts...) +} + +// SessionBusPrivate returns a new private connection to the session bus. If +// the session bus is not already open, do not attempt to launch it. +func SessionBusPrivateNoAutoStartup(opts ...ConnOption) (*Conn, error) { + address, err := getSessionBusAddress(false) if err != nil { return nil, err } @@ -121,7 +135,7 @@ func SystemBus() (conn *Conn, err error) { // ConnectSessionBus connects to the session bus. func ConnectSessionBus(opts ...ConnOption) (*Conn, error) { - address, err := getSessionBusAddress() + address, err := getSessionBusAddress(true) if err != nil { return nil, err } @@ -180,7 +194,7 @@ func Dial(address string, opts ...ConnOption) (*Conn, error) { // // Deprecated: use Dial with options instead. func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) { - return Dial(address, WithSignalHandler(signalHandler)) + return Dial(address, WithHandler(handler), WithSignalHandler(signalHandler)) } // ConnOption is a connection option. diff --git a/vendor/github.com/godbus/dbus/v5/message.go b/vendor/github.com/godbus/dbus/v5/message.go index dd86aff4f..16693eb30 100644 --- a/vendor/github.com/godbus/dbus/v5/message.go +++ b/vendor/github.com/godbus/dbus/v5/message.go @@ -279,8 +279,8 @@ func (msg *Message) EncodeToWithFDs(out io.Writer, order binary.ByteOrder) (fds // be either binary.LittleEndian or binary.BigEndian. If the message is not // valid or an error occurs when writing, an error is returned. func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) (err error) { - _, err = msg.EncodeToWithFDs(out, order); - return err; + _, err = msg.EncodeToWithFDs(out, order) + return err } // IsValid checks whether msg is a valid message and returns an diff --git a/vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go b/vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go new file mode 100644 index 000000000..af7bafdf9 --- /dev/null +++ b/vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go @@ -0,0 +1,14 @@ +package dbus + +import "io" + +func (t *unixTransport) SendNullByte() error { + n, _, err := t.UnixConn.WriteMsgUnix([]byte{0}, nil, nil) + if err != nil { + return err + } + if n != 1 { + return io.ErrShortWrite + } + return nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index afe18287d..3fd9cbcc8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -95,7 +95,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.46.1-0.20211008123044-d846f5aaec0e +# github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f github.com/containers/common/libimage github.com/containers/common/libimage/manifests github.com/containers/common/pkg/apparmor @@ -108,6 +108,7 @@ github.com/containers/common/pkg/completion github.com/containers/common/pkg/config github.com/containers/common/pkg/defaultnet github.com/containers/common/pkg/filters +github.com/containers/common/pkg/flag github.com/containers/common/pkg/manifests github.com/containers/common/pkg/parse github.com/containers/common/pkg/report @@ -345,7 +346,7 @@ github.com/ghodss/yaml github.com/go-logr/logr # github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 github.com/go-task/slim-sprig -# github.com/godbus/dbus/v5 v5.0.5 +# github.com/godbus/dbus/v5 v5.0.6 github.com/godbus/dbus/v5 # github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf/gogoproto @@ -798,10 +799,10 @@ gopkg.in/tomb.v1 gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gopkg.in/yaml.v3 -# k8s.io/api v0.22.2 +# k8s.io/api v0.22.3 k8s.io/api/apps/v1 k8s.io/api/core/v1 -# k8s.io/apimachinery v0.22.2 +# k8s.io/apimachinery v0.22.3 k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/apis/meta/v1 k8s.io/apimachinery/pkg/conversion |