diff options
60 files changed, 480 insertions, 178 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index b6ef69a96..ef6ac5e8b 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -378,8 +378,7 @@ osx_alt_build_task: always: *binary_artifacts -# This task is a stub: In the future it will be used to verify -# podman is compatible with the docker python-module. +# Verify podman is compatible with the docker python-module. docker-py_test_task: name: Docker-py Compat. alias: docker-py_test diff --git a/.gitignore b/.gitignore index 0a3caf8ca..08e5309ee 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ release.txt /test/goecho/goecho /test/testvol/testvol .vscode* +tags result # Necessary to prevent hack/tree-status.sh false-positive /*runner_stats.log @@ -257,7 +257,7 @@ test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go) .PHONY: codespell codespell: - codespell -S bin,vendor,.git,go.sum,changelog.txt,.cirrus.yml,"RELEASE_NOTES.md,*.xz,*.gz,*.tar,*.tgz,bin2img,*ico,*.png,*.1,*.5,copyimg,*.orig,apidoc.go" -L uint,iff,od,seeked,splitted,marge,ERRO,hist,ether -w + codespell -S bin,vendor,.git,go.sum,changelog.txt,.cirrus.yml,"RELEASE_NOTES.md,*.xz,*.gz,*.ps1,*.tar,*.tgz,bin2img,*ico,*.png,*.1,*.5,copyimg,*.orig,apidoc.go" -L uint,iff,od,seeked,splitted,marge,ERRO,hist,ether -w .PHONY: validate validate: gofmt lint .gitvalidation validate.completions man-page-check swagger-check tests-included tests-expect-exit @@ -493,10 +493,12 @@ validate.completions: if [ -x /bin/zsh ]; then /bin/zsh completions/zsh/_podman; fi if [ -x /bin/fish ]; then /bin/fish completions/fish/podman.fish; fi +# Note: Assumes test/python/requirements.txt is installed & available .PHONY: run-docker-py-tests run-docker-py-tests: - $(eval testLogs=$(shell mktemp podman_tmp_XXXX)) - ./bin/podman run --rm --security-opt label=disable --privileged -v $(testLogs):/testLogs --net=host -e DOCKER_HOST=tcp://localhost:8080 $(DOCKERPY_IMAGE) sh -c "pytest $(DOCKERPY_TEST) " + touch test/__init__.py + pytest test/python/docker/ + -rm test/__init__.py .PHONY: localunit localunit: test/goecho/goecho @@ -841,11 +843,13 @@ clean: ## Clean all make artifacts build \ test/checkseccomp/checkseccomp \ test/goecho/goecho \ + test/__init__.py \ test/testdata/redis-image \ libpod/container_ffjson.go \ libpod/pod_ffjson.go \ libpod/container_easyjson.go \ libpod/pod_easyjson.go \ .install.goimports \ - docs/build + docs/build \ + venv make -C docs clean diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index 08b2f6235..9a4524b46 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -323,6 +323,18 @@ func prefixSlice(pre string, slice []string) []string { return slice } +func suffixCompSlice(suf string, slice []string) []string { + for i := range slice { + split := strings.SplitN(slice[i], "\t", 2) + if len(split) > 1 { + slice[i] = split[0] + suf + "\t" + split[1] + } else { + slice[i] = slice[i] + suf + } + } + return slice +} + func completeKeyValues(toComplete string, k keyValueCompletion) ([]string, cobra.ShellCompDirective) { suggestions := make([]string, 0, len(k)) directive := cobra.ShellCompDirectiveNoFileComp @@ -664,6 +676,42 @@ func AutocompleteSystemConnections(cmd *cobra.Command, args []string, toComplete return suggestions, cobra.ShellCompDirectiveNoFileComp } +// AutocompleteScp returns a list of connections, images, or both, depending on the amount of arguments +func AutocompleteScp(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + switch len(args) { + case 0: + split := strings.SplitN(toComplete, "::", 2) + if len(split) > 1 { + imageSuggestions, _ := getImages(cmd, split[1]) + return prefixSlice(split[0]+"::", imageSuggestions), cobra.ShellCompDirectiveNoFileComp + } + connectionSuggestions, _ := AutocompleteSystemConnections(cmd, args, toComplete) + imageSuggestions, _ := getImages(cmd, toComplete) + totalSuggestions := append(suffixCompSlice("::", connectionSuggestions), imageSuggestions...) + directive := cobra.ShellCompDirectiveNoFileComp + // if we have connections do not add a space after the completion + if len(connectionSuggestions) > 0 { + directive = cobra.ShellCompDirectiveNoFileComp | cobra.ShellCompDirectiveNoSpace + } + return totalSuggestions, directive + case 1: + split := strings.SplitN(args[0], "::", 2) + if len(split) > 1 { + if len(split[1]) > 0 { + return nil, cobra.ShellCompDirectiveNoFileComp + } + imageSuggestions, _ := getImages(cmd, toComplete) + return imageSuggestions, cobra.ShellCompDirectiveNoFileComp + } + connectionSuggestions, _ := AutocompleteSystemConnections(cmd, args, toComplete) + return suffixCompSlice("::", connectionSuggestions), cobra.ShellCompDirectiveNoFileComp + } + return nil, cobra.ShellCompDirectiveNoFileComp +} + /* -------------- Flags ----------------- */ // AutocompleteDetachKeys - Autocomplete detach-keys options. diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go index 0a969bfd2..0fdf3ce08 100644 --- a/cmd/podman/common/create_opts.go +++ b/cmd/podman/common/create_opts.go @@ -356,51 +356,55 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c CPUSetMems: cc.HostConfig.CpusetMems, // Detach: false, // don't need // DetachKeys: "", // don't need - Devices: devices, - DeviceCGroupRule: nil, - DeviceReadBPs: readBps, - DeviceReadIOPs: readIops, - DeviceWriteBPs: writeBps, - DeviceWriteIOPs: writeIops, - Entrypoint: entrypoint, - Env: cc.Config.Env, - Expose: expose, - GroupAdd: cc.HostConfig.GroupAdd, - Hostname: cc.Config.Hostname, - ImageVolume: "bind", - Init: init, - Interactive: cc.Config.OpenStdin, - IPC: string(cc.HostConfig.IpcMode), - Label: stringMaptoArray(cc.Config.Labels), - LogDriver: cc.HostConfig.LogConfig.Type, - LogOptions: stringMaptoArray(cc.HostConfig.LogConfig.Config), - Name: cc.Name, - OOMScoreAdj: cc.HostConfig.OomScoreAdj, - Arch: "", - OS: "", - Variant: "", - PID: string(cc.HostConfig.PidMode), - PIDsLimit: cc.HostConfig.PidsLimit, - Privileged: cc.HostConfig.Privileged, - PublishAll: cc.HostConfig.PublishAllPorts, - Quiet: false, - ReadOnly: cc.HostConfig.ReadonlyRootfs, - ReadOnlyTmpFS: true, // podman default - Rm: cc.HostConfig.AutoRemove, - SecurityOpt: cc.HostConfig.SecurityOpt, - StopSignal: cc.Config.StopSignal, - StorageOpt: stringMaptoArray(cc.HostConfig.StorageOpt), - Sysctl: stringMaptoArray(cc.HostConfig.Sysctls), - Systemd: "true", // podman default - TmpFS: parsedTmp, - TTY: cc.Config.Tty, - User: cc.Config.User, - UserNS: string(cc.HostConfig.UsernsMode), - UTS: string(cc.HostConfig.UTSMode), - Mount: mounts, - VolumesFrom: cc.HostConfig.VolumesFrom, - Workdir: cc.Config.WorkingDir, - Net: &netInfo, + Devices: devices, + DeviceCGroupRule: nil, + DeviceReadBPs: readBps, + DeviceReadIOPs: readIops, + DeviceWriteBPs: writeBps, + DeviceWriteIOPs: writeIops, + Entrypoint: entrypoint, + Env: cc.Config.Env, + Expose: expose, + GroupAdd: cc.HostConfig.GroupAdd, + Hostname: cc.Config.Hostname, + ImageVolume: "bind", + Init: init, + Interactive: cc.Config.OpenStdin, + IPC: string(cc.HostConfig.IpcMode), + Label: stringMaptoArray(cc.Config.Labels), + LogDriver: cc.HostConfig.LogConfig.Type, + LogOptions: stringMaptoArray(cc.HostConfig.LogConfig.Config), + Name: cc.Name, + OOMScoreAdj: cc.HostConfig.OomScoreAdj, + Arch: "", + OS: "", + Variant: "", + PID: string(cc.HostConfig.PidMode), + PIDsLimit: cc.HostConfig.PidsLimit, + Privileged: cc.HostConfig.Privileged, + PublishAll: cc.HostConfig.PublishAllPorts, + Quiet: false, + ReadOnly: cc.HostConfig.ReadonlyRootfs, + ReadOnlyTmpFS: true, // podman default + Rm: cc.HostConfig.AutoRemove, + SecurityOpt: cc.HostConfig.SecurityOpt, + StopSignal: cc.Config.StopSignal, + StorageOpt: stringMaptoArray(cc.HostConfig.StorageOpt), + Sysctl: stringMaptoArray(cc.HostConfig.Sysctls), + Systemd: "true", // podman default + TmpFS: parsedTmp, + TTY: cc.Config.Tty, + User: cc.Config.User, + UserNS: string(cc.HostConfig.UsernsMode), + UTS: string(cc.HostConfig.UTSMode), + Mount: mounts, + VolumesFrom: cc.HostConfig.VolumesFrom, + Workdir: cc.Config.WorkingDir, + Net: &netInfo, + HealthInterval: DefaultHealthCheckInterval, + HealthRetries: DefaultHealthCheckRetries, + HealthTimeout: DefaultHealthCheckTimeout, + HealthStartPeriod: DefaultHealthCheckStartPeriod, } if !rootless.IsRootless() { var ulimits []string @@ -527,10 +531,18 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c finCmd = finCmd[:len(finCmd)-1] } cliOpts.HealthCmd = finCmd - cliOpts.HealthInterval = cc.Config.Healthcheck.Interval.String() - cliOpts.HealthRetries = uint(cc.Config.Healthcheck.Retries) - cliOpts.HealthStartPeriod = cc.Config.Healthcheck.StartPeriod.String() - cliOpts.HealthTimeout = cc.Config.Healthcheck.Timeout.String() + if cc.Config.Healthcheck.Interval > 0 { + cliOpts.HealthInterval = cc.Config.Healthcheck.Interval.String() + } + if cc.Config.Healthcheck.Retries > 0 { + cliOpts.HealthRetries = uint(cc.Config.Healthcheck.Retries) + } + if cc.Config.Healthcheck.StartPeriod > 0 { + cliOpts.HealthStartPeriod = cc.Config.Healthcheck.StartPeriod.String() + } + if cc.Config.Healthcheck.Timeout > 0 { + cliOpts.HealthTimeout = cc.Config.Healthcheck.Timeout.String() + } } // specgen assumes the image name is arg[0] diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 8d6a21cb7..59d32f568 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -685,7 +685,7 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start concat := "" if cmdArr[0] == "CMD" || cmdArr[0] == "none" { // this is for compat, we are already split properly for most compat cases cmdArr = strings.Fields(inCmd) - } else if cmdArr[0] != "CMD-SHELL" { // this is for podman side of things, wont contain the keywords + } else if cmdArr[0] != "CMD-SHELL" { // this is for podman side of things, won't contain the keywords if isArr && len(cmdArr) > 1 { // an array of consecutive commands cmdArr = append([]string{"CMD"}, cmdArr...) } else { // one singular command diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 906ae4452..a57488af2 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -13,6 +13,7 @@ import ( "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/utils" + "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/specgen" "github.com/containers/podman/v3/pkg/util" @@ -105,8 +106,8 @@ func create(cmd *cobra.Command, args []string) error { if !cmd.Flags().Changed("pod") { return errors.New("must specify pod value with init-ctr") } - if !util.StringInSlice(initctr, []string{"always", "oneshot"}) { - return errors.New("init-ctr value must be 'always' or 'oneshot'") + if !util.StringInSlice(initctr, []string{define.AlwaysInitContainer, define.OneShotInitContainer}) { + return errors.Errorf("init-ctr value must be '%s' or '%s'", define.AlwaysInitContainer, define.OneShotInitContainer) } cliVals.InitContainerType = initctr } diff --git a/cmd/podman/images/scp.go b/cmd/podman/images/scp.go index a47d01995..176563440 100644 --- a/cmd/podman/images/scp.go +++ b/cmd/podman/images/scp.go @@ -33,7 +33,7 @@ var ( Short: "securely copy images", RunE: scp, Args: cobra.RangeArgs(1, 2), - ValidArgsFunction: common.AutocompleteImages, + ValidArgsFunction: common.AutocompleteScp, Example: `podman image scp myimage:latest otherhost::`, } ) diff --git a/cmd/podman/registry/config.go b/cmd/podman/registry/config.go index b512ba341..50e488b02 100644 --- a/cmd/podman/registry/config.go +++ b/cmd/podman/registry/config.go @@ -89,7 +89,12 @@ func newPodmanConfig() { // use for the containers.conf configuration file. func setXdgDirs() error { if !rootless.IsRootless() { - return nil + // unset XDG_RUNTIME_DIR for root + // Sometimes XDG_RUNTIME_DIR is set to /run/user/0 sometimes it is unset, + // the inconsistency is causing issues for the dnsname plugin. + // It is already set to an empty string for conmon so lets do the same + // for podman. see #10806 and #10745 + return os.Unsetenv("XDG_RUNTIME_DIR") } // Setup XDG_RUNTIME_DIR diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh index da43ffb0a..c1972b90f 100755 --- a/contrib/cirrus/runner.sh +++ b/contrib/cirrus/runner.sh @@ -88,7 +88,8 @@ function _run_bindings() { } function _run_docker-py() { - msg "This is docker-py stub, it is only a stub" + source venv/bin/activate + make run-docker-py-tests } function _run_endpoint() { diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 86b8d78ef..3f2176fd6 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -191,7 +191,19 @@ case "$TEST_FLAVOR" in bigto dnf install -y glibc-minimal-langpack rpm-build fi ;& - docker-py) ;& + docker-py) + remove_packaged_podman_files + make install PREFIX=/usr ETCDIR=/etc + + # TODO: Don't install stuff at test runtime! Do this from + # cache_images/fedora_packaging.sh in containers/automation_images + # and STRONGLY prefer installing RPMs vs pip packages in venv + dnf install -y python3-virtualenv python3-pytest4 + virtualenv venv + source venv/bin/activate + pip install --upgrade pip + pip install --requirement $GOSRC/test/python/requirements.txt + ;; build) make clean ;; unit) ;; apiv2) ;& # use next item diff --git a/contrib/podmanimage/README.md b/contrib/podmanimage/README.md index 6effec38b..b7be328c7 100644 --- a/contrib/podmanimage/README.md +++ b/contrib/podmanimage/README.md @@ -17,10 +17,10 @@ default to `/`. The container images are: * `quay.io/containers/podman:<version>` and `quay.io/podman/stable:<version>` - - These images are built when a new Podman version becomes available in - Fedora. These images are intended to be unchanging and stable, they will - never be updated by automation once they've been pushed. For build details, - please [see the configuration file](stable/Dockerfile). + These images are built daily. They are intended to contain an unchanging + and stable version of podman. Though for the most recent `<version>` tag, + image contents will be updated to incorporate (especially) security upgrades. + For build details, please [see the configuration file](stable/Dockerfile). * `quay.io/containers/podman:latest` and `quay.io/podman/stable:latest` - Built daily using the same Dockerfile as above. The Podman version will remain the "latest" available in Fedora, however the other image diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 723592016..b73f6c05a 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -453,10 +453,9 @@ When using pods, create an init style container, which is run after the infra co but before regular pod containers are started. Init containers are useful for running setup operations for the pod's applications. -Valid values for `init-ctr` type are *always* or *oneshot*. The *always* value -means the container will run with each and every `pod start`, whereas the *oneshot* -value means is will ony run once when the pod is started and then the container is -removed. +Valid values for `init-ctr` type are *always* or *once*. The *always* value +means the container will run with each and every `pod start`, whereas the *once* +value means the container will only run once when the pod is started and then the container is removed. Init containers are only run on pod `start`. Restarting a pod will not execute any init containers should they be present. Furthermore, init containers can only be created in a diff --git a/docs/source/markdown/podman-pod-ps.1.md b/docs/source/markdown/podman-pod-ps.1.md index 156adccaa..ed0789e93 100644 --- a/docs/source/markdown/podman-pod-ps.1.md +++ b/docs/source/markdown/podman-pod-ps.1.md @@ -98,6 +98,7 @@ Valid filters are listed below: | id | [ID] Pod's ID (accepts regex) | | name | [Name] Pod's name (accepts regex) | | label | [Key] or [Key=Value] Label assigned to a container | +| until | Only list pods created before given timestamp | | status | Pod's status: `stopped`, `running`, `paused`, `exited`, `dead`, `created`, `degraded` | | network | [Network] name or full ID of network | | ctr-names | Container name within the pod (accepts regex) | @@ -17,7 +17,7 @@ require ( github.com/containers/image/v5 v5.15.0 github.com/containers/ocicrypt v1.1.2 github.com/containers/psgo v1.5.2 - github.com/containers/storage v1.34.0 + github.com/containers/storage v1.34.1 github.com/coreos/go-systemd/v22 v22.3.2 github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3 github.com/cri-o/ocicni v0.2.1-0.20210621164014-d0acc7862283 @@ -260,8 +260,8 @@ github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3E github.com/containers/storage v1.32.6/go.mod h1:mdB+b89p+jU8zpzLTVXA0gWMmIo0WrkfGMh1R8O2IQw= github.com/containers/storage v1.33.0/go.mod h1:FUZPF4nJijX8ixdhByZJXf02cvbyLi6dyDwXdIe8QVY= github.com/containers/storage v1.33.1/go.mod h1:FUZPF4nJijX8ixdhByZJXf02cvbyLi6dyDwXdIe8QVY= -github.com/containers/storage v1.34.0 h1:39MhQe+3knl2G6WcaYf24Fpqqz6gbdLK/52Ms5wV+II= -github.com/containers/storage v1.34.0/go.mod h1:t6I+hTgPU0/tVxQ75vw406wDi/TXwYBqZp4QZV9N7b8= +github.com/containers/storage v1.34.1 h1:PsBGMH7hwuQ3MOr7qTgPznFrE8ebfIbwQbg2gKvg0lE= +github.com/containers/storage v1.34.1/go.mod h1:FY2TcbfgCLMU4lYoKnlZeZXeH353TOTbpDEA+sAcqAY= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -583,8 +583,8 @@ github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.3 h1:BtAvtV1+h0YwSVwWoYXMREPpYu9VzTJ9QDI1TEg/iQQ= -github.com/klauspost/compress v1.13.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -751,7 +751,6 @@ github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwy github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/opencontainers/selinux v1.8.3/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo= github.com/opencontainers/selinux v1.8.4 h1:krlgQ6/j9CkCXT5oW0yVXdQFOME3NjKuuAZXuR6O7P4= github.com/opencontainers/selinux v1.8.4/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo= github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656 h1:WaxyNFpmIDu4i6so9r6LVFIbSaXqsj8oitMitt86ae4= diff --git a/libpod/container.go b/libpod/container.go index d5d5ef1a5..80fd35c09 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -240,7 +240,7 @@ type ContainerImageVolume struct { type ContainerSecret struct { // Secret is the secret *secrets.Secret - // UID is tbe UID of the secret file + // UID is the UID of the secret file UID uint32 // GID is the GID of the secret file GID uint32 diff --git a/libpod/container_config.go b/libpod/container_config.go index 72a969fe6..e15030c15 100644 --- a/libpod/container_config.go +++ b/libpod/container_config.go @@ -376,6 +376,6 @@ type ContainerMiscConfig struct { // EnvSecrets are secrets that are set as environment variables EnvSecrets map[string]*secrets.Secret `json:"secret_env,omitempty"` // InitContainerType specifies if the container is an initcontainer - // and if so, what type: always or oneshot are possible non-nil entries + // and if so, what type: always or once are possible non-nil entries InitContainerType string `json:"init_container_type,omitempty"` } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 6d2f7bddc..f21aebb09 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1782,7 +1782,7 @@ func (c *Container) generateResolvConf() (string, error) { cniResponse := c.state.NetworkStatus for _, i := range cniResponse { for _, ip := range i.IPs { - // Note: only using To16() does not work since it also returns a vaild ip for ipv4 + // Note: only using To16() does not work since it also returns a valid ip for ipv4 if ip.Address.IP.To4() == nil && ip.Address.IP.To16() != nil { ipv6 = true } diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go index d4afaa52a..11f1be7f9 100644 --- a/libpod/container_log_linux.go +++ b/libpod/container_log_linux.go @@ -79,7 +79,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption break } if cursorError != nil { - return errors.Wrap(cursorError, "inital journal cursor") + return errors.Wrap(cursorError, "initial journal cursor") } // We need the container's events in the same journal to guarantee diff --git a/libpod/define/container.go b/libpod/define/container.go index f0aca92aa..bb44a6a4a 100644 --- a/libpod/define/container.go +++ b/libpod/define/container.go @@ -34,5 +34,5 @@ const ( AlwaysInitContainer = "always" // OneShotInitContainer is a container that only runs as init once // and is then deleted. - OneShotInitContainer = "oneshot" + OneShotInitContainer = "once" ) diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 8e9b5997c..2ed2bb01b 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -173,11 +173,27 @@ func (r *RootlessCNI) Do(toRun func() error) error { // the link target will be available in the mount ns. // see: https://github.com/containers/podman/issues/10855 resolvePath := "/etc/resolv.conf" - resolvePath, err = filepath.EvalSymlinks(resolvePath) - if err != nil { - return err + for i := 0; i < 255; i++ { + // Do not use filepath.EvalSymlinks, we only want the first symlink under /run. + // If /etc/resolv.conf has more than one symlink under /run, e.g. + // -> /run/systemd/resolve/stub-resolv.conf -> /run/systemd/resolve/resolv.conf + // we would put the netns resolv.conf file to the last path. However this will + // break dns because the second link does not exists in the mount ns. + // see https://github.com/containers/podman/issues/11222 + link, err := os.Readlink(resolvePath) + if err != nil { + // if there is no symlink exit + break + } + resolvePath = filepath.Join(filepath.Dir(resolvePath), link) + if strings.HasPrefix(resolvePath, "/run/") { + break + } + if i == 254 { + return errors.New("too many symlinks while resolving /etc/resolv.conf") + } } - logrus.Debugf("The actual path of /etc/resolv.conf on the host is %q", resolvePath) + logrus.Debugf("The path of /etc/resolv.conf in the mount ns is %q", resolvePath) // When /etc/resolv.conf on the host is a symlink to /run/systemd/resolve/stub-resolv.conf, // we have to mount an empty filesystem on /run/systemd/resolve in the child namespace, // so as to isolate the directory from the host mount namespace. @@ -1219,7 +1235,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro return err } - // OCICNI will set the loopback adpter down on teardown so we should set it up again + // OCICNI will set the loopback adapter down on teardown so we should set it up again err = c.state.NetNS.Do(func(_ ns.NetNS) error { link, err := netlink.LinkByName("lo") if err != nil { @@ -1229,7 +1245,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro return err }) if err != nil { - logrus.Warnf("failed to set loopback adpter up in the container: %v", err) + logrus.Warnf("failed to set loopback adapter up in the container: %v", err) } // Reload ports when there are still connected networks, maybe we removed the network interface with the child ip. // Reloading without connected networks does not make sense, so we can skip this step. diff --git a/libpod/options.go b/libpod/options.go index b94ef88ba..59aec66c6 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -268,7 +268,7 @@ func WithRegistriesConf(path string) RuntimeOption { logrus.Debugf("Setting custom registries.conf: %q", path) return func(rt *Runtime) error { if _, err := os.Stat(path); err != nil { - return errors.Wrap(err, "error locating specified registries.conf") + return errors.Wrap(err, "locating specified registries.conf") } if rt.imageContext == nil { rt.imageContext = &types.SystemContext{ @@ -1453,7 +1453,7 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { for _, vol := range volumes { mountOpts, err := util.ProcessOptions(vol.Options, false, "") if err != nil { - return errors.Wrapf(err, "error processing options for named volume %q mounted at %q", vol.Name, vol.Dest) + return errors.Wrapf(err, "processing options for named volume %q mounted at %q", vol.Name, vol.Dest) } ctr.config.NamedVolumes = append(ctr.config.NamedVolumes, &ContainerNamedVolume{ diff --git a/libpod/pod_api.go b/libpod/pod_api.go index 6fea2dfd8..716eb2e5b 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -32,14 +32,14 @@ func (p *Pod) startInitContainers(ctx context.Context) error { if rc != 0 { return errors.Errorf("init container %s exited with code %d", initCon.ID(), rc) } - // If the container is an oneshot init container, we need to remove it + // If the container is a once init container, we need to remove it // after it runs if initCon.Config().InitContainerType == define.OneShotInitContainer { icLock := initCon.lock icLock.Lock() if err := p.runtime.removeContainer(ctx, initCon, false, false, true); err != nil { icLock.Unlock() - return errors.Wrapf(err, "failed to remove oneshot init container %s", initCon.ID()) + return errors.Wrapf(err, "failed to remove once init container %s", initCon.ID()) } // Removing a container this way requires an explicit call to clean up the db if err := p.runtime.state.RemoveContainerFromPod(p, initCon); err != nil { diff --git a/libpod/shutdown/handler.go b/libpod/shutdown/handler.go index 848b6729a..1e8a9ec3b 100644 --- a/libpod/shutdown/handler.go +++ b/libpod/shutdown/handler.go @@ -35,7 +35,7 @@ func Start() error { return nil } - sigChan = make(chan os.Signal, 1) + sigChan = make(chan os.Signal, 2) cancelChan = make(chan bool, 1) stopped = false diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 08d1df4b8..0fcca1821 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -34,13 +34,16 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { contentType := hdr[0] switch contentType { case "application/tar": - logrus.Warnf("tar file content type is %s, should use \"application/x-tar\" content type", contentType) + logrus.Infof("tar file content type is %s, should use \"application/x-tar\" content type", contentType) case "application/x-tar": break default: - utils.BadRequest(w, "Content-Type", hdr[0], - fmt.Errorf("Content-Type: %s is not supported. Should be \"application/x-tar\"", hdr[0])) - return + if utils.IsLibpodRequest(r) { + utils.BadRequest(w, "Content-Type", hdr[0], + fmt.Errorf("Content-Type: %s is not supported. Should be \"application/x-tar\"", hdr[0])) + return + } + logrus.Infof("tar file content type is %s, should use \"application/x-tar\" content type", contentType) } } diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go index 04b415638..3c13c6e20 100644 --- a/pkg/api/handlers/libpod/images_pull.go +++ b/pkg/api/handlers/libpod/images_pull.go @@ -33,6 +33,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) { TLSVerify bool `schema:"tlsVerify"` AllTags bool `schema:"allTags"` PullPolicy string `schema:"policy"` + Quiet bool `schema:"quiet"` }{ TLSVerify: true, PullPolicy: "always", @@ -116,8 +117,10 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) { select { case s := <-writer.Chan(): report.Stream = string(s) - if err := enc.Encode(report); err != nil { - logrus.Warnf("Failed to encode json: %v", err) + if !query.Quiet { + if err := enc.Encode(report); err != nil { + logrus.Warnf("Failed to encode json: %v", err) + } } flush() case <-runCtx.Done(): diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go index 1e8edb6dd..1e3647a3e 100644 --- a/pkg/api/handlers/utils/images.go +++ b/pkg/api/handlers/utils/images.go @@ -27,7 +27,7 @@ func IsRegistryReference(name string) error { if imageRef.Transport().Name() == docker.Transport.Name() { return nil } - return errors.Errorf("unsupport transport %s in %q: only docker transport is supported", imageRef.Transport().Name(), name) + return errors.Errorf("unsupported transport %s in %q: only docker transport is supported", imageRef.Transport().Name(), name) } // ParseStorageReference parses the specified image name to a diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 2103c093c..1c61f7f84 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -962,6 +962,15 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: "Mandatory reference to the image (e.g., quay.io/image/name:tag)" // type: string // - in: query + // name: quiet + // description: "silences extra stream data on pull" + // type: boolean + // default: false + // - in: query + // name: credentials + // description: "username:password for the registry" + // type: string + // - in: query // name: Arch // description: Pull image for the specified architecture. // type: string diff --git a/pkg/api/server/register_pods.go b/pkg/api/server/register_pods.go index 3bcc50ba4..58234005e 100644 --- a/pkg/api/server/register_pods.go +++ b/pkg/api/server/register_pods.go @@ -17,7 +17,18 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error { // - in: query // name: filters // type: string - // description: needs description and plumbing for filters + // description: | + // JSON encoded value of the filters (a map[string][]string) to process on the pods list. Available filters: + // - `id=<pod-id>` Matches all of pod id. + // - `label=<key>` or `label=<key>:<value>` Matches pods based on the presence of a label alone or a label and a value. + // - `name=<pod-name>` Matches all of pod name. + // - `until=<timestamp>` List pods created before this timestamp. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time. + // - `status=<pod-status>` Pod's status: `stopped`, `running`, `paused`, `exited`, `dead`, `created`, `degraded`. + // - `network=<pod-network>` Name or full ID of network. + // - `ctr-names=<pod-ctr-names>` Container name within the pod. + // - `ctr-ids=<pod-ctr-ids>` Container ID within the pod. + // - `ctr-status=<pod-ctr-status>` Container status within the pod. + // - `ctr-number=<pod-ctr-number>` Number of containers in the pod. // responses: // 200: // $ref: "#/responses/ListPodsResponse" diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go index dc9fed2a4..269cd2d27 100644 --- a/pkg/domain/filters/containers.go +++ b/pkg/domain/filters/containers.go @@ -214,7 +214,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo networkMode := c.NetworkMode() // support docker like `--filter network=container:<IDorName>` // check if networkMode is configured as `container:<ctr>` - // peform a match against filter `container:<IDorName>` + // perform a match against filter `container:<IDorName>` // networks is already going to be empty if `container:<ctr>` is configured as Mode if strings.HasPrefix(networkMode, "container:") { networkModeContainerPart := strings.SplitN(networkMode, ":", 2) diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go index 9a1c7d19d..9a2f0a3ba 100644 --- a/pkg/domain/filters/pods.go +++ b/pkg/domain/filters/pods.go @@ -116,6 +116,17 @@ func GeneratePodFilterFunc(filter string, filterValues []string) ( labels := p.Labels() return util.MatchLabelFilters(filterValues, labels) }, nil + case "until": + return func(p *libpod.Pod) bool { + until, err := util.ComputeUntilTimestamp(filterValues) + if err != nil { + return false + } + if p.CreatedTime().Before(until) { + return true + } + return false + }, nil case "network": return func(p *libpod.Pod) bool { infra, err := p.InfraContainer() diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go index 26e199aee..a9bd2d5fb 100644 --- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go +++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go @@ -12,13 +12,17 @@ import ( "github.com/sirupsen/logrus" ) +// Make sure the signal buffer is sufficiently big. +// runc is using the same value. +const signalBufferSize = 2048 + // ProxySignals ... func ProxySignals(ctr *libpod.Container) { // Stop catching the shutdown signals (SIGINT, SIGTERM) - they're going // to the container now. shutdown.Stop() - sigBuffer := make(chan os.Signal, 128) + sigBuffer := make(chan os.Signal, signalBufferSize) signal.CatchAll(sigBuffer) logrus.Debugf("Enabling signal proxying") diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 7b1ebcb03..a92892957 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -605,10 +605,12 @@ func CheckActiveVM() (bool, string, error) { // startHostNetworking runs a binary on the host system that allows users // to setup port forwarding to the podman virtual machine func (v *MachineVM) startHostNetworking() error { - binary := filepath.Join("/usr/lib/podman/", machine.ForwarderBinaryName) - if _, err := os.Stat(binary); os.IsNotExist(err) { - return errors.Errorf("unable to find %s", binary) + // TODO we may wish to configure the directory in containers common + binary := filepath.Join("/usr/libexec/podman/", machine.ForwarderBinaryName) + if _, err := os.Stat(binary); err != nil { + return err } + // Listen on all at port 7777 for setting up and tearing // down forwarding listenSocket := "tcp://0.0.0.0:7777" diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index 9ef56acb4..c046ecde7 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -397,8 +397,6 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo return false, -1, errors.Wrapf(err, "error setting up the process") } - c := make(chan os.Signal, 1) - signals := []os.Signal{} for sig := 0; sig < numSig; sig++ { if sig == int(unix.SIGTSTP) { @@ -407,6 +405,7 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo signals = append(signals, unix.Signal(sig)) } + c := make(chan os.Signal, len(signals)) gosignal.Notify(c, signals...) defer gosignal.Reset() go func() { diff --git a/pkg/specgen/generate/storage.go b/pkg/specgen/generate/storage.go index 13f336594..de655ad7d 100644 --- a/pkg/specgen/generate/storage.go +++ b/pkg/specgen/generate/storage.go @@ -10,6 +10,7 @@ import ( "github.com/containers/common/libimage" "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/parse" "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/specgen" @@ -59,6 +60,9 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru for _, m := range s.Mounts { // Ensure that mount dest is clean, so that it can be // compared against named volumes and avoid duplicate mounts. + if err = parse.ValidateVolumeCtrDir(m.Destination); err != nil { + return nil, nil, nil, err + } cleanDestination := filepath.Clean(m.Destination) if _, ok := unifiedMounts[cleanDestination]; ok { return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified mounts - multiple mounts at %q", cleanDestination) @@ -67,34 +71,54 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru } for _, m := range commonMounts { - if _, ok := unifiedMounts[m.Destination]; !ok { - unifiedMounts[m.Destination] = m + if err = parse.ValidateVolumeCtrDir(m.Destination); err != nil { + return nil, nil, nil, err + } + cleanDestination := filepath.Clean(m.Destination) + if _, ok := unifiedMounts[cleanDestination]; !ok { + unifiedMounts[cleanDestination] = m } } for _, v := range s.Volumes { - if _, ok := unifiedVolumes[v.Dest]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Dest) + if err = parse.ValidateVolumeCtrDir(v.Dest); err != nil { + return nil, nil, nil, err } - unifiedVolumes[v.Dest] = v + cleanDestination := filepath.Clean(v.Dest) + if _, ok := unifiedVolumes[cleanDestination]; ok { + return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", cleanDestination) + } + unifiedVolumes[cleanDestination] = v } for _, v := range commonVolumes { - if _, ok := unifiedVolumes[v.Dest]; !ok { - unifiedVolumes[v.Dest] = v + if err = parse.ValidateVolumeCtrDir(v.Dest); err != nil { + return nil, nil, nil, err + } + cleanDestination := filepath.Clean(v.Dest) + if _, ok := unifiedVolumes[cleanDestination]; !ok { + unifiedVolumes[cleanDestination] = v } } for _, v := range s.OverlayVolumes { - if _, ok := unifiedOverlays[v.Destination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Destination) + if err = parse.ValidateVolumeCtrDir(v.Destination); err != nil { + return nil, nil, nil, err } - unifiedOverlays[v.Destination] = v + cleanDestination := filepath.Clean(v.Destination) + if _, ok := unifiedOverlays[cleanDestination]; ok { + return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", cleanDestination) + } + unifiedOverlays[cleanDestination] = v } for _, v := range commonOverlayVolumes { - if _, ok := unifiedOverlays[v.Destination]; ok { - unifiedOverlays[v.Destination] = v + if err = parse.ValidateVolumeCtrDir(v.Destination); err != nil { + return nil, nil, nil, err + } + cleanDestination := filepath.Clean(v.Destination) + if _, ok := unifiedOverlays[cleanDestination]; !ok { + unifiedOverlays[cleanDestination] = v } } @@ -190,6 +214,9 @@ 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": @@ -304,9 +331,13 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s if _, ok := finalMounts[namedVol.Dest]; ok { logrus.Debugf("Overriding named volume mount to %s with new named volume from container %s", namedVol.Dest, ctr.ID()) } + if err = parse.ValidateVolumeCtrDir(namedVol.Dest); err != nil { + return nil, nil, err + } + cleanDest := filepath.Clean(namedVol.Dest) newVol := new(specgen.NamedVolume) - newVol.Dest = namedVol.Dest + newVol.Dest = cleanDest newVol.Options = namedVol.Options newVol.Name = namedVol.Name diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index fc647227e..2252ef405 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -184,7 +184,7 @@ type ContainerBasicConfig struct { // Optional. EnvSecrets map[string]string `json:"secret_env,omitempty"` // InitContainerType describes if this container is an init container - // and if so, what type: always or oneshot + // and if so, what type: always or once InitContainerType string `json:"init_container_type"` // Personality allows users to configure different execution domains. // Execution domains tell Linux how to map signal numbers into signal actions. diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go index d85d2bdd1..eca8c0c35 100644 --- a/pkg/specgen/volumes.go +++ b/pkg/specgen/volumes.go @@ -1,7 +1,6 @@ package specgen import ( - "path/filepath" "strings" "github.com/containers/common/pkg/parse" @@ -93,11 +92,6 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na return nil, nil, nil, errors.New("host directory cannot be empty") } } - if err := parse.ValidateVolumeCtrDir(dest); err != nil { - return nil, nil, nil, err - } - - cleanDest := filepath.Clean(dest) if strings.HasPrefix(src, "/") || strings.HasPrefix(src, ".") { // This is not a named volume @@ -120,7 +114,7 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na if overlayFlag { // This is a overlay volume newOverlayVol := new(OverlayVolume) - newOverlayVol.Destination = cleanDest + newOverlayVol.Destination = dest newOverlayVol.Source = src newOverlayVol.Options = options @@ -130,7 +124,7 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na overlayVolumes[newOverlayVol.Destination] = newOverlayVol } else { newMount := spec.Mount{ - Destination: cleanDest, + Destination: dest, Type: "bind", Source: src, Options: options, @@ -144,7 +138,7 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na // This is a named volume newNamedVol := new(NamedVolume) newNamedVol.Name = src - newNamedVol.Dest = cleanDest + newNamedVol.Dest = dest newNamedVol.Options = options if _, ok := volumes[newNamedVol.Dest]; ok { diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 774590f44..63fad0286 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -618,6 +618,12 @@ func ValidateSysctls(strSlice []string) (map[string]string, error) { if len(arr) < 2 { return nil, errors.Errorf("%s is invalid, sysctl values must be in the form of KEY=VALUE", val) } + + trimmed := fmt.Sprintf("%s=%s", strings.TrimSpace(arr[0]), strings.TrimSpace(arr[1])) + if trimmed != val { + return nil, errors.Errorf("'%s' is invalid, extra spaces found", val) + } + if validSysctlMap[arr[0]] { sysctl[arr[0]] = arr[1] continue diff --git a/pkg/util/utils_test.go b/pkg/util/utils_test.go index 027acbdab..62de7509f 100644 --- a/pkg/util/utils_test.go +++ b/pkg/util/utils_test.go @@ -1,6 +1,7 @@ package util import ( + "fmt" "testing" "time" @@ -259,6 +260,28 @@ func TestValidateSysctlBadSysctl(t *testing.T) { assert.Error(t, err) } +func TestValidateSysctlBadSysctlWithExtraSpaces(t *testing.T) { + expectedError := "'%s' is invalid, extra spaces found" + + // should fail fast on first sysctl + strSlice1 := []string{ + "net.ipv4.ping_group_range = 0 0", + "net.ipv4.ping_group_range=0 0 ", + } + _, err := ValidateSysctls(strSlice1) + assert.Error(t, err) + assert.Equal(t, err.Error(), fmt.Sprintf(expectedError, strSlice1[0])) + + // should fail on second sysctl + strSlice2 := []string{ + "net.ipv4.ping_group_range=0 0", + "net.ipv4.ping_group_range=0 0 ", + } + _, err = ValidateSysctls(strSlice2) + assert.Error(t, err) + assert.Equal(t, err.Error(), fmt.Sprintf(expectedError, strSlice2[1])) +} + func TestCoresToPeriodAndQuota(t *testing.T) { cores := 1.0 expectedPeriod := DefaultCPUPeriod diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at index 195b11ff0..abc8d44b7 100644 --- a/test/apiv2/10-images.at +++ b/test/apiv2/10-images.at @@ -173,7 +173,7 @@ curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \ BUILD_TEST_ERROR="" if ! grep -q '200 OK' "${TMPD}/headers.txt"; then - echo -e "${red}NOK: Image build from tar failed response was not 200 OK" + echo -e "${red}NOK: Image build from tar failed response was not 200 OK (application/x-tar)" BUILD_TEST_ERROR="1" fi @@ -182,6 +182,38 @@ if ! grep -q 'quay.io/libpod/alpine_labels' "${TMPD}/response.txt"; then BUILD_TEST_ERROR="1" fi +curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \ + -H "content-type: application/tar" \ + --dump-header "${TMPD}/headers.txt" \ + -o /dev/null \ + "http://$HOST:$PORT/v1.40/libpod/build?dockerfile=containerfile" &> /dev/null +if ! grep -q '200 OK' "${TMPD}/headers.txt"; then + echo -e "${red}NOK: Image build from tar failed response was not 200 OK (application/tar)" + BUILD_TEST_ERROR="1" +fi + +# Yes, this is very un-RESTful re: Content-Type header ignored when compatibility endpoint used +# See https://github.com/containers/podman/issues/11012 +curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \ + -H "content-type: application/json" \ + --dump-header "${TMPD}/headers.txt" \ + -o /dev/null \ + "http://$HOST:$PORT/v1.40/build?dockerfile=containerfile" &> /dev/null +if ! grep -q '200 OK' "${TMPD}/headers.txt"; then + echo -e "${red}NOK: Image build from tar failed response was not 200 OK (application/tar)" + BUILD_TEST_ERROR="1" +fi + +curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \ + -H "content-type: application/json" \ + --dump-header "${TMPD}/headers.txt" \ + -o /dev/null \ + "http://$HOST:$PORT/v1.40/libpod/build?dockerfile=containerfile" &> /dev/null +if ! grep -q '400 Bad Request' "${TMPD}/headers.txt"; then + echo -e "${red}NOK: Image build should have failed with 400 (wrong Content-Type)" + BUILD_TEST_ERROR="1" +fi + cleanBuildTest if [[ "${BUILD_TEST_ERROR}" ]]; then exit 1 diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index 610d3e36d..e2eb94233 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -356,3 +356,14 @@ t GET containers/$cid/json 200 \ .HostConfig.NetworkMode="bridge" t DELETE containers/$cid?v=true 204 + +# Test Compat Create with healthcheck, check default values +t POST containers/create Image=$IMAGE Cmd='["top"]' Healthcheck='{"Test":["true"]}' 201 \ + .Id~[0-9a-f]\\{64\\} +cid=$(jq -r '.Id' <<<"$output") +t GET containers/$cid/json 200 \ + .Config.Healthcheck.Interval=30000000000 \ + .Config.Healthcheck.Timeout=30000000000 \ + .Config.Healthcheck.Retries=3 + +t DELETE containers/$cid?v=true 204 diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at index 94c72dbaa..985b26411 100644 --- a/test/apiv2/40-pods.at +++ b/test/apiv2/40-pods.at @@ -19,6 +19,9 @@ t GET libpod/pods/json 200 \ .[0].Id=$pod_id \ .[0].Containers\|length=1 +t GET libpod/pods/json?filters='{"until":["500000"]}' 200 length=0 +t GET libpod/pods/json?filters='{"until":["5000000000"]}' 200 length=1 + # Cannot create a dup pod with the same name t POST "libpod/pods/create (dup pod)" name=foo 409 \ .cause="pod already exists" diff --git a/test/apiv2/python/rest_api/test_v2_0_0_image.py b/test/apiv2/python/rest_api/test_v2_0_0_image.py index 3e8ecb1ef..bcacaa935 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_image.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_image.py @@ -87,6 +87,27 @@ class ImageTestCase(APITestCase): self.assertTrue(keys["images"], "Expected to find images stanza") self.assertTrue(keys["stream"], "Expected to find stream progress stanza's") + r = requests.post(self.uri("/images/pull?reference=alpine&quiet=true"), timeout=15) + self.assertEqual(r.status_code, 200, r.status_code) + text = r.text + keys = { + "error": False, + "id": False, + "images": False, + "stream": False, + } + # Read and record stanza's from pull + for line in str.splitlines(text): + obj = json.loads(line) + key_list = list(obj.keys()) + for k in key_list: + keys[k] = True + + self.assertFalse(keys["error"], "Expected no errors") + self.assertTrue(keys["id"], "Expected to find id stanza") + self.assertTrue(keys["images"], "Expected to find images stanza") + self.assertFalse(keys["stream"], "Expected to find stream progress stanza's") + def test_create(self): r = requests.post( self.podman_url + "/v1.40/images/create?fromImage=alpine&platform=linux/amd64/v8", diff --git a/test/e2e/pod_initcontainers_test.go b/test/e2e/pod_initcontainers_test.go index 606294f51..11e7ca400 100644 --- a/test/e2e/pod_initcontainers_test.go +++ b/test/e2e/pod_initcontainers_test.go @@ -98,10 +98,10 @@ var _ = Describe("Podman init containers", func() { Expect(checkLog.OutputToString()).To(Equal(content)) }) - It("podman make sure oneshot container is removed", func() { + It("podman make sure once container is removed", func() { filename := filepath.Join("/dev/shm", RandomString(12)) content := RandomString(16) - session := podmanTest.Podman([]string{"create", "--init-ctr", "oneshot", "--pod", "new:foobar", ALPINE, "bin/sh", "-c", fmt.Sprintf("echo %s > %s", content, filename)}) + session := podmanTest.Podman([]string{"create", "--init-ctr", "once", "--pod", "new:foobar", ALPINE, "bin/sh", "-c", fmt.Sprintf("echo %s > %s", content, filename)}) session.WaitWithDefaultTimeout() initContainerID := session.OutputToString() Expect(session).Should(Exit(0)) diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go index c27539d6f..b4a0df904 100644 --- a/test/e2e/pod_ps_test.go +++ b/test/e2e/pod_ps_test.go @@ -108,6 +108,22 @@ var _ = Describe("Podman ps", func() { Expect(result).Should(Exit(0)) }) + It("podman pod ps --filter until", func() { + name := "mypod" + _, ec, _ := podmanTest.CreatePod(map[string][]string{"--name": {name}}) + Expect(ec).To(Equal(0)) + + result := podmanTest.Podman([]string{"pod", "ps", "--filter", "until=50"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(Not(ContainSubstring(name))) + + result = podmanTest.Podman([]string{"pod", "ps", "--filter", "until=5000000000"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(ContainSubstring(name)) + }) + It("podman pod ps filter name regexp", func() { _, ec, podid := podmanTest.CreatePod(map[string][]string{"--name": {"mypod"}}) Expect(ec).To(Equal(0)) diff --git a/test/e2e/run_device_test.go b/test/e2e/run_device_test.go index 40de1d50d..08905aed2 100644 --- a/test/e2e/run_device_test.go +++ b/test/e2e/run_device_test.go @@ -41,36 +41,35 @@ var _ = Describe("Podman run device", func() { }) It("podman run device test", func() { - session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg", ALPINE, "ls", "--color=never", "/dev/kmsg"}) + session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg", ALPINE, "test", "-c", "/dev/kmsg"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(Equal("/dev/kmsg")) }) It("podman run device rename test", func() { - session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:/dev/kmsg1", ALPINE, "ls", "--color=never", "/dev/kmsg1"}) + // TODO: Confirm absence of /dev/kmsg in container + session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:/dev/kmsg1", ALPINE, "test", "-c", "/dev/kmsg1"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(Equal("/dev/kmsg1")) }) It("podman run device permission test", func() { - session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:r", ALPINE, "ls", "--color=never", "/dev/kmsg"}) + // TODO: Confirm write-permission failure + session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:r", ALPINE, "test", "-r", "/dev/kmsg"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(Equal("/dev/kmsg")) }) It("podman run device rename and permission test", func() { - session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:/dev/kmsg1:r", ALPINE, "ls", "--color=never", "/dev/kmsg1"}) + // TODO: Confirm write-permission failure + session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:/dev/kmsg1:r", ALPINE, "test", "-r", "/dev/kmsg1"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(Equal("/dev/kmsg1")) }) It("podman run device rename and bad permission test", func() { - session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:/dev/kmsg1:rd", ALPINE, "ls", "--color=never", "/dev/kmsg1"}) + session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:/dev/kmsg1:rd", ALPINE, "true"}) session.WaitWithDefaultTimeout() - Expect(session).To(ExitWithError()) + Expect(session).Should(Exit(125)) }) It("podman run device host device and container device parameter are directories", func() { @@ -89,12 +88,13 @@ var _ = Describe("Podman run device", func() { }) It("podman run device host device with --privileged", func() { - if _, err := os.Stat("/dev/kvm"); err != nil { - Skip("/dev/kvm not available") - } - session := podmanTest.Podman([]string{"run", "--privileged", ALPINE, "ls", "/dev/kvm"}) + session := podmanTest.Podman([]string{"run", "--privileged", ALPINE, "test", "-c", "/dev/kmsg"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + // verify --privileged is required + session2 := podmanTest.Podman([]string{"run", ALPINE, "test", "-c", "/dev/kmsg"}) + session2.WaitWithDefaultTimeout() + Expect(session2).Should((Exit(1))) }) It("podman run CDI device test", func() { @@ -109,14 +109,13 @@ var _ = Describe("Podman run device", func() { err = cmd.Run() Expect(err).To(BeNil()) - session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "myKmsg", ALPINE, "ls", "--color=never", "/dev/kmsg1"}) + session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "myKmsg", ALPINE, "test", "-c", "/dev/kmsg1"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(Equal("/dev/kmsg1")) }) It("podman run --gpus noop", func() { - session := podmanTest.Podman([]string{"run", "--gpus", "all", ALPINE, "ls", "/"}) + session := podmanTest.Podman([]string{"run", "--gpus", "all", ALPINE, "true"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) }) diff --git a/test/python/requirements.txt b/test/python/requirements.txt index ee85bf1d1..f177f76fc 100644 --- a/test/python/requirements.txt +++ b/test/python/requirements.txt @@ -1,5 +1,5 @@ docker~=4.4.3 - +requests-mock~=1.9.3 requests~=2.20.0 setuptools~=50.3.2 python-dateutil~=2.8.1 diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats index 69ebebcd6..8bb32b5b7 100644 --- a/test/system/255-auto-update.bats +++ b/test/system/255-auto-update.bats @@ -102,7 +102,7 @@ function _wait_service_ready() { let timeout=$timeout-1 done - # Print serivce status as debug information before failed the case + # Print service status as debug information before failed the case systemctl status $sname die "Timed out waiting for $sname to start" } @@ -305,7 +305,7 @@ EOF fi done - # Only check the last service is started. Previous services should already actived. + # Only check that the last service is started. Previous services should already be activated. _wait_service_ready container-$cname.service run_podman commit --change CMD=/bin/bash $local_cname quay.io/libpod/localtest:latest # Exit code is expected, due to invalid 'fakevalue' diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index 6ffee7eaf..3ebe45e63 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -210,6 +210,9 @@ load helpers $IMAGE nc -l -n -v -p $myport cid="$output" + # check that dns is working inside the container + run_podman exec $cid nslookup google.com + # emit random string, and check it teststring=$(random_string 30) echo "$teststring" | nc 127.0.0.1 $myport diff --git a/test/system/700-play.bats b/test/system/700-play.bats index 3e6961b08..498956b9a 100644 --- a/test/system/700-play.bats +++ b/test/system/700-play.bats @@ -94,9 +94,9 @@ RELABEL="system_u:object_r:container_file_t:s0" mkdir -p $TESTDIR echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml run_podman 125 play kube --network bridge $PODMAN_TMPDIR/test.yaml - is "$output" ".*invalid value passed to --network: bridge or host networking must be configured in YAML" "podman plan-network should fail wth --network host" + is "$output" ".*invalid value passed to --network: bridge or host networking must be configured in YAML" "podman plan-network should fail with --network host" run_podman 125 play kube --network host $PODMAN_TMPDIR/test.yaml - is "$output" ".*invalid value passed to --network: bridge or host networking must be configured in YAML" "podman plan-network should fail wth --network host" + is "$output" ".*invalid value passed to --network: bridge or host networking must be configured in YAML" "podman plan-network should fail with --network host" run_podman play kube --network slirp4netns:port_handler=slirp4netns $PODMAN_TMPDIR/test.yaml run_podman pod rm -f test_pod } diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index 2b17ffd50..a95a46d9f 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.34.0 +1.34.1 diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go index abb9ab71d..f546f9b10 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go @@ -1941,7 +1941,7 @@ func (al *additionalLayer) Info() (io.ReadCloser, error) { return os.Open(filepath.Join(al.path, "info")) } -// Blob returns a reader of the raw contents of this leyer. +// Blob returns a reader of the raw contents of this layer. func (al *additionalLayer) Blob() (io.ReadCloser, error) { return os.Open(filepath.Join(al.path, "blob")) } diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod index ff14799a2..d2d438d93 100644 --- a/vendor/github.com/containers/storage/go.mod +++ b/vendor/github.com/containers/storage/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/go-intervals v0.0.2 github.com/hashicorp/go-multierror v1.1.1 github.com/json-iterator/go v1.1.11 - github.com/klauspost/compress v1.13.3 + github.com/klauspost/compress v1.13.4 github.com/klauspost/pgzip v1.2.5 github.com/mattn/go-shellwords v1.0.12 github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible @@ -18,7 +18,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/runc v1.0.1 github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 - github.com/opencontainers/selinux v1.8.3 + github.com/opencontainers/selinux v1.8.4 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.0 diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum index 71ababfb2..da7a8f53e 100644 --- a/vendor/github.com/containers/storage/go.sum +++ b/vendor/github.com/containers/storage/go.sum @@ -388,8 +388,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.3 h1:BtAvtV1+h0YwSVwWoYXMREPpYu9VzTJ9QDI1TEg/iQQ= -github.com/klauspost/compress v1.13.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -482,8 +482,8 @@ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mo github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/opencontainers/selinux v1.8.3 h1:tzZR7AuKB5gU1+53uBkoG4XdIFGZzvJTOVoNbRQI8/4= -github.com/opencontainers/selinux v1.8.3/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo= +github.com/opencontainers/selinux v1.8.4 h1:krlgQ6/j9CkCXT5oW0yVXdQFOME3NjKuuAZXuR6O7P4= +github.com/opencontainers/selinux v1.8.4/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go index fa0dce033..b85ff7e70 100644 --- a/vendor/github.com/containers/storage/layers.go +++ b/vendor/github.com/containers/storage/layers.go @@ -27,6 +27,7 @@ import ( digest "github.com/opencontainers/go-digest" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/vbatts/tar-split/archive/tar" "github.com/vbatts/tar-split/tar/asm" "github.com/vbatts/tar-split/tar/storage" @@ -1407,7 +1408,7 @@ func (r *layerStore) Diff(from, to string, options *DiffOptions) (io.ReadCloser, if ad, ok := r.driver.(drivers.AdditionalLayerStoreDriver); ok { if aLayer, err := ad.LookupAdditionalLayerByID(to); err == nil { - // This is an additional layer. We leverage blob API for aquiring the reproduced raw blob. + // This is an additional layer. We leverage blob API for acquiring the reproduced raw blob. info, err := aLayer.Info() if err != nil { aLayer.Release() @@ -1529,6 +1530,9 @@ func (r *layerStore) ApplyDiff(to string, diff io.Reader) (size int64, err error if err != nil { compressor = pgzip.NewWriter(&tsdata) } + if err := compressor.SetConcurrency(1024*1024, 1); err != nil { // 1024*1024 is the hard-coded default; we're not changing that + logrus.Infof("error setting compression concurrency threads to 1: %v; ignoring", err) + } metadata := storage.NewJSONPacker(compressor) uncompressed, err := archive.DecompressStream(defragmented) if err != nil { diff --git a/vendor/github.com/containers/storage/types/utils.go b/vendor/github.com/containers/storage/types/utils.go index 5dbbb4403..b7ab07342 100644 --- a/vendor/github.com/containers/storage/types/utils.go +++ b/vendor/github.com/containers/storage/types/utils.go @@ -160,9 +160,6 @@ func expandEnvPath(path string, rootlessUID int) (string, error) { path = os.ExpandEnv(path) newpath, err := filepath.EvalSymlinks(path) if err != nil { - if !os.IsNotExist(err) { - return "", err - } newpath = filepath.Clean(path) } return newpath, nil diff --git a/vendor/github.com/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md index 48851e0ce..d6a26466c 100644 --- a/vendor/github.com/klauspost/compress/README.md +++ b/vendor/github.com/klauspost/compress/README.md @@ -5,6 +5,7 @@ This package provides various compression algorithms. * [zstandard](https://github.com/klauspost/compress/tree/master/zstd#zstd) compression and decompression in pure Go.
* [S2](https://github.com/klauspost/compress/tree/master/s2#s2-compression) is a high performance replacement for Snappy.
* Optimized [deflate](https://godoc.org/github.com/klauspost/compress/flate) packages which can be used as a dropin replacement for [gzip](https://godoc.org/github.com/klauspost/compress/gzip), [zip](https://godoc.org/github.com/klauspost/compress/zip) and [zlib](https://godoc.org/github.com/klauspost/compress/zlib).
+* [snappy](https://github.com/klauspost/compress/tree/master/snappy) is a drop-in replacement for `github.com/golang/snappy` offering better compression and concurrent streams.
* [huff0](https://github.com/klauspost/compress/tree/master/huff0) and [FSE](https://github.com/klauspost/compress/tree/master/fse) implementations for raw entropy encoding.
* [gzhttp](https://github.com/klauspost/compress/tree/master/gzhttp) Provides client and server wrappers for handling gzipped requests efficiently.
* [pgzip](https://github.com/klauspost/pgzip) is a separate package that provides a very fast parallel gzip implementation.
@@ -16,6 +17,15 @@ This package provides various compression algorithms. # changelog
+* Aug 3, 2021 (v1.13.3)
+
+ * zstd: Improve Best compression [#404](https://github.com/klauspost/compress/pull/404)
+ * zstd: Fix WriteTo error forwarding [#411](https://github.com/klauspost/compress/pull/411)
+ * gzhttp: Return http.HandlerFunc instead of http.Handler. Unlikely breaking change. [#406](https://github.com/klauspost/compress/pull/406)
+ * s2sx: Fix max size error [#399](https://github.com/klauspost/compress/pull/399)
+ * zstd: Add optional stream content size on reset [#401](https://github.com/klauspost/compress/pull/401)
+ * zstd: use SpeedBestCompression for level >= 10 [#410](https://github.com/klauspost/compress/pull/410)
+
* Jun 14, 2021 (v1.13.1)
* s2: Add full Snappy output support [#396](https://github.com/klauspost/compress/pull/396)
diff --git a/vendor/github.com/klauspost/compress/zstd/enc_best.go b/vendor/github.com/klauspost/compress/zstd/enc_best.go index 41025d62b..96028ecd8 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_best.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_best.go @@ -5,6 +5,7 @@ package zstd import ( + "bytes" "fmt" "github.com/klauspost/compress" @@ -208,6 +209,11 @@ encodeLoop: if s-offset >= e.maxMatchOff || load3232(src, offset) != first { return match{s: s, est: highScore} } + if debugAsserts { + if !bytes.Equal(src[s:s+4], src[offset:offset+4]) { + panic(fmt.Sprintf("first match mismatch: %v != %v, first: %08x", src[s:s+4], src[offset:offset+4], first)) + } + } m := match{offset: offset, s: s, length: 4 + e.matchlen(s+4, offset+4, src), rep: rep} m.estBits(bitsPerByte) return m @@ -218,17 +224,17 @@ encodeLoop: best = bestOf(best, matchAt(candidateS.prev-e.cur, s, uint32(cv), -1)) if canRepeat && best.length < goodEnough { - cv := uint32(cv >> 8) + cv32 := uint32(cv >> 8) spp := s + 1 - best = bestOf(best, matchAt(spp-offset1, spp, cv, 1)) - best = bestOf(best, matchAt(spp-offset2, spp, cv, 2)) - best = bestOf(best, matchAt(spp-offset3, spp, cv, 3)) + best = bestOf(best, matchAt(spp-offset1, spp, cv32, 1)) + best = bestOf(best, matchAt(spp-offset2, spp, cv32, 2)) + best = bestOf(best, matchAt(spp-offset3, spp, cv32, 3)) if best.length > 0 { - cv >>= 16 + cv32 = uint32(cv >> 24) spp += 2 - best = bestOf(best, matchAt(spp-offset1, spp, cv, 1)) - best = bestOf(best, matchAt(spp-offset2, spp, cv, 2)) - best = bestOf(best, matchAt(spp-offset3, spp, cv, 3)) + best = bestOf(best, matchAt(spp-offset1, spp, cv32, 1)) + best = bestOf(best, matchAt(spp-offset2, spp, cv32, 2)) + best = bestOf(best, matchAt(spp-offset3, spp, cv32, 3)) } } // Load next and check... @@ -281,6 +287,12 @@ encodeLoop: } } + if debugAsserts { + if !bytes.Equal(src[best.s:best.s+best.length], src[best.offset:best.offset+best.length]) { + panic(fmt.Sprintf("match mismatch: %v != %v", src[best.s:best.s+best.length], src[best.offset:best.offset+best.length])) + } + } + // We have a match, we can store the forward value if best.rep > 0 { s = best.s @@ -356,7 +368,7 @@ encodeLoop: panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) } - if debugAsserts && canRepeat && int(offset1) > len(src) { + if debugAsserts && int(offset1) > len(src) { panic("invalid offset") } diff --git a/vendor/modules.txt b/vendor/modules.txt index 64de28cc3..204789a96 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -198,7 +198,7 @@ github.com/containers/psgo/internal/dev github.com/containers/psgo/internal/host github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/process -# github.com/containers/storage v1.34.0 +# github.com/containers/storage v1.34.1 github.com/containers/storage github.com/containers/storage/drivers github.com/containers/storage/drivers/aufs @@ -405,7 +405,7 @@ github.com/json-iterator/go # github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a github.com/juju/ansiterm github.com/juju/ansiterm/tabwriter -# github.com/klauspost/compress v1.13.3 +# github.com/klauspost/compress v1.13.4 github.com/klauspost/compress github.com/klauspost/compress/flate github.com/klauspost/compress/fse |