summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/volumes.go29
-rw-r--r--cmd/podman/containers/exec.go4
-rw-r--r--cmd/podman/images/list.go6
-rw-r--r--cmd/podman/pods/ps.go5
-rw-r--r--cmd/podman/system/migrate.go2
-rw-r--r--cmd/podman/system/renumber.go2
-rw-r--r--cmd/podman/system/reset.go2
-rw-r--r--cmd/podman/system/service.go2
-rw-r--r--cmd/podman/system/service_abi.go2
-rw-r--r--cmd/podman/system/service_unsupported.go2
-rw-r--r--cmd/podman/system/varlink.go2
-rw-r--r--go.mod8
-rw-r--r--go.sum14
-rw-r--r--pkg/api/handlers/compat/resize.go4
-rw-r--r--pkg/api/handlers/utils/pods.go1
-rw-r--r--pkg/api/server/register_exec.go2
-rw-r--r--pkg/bindings/connection.go60
-rw-r--r--pkg/bindings/containers/attach.go481
-rw-r--r--pkg/bindings/containers/containers.go253
-rw-r--r--pkg/domain/entities/pods.go1
-rw-r--r--pkg/domain/infra/abi/pods.go1
-rw-r--r--pkg/domain/infra/tunnel/containers.go36
-rw-r--r--pkg/specgen/container_validate.go3
-rw-r--r--test/e2e/exec_test.go2
-rw-r--r--test/e2e/images_test.go15
-rw-r--r--test/e2e/pod_ps_test.go16
-rw-r--r--test/system/075-exec.bats15
-rw-r--r--test/system/200-pod.bats32
-rw-r--r--test/system/500-networking.bats23
-rw-r--r--troubleshooting.md39
-rw-r--r--vendor/github.com/containers/psgo/SECURITY.md3
-rw-r--r--vendor/github.com/containers/psgo/psgo.go4
-rw-r--r--vendor/github.com/onsi/ginkgo/CHANGELOG.md5
-rw-r--r--vendor/github.com/onsi/ginkgo/README.md18
-rw-r--r--vendor/github.com/onsi/ginkgo/config/config.go2
-rw-r--r--vendor/github.com/onsi/ginkgo/extensions/table/table.go37
-rw-r--r--vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go33
-rw-r--r--vendor/github.com/onsi/ginkgo/ginkgo_dsl.go85
-rw-r--r--vendor/github.com/onsi/ginkgo/internal/global/init.go18
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go10
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go29
-rw-r--r--vendor/modules.txt9
42 files changed, 862 insertions, 455 deletions
diff --git a/cmd/podman/common/volumes.go b/cmd/podman/common/volumes.go
index a70410ad3..63bb8e5f0 100644
--- a/cmd/podman/common/volumes.go
+++ b/cmd/podman/common/volumes.go
@@ -209,36 +209,21 @@ func getBindMount(args []string) (spec.Mount, error) {
switch kv[0] {
case "bind-nonrecursive":
newMount.Options = append(newMount.Options, "bind")
- case "readonly", "read-only":
- if setRORW {
- return newMount, errors.Wrapf(optionArgError, "cannot pass 'readonly', 'ro', or 'rw' options more than once")
- }
- setRORW = true
- switch len(kv) {
- case 1:
- newMount.Options = append(newMount.Options, "ro")
- case 2:
- switch strings.ToLower(kv[1]) {
- case "true":
- newMount.Options = append(newMount.Options, "ro")
- case "false":
- // RW is default, so do nothing
- default:
- return newMount, errors.Wrapf(optionArgError, "readonly must be set to true or false, instead received %q", kv[1])
- }
- default:
- return newMount, errors.Wrapf(optionArgError, "badly formatted option %q", val)
- }
- case "ro", "rw":
+ case "readonly", "ro", "rw":
if setRORW {
return newMount, errors.Wrapf(optionArgError, "cannot pass 'readonly', 'ro', or 'rw' options more than once")
}
setRORW = true
// Can be formatted as one of:
+ // readonly
+ // readonly=[true|false]
// ro
// ro=[true|false]
// rw
// rw=[true|false]
+ if kv[0] == "readonly" {
+ kv[0] = "ro"
+ }
switch len(kv) {
case 1:
newMount.Options = append(newMount.Options, kv[0])
@@ -253,7 +238,7 @@ func getBindMount(args []string) (spec.Mount, error) {
newMount.Options = append(newMount.Options, "ro")
}
default:
- return newMount, errors.Wrapf(optionArgError, "%s must be set to true or false, instead received %q", kv[0], kv[1])
+ return newMount, errors.Wrapf(optionArgError, "'readonly', 'ro', or 'rw' must be set to true or false, instead received %q", kv[1])
}
default:
return newMount, errors.Wrapf(optionArgError, "badly formatted option %q", val)
diff --git a/cmd/podman/containers/exec.go b/cmd/podman/containers/exec.go
index 7554d6a93..41f100768 100644
--- a/cmd/podman/containers/exec.go
+++ b/cmd/podman/containers/exec.go
@@ -67,14 +67,14 @@ func execFlags(flags *pflag.FlagSet) {
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode},
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: execCommand,
})
flags := execCommand.Flags()
execFlags(flags)
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode},
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: containerExecCommand,
Parent: containerCmd,
})
diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go
index 4f8948b8b..23757104b 100644
--- a/cmd/podman/images/list.go
+++ b/cmd/podman/images/list.go
@@ -234,11 +234,7 @@ func imageListFormat(flags listFlagType) (string, string) {
}
hdr += "\tIMAGE ID"
- if flags.noTrunc {
- row += "\tsha256:{{.ID}}"
- } else {
- row += "\t{{.ID}}"
- }
+ row += "\t{{.ID}}"
hdr += "\tCREATED\tSIZE"
row += "\t{{.Created}}\t{{.Size}}"
diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go
index 5703bd172..1385ff270 100644
--- a/cmd/podman/pods/ps.go
+++ b/cmd/podman/pods/ps.go
@@ -178,6 +178,11 @@ func (l ListPodReporter) Created() string {
return units.HumanDuration(time.Since(l.ListPodsReport.Created)) + " ago"
}
+// Labels returns a map of the pod's labels
+func (l ListPodReporter) Labels() map[string]string {
+ return l.ListPodsReport.Labels
+}
+
// NumberofContainers returns an int representation for
// the number of containers belonging to the pod
func (l ListPodReporter) NumberOfContainers() int {
diff --git a/cmd/podman/system/migrate.go b/cmd/podman/system/migrate.go
index 13aa162c7..28c23d88f 100644
--- a/cmd/podman/system/migrate.go
+++ b/cmd/podman/system/migrate.go
@@ -1,3 +1,5 @@
+// +build !remote
+
package system
import (
diff --git a/cmd/podman/system/renumber.go b/cmd/podman/system/renumber.go
index 5ee6b3be6..b90640de3 100644
--- a/cmd/podman/system/renumber.go
+++ b/cmd/podman/system/renumber.go
@@ -1,3 +1,5 @@
+// +build !remote
+
package system
import (
diff --git a/cmd/podman/system/reset.go b/cmd/podman/system/reset.go
index 6caa91690..b16fbd9c7 100644
--- a/cmd/podman/system/reset.go
+++ b/cmd/podman/system/reset.go
@@ -1,3 +1,5 @@
+// +build !remote
+
package system
import (
diff --git a/cmd/podman/system/service.go b/cmd/podman/system/service.go
index 0f42ae28b..1b07ee301 100644
--- a/cmd/podman/system/service.go
+++ b/cmd/podman/system/service.go
@@ -1,4 +1,4 @@
-// +build linux
+// +build linux,!remote
package system
diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go
index 3da6ccfc7..501650839 100644
--- a/cmd/podman/system/service_abi.go
+++ b/cmd/podman/system/service_abi.go
@@ -1,4 +1,4 @@
-// +build ABISupport
+// +build ABISupport,!remote
package system
diff --git a/cmd/podman/system/service_unsupported.go b/cmd/podman/system/service_unsupported.go
index 95f8189f6..82272c882 100644
--- a/cmd/podman/system/service_unsupported.go
+++ b/cmd/podman/system/service_unsupported.go
@@ -1,4 +1,4 @@
-// +build !ABISupport
+// +build !ABISupport,!remote
package system
diff --git a/cmd/podman/system/varlink.go b/cmd/podman/system/varlink.go
index 6a38b3d28..19535e539 100644
--- a/cmd/podman/system/varlink.go
+++ b/cmd/podman/system/varlink.go
@@ -1,4 +1,4 @@
-// +build linux
+// +build linux,!remote
package system
diff --git a/go.mod b/go.mod
index dd2550585..617f118f1 100644
--- a/go.mod
+++ b/go.mod
@@ -14,9 +14,9 @@ require (
github.com/containers/common v0.12.0
github.com/containers/conmon v2.0.16+incompatible
github.com/containers/image/v5 v5.4.5-0.20200529084758-46b2ee6aebb0
- github.com/containers/psgo v1.5.0
+ github.com/containers/psgo v1.5.1
github.com/containers/storage v1.20.1
- github.com/coreos/go-systemd/v22 v22.0.0
+ github.com/coreos/go-systemd/v22 v22.1.0
github.com/cri-o/ocicni v0.2.0
github.com/cyphar/filepath-securejoin v0.2.2
github.com/davecgh/go-spew v1.1.1
@@ -35,11 +35,11 @@ require (
github.com/hpcloud/tail v1.0.0
github.com/json-iterator/go v1.1.9
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618
- github.com/onsi/ginkgo v1.12.2
+ github.com/onsi/ginkgo v1.12.3
github.com/onsi/gomega v1.10.1
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
- github.com/opencontainers/runc v1.0.0-rc9
+ github.com/opencontainers/runc v1.0.0-rc90
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2
github.com/opencontainers/runtime-tools v0.9.0
github.com/opencontainers/selinux v1.5.2
diff --git a/go.sum b/go.sum
index 12823b765..38fdfe902 100644
--- a/go.sum
+++ b/go.sum
@@ -47,6 +47,7 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s=
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
+github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 h1:uict5mhHFTzKLUCufdSLym7z/J0CbBJT59lYbP9wtbg=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
@@ -81,8 +82,8 @@ github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDpl
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.0.2 h1:Q0/IPs8ohfbXNxEfyJ2pFVmvJu5BhqJUAmc6ES9NKbo=
github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNjsqWarIUce4M=
-github.com/containers/psgo v1.5.0 h1:uofUREsrm0Ls5K4tkEIFPqWSHKyg3Bvoqo/Q2eDmj8g=
-github.com/containers/psgo v1.5.0/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
+github.com/containers/psgo v1.5.1 h1:MQNb7FLbXqBdqz6u4lI2QWizVz4RSTzs1+Nk9XT1iVA=
+github.com/containers/psgo v1.5.1/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
github.com/containers/storage v1.18.2/go.mod h1:WTBMf+a9ZZ/LbmEVeLHH2TX4CikWbO1Bt+/m58ZHVPg=
github.com/containers/storage v1.19.1/go.mod h1:KbXjSwKnx17ejOsjFcCXSf78mCgZkQSLPBNTMRc3XrQ=
github.com/containers/storage v1.19.2/go.mod h1:gYCp3jzgXkvubO0rI14QAjz5Mxm/qKJgLmHFyqayDnw=
@@ -96,8 +97,8 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/go-systemd/v22 v22.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28=
-github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
+github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg=
+github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@@ -315,6 +316,8 @@ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.12.2 h1:Ke9m3h2Hu0wsZ45yewCqhYr3Z+emcNTuLY2nMWCkrSI=
github.com/onsi/ginkgo v1.12.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
+github.com/onsi/ginkgo v1.12.3 h1:+RYp9QczoWz9zfUyLP/5SLXQVhfr6gZOoKGfQqHuLZQ=
+github.com/onsi/ginkgo v1.12.3/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -336,6 +339,8 @@ github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4/go.mod h1:qT5X
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU4LguQVtc=
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opencontainers/runc v1.0.0-rc90 h1:4+xo8mtWixbHoEm451+WJNUrq12o2/tDsyK9Vgc/NcA=
+github.com/opencontainers/runc v1.0.0-rc90/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2 h1:9mv9SC7GWmRWE0J/+oD8w3GsN2KYGKtg6uwLN7hfP5E=
@@ -448,6 +453,7 @@ github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ulikunitz/xz v0.5.7 h1:YvTNdFzX6+W5m9msiYg/zpkSURPPtOlzbqYjrFn7Yt4=
github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5 h1:MCfT24H3f//U5+UCrZp1/riVO3B50BovxtDiNn0XKkk=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b h1:hdDRrn9OP/roL8a/e/5Zu85ldrcdndu9IeBj2OEvQm0=
diff --git a/pkg/api/handlers/compat/resize.go b/pkg/api/handlers/compat/resize.go
index 231b53175..478a8fab4 100644
--- a/pkg/api/handlers/compat/resize.go
+++ b/pkg/api/handlers/compat/resize.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/gorilla/mux"
"github.com/gorilla/schema"
"github.com/pkg/errors"
"k8s.io/client-go/tools/remotecommand"
@@ -37,9 +38,9 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) {
}
var status int
- name := utils.GetName(r)
switch {
case strings.Contains(r.URL.Path, "/containers/"):
+ name := utils.GetName(r)
ctnr, err := runtime.LookupContainer(name)
if err != nil {
utils.ContainerNotFound(w, name, err)
@@ -61,6 +62,7 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) {
// reasons.
status = http.StatusOK
case strings.Contains(r.URL.Path, "/exec/"):
+ name := mux.Vars(r)["id"]
ctnr, err := runtime.GetExecSessionContainer(name)
if err != nil {
utils.SessionNotFound(w, name, err)
diff --git a/pkg/api/handlers/utils/pods.go b/pkg/api/handlers/utils/pods.go
index fb795fa6a..5b6f6d34d 100644
--- a/pkg/api/handlers/utils/pods.go
+++ b/pkg/api/handlers/utils/pods.go
@@ -66,6 +66,7 @@ func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport
Namespace: pod.Namespace(),
Status: status,
InfraId: infraId,
+ Labels: pod.Labels(),
}
for _, ctr := range ctrs {
state, err := ctr.State()
diff --git a/pkg/api/server/register_exec.go b/pkg/api/server/register_exec.go
index 1533edba9..17181d286 100644
--- a/pkg/api/server/register_exec.go
+++ b/pkg/api/server/register_exec.go
@@ -310,7 +310,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchExecInstance"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/exec/{id}/resize"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/exec/{id}/resize"), s.APIHandler(compat.ResizeTTY)).Methods(http.MethodPost)
// swagger:operation GET /libpod/exec/{id}/json libpod libpodInspectExec
// ---
// tags:
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index e9032f083..c26093a7f 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -24,7 +24,7 @@ import (
)
var (
- basePath = &url.URL{
+ BasePath = &url.URL{
Scheme: "http",
Host: "d",
Path: "/v" + APIVersion.String() + "/libpod",
@@ -37,15 +37,14 @@ type APIResponse struct {
}
type Connection struct {
- _url *url.URL
- client *http.Client
- conn *net.Conn
+ Uri *url.URL
+ Client *http.Client
}
type valueKey string
const (
- clientKey = valueKey("client")
+ clientKey = valueKey("Client")
)
// GetClient from context build by NewConnection()
@@ -59,7 +58,7 @@ func GetClient(ctx context.Context) (*Connection, error) {
// JoinURL elements with '/'
func JoinURL(elements ...string) string {
- return strings.Join(elements, "/")
+ return "/" + strings.Join(elements, "/")
}
// NewConnection takes a URI as a string and returns a context with the
@@ -88,7 +87,7 @@ func NewConnection(ctx context.Context, uri string, identity ...string) (context
return nil, errors.Wrapf(err, "Value of PODMAN_HOST is not a valid url: %s", uri)
}
- // Now we setup the http client to use the connection above
+ // Now we setup the http Client to use the connection above
var connection Connection
switch _url.Scheme {
case "ssh":
@@ -125,16 +124,12 @@ func NewConnection(ctx context.Context, uri string, identity ...string) (context
func tcpClient(_url *url.URL) (Connection, error) {
connection := Connection{
- _url: _url,
+ Uri: _url,
}
- connection.client = &http.Client{
+ connection.Client = &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
- conn, err := net.Dial("tcp", _url.Host)
- if c, ok := ctx.Value(clientKey).(*Connection); ok {
- c.conn = &conn
- }
- return conn, err
+ return net.Dial("tcp", _url.Host)
},
DisableCompression: true,
},
@@ -167,11 +162,11 @@ func pingNewConnection(ctx context.Context) error {
}
switch APIVersion.Compare(versionSrv) {
- case 1, 0:
- // Server's job when client version is equal or older
+ case -1, 0:
+ // Server's job when Client version is equal or older
return nil
- case -1:
- return errors.Errorf("server API version is too old. client %q server %q", APIVersion.String(), versionSrv.String())
+ case 1:
+ return errors.Errorf("server API version is too old. Client %q server %q", APIVersion.String(), versionSrv.String())
}
}
return errors.Errorf("ping response was %q", response.StatusCode)
@@ -217,31 +212,22 @@ func sshClient(_url *url.URL, identity string, secure bool) (Connection, error)
return Connection{}, errors.Wrapf(err, "Connection to bastion host (%s) failed.", _url.String())
}
- connection := Connection{_url: _url}
- connection.client = &http.Client{
+ connection := Connection{Uri: _url}
+ connection.Client = &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
- conn, err := bastion.Dial("unix", _url.Path)
- if c, ok := ctx.Value(clientKey).(*Connection); ok {
- c.conn = &conn
- }
- return conn, err
+ return bastion.Dial("unix", _url.Path)
},
}}
return connection, nil
}
func unixClient(_url *url.URL) (Connection, error) {
- connection := Connection{_url: _url}
- connection.client = &http.Client{
+ connection := Connection{Uri: _url}
+ connection.Client = &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
- d := net.Dialer{}
- conn, err := d.DialContext(ctx, "unix", _url.Path)
- if c, ok := ctx.Value(clientKey).(*Connection); ok {
- c.conn = &conn
- }
- return conn, err
+ return (&net.Dialer{}).DialContext(ctx, "unix", _url.Path)
},
DisableCompression: true,
},
@@ -263,7 +249,7 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string,
// Lets eventually use URL for this which might lead to safer
// usage
safeEndpoint := fmt.Sprintf(endpoint, safePathValues...)
- e := basePath.String() + safeEndpoint
+ e := BasePath.String() + safeEndpoint
req, err := http.NewRequest(httpMethod, e, httpBody)
if err != nil {
return nil, err
@@ -277,7 +263,7 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string,
req = req.WithContext(context.WithValue(context.Background(), clientKey, c))
// Give the Do three chances in the case of a comm/service hiccup
for i := 0; i < 3; i++ {
- response, err = c.client.Do(req) // nolint
+ response, err = c.Client.Do(req) // nolint
if err == nil {
break
}
@@ -286,10 +272,6 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string,
return &APIResponse{response, req}, err
}
-func (c *Connection) Write(b []byte) (int, error) {
- return (*c.conn).Write(b)
-}
-
// FiltersToString converts our typical filter format of a
// map[string][]string to a query/html safe string.
func FiltersToString(filters map[string][]string) (string, error) {
diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go
new file mode 100644
index 000000000..b7f35c30d
--- /dev/null
+++ b/pkg/bindings/containers/attach.go
@@ -0,0 +1,481 @@
+package containers
+
+import (
+ "bytes"
+ "context"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+ "os"
+ "os/signal"
+ "reflect"
+ "strconv"
+ "time"
+
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/bindings"
+ sig "github.com/containers/libpod/pkg/signal"
+ "github.com/containers/libpod/utils"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+// Attach attaches to a running container
+func Attach(ctx context.Context, nameOrId string, detachKeys *string, logs, stream *bool, stdin io.Reader, stdout io.Writer, stderr io.Writer, attachReady chan bool) error {
+ isSet := struct {
+ stdin bool
+ stdout bool
+ stderr bool
+ }{
+ stdin: !(stdin == nil || reflect.ValueOf(stdin).IsNil()),
+ stdout: !(stdout == nil || reflect.ValueOf(stdout).IsNil()),
+ stderr: !(stderr == nil || reflect.ValueOf(stderr).IsNil()),
+ }
+ // Ensure golang can determine that interfaces are "really" nil
+ if !isSet.stdin {
+ stdin = (io.Reader)(nil)
+ }
+ if !isSet.stdout {
+ stdout = (io.Writer)(nil)
+ }
+ if !isSet.stderr {
+ stderr = (io.Writer)(nil)
+ }
+
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+
+ // Do we need to wire in stdin?
+ ctnr, err := Inspect(ctx, nameOrId, bindings.PFalse)
+ if err != nil {
+ return err
+ }
+
+ params := url.Values{}
+ if detachKeys != nil {
+ params.Add("detachKeys", *detachKeys)
+ }
+ if logs != nil {
+ params.Add("logs", fmt.Sprintf("%t", *logs))
+ }
+ if stream != nil {
+ params.Add("stream", fmt.Sprintf("%t", *stream))
+ }
+ if isSet.stdin {
+ params.Add("stdin", "true")
+ }
+ if isSet.stdout {
+ params.Add("stdout", "true")
+ }
+ if isSet.stderr {
+ params.Add("stderr", "true")
+ }
+
+ // Unless all requirements are met, don't use "stdin" is a terminal
+ file, ok := stdin.(*os.File)
+ needTTY := ok && terminal.IsTerminal(int(file.Fd())) && ctnr.Config.Tty
+ if needTTY {
+ state, err := setRawTerminal(file)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err := terminal.Restore(int(file.Fd()), state); err != nil {
+ logrus.Errorf("unable to restore terminal: %q", err)
+ }
+ logrus.SetFormatter(&logrus.TextFormatter{})
+ }()
+ }
+
+ headers := make(map[string]string)
+ headers["Connection"] = "Upgrade"
+ headers["Upgrade"] = "tcp"
+
+ var socket net.Conn
+ socketSet := false
+ dialContext := conn.Client.Transport.(*http.Transport).DialContext
+ t := &http.Transport{
+ DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
+ c, err := dialContext(ctx, network, address)
+ if err != nil {
+ return nil, err
+ }
+ if !socketSet {
+ socket = c
+ socketSet = true
+ }
+ return c, err
+ },
+ IdleConnTimeout: time.Duration(0),
+ }
+ conn.Client.Transport = t
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/attach", params, headers, nameOrId)
+ if err != nil {
+ return err
+ }
+ if !(response.IsSuccess() || response.IsInformational()) {
+ return response.Process(nil)
+ }
+
+ if needTTY {
+ winChange := make(chan os.Signal, 1)
+ signal.Notify(winChange, sig.SIGWINCH)
+ winCtx, winCancel := context.WithCancel(ctx)
+ defer winCancel()
+
+ go attachHandleResize(ctx, winCtx, winChange, false, nameOrId, file)
+ }
+
+ // If we are attaching around a start, we need to "signal"
+ // back that we are in fact attached so that started does
+ // not execute before we can attach.
+ if attachReady != nil {
+ attachReady <- true
+ }
+
+ if isSet.stdin {
+ go func() {
+ logrus.Debugf("Copying STDIN to socket")
+ _, err := utils.CopyDetachable(socket, stdin, []byte{})
+ if err != nil {
+ logrus.Error("failed to write input to service: " + err.Error())
+ }
+ }()
+ }
+
+ buffer := make([]byte, 1024)
+ if ctnr.Config.Tty {
+ logrus.Debugf("Copying STDOUT of container in terminal mode")
+
+ if !isSet.stdout {
+ return fmt.Errorf("container %q requires stdout to be set", ctnr.ID)
+ }
+ // If not multiplex'ed, read from server and write to stdout
+ _, err := io.Copy(stdout, socket)
+ if err != nil {
+ return err
+ }
+ } else {
+ logrus.Debugf("Copying standard streams of container in non-terminal mode")
+ for {
+ // Read multiplexed channels and write to appropriate stream
+ fd, l, err := DemuxHeader(socket, buffer)
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return nil
+ }
+ return err
+ }
+ frame, err := DemuxFrame(socket, buffer, l)
+ if err != nil {
+ return err
+ }
+
+ switch {
+ case fd == 0 && isSet.stdout:
+ _, err := stdout.Write(frame[0:l])
+ if err != nil {
+ return err
+ }
+ case fd == 1 && isSet.stdout:
+ _, err := stdout.Write(frame[0:l])
+ if err != nil {
+ return err
+ }
+ case fd == 2 && isSet.stderr:
+ _, err := stderr.Write(frame[0:l])
+ if err != nil {
+ return err
+ }
+ case fd == 3:
+ return fmt.Errorf("error from service from stream: %s", frame)
+ default:
+ return fmt.Errorf("unrecognized channel in header: %d, 0-3 supported", fd)
+ }
+ }
+ }
+ return nil
+}
+
+// DemuxHeader reads header for stream from server multiplexed stdin/stdout/stderr/2nd error channel
+func DemuxHeader(r io.Reader, buffer []byte) (fd, sz int, err error) {
+ n, err := io.ReadFull(r, buffer[0:8])
+ if err != nil {
+ return
+ }
+ if n < 8 {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+
+ fd = int(buffer[0])
+ if fd < 0 || fd > 3 {
+ err = errors.Wrapf(ErrLostSync, fmt.Sprintf(`channel "%d" found, 0-3 supported`, fd))
+ return
+ }
+
+ sz = int(binary.BigEndian.Uint32(buffer[4:8]))
+ return
+}
+
+// DemuxFrame reads contents for frame from server multiplexed stdin/stdout/stderr/2nd error channel
+func DemuxFrame(r io.Reader, buffer []byte, length int) (frame []byte, err error) {
+ if len(buffer) < length {
+ buffer = append(buffer, make([]byte, length-len(buffer)+1)...)
+ }
+
+ n, err := io.ReadFull(r, buffer[0:length])
+ if err != nil {
+ return nil, nil
+ }
+ if n < length {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+
+ return buffer[0:length], nil
+}
+
+// ResizeContainerTTY sets container's TTY height and width in characters
+func ResizeContainerTTY(ctx context.Context, nameOrId string, height *int, width *int) error {
+ return resizeTTY(ctx, bindings.JoinURL("containers", nameOrId, "resize"), height, width)
+}
+
+// ResizeExecTTY sets session's TTY height and width in characters
+func ResizeExecTTY(ctx context.Context, nameOrId string, height *int, width *int) error {
+ return resizeTTY(ctx, bindings.JoinURL("exec", nameOrId, "resize"), height, width)
+}
+
+// resizeTTY set size of TTY of container
+func resizeTTY(ctx context.Context, endpoint string, height *int, width *int) error {
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+
+ params := url.Values{}
+ if height != nil {
+ params.Set("h", strconv.Itoa(*height))
+ }
+ if width != nil {
+ params.Set("w", strconv.Itoa(*width))
+ }
+ rsp, err := conn.DoRequest(nil, http.MethodPost, endpoint, params, nil)
+ if err != nil {
+ return err
+ }
+ return rsp.Process(nil)
+}
+
+type rawFormatter struct {
+ logrus.TextFormatter
+}
+
+func (f *rawFormatter) Format(entry *logrus.Entry) ([]byte, error) {
+ buffer, err := f.TextFormatter.Format(entry)
+ if err != nil {
+ return buffer, err
+ }
+ return append(buffer, '\r'), nil
+}
+
+// This is intended to be run as a goroutine, handling resizing for a container
+// or exec session.
+func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, isExec bool, id string, file *os.File) {
+ // Prime the pump, we need one reset to ensure everything is ready
+ winChange <- sig.SIGWINCH
+ for {
+ select {
+ case <-winCtx.Done():
+ return
+ case <-winChange:
+ h, w, err := terminal.GetSize(int(file.Fd()))
+ if err != nil {
+ logrus.Warnf("failed to obtain TTY size: " + err.Error())
+ }
+
+ var resizeErr error
+ if isExec {
+ resizeErr = ResizeExecTTY(ctx, id, &h, &w)
+ } else {
+ resizeErr = ResizeContainerTTY(ctx, id, &h, &w)
+ }
+ if resizeErr != nil {
+ logrus.Warnf("failed to resize TTY: " + resizeErr.Error())
+ }
+ }
+ }
+}
+
+// Configure the given terminal for raw mode
+func setRawTerminal(file *os.File) (*terminal.State, error) {
+ state, err := terminal.MakeRaw(int(file.Fd()))
+ if err != nil {
+ return nil, err
+ }
+
+ logrus.SetFormatter(&rawFormatter{})
+
+ return state, err
+}
+
+// ExecStartAndAttach starts and attaches to a given exec session.
+func ExecStartAndAttach(ctx context.Context, sessionID string, streams *define.AttachStreams) error {
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+
+ // TODO: Make this configurable (can't use streams' InputStream as it's
+ // buffered)
+ terminalFile := os.Stdin
+
+ logrus.Debugf("Starting & Attaching to exec session ID %q", sessionID)
+
+ // We need to inspect the exec session first to determine whether to use
+ // -t.
+ resp, err := conn.DoRequest(nil, http.MethodGet, "/exec/%s/json", nil, nil, sessionID)
+ if err != nil {
+ return err
+ }
+
+ respStruct := new(define.InspectExecSession)
+ if err := resp.Process(respStruct); err != nil {
+ return err
+ }
+ isTerm := true
+ if respStruct.ProcessConfig != nil {
+ isTerm = respStruct.ProcessConfig.Tty
+ }
+
+ // If we are in TTY mode, we need to set raw mode for the terminal.
+ // TODO: Share all of this with Attach() for containers.
+ needTTY := terminalFile != nil && terminal.IsTerminal(int(terminalFile.Fd())) && isTerm
+ if needTTY {
+ state, err := setRawTerminal(terminalFile)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err := terminal.Restore(int(terminalFile.Fd()), state); err != nil {
+ logrus.Errorf("unable to restore terminal: %q", err)
+ }
+ logrus.SetFormatter(&logrus.TextFormatter{})
+ }()
+ }
+
+ body := struct {
+ Detach bool `json:"Detach"`
+ }{
+ Detach: false,
+ }
+ bodyJSON, err := json.Marshal(body)
+ if err != nil {
+ return err
+ }
+
+ var socket net.Conn
+ socketSet := false
+ dialContext := conn.Client.Transport.(*http.Transport).DialContext
+ t := &http.Transport{
+ DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
+ c, err := dialContext(ctx, network, address)
+ if err != nil {
+ return nil, err
+ }
+ if !socketSet {
+ socket = c
+ socketSet = true
+ }
+ return c, err
+ },
+ IdleConnTimeout: time.Duration(0),
+ }
+ conn.Client.Transport = t
+ response, err := conn.DoRequest(bytes.NewReader(bodyJSON), http.MethodPost, "/exec/%s/start", nil, nil, sessionID)
+ if err != nil {
+ return err
+ }
+ if !(response.IsSuccess() || response.IsInformational()) {
+ return response.Process(nil)
+ }
+
+ if needTTY {
+ winChange := make(chan os.Signal, 1)
+ signal.Notify(winChange, sig.SIGWINCH)
+ winCtx, winCancel := context.WithCancel(ctx)
+ defer winCancel()
+
+ go attachHandleResize(ctx, winCtx, winChange, true, sessionID, terminalFile)
+ }
+
+ if streams.AttachInput {
+ go func() {
+ logrus.Debugf("Copying STDIN to socket")
+ _, err := utils.CopyDetachable(socket, streams.InputStream, []byte{})
+ if err != nil {
+ logrus.Error("failed to write input to service: " + err.Error())
+ }
+ }()
+ }
+
+ buffer := make([]byte, 1024)
+ if isTerm {
+ logrus.Debugf("Handling terminal attach to exec")
+ if !streams.AttachOutput {
+ return fmt.Errorf("exec session %s has a terminal and must have STDOUT enabled", sessionID)
+ }
+ // If not multiplex'ed, read from server and write to stdout
+ _, err := utils.CopyDetachable(streams.OutputStream, socket, []byte{})
+ if err != nil {
+ return err
+ }
+ } else {
+ logrus.Debugf("Handling non-terminal attach to exec")
+ for {
+ // Read multiplexed channels and write to appropriate stream
+ fd, l, err := DemuxHeader(socket, buffer)
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return nil
+ }
+ return err
+ }
+ frame, err := DemuxFrame(socket, buffer, l)
+ if err != nil {
+ return err
+ }
+
+ switch {
+ case fd == 0 && streams.AttachOutput:
+ _, err := streams.OutputStream.Write(frame[0:l])
+ if err != nil {
+ return err
+ }
+ case fd == 1 && streams.AttachInput:
+ // Write STDIN to STDOUT (echoing characters
+ // typed by another attach session)
+ _, err := streams.OutputStream.Write(frame[0:l])
+ if err != nil {
+ return err
+ }
+ case fd == 2 && streams.AttachError:
+ _, err := streams.ErrorStream.Write(frame[0:l])
+ if err != nil {
+ return err
+ }
+ case fd == 3:
+ return fmt.Errorf("error from service from stream: %s", frame)
+ default:
+ return fmt.Errorf("unrecognized channel in header: %d, 0-3 supported", fd)
+ }
+ }
+ }
+ return nil
+}
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index 516f3d282..929b6bbd5 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -2,14 +2,9 @@ package containers
import (
"context"
- "encoding/binary"
- "fmt"
"io"
"net/http"
"net/url"
- "os"
- "os/signal"
- "reflect"
"strconv"
"strings"
@@ -17,10 +12,7 @@ import (
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/domain/entities"
- sig "github.com/containers/libpod/pkg/signal"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
- "golang.org/x/crypto/ssh/terminal"
)
var (
@@ -345,248 +337,3 @@ func ContainerInit(ctx context.Context, nameOrID string) error {
}
return response.Process(nil)
}
-
-// Attach attaches to a running container
-func Attach(ctx context.Context, nameOrId string, detachKeys *string, logs, stream *bool, stdin io.Reader, stdout io.Writer, stderr io.Writer, attachReady chan bool) error {
- isSet := struct {
- stdin bool
- stdout bool
- stderr bool
- }{
- stdin: !(stdin == nil || reflect.ValueOf(stdin).IsNil()),
- stdout: !(stdout == nil || reflect.ValueOf(stdout).IsNil()),
- stderr: !(stderr == nil || reflect.ValueOf(stderr).IsNil()),
- }
- // Ensure golang can determine that interfaces are "really" nil
- if !isSet.stdin {
- stdin = (io.Reader)(nil)
- }
- if !isSet.stdout {
- stdout = (io.Writer)(nil)
- }
- if !isSet.stderr {
- stderr = (io.Writer)(nil)
- }
-
- conn, err := bindings.GetClient(ctx)
- if err != nil {
- return err
- }
-
- // Do we need to wire in stdin?
- ctnr, err := Inspect(ctx, nameOrId, bindings.PFalse)
- if err != nil {
- return err
- }
-
- params := url.Values{}
- if detachKeys != nil {
- params.Add("detachKeys", *detachKeys)
- }
- if logs != nil {
- params.Add("logs", fmt.Sprintf("%t", *logs))
- }
- if stream != nil {
- params.Add("stream", fmt.Sprintf("%t", *stream))
- }
- if isSet.stdin {
- params.Add("stdin", "true")
- }
- if isSet.stdout {
- params.Add("stdout", "true")
- }
- if isSet.stderr {
- params.Add("stderr", "true")
- }
-
- // Unless all requirements are met, don't use "stdin" is a terminal
- file, ok := stdin.(*os.File)
- needTTY := ok && terminal.IsTerminal(int(file.Fd())) && ctnr.Config.Tty
- if needTTY {
- state, err := terminal.MakeRaw(int(file.Fd()))
- if err != nil {
- return err
- }
-
- logrus.SetFormatter(&rawFormatter{})
-
- defer func() {
- if err := terminal.Restore(int(file.Fd()), state); err != nil {
- logrus.Errorf("unable to restore terminal: %q", err)
- }
- logrus.SetFormatter(&logrus.TextFormatter{})
- }()
-
- winChange := make(chan os.Signal, 1)
- signal.Notify(winChange, sig.SIGWINCH)
- winCtx, winCancel := context.WithCancel(ctx)
- defer winCancel()
-
- go func() {
- // Prime the pump, we need one reset to ensure everything is ready
- winChange <- sig.SIGWINCH
- for {
- select {
- case <-winCtx.Done():
- return
- case <-winChange:
- h, w, err := terminal.GetSize(int(file.Fd()))
- if err != nil {
- logrus.Warnf("failed to obtain TTY size: " + err.Error())
- }
-
- if err := ResizeContainerTTY(ctx, nameOrId, &h, &w); err != nil {
- logrus.Warnf("failed to resize TTY: " + err.Error())
- }
- }
- }
- }()
- }
-
- response, err := conn.DoRequest(stdin, http.MethodPost, "/containers/%s/attach", params, nil, nameOrId)
- if err != nil {
- return err
- }
- if !(response.IsSuccess() || response.IsInformational()) {
- return response.Process(nil)
- }
-
- // If we are attaching around a start, we need to "signal"
- // back that we are in fact attached so that started does
- // not execute before we can attach.
- if attachReady != nil {
- attachReady <- true
- }
-
- buffer := make([]byte, 1024)
- if ctnr.Config.Tty {
- if !isSet.stdout {
- return fmt.Errorf("container %q requires stdout to be set", ctnr.ID)
- }
- // If not multiplex'ed, read from server and write to stdout
- _, err := io.Copy(stdout, response.Body)
- if err != nil {
- return err
- }
- } else {
- for {
- // Read multiplexed channels and write to appropriate stream
- fd, l, err := DemuxHeader(response.Body, buffer)
- if err != nil {
- if errors.Is(err, io.EOF) {
- return nil
- }
- return err
- }
- frame, err := DemuxFrame(response.Body, buffer, l)
- if err != nil {
- return err
- }
-
- switch {
- case fd == 0 && isSet.stdout:
- _, err := stdout.Write(frame[0:l])
- if err != nil {
- return err
- }
- case fd == 1 && isSet.stdout:
- _, err := stdout.Write(frame[0:l])
- if err != nil {
- return err
- }
- case fd == 2 && isSet.stderr:
- _, err := stderr.Write(frame[0:l])
- if err != nil {
- return err
- }
- case fd == 3:
- return fmt.Errorf("error from service from stream: %s", frame)
- default:
- return fmt.Errorf("unrecognized channel in header: %d, 0-3 supported", fd)
- }
- }
- }
- return nil
-}
-
-// DemuxHeader reads header for stream from server multiplexed stdin/stdout/stderr/2nd error channel
-func DemuxHeader(r io.Reader, buffer []byte) (fd, sz int, err error) {
- n, err := io.ReadFull(r, buffer[0:8])
- if err != nil {
- return
- }
- if n < 8 {
- err = io.ErrUnexpectedEOF
- return
- }
-
- fd = int(buffer[0])
- if fd < 0 || fd > 3 {
- err = errors.Wrapf(ErrLostSync, fmt.Sprintf(`channel "%d" found, 0-3 supported`, fd))
- return
- }
-
- sz = int(binary.BigEndian.Uint32(buffer[4:8]))
- return
-}
-
-// DemuxFrame reads contents for frame from server multiplexed stdin/stdout/stderr/2nd error channel
-func DemuxFrame(r io.Reader, buffer []byte, length int) (frame []byte, err error) {
- if len(buffer) < length {
- buffer = append(buffer, make([]byte, length-len(buffer)+1)...)
- }
-
- n, err := io.ReadFull(r, buffer[0:length])
- if err != nil {
- return nil, nil
- }
- if n < length {
- err = io.ErrUnexpectedEOF
- return
- }
-
- return buffer[0:length], nil
-}
-
-// ResizeContainerTTY sets container's TTY height and width in characters
-func ResizeContainerTTY(ctx context.Context, nameOrId string, height *int, width *int) error {
- return resizeTTY(ctx, bindings.JoinURL("containers", nameOrId, "resize"), height, width)
-}
-
-// ResizeExecTTY sets session's TTY height and width in characters
-func ResizeExecTTY(ctx context.Context, nameOrId string, height *int, width *int) error {
- return resizeTTY(ctx, bindings.JoinURL("exec", nameOrId, "resize"), height, width)
-}
-
-// resizeTTY set size of TTY of container
-func resizeTTY(ctx context.Context, endpoint string, height *int, width *int) error {
- conn, err := bindings.GetClient(ctx)
- if err != nil {
- return err
- }
-
- params := url.Values{}
- if height != nil {
- params.Set("h", strconv.Itoa(*height))
- }
- if width != nil {
- params.Set("w", strconv.Itoa(*width))
- }
- rsp, err := conn.DoRequest(nil, http.MethodPost, endpoint, params, nil)
- if err != nil {
- return err
- }
- return rsp.Process(nil)
-}
-
-type rawFormatter struct {
- logrus.TextFormatter
-}
-
-func (f *rawFormatter) Format(entry *logrus.Entry) ([]byte, error) {
- buffer, err := f.TextFormatter.Format(entry)
- if err != nil {
- return buffer, err
- }
- return append(buffer, '\r'), nil
-}
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index 1a38a7aa4..37acba6e6 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -29,6 +29,7 @@ type ListPodsReport struct {
Name string
Namespace string
Status string
+ Labels map[string]string
}
type ListPodContainer struct {
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index 16c222cbd..320880920 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -360,6 +360,7 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
Name: p.Name(),
Namespace: p.Namespace(),
Status: status,
+ Labels: p.Labels(),
})
}
return reports, nil
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index beba55c2b..e1c859e7c 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -2,6 +2,7 @@ package tunnel
import (
"context"
+ "fmt"
"io"
"os"
"strconv"
@@ -11,6 +12,7 @@ import (
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/bindings/containers"
"github.com/containers/libpod/pkg/domain/entities"
@@ -375,7 +377,39 @@ func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string,
}
func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, options entities.ExecOptions, streams define.AttachStreams) (int, error) {
- return 125, errors.New("not implemented")
+ env := []string{}
+ for k, v := range options.Envs {
+ env = append(env, fmt.Sprintf("%s=%s", k, v))
+ }
+
+ createConfig := new(handlers.ExecCreateConfig)
+ createConfig.User = options.User
+ createConfig.Privileged = options.Privileged
+ createConfig.Tty = options.Tty
+ createConfig.AttachStdin = options.Interactive
+ createConfig.AttachStdout = true
+ createConfig.AttachStderr = true
+ createConfig.Detach = false
+ createConfig.DetachKeys = options.DetachKeys
+ createConfig.Env = env
+ createConfig.WorkingDir = options.WorkDir
+ createConfig.Cmd = options.Cmd
+
+ sessionID, err := containers.ExecCreate(ic.ClientCxt, nameOrId, createConfig)
+ if err != nil {
+ return 125, err
+ }
+
+ if err := containers.ExecStartAndAttach(ic.ClientCxt, sessionID, &streams); err != nil {
+ return 125, err
+ }
+
+ inspectOut, err := containers.ExecInspect(ic.ClientCxt, sessionID)
+ if err != nil {
+ return 125, err
+ }
+
+ return inspectOut.ExitCode, nil
}
func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID string, options entities.ExecOptions) (string, error) {
diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go
index 94e456c52..75da38c0e 100644
--- a/pkg/specgen/container_validate.go
+++ b/pkg/specgen/container_validate.go
@@ -50,7 +50,8 @@ func (s *SpecGenerator) Validate() error {
}
// imagevolumemode must be one of ignore, tmpfs, or anonymous if given
if len(s.ContainerStorageConfig.ImageVolumeMode) > 0 && !util.StringInSlice(strings.ToLower(s.ContainerStorageConfig.ImageVolumeMode), ImageVolumeModeValues) {
- return errors.Errorf("ImageVolumeMode values must be one of %s", strings.Join(ImageVolumeModeValues, ","))
+ return errors.Errorf("invalid ImageVolumeMode %q, value must be one of %s",
+ s.ContainerStorageConfig.ImageVolumeMode, strings.Join(ImageVolumeModeValues, ","))
}
// shmsize conflicts with IPC namespace
if s.ContainerStorageConfig.ShmSize != nil && !s.ContainerStorageConfig.IpcNS.IsPrivate() {
diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go
index 87dddb233..8ec666c2b 100644
--- a/test/e2e/exec_test.go
+++ b/test/e2e/exec_test.go
@@ -18,7 +18,6 @@ var _ = Describe("Podman exec", func() {
)
BeforeEach(func() {
- Skip(v2remotefail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
@@ -285,6 +284,7 @@ var _ = Describe("Podman exec", func() {
})
It("podman exec --detach", func() {
+ Skip(v2remotefail)
ctrName := "testctr"
ctr := podmanTest.Podman([]string{"run", "-t", "-i", "-d", "--name", ctrName, ALPINE, "top"})
ctr.WaitWithDefaultTimeout()
diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go
index 9a073cde6..b16cff411 100644
--- a/test/e2e/images_test.go
+++ b/test/e2e/images_test.go
@@ -151,7 +151,6 @@ var _ = Describe("Podman images", func() {
})
It("podman images filter reference", func() {
- SkipIfRemote()
podmanTest.RestoreAllArtifacts()
result := podmanTest.PodmanNoCache([]string{"images", "-q", "-f", "reference=docker.io*"})
result.WaitWithDefaultTimeout()
@@ -177,7 +176,6 @@ var _ = Describe("Podman images", func() {
})
It("podman images filter before image", func() {
- SkipIfRemote()
dockerfile := `FROM docker.io/library/alpine:latest
RUN apk update && apk add strace
`
@@ -189,7 +187,6 @@ RUN apk update && apk add strace
})
It("podman images filter after image", func() {
- SkipIfRemote()
podmanTest.RestoreAllArtifacts()
rmi := podmanTest.PodmanNoCache([]string{"rmi", "busybox"})
rmi.WaitWithDefaultTimeout()
@@ -205,7 +202,6 @@ RUN apk update && apk add strace
})
It("podman image list filter after image", func() {
- SkipIfRemote()
podmanTest.RestoreAllArtifacts()
rmi := podmanTest.PodmanNoCache([]string{"image", "rm", "busybox"})
rmi.WaitWithDefaultTimeout()
@@ -221,7 +217,6 @@ RUN apk update && apk add strace
})
It("podman images filter dangling", func() {
- SkipIfRemote()
dockerfile := `FROM docker.io/library/alpine:latest
`
podmanTest.BuildImage(dockerfile, "foobar.com/before:latest", "false")
@@ -233,9 +228,6 @@ RUN apk update && apk add strace
})
It("podman check for image with sha256: prefix", func() {
- if podmanTest.RemoteTest {
- Skip("Does not work on remote client")
- }
session := podmanTest.Podman([]string{"inspect", "--format=json", ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -248,9 +240,6 @@ RUN apk update && apk add strace
})
It("podman check for image with sha256: prefix", func() {
- if podmanTest.RemoteTest {
- Skip("Does not work on remote client")
- }
session := podmanTest.Podman([]string{"image", "inspect", "--format=json", ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -297,7 +286,6 @@ RUN apk update && apk add strace
})
It("podman images --all flag", func() {
- SkipIfRemote()
podmanTest.RestoreAllArtifacts()
dockerfile := `FROM docker.io/library/alpine:latest
RUN mkdir hello
@@ -317,7 +305,6 @@ ENV foo=bar
})
It("podman images filter by label", func() {
- SkipIfRemote()
dockerfile := `FROM docker.io/library/alpine:latest
LABEL version="1.0"
LABEL "com.example.vendor"="Example Vendor"
@@ -330,7 +317,6 @@ LABEL "com.example.vendor"="Example Vendor"
})
It("podman with images with no layers", func() {
- SkipIfRemote()
dockerfile := strings.Join([]string{
`FROM scratch`,
`LABEL org.opencontainers.image.authors="<somefolks@example.org>"`,
@@ -395,7 +381,6 @@ LABEL "com.example.vendor"="Example Vendor"
})
It("podman images --filter readonly", func() {
- SkipIfRemote()
dockerfile := `FROM docker.io/library/alpine:latest
`
podmanTest.BuildImage(dockerfile, "foobar.com/before:latest", "false")
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index 81d97b72d..8dcaf6af1 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -243,4 +243,20 @@ var _ = Describe("Podman ps", func() {
infra.WaitWithDefaultTimeout()
Expect(len(infra.OutputToString())).To(BeZero())
})
+
+ It("podman pod ps format with labels", func() {
+ _, ec, _ := podmanTest.CreatePod("")
+ Expect(ec).To(Equal(0))
+
+ _, ec1, _ := podmanTest.CreatePodWithLabels("", map[string]string{
+ "io.podman.test.label": "value1",
+ "io.podman.test.key": "irrelevant-value",
+ })
+ Expect(ec1).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"pod", "ps", "--format", "{{.Labels}}"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("value1"))
+ })
})
diff --git a/test/system/075-exec.bats b/test/system/075-exec.bats
index 36e9d57ec..f8c7f2766 100644
--- a/test/system/075-exec.bats
+++ b/test/system/075-exec.bats
@@ -50,6 +50,7 @@ load helpers
}
# Issue #4785 - piping to exec statement - fixed in #4818
+# Issue #5046 - piping to exec truncates results (actually a conmon issue)
@test "podman exec - cat from stdin" {
skip_if_remote
@@ -60,6 +61,20 @@ load helpers
run_podman exec -i $cid cat < <(echo $echo_string)
is "$output" "$echo_string" "output read back from 'exec cat'"
+ # #5046 - large file content gets lost via exec
+ # Generate a large file with random content; get a hash of its content
+ local bigfile=${PODMAN_TMPDIR}/bigfile
+ dd if=/dev/urandom of=$bigfile bs=1024 count=1500
+ expect=$(sha512sum $bigfile | awk '{print $1}')
+ # Transfer it to container, via exec, make sure correct #bytes are sent
+ run_podman exec -i $cid dd of=/tmp/bigfile bs=512 <$bigfile
+ is "${lines[0]}" "3000+0 records in" "dd: number of records in"
+ is "${lines[1]}" "3000+0 records out" "dd: number of records out"
+ # Verify sha. '% *' strips off the path, keeping only the SHA
+ run_podman exec $cid sha512sum /tmp/bigfile
+ is "${output% *}" "$expect" "SHA of file in container"
+
+ # Clean up
run_podman exec $cid touch /stop
run_podman wait $cid
run_podman rm $cid
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index f34cd0707..0d14ca990 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -56,7 +56,11 @@ function teardown() {
skip_if_remote "podman-pod does not work with podman-remote"
podname=pod$(random_string)
+ run_podman 1 pod exists $podname
run_podman pod create --infra=true --name=$podname
+ podid="$output"
+ run_podman pod exists $podname
+ run_podman pod exists $podid
# Randomly-assigned port in the 5xxx range
for port in $(shuf -i 5000-5999);do
@@ -91,6 +95,10 @@ function teardown() {
# ...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
}
# Random byte
@@ -131,6 +139,9 @@ function random_ip() {
hostname=$(random_string | tr A-Z a-z).$(random_string | tr A-Z a-z).net
+ labelname=$(random_string 11)
+ labelvalue=$(random_string 22)
+
pod_id_file=${PODMAN_TMPDIR}/pod-id-file
# Create a pod with all the desired options
@@ -143,7 +154,8 @@ function random_ip() {
--add-host "$add_host_n:$add_host_ip" \
--dns "$dns_server" \
--dns-search "$dns_search" \
- --dns-opt "$dns_opt"
+ --dns-opt "$dns_opt" \
+ --label "${labelname}=${labelvalue}"
pod_id="$output"
# Check --pod-id-file
@@ -168,18 +180,20 @@ function random_ip() {
is "$output" ".*nameserver $dns_server" "--dns [server] was added"
is "$output" ".*search $dns_search" "--dns-search was added"
is "$output" ".*options $dns_opt" "--dns-opt was added"
-}
-@test "podman pod inspect - format" {
- skip_if_remote "podman-pod does not work with podman-remote"
+ # pod inspect
+ run_podman pod inspect --format '{{.Name}}: {{.ID}} : {{.NumContainers}} : {{.Labels}}' mypod
+ is "$output" "mypod: $pod_id : 1 : map\[${labelname}:${labelvalue}]" \
+ "pod inspect --format ..."
- run_podman pod create --name podtest
- podid=$output
+ # pod ps
+ run_podman pod ps --format '{{.ID}} {{.Name}} {{.Status}} {{.Labels}}'
+ is "$output" "${pod_id:0:12} mypod Running map\[${labelname}:${labelvalue}]" "pod ps"
- run_podman pod inspect --format '-> {{.Name}}: {{.NumContainers}}' podtest
- is "$output" "-> podtest: 1"
+ run_podman pod ps --no-trunc --filter "label=${labelname}=${labelvalue}" --format '{{.ID}}'
+ is "$output" "$pod_id" "pod ps --filter label=..."
- run_podman pod rm -f podtest
+ run_podman pod rm -f mypod
}
# vim: filetype=sh
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index cd836610b..c9d1984d0 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -60,4 +60,27 @@ load helpers
run_podman rmi busybox
}
+# Issue #5466 - port-forwarding doesn't work with this option and -d
+@test "podman networking: port with --userns=keep-id" {
+ skip_if_remote
+
+ # FIXME: randomize port, and create second random host port
+ myport=54321
+
+ # Container will exit as soon as 'nc' receives input
+ run_podman run -d --userns=keep-id -p 127.0.0.1:$myport:$myport \
+ $IMAGE nc -l -p $myport
+ cid="$output"
+
+ # emit random string, and check it
+ teststring=$(random_string 30)
+ echo "$teststring" | nc 127.0.0.1 $myport
+
+ run_podman logs $cid
+ is "$output" "$teststring" "test string received on container"
+
+ # Clean up
+ run_podman rm $cid
+}
+
# vim: filetype=sh
diff --git a/troubleshooting.md b/troubleshooting.md
index 167ee14c3..bad9d8102 100644
--- a/troubleshooting.md
+++ b/troubleshooting.md
@@ -553,3 +553,42 @@ this, use the following command before logging out: `loginctl enable-linger`.
To later revert the linger functionality, use `loginctl disable-linger`.
LOGINCTL(1), SYSTEMD(1)
+
+### 23) Containers default detach keys conflict with shell history navigation
+
+Podman defaults to `ctrl-p,ctrl-q` to detach from a running containers. The
+bash and zsh shells default to ctrl-p for the displaying of the previous
+command. This causes issues when running a shell inside of a container.
+
+#### Symptom
+
+With the default detach key combo ctrl-p,ctrl-q, shell history navigation
+(tested in bash and zsh) using ctrl-p to access the previous command will not
+display this previous command. Or anything else. Conmon is waiting for an
+additional character to see if the user wants to detach from the container.
+Adding additional characters to the command will cause it to be displayed along
+with the additonal character. If the user types ctrl-p a second time the shell
+display the 2nd to last command.
+
+#### Solution
+
+The solution to this is to change the default detach_keys. For example in order
+to change the defaults to `ctrl-q,ctrl-q` use the `--detach-keys` option.
+
+```
+podman run -ti --detach-keys ctrl-q,ctrl-q fedora sh
+```
+
+To make this change the default for all containers, users can modify the
+containers.conf file. This can be done simply in your homedir, but adding the
+following lines to users containers.conf
+
+```
+$ cat >> ~/.config/containers/containers.conf < _eof
+[engine]
+detach_keys="ctrl-q,ctrl-q"
+_eof
+```
+
+In order to effect root running containers and all users, modify the system
+wide defaults in /etc/containers/containers.conf
diff --git a/vendor/github.com/containers/psgo/SECURITY.md b/vendor/github.com/containers/psgo/SECURITY.md
new file mode 100644
index 000000000..5d5ba254a
--- /dev/null
+++ b/vendor/github.com/containers/psgo/SECURITY.md
@@ -0,0 +1,3 @@
+## Security and Disclosure Information Policy for the psgo Project
+
+The psgo Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/master/SECURITY.md) for the Containers Projects.
diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go
index 57132c94e..c75fc3815 100644
--- a/vendor/github.com/containers/psgo/psgo.go
+++ b/vendor/github.com/containers/psgo/psgo.go
@@ -847,7 +847,7 @@ func processHPID(p *process.Process, ctx *psContext) (string, error) {
func processHUSER(p *process.Process, ctx *psContext) (string, error) {
if hp := findHostProcess(p, ctx); hp != nil {
if ctx.opts != nil && len(ctx.opts.UIDMap) > 0 {
- return findID(p.Status.Uids[1], ctx.opts.UIDMap, process.LookupUID, "/proc/sys/fs/overflowuid")
+ return findID(hp.Status.Uids[1], ctx.opts.UIDMap, process.LookupUID, "/proc/sys/fs/overflowuid")
}
return hp.Huser, nil
}
@@ -860,7 +860,7 @@ func processHUSER(p *process.Process, ctx *psContext) (string, error) {
func processHGROUP(p *process.Process, ctx *psContext) (string, error) {
if hp := findHostProcess(p, ctx); hp != nil {
if ctx.opts != nil && len(ctx.opts.GIDMap) > 0 {
- return findID(p.Status.Gids[1], ctx.opts.GIDMap, process.LookupGID, "/proc/sys/fs/overflowgid")
+ return findID(hp.Status.Gids[1], ctx.opts.GIDMap, process.LookupGID, "/proc/sys/fs/overflowgid")
}
return hp.Hgroup, nil
}
diff --git a/vendor/github.com/onsi/ginkgo/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/CHANGELOG.md
index 52d8ca36d..395fa90f4 100644
--- a/vendor/github.com/onsi/ginkgo/CHANGELOG.md
+++ b/vendor/github.com/onsi/ginkgo/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 1.12.3
+
+### Fixes
+- Print correct code location of failing table test (#666) [c6d7afb]
+
## 1.12.2
### Fixes
diff --git a/vendor/github.com/onsi/ginkgo/README.md b/vendor/github.com/onsi/ginkgo/README.md
index 2fda7b9eb..ddb0cd882 100644
--- a/vendor/github.com/onsi/ginkgo/README.md
+++ b/vendor/github.com/onsi/ginkgo/README.md
@@ -4,7 +4,23 @@
Jump to the [docs](https://onsi.github.io/ginkgo/) to learn more. To start rolling your Ginkgo tests *now* [keep reading](#set-me-up)!
-If you have a question, comment, bug report, feature request, etc. please open a GitHub issue.
+If you have a question, comment, bug report, feature request, etc. please open a GitHub issue, or visit the [Ginkgo Slack channel](https://app.slack.com/client/T029RQSE6/CQQ50BBNW).
+
+## TLDR
+Ginkgo builds on Go's `testing` package, allowing expressive [Behavior-Driven Development](https://en.wikipedia.org/wiki/Behavior-driven_development) ("BDD") style tests.
+It is typically (and optionally) paired with the [Gomega](https://github.com/onsi/gomega) matcher library.
+
+```go
+Describe("the strings package", func() {
+ Context("strings.Contains()", func() {
+ When("the string contains the substring in the middle", func() {
+ It("returns `true`", func() {
+ Expect(strings.Contains("Ginkgo is awesome", "is")).To(BeTrue())
+ })
+ })
+ })
+})
+```
## Feature List
diff --git a/vendor/github.com/onsi/ginkgo/config/config.go b/vendor/github.com/onsi/ginkgo/config/config.go
index 342645022..5d4b35732 100644
--- a/vendor/github.com/onsi/ginkgo/config/config.go
+++ b/vendor/github.com/onsi/ginkgo/config/config.go
@@ -20,7 +20,7 @@ import (
"fmt"
)
-const VERSION = "1.12.2"
+const VERSION = "1.12.3"
type GinkgoConfigType struct {
RandomSeed int64
diff --git a/vendor/github.com/onsi/ginkgo/extensions/table/table.go b/vendor/github.com/onsi/ginkgo/extensions/table/table.go
index ae8ab7d24..2ed5314f2 100644
--- a/vendor/github.com/onsi/ginkgo/extensions/table/table.go
+++ b/vendor/github.com/onsi/ginkgo/extensions/table/table.go
@@ -12,7 +12,9 @@ import (
"fmt"
"reflect"
- "github.com/onsi/ginkgo"
+ "github.com/onsi/ginkgo/internal/codelocation"
+ "github.com/onsi/ginkgo/internal/global"
+ "github.com/onsi/ginkgo/types"
)
/*
@@ -42,7 +44,7 @@ It's important to understand that the `Describe`s and `It`s are generated at eva
Individual Entries can be focused (with FEntry) or marked pending (with PEntry or XEntry). In addition, the entire table can be focused or marked pending with FDescribeTable and PDescribeTable/XDescribeTable.
*/
func DescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
- describeTable(description, itBody, entries, false, false)
+ describeTable(description, itBody, entries, types.FlagTypeNone)
return true
}
@@ -50,7 +52,7 @@ func DescribeTable(description string, itBody interface{}, entries ...TableEntry
You can focus a table with `FDescribeTable`. This is equivalent to `FDescribe`.
*/
func FDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
- describeTable(description, itBody, entries, false, true)
+ describeTable(description, itBody, entries, types.FlagTypeFocused)
return true
}
@@ -58,7 +60,7 @@ func FDescribeTable(description string, itBody interface{}, entries ...TableEntr
You can mark a table as pending with `PDescribeTable`. This is equivalent to `PDescribe`.
*/
func PDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
- describeTable(description, itBody, entries, true, false)
+ describeTable(description, itBody, entries, types.FlagTypePending)
return true
}
@@ -66,33 +68,24 @@ func PDescribeTable(description string, itBody interface{}, entries ...TableEntr
You can mark a table as pending with `XDescribeTable`. This is equivalent to `XDescribe`.
*/
func XDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
- describeTable(description, itBody, entries, true, false)
+ describeTable(description, itBody, entries, types.FlagTypePending)
return true
}
-func describeTable(description string, itBody interface{}, entries []TableEntry, pending bool, focused bool) {
+func describeTable(description string, itBody interface{}, entries []TableEntry, flag types.FlagType) {
itBodyValue := reflect.ValueOf(itBody)
if itBodyValue.Kind() != reflect.Func {
panic(fmt.Sprintf("DescribeTable expects a function, got %#v", itBody))
}
- if pending {
- ginkgo.PDescribe(description, func() {
+ global.Suite.PushContainerNode(
+ description,
+ func() {
for _, entry := range entries {
entry.generateIt(itBodyValue)
}
- })
- } else if focused {
- ginkgo.FDescribe(description, func() {
- for _, entry := range entries {
- entry.generateIt(itBodyValue)
- }
- })
- } else {
- ginkgo.Describe(description, func() {
- for _, entry := range entries {
- entry.generateIt(itBodyValue)
- }
- })
- }
+ },
+ flag,
+ codelocation.New(2),
+ )
}
diff --git a/vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go b/vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go
index 93f3bc3b0..1a919a1fe 100644
--- a/vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go
+++ b/vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go
@@ -3,22 +3,31 @@ package table
import (
"reflect"
- "github.com/onsi/ginkgo"
+ "github.com/onsi/ginkgo/internal/codelocation"
+ "github.com/onsi/ginkgo/internal/global"
+ "github.com/onsi/ginkgo/types"
)
/*
TableEntry represents an entry in a table test. You generally use the `Entry` constructor.
*/
type TableEntry struct {
- Description string
- Parameters []interface{}
- Pending bool
- Focused bool
+ Description string
+ Parameters []interface{}
+ Pending bool
+ Focused bool
+ codeLocation types.CodeLocation
}
func (t TableEntry) generateIt(itBody reflect.Value) {
+ if t.codeLocation == (types.CodeLocation{}) {
+ // The user created the TableEntry struct directly instead of having used the (F/P/X)Entry constructors.
+ // Therefore default to the code location of the surrounding DescribeTable.
+ t.codeLocation = codelocation.New(5)
+ }
+
if t.Pending {
- ginkgo.PIt(t.Description)
+ global.Suite.PushItNode(t.Description, func() {}, types.FlagTypePending, t.codeLocation, 0)
return
}
@@ -38,9 +47,9 @@ func (t TableEntry) generateIt(itBody reflect.Value) {
}
if t.Focused {
- ginkgo.FIt(t.Description, body)
+ global.Suite.PushItNode(t.Description, body, types.FlagTypeFocused, t.codeLocation, global.DefaultTimeout)
} else {
- ginkgo.It(t.Description, body)
+ global.Suite.PushItNode(t.Description, body, types.FlagTypeNone, t.codeLocation, global.DefaultTimeout)
}
}
@@ -53,26 +62,26 @@ Subsequent parameters are saved off and sent to the callback passed in to `Descr
Each Entry ends up generating an individual Ginkgo It.
*/
func Entry(description string, parameters ...interface{}) TableEntry {
- return TableEntry{description, parameters, false, false}
+ return TableEntry{description, parameters, false, false, codelocation.New(1)}
}
/*
You can focus a particular entry with FEntry. This is equivalent to FIt.
*/
func FEntry(description string, parameters ...interface{}) TableEntry {
- return TableEntry{description, parameters, false, true}
+ return TableEntry{description, parameters, false, true, codelocation.New(1)}
}
/*
You can mark a particular entry as pending with PEntry. This is equivalent to PIt.
*/
func PEntry(description string, parameters ...interface{}) TableEntry {
- return TableEntry{description, parameters, true, false}
+ return TableEntry{description, parameters, true, false, codelocation.New(1)}
}
/*
You can mark a particular entry as pending with XEntry. This is equivalent to XIt.
*/
func XEntry(description string, parameters ...interface{}) TableEntry {
- return TableEntry{description, parameters, true, false}
+ return TableEntry{description, parameters, true, false, codelocation.New(1)}
}
diff --git a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go
index 3cbf89a35..30ff86f59 100644
--- a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go
+++ b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go
@@ -22,9 +22,8 @@ import (
"github.com/onsi/ginkgo/config"
"github.com/onsi/ginkgo/internal/codelocation"
- "github.com/onsi/ginkgo/internal/failer"
+ "github.com/onsi/ginkgo/internal/global"
"github.com/onsi/ginkgo/internal/remote"
- "github.com/onsi/ginkgo/internal/suite"
"github.com/onsi/ginkgo/internal/testingtproxy"
"github.com/onsi/ginkgo/internal/writer"
"github.com/onsi/ginkgo/reporters"
@@ -46,16 +45,10 @@ To circumvent this, you should call
at the top of the goroutine that caused this panic.
`
-const defaultTimeout = 1
-
-var globalSuite *suite.Suite
-var globalFailer *failer.Failer
func init() {
config.Flags(flag.CommandLine, "ginkgo", true)
GinkgoWriter = writer.New(os.Stdout)
- globalFailer = failer.New()
- globalSuite = suite.New(globalFailer)
}
//GinkgoWriter implements an io.Writer
@@ -156,7 +149,7 @@ type GinkgoTestDescription struct {
//CurrentGinkgoTestDescripton returns information about the current running test.
func CurrentGinkgoTestDescription() GinkgoTestDescription {
- summary, ok := globalSuite.CurrentRunningSpecSummary()
+ summary, ok := global.Suite.CurrentRunningSpecSummary()
if !ok {
return GinkgoTestDescription{}
}
@@ -223,7 +216,7 @@ func RunSpecsWithCustomReporters(t GinkgoTestingT, description string, specRepor
for i, reporter := range specReporters {
reporters[i] = reporter
}
- passed, hasFocusedTests := globalSuite.Run(t, description, reporters, writer, config.GinkgoConfig)
+ passed, hasFocusedTests := global.Suite.Run(t, description, reporters, writer, config.GinkgoConfig)
if passed && hasFocusedTests && strings.TrimSpace(os.Getenv("GINKGO_EDITOR_INTEGRATION")) == "" {
fmt.Println("PASS | FOCUSED")
os.Exit(types.GINKGO_FOCUS_EXIT_CODE)
@@ -252,7 +245,7 @@ func Skip(message string, callerSkip ...int) {
skip = callerSkip[0]
}
- globalFailer.Skip(message, codelocation.New(skip+1))
+ global.Failer.Skip(message, codelocation.New(skip+1))
panic(GINKGO_PANIC)
}
@@ -263,7 +256,7 @@ func Fail(message string, callerSkip ...int) {
skip = callerSkip[0]
}
- globalFailer.Fail(message, codelocation.New(skip+1))
+ global.Failer.Fail(message, codelocation.New(skip+1))
panic(GINKGO_PANIC)
}
@@ -280,7 +273,7 @@ func Fail(message string, callerSkip ...int) {
func GinkgoRecover() {
e := recover()
if e != nil {
- globalFailer.Panic(codelocation.New(1), e)
+ global.Failer.Panic(codelocation.New(1), e)
}
}
@@ -291,25 +284,25 @@ func GinkgoRecover() {
//equivalent. The difference is purely semantic -- you typically Describe the behavior of an object
//or method and, within that Describe, outline a number of Contexts and Whens.
func Describe(text string, body func()) bool {
- globalSuite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
+ global.Suite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
return true
}
//You can focus the tests within a describe block using FDescribe
func FDescribe(text string, body func()) bool {
- globalSuite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
+ global.Suite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
return true
}
//You can mark the tests within a describe block as pending using PDescribe
func PDescribe(text string, body func()) bool {
- globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
+ global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
return true
}
//You can mark the tests within a describe block as pending using XDescribe
func XDescribe(text string, body func()) bool {
- globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
+ global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
return true
}
@@ -320,25 +313,25 @@ func XDescribe(text string, body func()) bool {
//equivalent. The difference is purely semantic -- you typical Describe the behavior of an object
//or method and, within that Describe, outline a number of Contexts and Whens.
func Context(text string, body func()) bool {
- globalSuite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
+ global.Suite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
return true
}
//You can focus the tests within a describe block using FContext
func FContext(text string, body func()) bool {
- globalSuite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
+ global.Suite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
return true
}
//You can mark the tests within a describe block as pending using PContext
func PContext(text string, body func()) bool {
- globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
+ global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
return true
}
//You can mark the tests within a describe block as pending using XContext
func XContext(text string, body func()) bool {
- globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
+ global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
return true
}
@@ -349,25 +342,25 @@ func XContext(text string, body func()) bool {
//equivalent. The difference is purely semantic -- you typical Describe the behavior of an object
//or method and, within that Describe, outline a number of Contexts and Whens.
func When(text string, body func()) bool {
- globalSuite.PushContainerNode("when "+text, body, types.FlagTypeNone, codelocation.New(1))
+ global.Suite.PushContainerNode("when "+text, body, types.FlagTypeNone, codelocation.New(1))
return true
}
//You can focus the tests within a describe block using FWhen
func FWhen(text string, body func()) bool {
- globalSuite.PushContainerNode("when "+text, body, types.FlagTypeFocused, codelocation.New(1))
+ global.Suite.PushContainerNode("when "+text, body, types.FlagTypeFocused, codelocation.New(1))
return true
}
//You can mark the tests within a describe block as pending using PWhen
func PWhen(text string, body func()) bool {
- globalSuite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
+ global.Suite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
return true
}
//You can mark the tests within a describe block as pending using XWhen
func XWhen(text string, body func()) bool {
- globalSuite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
+ global.Suite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
return true
}
@@ -377,25 +370,25 @@ func XWhen(text string, body func()) bool {
//Ginkgo will normally run It blocks synchronously. To perform asynchronous tests, pass a
//function that accepts a Done channel. When you do this, you can also provide an optional timeout.
func It(text string, body interface{}, timeout ...float64) bool {
- globalSuite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
+ global.Suite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
return true
}
//You can focus individual Its using FIt
func FIt(text string, body interface{}, timeout ...float64) bool {
- globalSuite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
+ global.Suite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
return true
}
//You can mark Its as pending using PIt
func PIt(text string, _ ...interface{}) bool {
- globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
+ global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
return true
}
//You can mark Its as pending using XIt
func XIt(text string, _ ...interface{}) bool {
- globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
+ global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
return true
}
@@ -403,25 +396,25 @@ func XIt(text string, _ ...interface{}) bool {
//which "It" does not fit into a natural sentence flow. All the same protocols apply for Specify blocks
//which apply to It blocks.
func Specify(text string, body interface{}, timeout ...float64) bool {
- globalSuite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
+ global.Suite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
return true
}
//You can focus individual Specifys using FSpecify
func FSpecify(text string, body interface{}, timeout ...float64) bool {
- globalSuite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
+ global.Suite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
return true
}
//You can mark Specifys as pending using PSpecify
func PSpecify(text string, is ...interface{}) bool {
- globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
+ global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
return true
}
//You can mark Specifys as pending using XSpecify
func XSpecify(text string, is ...interface{}) bool {
- globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
+ global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
return true
}
@@ -452,25 +445,25 @@ func By(text string, callbacks ...func()) {
//The body function must have the signature:
// func(b Benchmarker)
func Measure(text string, body interface{}, samples int) bool {
- globalSuite.PushMeasureNode(text, body, types.FlagTypeNone, codelocation.New(1), samples)
+ global.Suite.PushMeasureNode(text, body, types.FlagTypeNone, codelocation.New(1), samples)
return true
}
//You can focus individual Measures using FMeasure
func FMeasure(text string, body interface{}, samples int) bool {
- globalSuite.PushMeasureNode(text, body, types.FlagTypeFocused, codelocation.New(1), samples)
+ global.Suite.PushMeasureNode(text, body, types.FlagTypeFocused, codelocation.New(1), samples)
return true
}
//You can mark Measurements as pending using PMeasure
func PMeasure(text string, _ ...interface{}) bool {
- globalSuite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
+ global.Suite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
return true
}
//You can mark Measurements as pending using XMeasure
func XMeasure(text string, _ ...interface{}) bool {
- globalSuite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
+ global.Suite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
return true
}
@@ -481,7 +474,7 @@ func XMeasure(text string, _ ...interface{}) bool {
//
//You may only register *one* BeforeSuite handler per test suite. You typically do so in your bootstrap file at the top level.
func BeforeSuite(body interface{}, timeout ...float64) bool {
- globalSuite.SetBeforeSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
+ global.Suite.SetBeforeSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
return true
}
@@ -494,7 +487,7 @@ func BeforeSuite(body interface{}, timeout ...float64) bool {
//
//You may only register *one* AfterSuite handler per test suite. You typically do so in your bootstrap file at the top level.
func AfterSuite(body interface{}, timeout ...float64) bool {
- globalSuite.SetAfterSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
+ global.Suite.SetAfterSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
return true
}
@@ -539,7 +532,7 @@ func AfterSuite(body interface{}, timeout ...float64) bool {
// Ω(err).ShouldNot(HaveOccurred())
// })
func SynchronizedBeforeSuite(node1Body interface{}, allNodesBody interface{}, timeout ...float64) bool {
- globalSuite.SetSynchronizedBeforeSuiteNode(
+ global.Suite.SetSynchronizedBeforeSuiteNode(
node1Body,
allNodesBody,
codelocation.New(1),
@@ -566,7 +559,7 @@ func SynchronizedBeforeSuite(node1Body interface{}, allNodesBody interface{}, ti
// dbRunner.Stop()
// })
func SynchronizedAfterSuite(allNodesBody interface{}, node1Body interface{}, timeout ...float64) bool {
- globalSuite.SetSynchronizedAfterSuiteNode(
+ global.Suite.SetSynchronizedAfterSuiteNode(
allNodesBody,
node1Body,
codelocation.New(1),
@@ -581,7 +574,7 @@ func SynchronizedAfterSuite(allNodesBody interface{}, node1Body interface{}, tim
//Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts
//a Done channel
func BeforeEach(body interface{}, timeout ...float64) bool {
- globalSuite.PushBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
+ global.Suite.PushBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
return true
}
@@ -591,7 +584,7 @@ func BeforeEach(body interface{}, timeout ...float64) bool {
//Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts
//a Done channel
func JustBeforeEach(body interface{}, timeout ...float64) bool {
- globalSuite.PushJustBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
+ global.Suite.PushJustBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
return true
}
@@ -601,7 +594,7 @@ func JustBeforeEach(body interface{}, timeout ...float64) bool {
//Like It blocks, JustAfterEach blocks can be made asynchronous by providing a body function that accepts
//a Done channel
func JustAfterEach(body interface{}, timeout ...float64) bool {
- globalSuite.PushJustAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
+ global.Suite.PushJustAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
return true
}
@@ -611,13 +604,13 @@ func JustAfterEach(body interface{}, timeout ...float64) bool {
//Like It blocks, AfterEach blocks can be made asynchronous by providing a body function that accepts
//a Done channel
func AfterEach(body interface{}, timeout ...float64) bool {
- globalSuite.PushAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
+ global.Suite.PushAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
return true
}
func parseTimeout(timeout ...float64) time.Duration {
if len(timeout) == 0 {
- return time.Duration(defaultTimeout * int64(time.Second))
+ return global.DefaultTimeout
} else {
return time.Duration(timeout[0] * float64(time.Second))
}
diff --git a/vendor/github.com/onsi/ginkgo/internal/global/init.go b/vendor/github.com/onsi/ginkgo/internal/global/init.go
new file mode 100644
index 000000000..711443200
--- /dev/null
+++ b/vendor/github.com/onsi/ginkgo/internal/global/init.go
@@ -0,0 +1,18 @@
+package global
+
+import (
+ "time"
+
+ "github.com/onsi/ginkgo/internal/failer"
+ "github.com/onsi/ginkgo/internal/suite"
+)
+
+const DefaultTimeout = time.Duration(1 * time.Second)
+
+var Suite *suite.Suite
+var Failer *failer.Failer
+
+func init() {
+ Failer = failer.New()
+ Suite = suite.New(Failer)
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
index 25ff51589..c0a965923 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
@@ -37,8 +37,18 @@ type Manager interface {
// restore the object later.
GetPaths() map[string]string
+ // GetUnifiedPath returns the unified path when running in unified mode.
+ // The value corresponds to the all values of GetPaths() map.
+ //
+ // GetUnifiedPath returns error when running in hybrid mode as well as
+ // in legacy mode.
+ GetUnifiedPath() (string, error)
+
// Sets the cgroup as configured.
Set(container *configs.Config) error
+
+ // Gets the cgroup as configured.
+ GetCgroups() (*configs.Cgroup, error)
}
type NotFoundError struct {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
index 60790f83b..dbcc58f5b 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
@@ -20,8 +20,9 @@ import (
)
const (
- CgroupNamePrefix = "name="
- CgroupProcesses = "cgroup.procs"
+ CgroupNamePrefix = "name="
+ CgroupProcesses = "cgroup.procs"
+ unifiedMountpoint = "/sys/fs/cgroup"
)
var (
@@ -40,7 +41,7 @@ var HugePageSizeUnitList = []string{"B", "KB", "MB", "GB", "TB", "PB"}
func IsCgroup2UnifiedMode() bool {
isUnifiedOnce.Do(func() {
var st syscall.Statfs_t
- if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil {
+ if err := syscall.Statfs(unifiedMountpoint, &st); err != nil {
panic("cannot statfs cgroup root")
}
isUnified = st.Type == unix.CGROUP2_SUPER_MAGIC
@@ -50,6 +51,9 @@ func IsCgroup2UnifiedMode() bool {
// https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
+ if IsCgroup2UnifiedMode() {
+ return unifiedMountpoint, nil
+ }
mnt, _, err := FindCgroupMountpointAndRoot(cgroupPath, subsystem)
return mnt, err
}
@@ -235,8 +239,8 @@ func GetCgroupMounts(all bool) ([]Mount, error) {
return nil, err
}
m := Mount{
- Mountpoint: "/sys/fs/cgroup",
- Root: "/sys/fs/cgroup",
+ Mountpoint: unifiedMountpoint,
+ Root: unifiedMountpoint,
Subsystems: availableControllers,
}
return []Mount{m}, nil
@@ -262,6 +266,21 @@ func GetCgroupMounts(all bool) ([]Mount, error) {
// GetAllSubsystems returns all the cgroup subsystems supported by the kernel
func GetAllSubsystems() ([]string, error) {
+ // /proc/cgroups is meaningless for v2
+ // https://github.com/torvalds/linux/blob/v5.3/Documentation/admin-guide/cgroup-v2.rst#deprecated-v1-core-features
+ if IsCgroup2UnifiedMode() {
+ // "pseudo" controllers do not appear in /sys/fs/cgroup/cgroup.controllers.
+ // - devices: implemented in kernel 4.15
+ // - freezer: implemented in kernel 5.2
+ // We assume these are always available, as it is hard to detect availability.
+ pseudo := []string{"devices", "freezer"}
+ data, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers")
+ if err != nil {
+ return nil, err
+ }
+ subsystems := append(pseudo, strings.Fields(string(data))...)
+ return subsystems, nil
+ }
f, err := os.Open("/proc/cgroups")
if err != nil {
return nil, err
diff --git a/vendor/modules.txt b/vendor/modules.txt
index f0e279be4..b84d9e017 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -146,7 +146,7 @@ github.com/containers/ocicrypt/keywrap/pgp
github.com/containers/ocicrypt/keywrap/pkcs7
github.com/containers/ocicrypt/spec
github.com/containers/ocicrypt/utils
-# github.com/containers/psgo v1.5.0
+# github.com/containers/psgo v1.5.1
github.com/containers/psgo
github.com/containers/psgo/internal/capabilities
github.com/containers/psgo/internal/cgroups
@@ -197,7 +197,7 @@ github.com/containers/storage/pkg/truncindex
github.com/containers/storage/pkg/unshare
# github.com/coreos/go-iptables v0.4.5
github.com/coreos/go-iptables/iptables
-# github.com/coreos/go-systemd/v22 v22.0.0
+# github.com/coreos/go-systemd/v22 v22.1.0
github.com/coreos/go-systemd/v22/activation
github.com/coreos/go-systemd/v22/dbus
github.com/coreos/go-systemd/v22/internal/dlopen
@@ -361,7 +361,7 @@ github.com/nxadm/tail/ratelimiter
github.com/nxadm/tail/util
github.com/nxadm/tail/watch
github.com/nxadm/tail/winfile
-# github.com/onsi/ginkgo v1.12.2
+# github.com/onsi/ginkgo v1.12.3
github.com/onsi/ginkgo
github.com/onsi/ginkgo/config
github.com/onsi/ginkgo/extensions/table
@@ -375,6 +375,7 @@ github.com/onsi/ginkgo/ginkgo/watch
github.com/onsi/ginkgo/internal/codelocation
github.com/onsi/ginkgo/internal/containernode
github.com/onsi/ginkgo/internal/failer
+github.com/onsi/ginkgo/internal/global
github.com/onsi/ginkgo/internal/leafnodes
github.com/onsi/ginkgo/internal/remote
github.com/onsi/ginkgo/internal/spec
@@ -408,7 +409,7 @@ github.com/opencontainers/go-digest
# github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
github.com/opencontainers/image-spec/specs-go
github.com/opencontainers/image-spec/specs-go/v1
-# github.com/opencontainers/runc v1.0.0-rc9
+# github.com/opencontainers/runc v1.0.0-rc90
github.com/opencontainers/runc/libcontainer/apparmor
github.com/opencontainers/runc/libcontainer/cgroups
github.com/opencontainers/runc/libcontainer/configs