summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/healthcheck/run.go5
-rw-r--r--cmd/podman/system/unshare.go21
-rw-r--r--docs/source/markdown/podman-generate-kube.1.md3
-rw-r--r--docs/source/markdown/podman-play-kube.1.md2
-rw-r--r--docs/source/markdown/podman-system-connection-add.1.md4
-rw-r--r--docs/source/markdown/podman-unshare.1.md29
-rw-r--r--go.mod7
-rw-r--r--go.sum16
-rw-r--r--libpod/container.go5
-rw-r--r--libpod/container_top_linux.go2
-rw-r--r--libpod/kube.go33
-rw-r--r--libpod/oci_conmon_linux.go4
-rw-r--r--libpod/runtime.go12
-rw-r--r--libpod/stats.go10
-rw-r--r--pkg/api/handlers/compat/auth.go3
-rw-r--r--pkg/api/handlers/compat/changes.go5
-rw-r--r--pkg/api/handlers/compat/containers.go21
-rw-r--r--pkg/api/handlers/compat/containers_archive.go5
-rw-r--r--pkg/api/handlers/compat/containers_attach.go7
-rw-r--r--pkg/api/handlers/compat/containers_create.go5
-rw-r--r--pkg/api/handlers/compat/containers_export.go3
-rw-r--r--pkg/api/handlers/compat/containers_logs.go5
-rw-r--r--pkg/api/handlers/compat/containers_pause.go3
-rw-r--r--pkg/api/handlers/compat/containers_prune.go5
-rw-r--r--pkg/api/handlers/compat/containers_restart.go5
-rw-r--r--pkg/api/handlers/compat/containers_start.go5
-rw-r--r--pkg/api/handlers/compat/containers_stats.go11
-rw-r--r--pkg/api/handlers/compat/containers_stop.go5
-rw-r--r--pkg/api/handlers/compat/containers_top.go5
-rw-r--r--pkg/api/handlers/compat/containers_unpause.go3
-rw-r--r--pkg/api/handlers/compat/events.go8
-rw-r--r--pkg/api/handlers/compat/exec.go9
-rw-r--r--pkg/api/handlers/compat/images.go25
-rw-r--r--pkg/api/handlers/compat/images_build.go7
-rw-r--r--pkg/api/handlers/compat/images_history.go3
-rw-r--r--pkg/api/handlers/compat/images_prune.go3
-rw-r--r--pkg/api/handlers/compat/images_push.go7
-rw-r--r--pkg/api/handlers/compat/images_remove.go5
-rw-r--r--pkg/api/handlers/compat/images_search.go5
-rw-r--r--pkg/api/handlers/compat/images_tag.go3
-rw-r--r--pkg/api/handlers/compat/info.go3
-rw-r--r--pkg/api/handlers/compat/networks.go20
-rw-r--r--pkg/api/handlers/compat/ping.go2
-rw-r--r--pkg/api/handlers/compat/resize.go5
-rw-r--r--pkg/api/handlers/compat/secrets.go9
-rw-r--r--pkg/api/handlers/compat/system.go3
-rw-r--r--pkg/api/handlers/compat/version.go3
-rw-r--r--pkg/api/handlers/compat/volumes.go20
-rw-r--r--pkg/api/handlers/libpod/containers.go31
-rw-r--r--pkg/api/handlers/libpod/containers_create.go3
-rw-r--r--pkg/api/handlers/libpod/containers_stats.go7
-rw-r--r--pkg/api/handlers/libpod/generate.go9
-rw-r--r--pkg/api/handlers/libpod/healthcheck.go3
-rw-r--r--pkg/api/handlers/libpod/images.go47
-rw-r--r--pkg/api/handlers/libpod/images_pull.go7
-rw-r--r--pkg/api/handlers/libpod/info.go3
-rw-r--r--pkg/api/handlers/libpod/manifests.go19
-rw-r--r--pkg/api/handlers/libpod/networks.go21
-rw-r--r--pkg/api/handlers/libpod/play.go7
-rw-r--r--pkg/api/handlers/libpod/pods.go39
-rw-r--r--pkg/api/handlers/libpod/secrets.go5
-rw-r--r--pkg/api/handlers/libpod/system.go7
-rw-r--r--pkg/api/handlers/libpod/volumes.go17
-rw-r--r--pkg/api/handlers/swagger/swagger.go9
-rw-r--r--pkg/api/handlers/utils/containers.go13
-rw-r--r--pkg/api/handlers/utils/images.go7
-rw-r--r--pkg/api/server/handler_api.go45
-rw-r--r--pkg/api/server/handler_logging.go51
-rw-r--r--pkg/api/server/handler_panic.go32
-rw-r--r--pkg/api/server/handler_rid.go34
-rw-r--r--pkg/api/server/idle/tracker.go10
-rw-r--r--pkg/api/server/register_containers.go4
-rw-r--r--pkg/api/server/server.go73
-rw-r--r--pkg/api/types/types.go13
-rw-r--r--pkg/bindings/test/containers_test.go6
-rw-r--r--pkg/domain/entities/play.go2
-rw-r--r--pkg/domain/infra/abi/play.go190
-rw-r--r--pkg/machine/ignition.go46
-rw-r--r--pkg/specgen/generate/kube/kube.go5
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_system.py13
-rw-r--r--test/e2e/generate_kube_test.go72
-rw-r--r--test/e2e/healthcheck_run_test.go9
-rw-r--r--test/e2e/pause_test.go5
-rw-r--r--test/e2e/play_kube_test.go57
-rw-r--r--test/e2e/unshare_test.go35
-rw-r--r--test/system/075-exec.bats28
-rw-r--r--test/system/125-import.bats63
-rw-r--r--test/system/220-healthcheck.bats2
-rw-r--r--vendor/github.com/containers/psgo/go.mod11
-rw-r--r--vendor/github.com/containers/psgo/go.sum85
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/ns.go8
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/status.go6
-rw-r--r--vendor/github.com/containers/psgo/internal/process/process.go9
-rw-r--r--vendor/github.com/containers/psgo/psgo.go18
-rw-r--r--vendor/github.com/containers/psgo/vendor.conf8
-rw-r--r--vendor/github.com/godbus/dbus/v5/README.md (renamed from vendor/github.com/godbus/dbus/v5/README.markdown)12
-rw-r--r--vendor/github.com/godbus/dbus/v5/auth.go13
-rw-r--r--vendor/github.com/godbus/dbus/v5/conn.go14
-rw-r--r--vendor/github.com/godbus/dbus/v5/decoder.go16
-rw-r--r--vendor/github.com/godbus/dbus/v5/encoder.go61
-rw-r--r--vendor/github.com/godbus/dbus/v5/export.go37
-rw-r--r--vendor/github.com/godbus/dbus/v5/message.go73
-rw-r--r--vendor/github.com/godbus/dbus/v5/sig.go66
-rw-r--r--vendor/github.com/godbus/dbus/v5/transport_generic.go10
-rw-r--r--vendor/github.com/godbus/dbus/v5/transport_unix.go24
-rw-r--r--vendor/github.com/gorilla/handlers/.travis.yml8
-rw-r--r--vendor/github.com/gorilla/handlers/LICENSE22
-rw-r--r--vendor/github.com/gorilla/handlers/README.md52
-rw-r--r--vendor/github.com/gorilla/handlers/canonical.go71
-rw-r--r--vendor/github.com/gorilla/handlers/compress.go84
-rw-r--r--vendor/github.com/gorilla/handlers/doc.go9
-rw-r--r--vendor/github.com/gorilla/handlers/handlers.go378
-rw-r--r--vendor/github.com/gorilla/handlers/proxy_headers.go113
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/selinux.go4
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go111
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go6
-rw-r--r--vendor/modules.txt8
117 files changed, 2175 insertions, 600 deletions
diff --git a/cmd/podman/healthcheck/run.go b/cmd/podman/healthcheck/run.go
index fe8dc2573..b03a07bc4 100644
--- a/cmd/podman/healthcheck/run.go
+++ b/cmd/podman/healthcheck/run.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/podman/v3/cmd/podman/common"
"github.com/containers/podman/v3/cmd/podman/registry"
+ "github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/spf13/cobra"
)
@@ -34,9 +35,9 @@ func run(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
- if response.Status == "unhealthy" {
+ if response.Status == define.HealthCheckUnhealthy {
registry.SetExitCode(1)
+ fmt.Println(response.Status)
}
- fmt.Println(response.Status)
return err
}
diff --git a/cmd/podman/system/unshare.go b/cmd/podman/system/unshare.go
index f930d8b62..50230609e 100644
--- a/cmd/podman/system/unshare.go
+++ b/cmd/podman/system/unshare.go
@@ -2,6 +2,7 @@ package system
import (
"os"
+ "os/exec"
"github.com/containers/common/pkg/completion"
"github.com/containers/podman/v3/cmd/podman/registry"
@@ -50,5 +51,23 @@ func unshare(cmd *cobra.Command, args []string) error {
args = []string{shell}
}
- return registry.ContainerEngine().Unshare(registry.Context(), args, unshareOptions)
+ err := registry.ContainerEngine().Unshare(registry.Context(), args, unshareOptions)
+ if err != nil {
+ if exitError, ok := err.(*exec.ExitError); ok {
+ // the user command inside the unshare env has failed
+ // we set the exit code, do not return the error to the user
+ // otherwise "exit status X" will be printed
+ registry.SetExitCode(exitError.ExitCode())
+ return nil
+ }
+ // cmd.Run() can return fs.ErrNotExist, fs.ErrPermission or exec.ErrNotFound
+ // follow podman run/exec standard with the exit codes
+ if errors.Is(err, os.ErrNotExist) || errors.Is(err, exec.ErrNotFound) {
+ registry.SetExitCode(127)
+ } else if errors.Is(err, os.ErrPermission) {
+ registry.SetExitCode(126)
+ }
+ return err
+ }
+ return nil
}
diff --git a/docs/source/markdown/podman-generate-kube.1.md b/docs/source/markdown/podman-generate-kube.1.md
index 2e00b58b6..2e9f68bf3 100644
--- a/docs/source/markdown/podman-generate-kube.1.md
+++ b/docs/source/markdown/podman-generate-kube.1.md
@@ -16,6 +16,9 @@ Volumes appear in the generated YAML according to two different volume types. Bi
Potential name conflicts between volumes are avoided by using a standard naming scheme for each volume type. The *hostPath* volume types are named according to the path on the host machine, replacing forward slashes with hyphens less any leading and trailing forward slashes. The special case of the filesystem root, `/`, translates to the name `root`. Additionally, the name is suffixed with `-host` to avoid naming conflicts with *persistentVolumeClaim* volumes. Each *persistentVolumeClaim* volume type uses the name of its associated named volume suffixed with `-pvc`.
+Note that if an init container is created with type `once` and the pod has been started, the init container will not show up in the generated kube YAML as `once` type init containers are deleted after they are run. If the pod has only been created and not started, it will be in the generated kube YAML.
+Init containers created with type `always` will always be generated in the kube YAML as they are never deleted, even after running to completion.
+
Note that the generated Kubernetes YAML file can be used to re-run the deployment via podman-play-kube(1).
## OPTIONS
diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md
index 6af1bde1d..c170d6495 100644
--- a/docs/source/markdown/podman-play-kube.1.md
+++ b/docs/source/markdown/podman-play-kube.1.md
@@ -20,6 +20,8 @@ Currently, the supported Kubernetes kinds are:
Only two volume types are supported by play kube, the *hostPath* and *persistentVolumeClaim* volume types. For the *hostPath* volume type, only the *default (empty)*, *DirectoryOrCreate*, *Directory*, *FileOrCreate*, *File*, and *Socket* subtypes are supported. The *CharDevice* and *BlockDevice* subtypes are not supported. Podman interprets the value of *hostPath* *path* as a file path when it contains at least one forward slash, otherwise Podman treats the value as the name of a named volume. When using a *persistentVolumeClaim*, the value for *claimName* is the name for the Podman named volume.
+Note: When playing a kube YAML with init containers, the init container will be created with init type value `always`.
+
Note: *hostPath* volume types created by play kube will be given an SELinux private label (Z)
Note: If the `:latest` tag is used, Podman will attempt to pull the image from a registry. If the image was built locally with Podman or Buildah, it will have `localhost` as the domain, in that case, Podman will use the image from the local store even if it has the `:latest` tag.
diff --git a/docs/source/markdown/podman-system-connection-add.1.md b/docs/source/markdown/podman-system-connection-add.1.md
index ad9acb4d8..fa763d7cc 100644
--- a/docs/source/markdown/podman-system-connection-add.1.md
+++ b/docs/source/markdown/podman-system-connection-add.1.md
@@ -41,9 +41,9 @@ $ podman system connection add QA podman.example.com
$ podman system connection add --identity ~/.ssh/dev_rsa production ssh://root@server.example.com:2222
-$ podman system connection add unix:///run/podman/podman.sock
+$ podman system connection add testing unix:///run/podman/podman.sock
-$ podman system connection add tcp://localhost:8080
+$ podman system connection add debug tcp://localhost:8080
```
## SEE ALSO
podman-system(1) , podman-system-connection(1) , containers.conf(5)
diff --git a/docs/source/markdown/podman-unshare.1.md b/docs/source/markdown/podman-unshare.1.md
index 2e7adfd34..72821b6e5 100644
--- a/docs/source/markdown/podman-unshare.1.md
+++ b/docs/source/markdown/podman-unshare.1.md
@@ -37,6 +37,35 @@ connect to a rootless container via IP address (CNI networking). This is otherwi
not possible from the host network namespace.
_Note: Using this option with more than one unshare session can have unexpected results._
+## Exit Codes
+
+The exit code from `podman unshare` gives information about why the container
+failed to run or why it exited. When `podman unshare` commands exit with a non-zero code,
+the exit codes follow the `chroot` standard, see below:
+
+ **125** The error is with podman **_itself_**
+
+ $ podman unshare --foo; echo $?
+ Error: unknown flag: --foo
+ 125
+
+ **126** Executing a _contained command_ and the _command_ cannot be invoked
+
+ $ podman unshare /etc; echo $?
+ Error: fork/exec /etc: permission denied
+ 126
+
+ **127** Executing a _contained command_ and the _command_ cannot be found
+
+ $ podman run busybox foo; echo $?
+ Error: fork/exec /usr/bin/bogus: no such file or directory
+ 127
+
+ **Exit code** _contained command_ exit code
+
+ $ podman run busybox /bin/sh -c 'exit 3'; echo $?
+ 3
+
## EXAMPLE
```
diff --git a/go.mod b/go.mod
index 7bf4c8878..3d2ac461b 100644
--- a/go.mod
+++ b/go.mod
@@ -16,7 +16,7 @@ require (
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.16.0
github.com/containers/ocicrypt v1.1.2
- github.com/containers/psgo v1.5.2
+ github.com/containers/psgo v1.6.0
github.com/containers/storage v1.35.0
github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
@@ -32,9 +32,10 @@ require (
github.com/dtylman/scp v0.0.0-20181017070807-f3000a34aef4
github.com/fsnotify/fsnotify v1.5.1
github.com/ghodss/yaml v1.0.0
- github.com/godbus/dbus/v5 v5.0.4
+ github.com/godbus/dbus/v5 v5.0.5
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/google/uuid v1.3.0
+ github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33
github.com/gorilla/mux v1.8.0
github.com/gorilla/schema v1.2.0
github.com/hashicorp/go-multierror v1.1.1
@@ -50,7 +51,7 @@ require (
github.com/opencontainers/runc v1.0.2
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
github.com/opencontainers/runtime-tools v0.9.0
- github.com/opencontainers/selinux v1.8.4
+ github.com/opencontainers/selinux v1.8.5
github.com/pkg/errors v0.9.1
github.com/pmezard/go-difflib v1.0.0
github.com/rootless-containers/rootlesskit v0.14.5
diff --git a/go.sum b/go.sum
index 945fec7e9..25c12325c 100644
--- a/go.sum
+++ b/go.sum
@@ -256,8 +256,8 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU
github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0=
github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
-github.com/containers/psgo v1.5.2 h1:3aoozst/GIwsrr/5jnFy3FrJay98uujPCu9lTuSZ/Cw=
-github.com/containers/psgo v1.5.2/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
+github.com/containers/psgo v1.6.0 h1:jkl/5kndKmJ/bnSFq8in6xRDAzgW26GnNuTxoycNFvk=
+github.com/containers/psgo v1.6.0/go.mod h1:ggVhB2KQi9qGZdqSlczqN0BwcJdotmpRru87S1anRO8=
github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM=
github.com/containers/storage v1.32.6/go.mod h1:mdB+b89p+jU8zpzLTVXA0gWMmIo0WrkfGMh1R8O2IQw=
github.com/containers/storage v1.33.1/go.mod h1:FUZPF4nJijX8ixdhByZJXf02cvbyLi6dyDwXdIe8QVY=
@@ -402,8 +402,9 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
-github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.0.5 h1:9Eg0XUhQxtkV8ykTMKtMMYY72g4NgxtRq4jgh4Ih5YM=
+github.com/godbus/dbus/v5 v5.0.5/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
@@ -498,6 +499,7 @@ github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3i
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 h1:893HsJqtxp9z1SF76gg6hY70hRY1wVlTSnC/h1yUDCo=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
@@ -731,7 +733,6 @@ github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod
github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283 h1:TVzvdjOalkJBNkbpPVMAr4KV9QRf2IjfxdyxwAK78Gs=
github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
-github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
@@ -756,8 +757,9 @@ 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.4 h1:krlgQ6/j9CkCXT5oW0yVXdQFOME3NjKuuAZXuR6O7P4=
github.com/opencontainers/selinux v1.8.4/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
+github.com/opencontainers/selinux v1.8.5 h1:OkT6bMHOQ1JQQO4ihjQ49sj0+wciDcjziSVTRn8VeTA=
+github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656 h1:WaxyNFpmIDu4i6so9r6LVFIbSaXqsj8oitMitt86ae4=
github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
@@ -767,7 +769,6 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
-github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -831,7 +832,6 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW
github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf h1:b0+ZBD3rohnkQ4q5duD1+RyTXTg9yk+qTOPMSQtapO0=
github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@@ -1116,7 +1116,6 @@ golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1200,6 +1199,7 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/libpod/container.go b/libpod/container.go
index 0986a0d80..a4bbb5dd0 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -1062,6 +1062,11 @@ func (c *Container) IsInfra() bool {
return c.config.IsInfra
}
+// IsInitCtr returns whether the container is an init container
+func (c *Container) IsInitCtr() bool {
+ return len(c.config.InitContainerType) > 0
+}
+
// IsReadOnly returns whether the container is running in read only mode
func (c *Container) IsReadOnly() bool {
return c.config.Spec.Root.Readonly
diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go
index ee03570ab..0d4cba85e 100644
--- a/libpod/container_top_linux.go
+++ b/libpod/container_top_linux.go
@@ -47,7 +47,7 @@ func (c *Container) Top(descriptors []string) ([]string, error) {
if psgoErr == nil {
return output, nil
}
- if errors.Cause(psgoErr) != psgo.ErrUnknownDescriptor {
+ if !errors.Is(psgoErr, psgo.ErrUnknownDescriptor) {
return nil, psgoErr
}
diff --git a/libpod/kube.go b/libpod/kube.go
index fff040adb..812bb101b 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -4,6 +4,7 @@ import (
"fmt"
"math/rand"
"os"
+ "sort"
"strconv"
"strings"
"time"
@@ -220,8 +221,14 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor
deDupPodVolumes := make(map[string]*v1.Volume)
first := true
podContainers := make([]v1.Container, 0, len(containers))
+ podInitCtrs := []v1.Container{}
podAnnotations := make(map[string]string)
dnsInfo := v1.PodDNSConfig{}
+
+ // Let's sort the containers in order of created time
+ // This will ensure that the init containers are defined in the correct order in the kube yaml
+ sort.Slice(containers, func(i, j int) bool { return containers[i].CreatedTime().Before(containers[j].CreatedTime()) })
+
for _, ctr := range containers {
if !ctr.IsInfra() {
// Convert auto-update labels into kube annotations
@@ -229,6 +236,8 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor
podAnnotations[k] = v
}
+ isInit := ctr.IsInitCtr()
+
ctr, volumes, _, err := containerToV1Container(ctr)
if err != nil {
return nil, err
@@ -245,6 +254,10 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor
ctr.Ports = ports
first = false
}
+ if isInit {
+ podInitCtrs = append(podInitCtrs, ctr)
+ continue
+ }
podContainers = append(podContainers, ctr)
// Deduplicate volumes, so if containers in the pod share a volume, it's only
// listed in the volumes section once
@@ -278,13 +291,14 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor
return newPodObject(
p.Name(),
podAnnotations,
+ podInitCtrs,
podContainers,
podVolumes,
&dnsInfo,
hostNetwork), nil
}
-func newPodObject(podName string, annotations map[string]string, containers []v1.Container, volumes []v1.Volume, dnsOptions *v1.PodDNSConfig, hostNetwork bool) *v1.Pod {
+func newPodObject(podName string, annotations map[string]string, initCtrs, containers []v1.Container, volumes []v1.Volume, dnsOptions *v1.PodDNSConfig, hostNetwork bool) *v1.Pod {
tm := v12.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
@@ -304,9 +318,10 @@ func newPodObject(podName string, annotations map[string]string, containers []v1
Annotations: annotations,
}
ps := v1.PodSpec{
- Containers: containers,
- Volumes: volumes,
- HostNetwork: hostNetwork,
+ Containers: containers,
+ HostNetwork: hostNetwork,
+ InitContainers: initCtrs,
+ Volumes: volumes,
}
if dnsOptions != nil {
ps.DNSConfig = dnsOptions
@@ -323,6 +338,7 @@ func newPodObject(podName string, annotations map[string]string, containers []v1
// for a single container. we "insert" that container description in a pod.
func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) {
kubeCtrs := make([]v1.Container, 0, len(ctrs))
+ kubeInitCtrs := []v1.Container{}
kubeVolumes := make([]v1.Volume, 0)
hostNetwork := true
podDNS := v1.PodDNSConfig{}
@@ -333,6 +349,8 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) {
kubeAnnotations[k] = v
}
+ isInit := ctr.IsInitCtr()
+
if !ctr.HostNetwork() {
hostNetwork = false
}
@@ -340,7 +358,11 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) {
if err != nil {
return nil, err
}
- kubeCtrs = append(kubeCtrs, kubeCtr)
+ if isInit {
+ kubeInitCtrs = append(kubeInitCtrs, kubeCtr)
+ } else {
+ kubeCtrs = append(kubeCtrs, kubeCtr)
+ }
kubeVolumes = append(kubeVolumes, kubeVols...)
// Combine DNS information in sum'd structure
@@ -379,6 +401,7 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) {
return newPodObject(
strings.ReplaceAll(ctrs[0].Name(), "_", ""),
kubeAnnotations,
+ kubeInitCtrs,
kubeCtrs,
kubeVolumes,
&podDNS,
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index 353e6af71..c00d83f95 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -46,7 +46,9 @@ import (
const (
// This is Conmon's STDIO_BUF_SIZE. I don't believe we have access to it
// directly from the Go code, so const it here
- bufferSize = conmonConfig.BufSize
+ // Important: The conmon attach socket uses an extra byte at the beginning of each
+ // message to specify the STREAM so we have to increase the buffer size by one
+ bufferSize = conmonConfig.BufSize + 1
)
// ConmonOCIRuntime is an OCI runtime managed by Conmon.
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 1c9c56d16..761fa08a2 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -335,8 +335,16 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// If user is rootless and XDG_RUNTIME_DIR is found, podman will not proceed with /tmp directory
// it will try to use existing XDG_RUNTIME_DIR
// if current user has no write access to XDG_RUNTIME_DIR we will fail later
- if unix.Access(runtime.storageConfig.RunRoot, unix.W_OK) != nil {
- logrus.Warnf("XDG_RUNTIME_DIR is pointing to a path which is not writable. Most likely podman will fail.")
+ if err := unix.Access(runtime.storageConfig.RunRoot, unix.W_OK); err != nil {
+ msg := "XDG_RUNTIME_DIR is pointing to a path which is not writable. Most likely podman will fail."
+ if errors.Is(err, os.ErrNotExist) {
+ // if dir does not exists try to create it
+ if err := os.MkdirAll(runtime.storageConfig.RunRoot, 0700); err != nil {
+ logrus.Warn(msg)
+ }
+ } else {
+ logrus.Warn(msg)
+ }
}
}
diff --git a/libpod/stats.go b/libpod/stats.go
index 6f0360ef1..975152535 100644
--- a/libpod/stats.go
+++ b/libpod/stats.go
@@ -30,7 +30,7 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de
}
}
- if c.state.State != define.ContainerStateRunning {
+ if c.state.State != define.ContainerStateRunning && c.state.State != define.ContainerStatePaused {
return stats, define.ErrCtrStateInvalid
}
@@ -54,6 +54,12 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de
return nil, err
}
+ // If the current total usage in the cgroup is less than what was previously
+ // recorded then it means the container was restarted and runs in a new cgroup
+ if previousStats.Duration > cgroupStats.CPU.Usage.Total {
+ previousStats = &define.ContainerStats{}
+ }
+
previousCPU := previousStats.CPUNano
now := uint64(time.Now().UnixNano())
stats.Duration = cgroupStats.CPU.Usage.Total
@@ -65,7 +71,7 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de
stats.MemLimit = getMemLimit(cgroupStats.Memory.Usage.Limit)
stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100
stats.PIDs = 0
- if conState == define.ContainerStateRunning {
+ if conState == define.ContainerStateRunning || conState == define.ContainerStatePaused {
stats.PIDs = cgroupStats.Pids.Current
}
stats.BlockInput, stats.BlockOutput = calculateBlockIO(cgroupStats)
diff --git a/pkg/api/handlers/compat/auth.go b/pkg/api/handlers/compat/auth.go
index 3594c9781..2244adc3d 100644
--- a/pkg/api/handlers/compat/auth.go
+++ b/pkg/api/handlers/compat/auth.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
docker "github.com/docker/docker/api/types"
"github.com/pkg/errors"
@@ -37,7 +38,7 @@ func Auth(w http.ResponseWriter, r *http.Request) {
skipTLS = types.NewOptionalBool(true)
}
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
sysCtx := runtime.SystemContext()
sysCtx.DockerInsecureSkipTLSVerify = skipTLS
diff --git a/pkg/api/handlers/compat/changes.go b/pkg/api/handlers/compat/changes.go
index dfe656755..fe580437d 100644
--- a/pkg/api/handlers/compat/changes.go
+++ b/pkg/api/handlers/compat/changes.go
@@ -6,13 +6,14 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
func Changes(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
Parent string `schema:"parent"`
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 95c09ff0e..26e1bf00b 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -14,6 +14,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/filters"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -31,7 +32,7 @@ import (
)
func RemoveContainer(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Force bool `schema:"force"`
Ignore bool `schema:"ignore"`
@@ -63,7 +64,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
options.Volumes = query.DockerVolumes
}
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
// Now use the ABI implementation to prevent us from having duplicate
// code.
containerEngine := abi.ContainerEngine{Libpod: runtime}
@@ -92,8 +93,8 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
}
func ListContainers(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
All bool `schema:"all"`
Limit int `schema:"limit"`
@@ -168,8 +169,8 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
}
func GetContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Size bool `schema:"size"`
}{
@@ -197,8 +198,8 @@ func GetContainer(w http.ResponseWriter, r *http.Request) {
func KillContainer(w http.ResponseWriter, r *http.Request) {
// /{version}/containers/(name)/kill
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Signal string `schema:"signal"`
}{
@@ -584,8 +585,8 @@ func formatCapabilities(slice []string) {
}
func RenameContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
name := utils.GetName(r)
query := struct {
diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index 541f702e7..cda23a399 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/copy"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -18,8 +19,8 @@ import (
)
func Archive(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
switch r.Method {
case http.MethodPut:
diff --git a/pkg/api/handlers/compat/containers_attach.go b/pkg/api/handlers/compat/containers_attach.go
index c230efbe0..40d5e2d4d 100644
--- a/pkg/api/handlers/compat/containers_attach.go
+++ b/pkg/api/handlers/compat/containers_attach.go
@@ -7,14 +7,15 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
"github.com/containers/podman/v3/pkg/api/server/idle"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/gorilla/schema"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
func AttachContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
DetachKeys string `schema:"detachKeys"`
@@ -104,7 +105,7 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
if <-hijackChan {
// If connection was Hijacked, we have to signal it's being closed
- t := r.Context().Value("idletracker").(*idle.Tracker)
+ t := r.Context().Value(api.IdleTrackerKey).(*idle.Tracker)
defer t.Close()
if err != nil {
diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go
index 9df35697a..94d20a04a 100644
--- a/pkg/api/handlers/compat/containers_create.go
+++ b/pkg/api/handlers/compat/containers_create.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/podman/v3/pkg/specgen"
@@ -18,8 +19,8 @@ import (
)
func CreateContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Name string `schema:"name"`
}{
diff --git a/pkg/api/handlers/compat/containers_export.go b/pkg/api/handlers/compat/containers_export.go
index 252d2d8b5..6b43a544b 100644
--- a/pkg/api/handlers/compat/containers_export.go
+++ b/pkg/api/handlers/compat/containers_export.go
@@ -7,11 +7,12 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/pkg/errors"
)
func ExportContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
con, err := runtime.LookupContainer(name)
if err != nil {
diff --git a/pkg/api/handlers/compat/containers_logs.go b/pkg/api/handlers/compat/containers_logs.go
index a7cfe09ea..4adcaa511 100644
--- a/pkg/api/handlers/compat/containers_logs.go
+++ b/pkg/api/handlers/compat/containers_logs.go
@@ -13,6 +13,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/logs"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/util"
"github.com/gorilla/schema"
"github.com/pkg/errors"
@@ -20,8 +21,8 @@ import (
)
func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
Follow bool `schema:"follow"`
diff --git a/pkg/api/handlers/compat/containers_pause.go b/pkg/api/handlers/compat/containers_pause.go
index d00b19acc..99c2f6bdc 100644
--- a/pkg/api/handlers/compat/containers_pause.go
+++ b/pkg/api/handlers/compat/containers_pause.go
@@ -5,10 +5,11 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
)
func PauseContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
// /{version}/containers/(name)/pause
name := utils.GetName(r)
diff --git a/pkg/api/handlers/compat/containers_prune.go b/pkg/api/handlers/compat/containers_prune.go
index 61ea7a89e..9fa8bc9f4 100644
--- a/pkg/api/handlers/compat/containers_prune.go
+++ b/pkg/api/handlers/compat/containers_prune.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities/reports"
"github.com/containers/podman/v3/pkg/domain/filters"
"github.com/containers/podman/v3/pkg/util"
@@ -14,7 +15,7 @@ import (
)
func PruneContainers(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filtersMap, err := util.PrepareFilters(r)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
@@ -65,7 +66,7 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) {
}
func PruneContainersHelper(r *http.Request, filterFuncs []libpod.ContainerFilter) ([]*reports.PruneReport, error) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
report, err := runtime.PruneContainers(filterFuncs)
if err != nil {
diff --git a/pkg/api/handlers/compat/containers_restart.go b/pkg/api/handlers/compat/containers_restart.go
index 46a6297fa..8ef2ff308 100644
--- a/pkg/api/handlers/compat/containers_restart.go
+++ b/pkg/api/handlers/compat/containers_restart.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/gorilla/schema"
@@ -13,8 +14,8 @@ import (
)
func RestartContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
// Now use the ABI implementation to prevent us from having duplicate
// code.
containerEngine := abi.ContainerEngine{Libpod: runtime}
diff --git a/pkg/api/handlers/compat/containers_start.go b/pkg/api/handlers/compat/containers_start.go
index f1ed1b2b8..ca2b5d84c 100644
--- a/pkg/api/handlers/compat/containers_start.go
+++ b/pkg/api/handlers/compat/containers_start.go
@@ -3,6 +3,7 @@ package compat
import (
"net/http"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/sirupsen/logrus"
"github.com/containers/podman/v3/libpod"
@@ -12,7 +13,7 @@ import (
)
func StartContainer(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
DetachKeys string `schema:"detachKeys"`
}{
@@ -26,7 +27,7 @@ func StartContainer(w http.ResponseWriter, r *http.Request) {
// TODO - start does not support adding detach keys
logrus.Info("the detach keys parameter is not supported on start container")
}
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
con, err := runtime.LookupContainer(name)
if err != nil {
diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go
index 851955207..e872f885a 100644
--- a/pkg/api/handlers/compat/containers_stats.go
+++ b/pkg/api/handlers/compat/containers_stats.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/cgroups"
docker "github.com/docker/docker/api/types"
"github.com/gorilla/schema"
@@ -18,12 +19,12 @@ import (
const DefaultStatsPeriod = 5 * time.Second
func StatsContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Stream bool `schema:"stream"`
- OneShot bool `schema:"one-shot"` //added schema for one shot
+ OneShot bool `schema:"one-shot"` // added schema for one shot
}{
Stream: true,
}
@@ -64,7 +65,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
coder := json.NewEncoder(w)
// Write header and content type.
w.WriteHeader(http.StatusOK)
- w.Header().Add("Content-Type", "application/json")
+ w.Header().Set("Content-Type", "application/json")
if flusher, ok := w.(http.Flusher); ok {
flusher.Flush()
}
@@ -97,7 +98,7 @@ streamLabel: // A label to flatten the scope
default:
// Container stats
- stats, err := ctnr.GetContainerStats(stats)
+ stats, err = ctnr.GetContainerStats(stats)
if err != nil {
logrus.Errorf("Unable to get container stats: %v", err)
return
diff --git a/pkg/api/handlers/compat/containers_stop.go b/pkg/api/handlers/compat/containers_stop.go
index 3ae223693..10ac67f76 100644
--- a/pkg/api/handlers/compat/containers_stop.go
+++ b/pkg/api/handlers/compat/containers_stop.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/gorilla/schema"
@@ -13,8 +14,8 @@ import (
)
func StopContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
// Now use the ABI implementation to prevent us from having duplicate
// code.
containerEngine := abi.ContainerEngine{Libpod: runtime}
diff --git a/pkg/api/handlers/compat/containers_top.go b/pkg/api/handlers/compat/containers_top.go
index cae044a89..b5debd37d 100644
--- a/pkg/api/handlers/compat/containers_top.go
+++ b/pkg/api/handlers/compat/containers_top.go
@@ -7,13 +7,14 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
func TopContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
defaultValue := "-ef"
if utils.IsLibpodRequest(r) {
diff --git a/pkg/api/handlers/compat/containers_unpause.go b/pkg/api/handlers/compat/containers_unpause.go
index a37c4ba2a..3f4f2f531 100644
--- a/pkg/api/handlers/compat/containers_unpause.go
+++ b/pkg/api/handlers/compat/containers_unpause.go
@@ -5,10 +5,11 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
)
func UnpauseContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
// /{version}/containers/(name)/unpause
name := utils.GetName(r)
diff --git a/pkg/api/handlers/compat/events.go b/pkg/api/handlers/compat/events.go
index 9fbac91e0..a79b33ecc 100644
--- a/pkg/api/handlers/compat/events.go
+++ b/pkg/api/handlers/compat/events.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/util"
"github.com/gorilla/schema"
@@ -14,13 +15,12 @@ import (
"github.com/sirupsen/logrus"
)
-// NOTE: this endpoint serves both the docker-compatible one and the new libpod
-// one.
+// GetEvents endpoint serves both the docker-compatible one and the new libpod one
func GetEvents(w http.ResponseWriter, r *http.Request) {
var (
fromStart bool
- decoder = r.Context().Value("decoder").(*schema.Decoder)
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ decoder = r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
json = jsoniter.ConfigCompatibleWithStandardLibrary // FIXME: this should happen on the package level
)
diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go
index 77e62c112..ea61a1013 100644
--- a/pkg/api/handlers/compat/exec.go
+++ b/pkg/api/handlers/compat/exec.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
"github.com/containers/podman/v3/pkg/api/server/idle"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/specgen/generate"
"github.com/gorilla/mux"
"github.com/pkg/errors"
@@ -19,7 +20,7 @@ import (
// ExecCreateHandler creates an exec session for a given container.
func ExecCreateHandler(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
input := new(handlers.ExecCreateConfig)
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
@@ -101,7 +102,7 @@ func ExecCreateHandler(w http.ResponseWriter, r *http.Request) {
// ExecInspectHandler inspects a given exec session.
func ExecInspectHandler(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
sessionID := mux.Vars(r)["id"]
sessionCtr, err := runtime.GetExecSessionContainer(sessionID)
@@ -129,7 +130,7 @@ func ExecInspectHandler(w http.ResponseWriter, r *http.Request) {
// ExecStartHandler runs a given exec session.
func ExecStartHandler(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
sessionID := mux.Vars(r)["id"]
@@ -191,7 +192,7 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) {
if <-hijackChan {
// If connection was Hijacked, we have to signal it's being closed
- t := r.Context().Value("idletracker").(*idle.Tracker)
+ t := r.Context().Value(api.IdleTrackerKey).(*idle.Tracker)
defer t.Close()
if err != nil {
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index 6f8fb21f0..0b7ba8bee 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -17,6 +17,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -45,7 +46,7 @@ func mergeNameAndTagOrDigest(name, tagOrDigest string) string {
func ExportImage(w http.ResponseWriter, r *http.Request) {
// 200 ok
// 500 server
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
tmpfile, err := ioutil.TempFile("", "api.tar")
if err != nil {
@@ -89,8 +90,8 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
var (
destImage string
)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
Author string `schema:"author"`
@@ -162,8 +163,8 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
// 200 no error
// 404 repo does not exist or no read access
// 500 internal
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
Changes []string `schema:"changes"`
@@ -234,8 +235,8 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
// 200 no error
// 404 repo does not exist or no read access
// 500 internal
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
FromImage string `schema:"fromImage"`
@@ -301,7 +302,7 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
}
w.WriteHeader(http.StatusOK)
- w.Header().Add("Content-Type", "application/json")
+ w.Header().Set("Content-Type", "application/json")
flush()
enc := json.NewEncoder(w)
@@ -407,8 +408,8 @@ func GetImages(w http.ResponseWriter, r *http.Request) {
func LoadImages(w http.ResponseWriter, r *http.Request) {
// TODO this is basically wrong
// TODO ... improve these ^ messages to something useful
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
Changes map[string]string `json:"changes"` // Ignored
@@ -465,8 +466,8 @@ func LoadImages(w http.ResponseWriter, r *http.Request) {
func ExportImages(w http.ResponseWriter, r *http.Request) {
// 200 OK
// 500 Error
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
Names []string `schema:"names"`
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index 0fcca1821..6855742b2 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -20,6 +20,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/pkg/channel"
"github.com/containers/storage/pkg/archive"
@@ -128,7 +129,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
Tag: []string{},
}
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
return
@@ -410,7 +411,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
reporter := channel.NewWriter(make(chan []byte))
defer reporter.Close()
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
rtc, err := runtime.GetConfig()
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
@@ -520,7 +521,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
// Send headers and prime client for stream to come
w.WriteHeader(http.StatusOK)
- w.Header().Add("Content-Type", "application/json")
+ w.Header().Set("Content-Type", "application/json")
flush()
body := w.(io.Writer)
diff --git a/pkg/api/handlers/compat/images_history.go b/pkg/api/handlers/compat/images_history.go
index 54c893f47..0c6b9fa88 100644
--- a/pkg/api/handlers/compat/images_history.go
+++ b/pkg/api/handlers/compat/images_history.go
@@ -6,11 +6,12 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/pkg/errors"
)
func HistoryImage(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
newImage, _, err := runtime.LibimageRuntime().LookupImage(name, nil)
diff --git a/pkg/api/handlers/compat/images_prune.go b/pkg/api/handlers/compat/images_prune.go
index bbbfb5577..5728c83c7 100644
--- a/pkg/api/handlers/compat/images_prune.go
+++ b/pkg/api/handlers/compat/images_prune.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/podman/v3/pkg/util"
@@ -19,7 +20,7 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
var (
filters []string
)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
if err != nil {
diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go
index 62f8cdc77..07ff76819 100644
--- a/pkg/api/handlers/compat/images_push.go
+++ b/pkg/api/handlers/compat/images_push.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -22,8 +23,8 @@ import (
// PushImage is the handler for the compat http endpoint for pushing images.
func PushImage(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
digestFile, err := ioutil.TempFile("", "digest.txt")
if err != nil {
@@ -105,7 +106,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
}
w.WriteHeader(http.StatusOK)
- w.Header().Add("Content-Type", "application/json")
+ w.Header().Set("Content-Type", "application/json")
flush()
var report jsonmessage.JSONMessage
diff --git a/pkg/api/handlers/compat/images_remove.go b/pkg/api/handlers/compat/images_remove.go
index 390f25caf..2dc247c1f 100644
--- a/pkg/api/handlers/compat/images_remove.go
+++ b/pkg/api/handlers/compat/images_remove.go
@@ -5,6 +5,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/storage"
@@ -13,8 +14,8 @@ import (
)
func RemoveImage(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
Force bool `schema:"force"`
diff --git a/pkg/api/handlers/compat/images_search.go b/pkg/api/handlers/compat/images_search.go
index 13a3693fa..01282513e 100644
--- a/pkg/api/handlers/compat/images_search.go
+++ b/pkg/api/handlers/compat/images_search.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -16,8 +17,8 @@ import (
)
func SearchImages(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Term string `json:"term"`
Limit int `json:"limit"`
diff --git a/pkg/api/handlers/compat/images_tag.go b/pkg/api/handlers/compat/images_tag.go
index 199ad0488..7858298be 100644
--- a/pkg/api/handlers/compat/images_tag.go
+++ b/pkg/api/handlers/compat/images_tag.go
@@ -6,11 +6,12 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/pkg/errors"
)
func TagImage(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
// /v1.xx/images/(name)/tag
name := utils.GetName(r)
diff --git a/pkg/api/handlers/compat/info.go b/pkg/api/handlers/compat/info.go
index 2c26c7bf8..941718a8b 100644
--- a/pkg/api/handlers/compat/info.go
+++ b/pkg/api/handlers/compat/info.go
@@ -15,6 +15,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/rootless"
docker "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry"
@@ -27,7 +28,7 @@ import (
func GetInfo(w http.ResponseWriter, r *http.Request) {
// 200 ok
// 500 internal
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
infoData, err := runtime.Info()
if err != nil {
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index b990a916b..847e6dcff 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -14,11 +14,13 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/network"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
networkid "github.com/containers/podman/v3/pkg/network"
"github.com/containers/podman/v3/pkg/util"
"github.com/docker/docker/api/types"
+
dockerNetwork "github.com/docker/docker/api/types/network"
"github.com/gorilla/schema"
"github.com/pkg/errors"
@@ -32,7 +34,7 @@ type pluginInterface struct {
}
func InspectNetwork(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
// scope is only used to see if the user passes any illegal value, verbose is not used but implemented
// for compatibility purposes only.
@@ -42,7 +44,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
}{
scope: "local",
}
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
@@ -195,7 +197,7 @@ func getPlugin(plugins []*libcni.NetworkConfig) (pluginInterface, error) {
}
func ListNetworks(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
@@ -234,7 +236,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
name string
networkCreate types.NetworkCreateRequest
)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
if err := json.NewDecoder(r.Body).Decode(&networkCreate); err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
@@ -304,7 +306,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
}
func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
ic := abi.ContainerEngine{Libpod: runtime}
query := struct {
@@ -313,7 +315,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
// This is where you can override the golang default value for one of fields
}
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
@@ -348,7 +350,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
// Connect adds a container to a network
func Connect(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
var (
aliases []string
@@ -382,7 +384,7 @@ func Connect(w http.ResponseWriter, r *http.Request) {
// Disconnect removes a container from a network
func Disconnect(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
var netDisconnect types.NetworkDisconnect
if err := json.NewDecoder(r.Body).Decode(&netDisconnect); err != nil {
@@ -409,7 +411,7 @@ func Disconnect(w http.ResponseWriter, r *http.Request) {
// Prune removes unused networks
func Prune(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
diff --git a/pkg/api/handlers/compat/ping.go b/pkg/api/handlers/compat/ping.go
index 5513e902e..ce32d9b7c 100644
--- a/pkg/api/handlers/compat/ping.go
+++ b/pkg/api/handlers/compat/ping.go
@@ -13,7 +13,7 @@ import (
// Clients will use the Header availability to test which backend engine is in use.
// Note: Additionally handler supports GET and HEAD methods
func Ping(w http.ResponseWriter, r *http.Request) {
- // Note API-Version and Libpod-API-Version are set in handler_api.go
+ // Note: API-Version and Libpod-API-Version are set in handler_api.go
w.Header().Set("BuildKit-Version", "")
w.Header().Set("Builder-Version", "")
w.Header().Set("Docker-Experimental", "true")
diff --git a/pkg/api/handlers/compat/resize.go b/pkg/api/handlers/compat/resize.go
index 844fb74c4..d7796658b 100644
--- a/pkg/api/handlers/compat/resize.go
+++ b/pkg/api/handlers/compat/resize.go
@@ -8,14 +8,15 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/gorilla/mux"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
func ResizeTTY(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
// /containers/{id}/resize
query := struct {
diff --git a/pkg/api/handlers/compat/secrets.go b/pkg/api/handlers/compat/secrets.go
index 7dd17ea94..52cfe03ba 100644
--- a/pkg/api/handlers/compat/secrets.go
+++ b/pkg/api/handlers/compat/secrets.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/podman/v3/pkg/util"
@@ -17,7 +18,7 @@ import (
func ListSecrets(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
)
filtersMap, err := util.PrepareFilters(r)
if err != nil {
@@ -53,7 +54,7 @@ func ListSecrets(w http.ResponseWriter, r *http.Request) {
func InspectSecret(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
)
name := utils.GetName(r)
names := []string{name}
@@ -86,7 +87,7 @@ func InspectSecret(w http.ResponseWriter, r *http.Request) {
func RemoveSecret(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
)
opts := entities.SecretRmOptions{}
@@ -106,7 +107,7 @@ func RemoveSecret(w http.ResponseWriter, r *http.Request) {
func CreateSecret(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
)
opts := entities.SecretCreateOptions{}
createParams := struct {
diff --git a/pkg/api/handlers/compat/system.go b/pkg/api/handlers/compat/system.go
index 57702698b..1e78db181 100644
--- a/pkg/api/handlers/compat/system.go
+++ b/pkg/api/handlers/compat/system.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
docker "github.com/docker/docker/api/types"
@@ -14,7 +15,7 @@ import (
func GetDiskUsage(w http.ResponseWriter, r *http.Request) {
options := entities.SystemDfOptions{}
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
ic := abi.ContainerEngine{Libpod: runtime}
df, err := ic.SystemDf(r.Context(), options)
if err != nil {
diff --git a/pkg/api/handlers/compat/version.go b/pkg/api/handlers/compat/version.go
index a115cc885..01cbb252c 100644
--- a/pkg/api/handlers/compat/version.go
+++ b/pkg/api/handlers/compat/version.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/entities/types"
"github.com/containers/podman/v3/version"
@@ -17,7 +18,7 @@ import (
)
func VersionHandler(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
running, err := define.GetVersion()
if err != nil {
diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go
index 1ff1468e7..0f9b66888 100644
--- a/pkg/api/handlers/compat/volumes.go
+++ b/pkg/api/handlers/compat/volumes.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/filters"
"github.com/containers/podman/v3/pkg/domain/infra/abi/parse"
"github.com/containers/podman/v3/pkg/util"
@@ -21,9 +22,8 @@ import (
)
func ListVolumes(w http.ResponseWriter, r *http.Request) {
- var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
- )
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+
filtersMap, err := util.PrepareFilters(r)
if err != nil {
utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
@@ -79,8 +79,8 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
func CreateVolume(w http.ResponseWriter, r *http.Request) {
var (
volumeOptions []libpod.VolumeCreateOption
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
- decoder = r.Context().Value("decoder").(*schema.Decoder)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder = r.Context().Value(api.DecoderKey).(*schema.Decoder)
)
/* No query string data*/
query := struct{}{}
@@ -181,7 +181,7 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
func InspectVolume(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
)
name := utils.GetName(r)
vol, err := runtime.GetVolume(name)
@@ -209,8 +209,8 @@ func InspectVolume(w http.ResponseWriter, r *http.Request) {
func RemoveVolume(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
- decoder = r.Context().Value("decoder").(*schema.Decoder)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder = r.Context().Value(api.DecoderKey).(*schema.Decoder)
)
query := struct {
Force bool `schema:"force"`
@@ -225,7 +225,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
}
/* The implications for `force` differ between Docker and us, so we can't
- * simply pass the `force` parameter to `runeimt.RemoveVolume()`.
+ * simply pass the `force` parameter to `runtime.RemoveVolume()`.
* Specifically, Docker's behavior seems to be that `force` means "do not
* error on missing volume"; ours means "remove any not-running containers
* using the volume at the same time".
@@ -263,7 +263,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
func PruneVolumes(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
)
filterMap, err := util.PrepareFilters(r)
if err != nil {
diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go
index 77269db8b..4639093f2 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/compat"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/podman/v3/pkg/util"
@@ -18,8 +19,8 @@ import (
)
func ContainerExists(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
// Now use the ABI implementation to prevent us from having duplicate
// code.
containerEngine := abi.ContainerEngine{Libpod: runtime}
@@ -58,7 +59,7 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) {
}
func ListContainers(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
All bool `schema:"all"`
External bool `schema:"external"`
@@ -89,7 +90,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
limit = query.Last
}
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
// Now use the ABI implementation to prevent us from having duplicate
// code.
containerEngine := abi.ContainerEngine{Libpod: runtime}
@@ -118,7 +119,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
}
func GetContainer(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Size bool `schema:"size"`
}{
@@ -130,7 +131,7 @@ func GetContainer(w http.ResponseWriter, r *http.Request) {
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
container, err := runtime.LookupContainer(name)
if err != nil {
@@ -150,7 +151,7 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) {
}
func UnmountContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
conn, err := runtime.LookupContainer(name)
if err != nil {
@@ -165,7 +166,7 @@ func UnmountContainer(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusNoContent, "")
}
func MountContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
conn, err := runtime.LookupContainer(name)
if err != nil {
@@ -181,7 +182,7 @@ func MountContainer(w http.ResponseWriter, r *http.Request) {
func ShowMountedContainers(w http.ResponseWriter, r *http.Request) {
response := make(map[string]string)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
conns, err := runtime.GetAllContainers()
if err != nil {
utils.InternalServerError(w, err)
@@ -201,7 +202,7 @@ func ShowMountedContainers(w http.ResponseWriter, r *http.Request) {
func Checkpoint(w http.ResponseWriter, r *http.Request) {
var targetFile string
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Keep bool `schema:"keep"`
LeaveRunning bool `schema:"leaveRunning"`
@@ -218,7 +219,7 @@ func Checkpoint(w http.ResponseWriter, r *http.Request) {
return
}
name := utils.GetName(r)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
ctr, err := runtime.LookupContainer(name)
if err != nil {
utils.ContainerNotFound(w, name, err)
@@ -268,7 +269,7 @@ func Restore(w http.ResponseWriter, r *http.Request) {
var (
targetFile string
)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Keep bool `schema:"keep"`
TCPEstablished bool `schema:"tcpEstablished"`
@@ -287,7 +288,7 @@ func Restore(w http.ResponseWriter, r *http.Request) {
return
}
name := utils.GetName(r)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
ctr, err := runtime.LookupContainer(name)
if err != nil {
utils.ContainerNotFound(w, name, err)
@@ -328,7 +329,7 @@ func Restore(w http.ResponseWriter, r *http.Request) {
func InitContainer(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
ctr, err := runtime.LookupContainer(name)
if err != nil {
utils.ContainerNotFound(w, name, err)
@@ -347,7 +348,7 @@ func InitContainer(w http.ResponseWriter, r *http.Request) {
}
func ShouldRestart(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
// Now use the ABI implementation to prevent us from having duplicate
// code.
containerEngine := abi.ContainerEngine{Libpod: runtime}
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
index 0e2163d5c..77bfe7b50 100644
--- a/pkg/api/handlers/libpod/containers_create.go
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/specgen/generate"
@@ -16,7 +17,7 @@ import (
// CreateContainer takes a specgenerator and makes a container. It returns
// the new container ID on success along with any warnings.
func CreateContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
var sg specgen.SpecGenerator
if err := json.NewDecoder(r.Body).Decode(&sg); err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
diff --git a/pkg/api/handlers/libpod/containers_stats.go b/pkg/api/handlers/libpod/containers_stats.go
index 8a04884b0..084f1252d 100644
--- a/pkg/api/handlers/libpod/containers_stats.go
+++ b/pkg/api/handlers/libpod/containers_stats.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/cgroups"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -16,8 +17,8 @@ import (
)
func StatsContainer(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
// Check if service is running rootless (cheap check)
if rootless.IsRootless() {
@@ -60,7 +61,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
// Write header and content type.
w.WriteHeader(http.StatusOK)
- w.Header().Add("Content-Type", "application/json")
+ w.Header().Set("Content-Type", "application/json")
if flusher, ok := w.(http.Flusher); ok {
flusher.Flush()
}
diff --git a/pkg/api/handlers/libpod/generate.go b/pkg/api/handlers/libpod/generate.go
index 8a2b93d0e..117c5e2aa 100644
--- a/pkg/api/handlers/libpod/generate.go
+++ b/pkg/api/handlers/libpod/generate.go
@@ -5,6 +5,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/podman/v3/pkg/util"
@@ -13,8 +14,8 @@ import (
)
func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Name bool `schema:"useName"`
New bool `schema:"new"`
@@ -59,8 +60,8 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
}
func GenerateKube(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Names []string `schema:"names"`
Service bool `schema:"service"`
diff --git a/pkg/api/handlers/libpod/healthcheck.go b/pkg/api/handlers/libpod/healthcheck.go
index 27478ddec..cad4378e5 100644
--- a/pkg/api/handlers/libpod/healthcheck.go
+++ b/pkg/api/handlers/libpod/healthcheck.go
@@ -6,10 +6,11 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
)
func RunHealthCheck(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
status, err := runtime.HealthCheck(name)
if err != nil {
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index d759f4824..72093c492 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -18,6 +18,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -41,7 +42,7 @@ import (
// create
func ImageExists(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
ir := abi.ImageEngine{Libpod: runtime}
@@ -58,9 +59,9 @@ func ImageExists(w http.ResponseWriter, r *http.Request) {
}
func ImageTree(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
WhatRequires bool `schema:"whatrequires"`
}{
@@ -101,8 +102,8 @@ func GetImage(w http.ResponseWriter, r *http.Request) {
}
func GetImages(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
All bool
Digests bool
@@ -146,8 +147,8 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
var (
err error
)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
All bool `schema:"all"`
}{
@@ -198,8 +199,8 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
var (
output string
)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Compress bool `schema:"compress"`
Format string `schema:"format"`
@@ -279,8 +280,8 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
var (
output string
)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Compress bool `schema:"compress"`
Format string `schema:"format"`
@@ -369,7 +370,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
}
func ImagesLoad(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
tmpfile, err := ioutil.TempFile("", "libpod-images-load.tar")
if err != nil {
@@ -398,8 +399,8 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
}
func ImagesImport(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Changes []string `schema:"changes"`
Message string `schema:"message"`
@@ -453,8 +454,8 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
// PushImage is the handler for the compat http endpoint for pushing images.
func PushImage(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
Destination string `schema:"destination"`
@@ -522,8 +523,8 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
destImage string
mimeType string
)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
Author string `schema:"author"`
@@ -597,7 +598,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
}
func UntagImage(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
tags := []string{} // Note: if empty, all tags will be removed from the image.
repo := r.Form.Get("repo")
@@ -641,8 +642,8 @@ func UntagImage(w http.ResponseWriter, r *http.Request) {
// ImagesBatchRemove is the endpoint for batch image removal.
func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
All bool `schema:"all"`
Force bool `schema:"force"`
@@ -665,8 +666,8 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) {
// ImagesRemove is the endpoint for removing one image.
func ImagesRemove(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Force bool `schema:"force"`
}{
diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go
index 3c13c6e20..fabdb326b 100644
--- a/pkg/api/handlers/libpod/images_pull.go
+++ b/pkg/api/handlers/libpod/images_pull.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/pkg/channel"
"github.com/containers/podman/v3/pkg/domain/entities"
@@ -23,8 +24,8 @@ import (
// transport or be normalized to one). Other transports are rejected as they
// do not make sense in a remote context.
func ImagesPull(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Reference string `schema:"reference"`
OS string `schema:"OS"`
@@ -107,7 +108,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
}
w.WriteHeader(http.StatusOK)
- w.Header().Add("Content-Type", "application/json")
+ w.Header().Set("Content-Type", "application/json")
flush()
enc := json.NewEncoder(w)
diff --git a/pkg/api/handlers/libpod/info.go b/pkg/api/handlers/libpod/info.go
index 8868d563d..67dc8637c 100644
--- a/pkg/api/handlers/libpod/info.go
+++ b/pkg/api/handlers/libpod/info.go
@@ -5,11 +5,12 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
)
func GetInfo(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
containerEngine := abi.ContainerEngine{Libpod: runtime}
info, err := containerEngine.Info(r.Context())
if err != nil {
diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go
index 2f36db583..869c83fa3 100644
--- a/pkg/api/handlers/libpod/manifests.go
+++ b/pkg/api/handlers/libpod/manifests.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -20,8 +21,8 @@ import (
)
func ManifestCreate(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Name []string `schema:"name"`
Image []string `schema:"image"`
@@ -57,7 +58,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) {
// ExistsManifest check if a manifest list exists
func ExistsManifest(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
imageEngine := abi.ImageEngine{Libpod: runtime}
@@ -74,7 +75,7 @@ func ExistsManifest(w http.ResponseWriter, r *http.Request) {
}
func ManifestInspect(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
imageEngine := abi.ImageEngine{Libpod: runtime}
@@ -94,7 +95,7 @@ func ManifestInspect(w http.ResponseWriter, r *http.Request) {
}
func ManifestAdd(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
var addOptions entities.ManifestAddOptions
if err := json.NewDecoder(r.Body).Decode(&addOptions); err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
@@ -124,8 +125,8 @@ func ManifestAdd(w http.ResponseWriter, r *http.Request) {
}
func ManifestRemove(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Digest string `schema:"digest"`
}{
@@ -155,8 +156,8 @@ func ManifestRemove(w http.ResponseWriter, r *http.Request) {
}
func ManifestPush(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
All bool `schema:"all"`
Destination string `schema:"destination"`
diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go
index e4f450e12..122ab1d3d 100644
--- a/pkg/api/handlers/libpod/networks.go
+++ b/pkg/api/handlers/libpod/networks.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/network"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/podman/v3/pkg/util"
@@ -16,8 +17,8 @@ import (
)
func CreateNetwork(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
options := entities.NetworkCreateOptions{}
if err := json.NewDecoder(r.Body).Decode(&options); err != nil {
utils.Error(w, "unable to marshall input", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
@@ -45,7 +46,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, report)
}
func ListNetworks(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
if err != nil {
utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
@@ -66,8 +67,8 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
}
func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Force bool `schema:"force"`
}{
@@ -100,8 +101,8 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
}
func InspectNetwork(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
}{
// override any golang type defaults
@@ -129,7 +130,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
// Connect adds a container to a network
func Connect(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
var netConnect entities.NetworkConnectOptions
if err := json.NewDecoder(r.Body).Decode(&netConnect); err != nil {
@@ -155,7 +156,7 @@ func Connect(w http.ResponseWriter, r *http.Request) {
// ExistsNetwork check if a network exists
func ExistsNetwork(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
ic := abi.ContainerEngine{Libpod: runtime}
@@ -173,7 +174,7 @@ func ExistsNetwork(w http.ResponseWriter, r *http.Request) {
// Prune removes unused networks
func Prune(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
if err != nil {
diff --git a/pkg/api/handlers/libpod/play.go b/pkg/api/handlers/libpod/play.go
index 4f79d5f20..0def32821 100644
--- a/pkg/api/handlers/libpod/play.go
+++ b/pkg/api/handlers/libpod/play.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -19,8 +20,8 @@ import (
)
func PlayKube(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Network string `schema:"network"`
TLSVerify bool `schema:"tlsVerify"`
@@ -121,7 +122,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
}
func PlayKubeDown(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml")
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 3d6cf093b..cc686c69d 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -14,6 +14,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/podman/v3/pkg/specgen"
@@ -27,7 +28,7 @@ import (
func PodCreate(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
err error
)
psg := specgen.PodSpecGenerator{InfraContainerSpec: &specgen.SpecGenerator{}}
@@ -100,7 +101,7 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
}
func Pods(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
if err != nil {
@@ -122,7 +123,7 @@ func Pods(w http.ResponseWriter, r *http.Request) {
}
func PodInspect(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
if err != nil {
@@ -144,8 +145,8 @@ func PodInspect(w http.ResponseWriter, r *http.Request) {
func PodStop(w http.ResponseWriter, r *http.Request) {
var (
stopError error
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
- decoder = r.Context().Value("decoder").(*schema.Decoder)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder = r.Context().Value(api.DecoderKey).(*schema.Decoder)
responses map[string]error
)
query := struct {
@@ -206,7 +207,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
}
func PodStart(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
if err != nil {
@@ -243,8 +244,8 @@ func PodStart(w http.ResponseWriter, r *http.Request) {
func PodDelete(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
- decoder = r.Context().Value("decoder").(*schema.Decoder)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder = r.Context().Value(api.DecoderKey).(*schema.Decoder)
)
query := struct {
Force bool `schema:"force"`
@@ -272,7 +273,7 @@ func PodDelete(w http.ResponseWriter, r *http.Request) {
}
func PodRestart(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
if err != nil {
@@ -308,7 +309,7 @@ func PodPrune(w http.ResponseWriter, r *http.Request) {
func PodPruneHelper(r *http.Request) ([]*entities.PodPruneReport, error) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
)
responses, err := runtime.PrunePods(r.Context())
if err != nil {
@@ -325,7 +326,7 @@ func PodPruneHelper(r *http.Request) ([]*entities.PodPruneReport, error) {
}
func PodPause(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
if err != nil {
@@ -351,7 +352,7 @@ func PodPause(w http.ResponseWriter, r *http.Request) {
}
func PodUnpause(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
if err != nil {
@@ -377,8 +378,8 @@ func PodUnpause(w http.ResponseWriter, r *http.Request) {
}
func PodTop(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
PsArgs string `schema:"ps_args"`
@@ -420,8 +421,8 @@ func PodTop(w http.ResponseWriter, r *http.Request) {
func PodKill(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
- decoder = r.Context().Value("decoder").(*schema.Decoder)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder = r.Context().Value(api.DecoderKey).(*schema.Decoder)
signal = "SIGKILL"
)
query := struct {
@@ -489,7 +490,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
}
func PodExists(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
_, err := runtime.LookupPod(name)
if err != nil {
@@ -500,8 +501,8 @@ func PodExists(w http.ResponseWriter, r *http.Request) {
}
func PodStats(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
NamesOrIDs []string `schema:"namesOrIDs"`
diff --git a/pkg/api/handlers/libpod/secrets.go b/pkg/api/handlers/libpod/secrets.go
index 7086d9e38..5cdff8387 100644
--- a/pkg/api/handlers/libpod/secrets.go
+++ b/pkg/api/handlers/libpod/secrets.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/gorilla/schema"
@@ -15,8 +16,8 @@ import (
func CreateSecret(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
- decoder = r.Context().Value("decoder").(*schema.Decoder)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder = r.Context().Value(api.DecoderKey).(*schema.Decoder)
)
decoder.RegisterConverter(map[string]string{}, func(str string) reflect.Value {
diff --git a/pkg/api/handlers/libpod/system.go b/pkg/api/handlers/libpod/system.go
index bca92a4af..b7c60736f 100644
--- a/pkg/api/handlers/libpod/system.go
+++ b/pkg/api/handlers/libpod/system.go
@@ -5,6 +5,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/podman/v3/pkg/util"
@@ -14,8 +15,8 @@ import (
// SystemPrune removes unused data
func SystemPrune(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
All bool `schema:"all"`
@@ -53,7 +54,7 @@ func SystemPrune(w http.ResponseWriter, r *http.Request) {
func DiskUsage(w http.ResponseWriter, r *http.Request) {
// Options are only used by the CLI
options := entities.SystemDfOptions{}
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
ic := abi.ContainerEngine{Libpod: runtime}
response, err := ic.SystemDf(r.Context(), options)
if err != nil {
diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go
index 68aec30d5..318758868 100644
--- a/pkg/api/handlers/libpod/volumes.go
+++ b/pkg/api/handlers/libpod/volumes.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/entities/reports"
"github.com/containers/podman/v3/pkg/domain/filters"
@@ -21,8 +22,8 @@ import (
func CreateVolume(w http.ResponseWriter, r *http.Request) {
var (
volumeOptions []libpod.VolumeCreateOption
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
- decoder = r.Context().Value("decoder").(*schema.Decoder)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder = r.Context().Value(api.DecoderKey).(*schema.Decoder)
)
query := struct {
}{
@@ -75,7 +76,7 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
func InspectVolume(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
)
name := utils.GetName(r)
vol, err := runtime.GetVolume(name)
@@ -96,7 +97,7 @@ func InspectVolume(w http.ResponseWriter, r *http.Request) {
func ListVolumes(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
)
filterMap, err := util.PrepareFilters(r)
if err != nil {
@@ -142,7 +143,7 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) {
func pruneVolumesHelper(r *http.Request) ([]*reports.PruneReport, error) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
)
filterMap, err := util.PrepareFilters(r)
if err != nil {
@@ -164,8 +165,8 @@ func pruneVolumesHelper(r *http.Request) ([]*reports.PruneReport, error) {
func RemoveVolume(w http.ResponseWriter, r *http.Request) {
var (
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
- decoder = r.Context().Value("decoder").(*schema.Decoder)
+ runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder = r.Context().Value(api.DecoderKey).(*schema.Decoder)
)
query := struct {
Force bool `schema:"force"`
@@ -197,7 +198,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
// ExistsVolume check if a volume exists
func ExistsVolume(w http.ResponseWriter, r *http.Request) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
ic := abi.ContainerEngine{Libpod: runtime}
diff --git a/pkg/api/handlers/swagger/swagger.go b/pkg/api/handlers/swagger/swagger.go
index 2296eea3a..9844839b7 100644
--- a/pkg/api/handlers/swagger/swagger.go
+++ b/pkg/api/handlers/swagger/swagger.go
@@ -176,3 +176,12 @@ type swagInspectPodResponse struct {
define.InspectPodData
}
}
+
+// Get stats for one or more containers
+// swagger:response ContainerStats
+type swagContainerStatsResponse struct {
+ // in:body
+ Body struct {
+ define.ContainerStats
+ }
+}
diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go
index fb1f8b7c1..5cdb31de1 100644
--- a/pkg/api/handlers/utils/containers.go
+++ b/pkg/api/handlers/utils/containers.go
@@ -8,6 +8,7 @@ import (
"time"
"github.com/containers/podman/v3/libpod/events"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -36,7 +37,7 @@ func WaitContainerDocker(w http.ResponseWriter, r *http.Request) {
query := waitQueryDocker{}
- decoder := ctx.Value("decoder").(*schema.Decoder)
+ decoder := ctx.Value(api.DecoderKey).(*schema.Decoder)
if err = decoder.Decode(&query, r.URL.Query()); err != nil {
Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
@@ -68,7 +69,7 @@ func WaitContainerDocker(w http.ResponseWriter, r *http.Request) {
// In docker compatibility mode we have to send headers in advance,
// otherwise docker client would freeze.
- w.Header().Add("Content-Type", "application/json")
+ w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
if flusher, ok := w.(http.Flusher); ok {
flusher.Flush()
@@ -103,7 +104,7 @@ func WaitContainerLibpod(w http.ResponseWriter, r *http.Request) {
interval = time.Millisecond * 250
conditions = []define.ContainerStatus{define.ContainerStateStopped, define.ContainerStateExited}
)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := waitQueryLibpod{}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
@@ -143,7 +144,7 @@ func WaitContainerLibpod(w http.ResponseWriter, r *http.Request) {
type containerWaitFn func(conditions ...define.ContainerStatus) (int32, error)
func createContainerWaitFn(ctx context.Context, containerName string, interval time.Duration) containerWaitFn {
- runtime := ctx.Value("runtime").(*libpod.Runtime)
+ runtime := ctx.Value(api.RuntimeKey).(*libpod.Runtime)
var containerEngine entities.ContainerEngine = &abi.ContainerEngine{Libpod: runtime}
return func(conditions ...define.ContainerStatus) (int32, error) {
@@ -205,7 +206,7 @@ func waitRemoved(ctrWait containerWaitFn) (int32, error) {
}
func waitNextExit(ctx context.Context, containerName string) (int32, error) {
- runtime := ctx.Value("runtime").(*libpod.Runtime)
+ runtime := ctx.Value(api.RuntimeKey).(*libpod.Runtime)
containerEngine := &abi.ContainerEngine{Libpod: runtime}
eventChannel := make(chan *events.Event)
errChannel := make(chan error)
@@ -237,7 +238,7 @@ func waitNotRunning(ctrWait containerWaitFn) (int32, error) {
}
func containerExists(ctx context.Context, name string) (bool, error) {
- runtime := ctx.Value("runtime").(*libpod.Runtime)
+ runtime := ctx.Value(api.RuntimeKey).(*libpod.Runtime)
var containerEngine entities.ContainerEngine = &abi.ContainerEngine{Libpod: runtime}
var ctrExistsOpts entities.ContainerExistsOptions
diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go
index 1e3647a3e..d5eb71aa1 100644
--- a/pkg/api/handlers/utils/images.go
+++ b/pkg/api/handlers/utils/images.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod"
+ api "github.com/containers/podman/v3/pkg/api/types"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
@@ -51,8 +52,8 @@ func ParseStorageReference(name string) (types.ImageReference, error) {
// GetImages is a common function used to get images for libpod and other compatibility
// mechanisms
func GetImages(w http.ResponseWriter, r *http.Request) ([]*libimage.Image, error) {
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
All bool
Digests bool
@@ -87,7 +88,7 @@ func GetImages(w http.ResponseWriter, r *http.Request) ([]*libimage.Image, error
}
func GetImage(r *http.Request, name string) (*libimage.Image, error) {
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
image, _, err := runtime.LibimageRuntime().LookupImage(name, nil)
if err != nil {
return nil, err
diff --git a/pkg/api/server/handler_api.go b/pkg/api/server/handler_api.go
index becc674c0..88b9b7397 100644
--- a/pkg/api/server/handler_api.go
+++ b/pkg/api/server/handler_api.go
@@ -1,61 +1,25 @@
package server
import (
- "context"
"fmt"
"net/http"
"runtime"
- "github.com/containers/podman/v3/pkg/api/handlers/utils"
- "github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/version"
- "github.com/google/uuid"
"github.com/sirupsen/logrus"
)
// APIHandler is a wrapper to enhance HandlerFunc's and remove redundant code
func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- // http.Server hides panics, we want to see them and fix the cause.
- defer func() {
- err := recover()
- if err != nil {
- buf := make([]byte, 1<<20)
- n := runtime.Stack(buf, true)
- logrus.Warnf("Recovering from API handler panic: %v, %s", err, buf[:n])
- // Try to inform client things went south... won't work if handler already started writing response body
- utils.InternalServerError(w, fmt.Errorf("%v", err))
- }
- }()
-
- // Wrapper to hide some boiler plate
+ // Wrapper to hide some boilerplate
fn := func(w http.ResponseWriter, r *http.Request) {
- rid := uuid.New().String()
- logrus.Infof("APIHandler(%s) -- %s %s BEGIN", rid, r.Method, r.URL.String())
- if logrus.IsLevelEnabled(logrus.DebugLevel) {
- for k, v := range r.Header {
- switch auth.HeaderAuthName(k) {
- case auth.XRegistryConfigHeader, auth.XRegistryAuthHeader:
- logrus.Debugf("APIHandler(%s) -- Header: %s=<hidden>", rid, k)
- default:
- logrus.Debugf("APIHandler(%s) -- Header: %s=%v", rid, k, v)
- }
- }
- }
- // Set in case handler wishes to correlate logging events
- r.Header.Set("X-Reference-Id", rid)
-
if err := r.ParseForm(); err != nil {
- logrus.Infof("Failed Request: unable to parse form: %q (%s)", err, rid)
+ logrus.WithFields(logrus.Fields{
+ "X-Reference-Id": r.Header.Get("X-Reference-Id"),
+ }).Info("Failed Request: unable to parse form: " + err.Error())
}
- // TODO: Use r.ConnContext when ported to go 1.13
- c := context.WithValue(r.Context(), "decoder", s.Decoder) // nolint
- c = context.WithValue(c, "runtime", s.Runtime) // nolint
- c = context.WithValue(c, "shutdownFunc", s.Shutdown) // nolint
- c = context.WithValue(c, "idletracker", s.idleTracker) // nolint
- r = r.WithContext(c)
-
cv := version.APIVersion[version.Compat][version.CurrentAPI]
w.Header().Set("API-Version", fmt.Sprintf("%d.%d", cv.Major, cv.Minor))
@@ -70,7 +34,6 @@ func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc {
}
h(w, r)
- logrus.Debugf("APIHandler(%s) -- %s %s END", rid, r.Method, r.URL.String())
}
fn(w, r)
}
diff --git a/pkg/api/server/handler_logging.go b/pkg/api/server/handler_logging.go
new file mode 100644
index 000000000..699fab7a5
--- /dev/null
+++ b/pkg/api/server/handler_logging.go
@@ -0,0 +1,51 @@
+package server
+
+import (
+ "io"
+ "io/ioutil"
+ "net/http"
+ "time"
+
+ "github.com/gorilla/mux"
+ "github.com/sirupsen/logrus"
+)
+
+type responseWriter struct {
+ http.ResponseWriter
+}
+
+var apiLogger = &logrus.Logger{
+ Formatter: &logrus.TextFormatter{
+ DisableColors: true,
+ DisableLevelTruncation: true,
+ FullTimestamp: true,
+ QuoteEmptyFields: true,
+ TimestampFormat: time.RFC3339,
+ },
+ Level: logrus.TraceLevel,
+ Out: logrus.StandardLogger().Out,
+}
+
+func (l responseWriter) Write(b []byte) (int, error) {
+ apiLogger.WithFields(logrus.Fields{
+ "API": "response",
+ "X-Reference-Id": l.Header().Get("X-Reference-Id"),
+ }).Trace(string(b))
+ return l.ResponseWriter.Write(b)
+}
+
+func loggingHandler() mux.MiddlewareFunc {
+ return func(h http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ annotated := apiLogger.WithFields(logrus.Fields{
+ "API": "request",
+ "X-Reference-Id": r.Header.Get("X-Reference-Id"),
+ })
+ r.Body = ioutil.NopCloser(
+ io.TeeReader(r.Body, annotated.WriterLevel(logrus.TraceLevel)))
+
+ w = responseWriter{ResponseWriter: w}
+ h.ServeHTTP(w, r)
+ })
+ }
+}
diff --git a/pkg/api/server/handler_panic.go b/pkg/api/server/handler_panic.go
new file mode 100644
index 000000000..f643db79a
--- /dev/null
+++ b/pkg/api/server/handler_panic.go
@@ -0,0 +1,32 @@
+package server
+
+import (
+ "fmt"
+ "net/http"
+ "runtime"
+
+ "github.com/containers/podman/v3/pkg/api/handlers/utils"
+ "github.com/gorilla/mux"
+ "github.com/sirupsen/logrus"
+)
+
+// panicHandler captures panics from endpoint handlers and logs stack trace
+func panicHandler() mux.MiddlewareFunc {
+ return func(h http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ // http.Server hides panics from handlers, we want to record them and fix the cause
+ defer func() {
+ err := recover()
+ if err != nil {
+ buf := make([]byte, 1<<20)
+ n := runtime.Stack(buf, true)
+ logrus.Warnf("Recovering from API service endpoint handler panic: %v, %s", err, buf[:n])
+ // Try to inform client things went south... won't work if handler already started writing response body
+ utils.InternalServerError(w, fmt.Errorf("%v", err))
+ }
+ }()
+
+ h.ServeHTTP(w, r)
+ })
+ }
+}
diff --git a/pkg/api/server/handler_rid.go b/pkg/api/server/handler_rid.go
new file mode 100644
index 000000000..b624b99a6
--- /dev/null
+++ b/pkg/api/server/handler_rid.go
@@ -0,0 +1,34 @@
+package server
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/containers/podman/v3/pkg/api/types"
+ "github.com/google/uuid"
+ "github.com/gorilla/handlers"
+ "github.com/gorilla/mux"
+ "github.com/sirupsen/logrus"
+)
+
+// referenceIDHandler adds X-Reference-Id Header allowing event correlation
+// and Apache style request logging
+func referenceIDHandler() mux.MiddlewareFunc {
+ return func(h http.Handler) http.Handler {
+ return handlers.CombinedLoggingHandler(logrus.StandardLogger().Out,
+ http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ rid := r.Header.Get("X-Reference-Id")
+ if rid == "" {
+ if c := r.Context().Value(types.ConnKey); c == nil {
+ rid = uuid.New().String()
+ } else {
+ rid = fmt.Sprintf("%p", c)
+ }
+ }
+
+ r.Header.Set("X-Reference-Id", rid)
+ w.Header().Set("X-Reference-Id", rid)
+ h.ServeHTTP(w, r)
+ }))
+ }
+}
diff --git a/pkg/api/server/idle/tracker.go b/pkg/api/server/idle/tracker.go
index 687ebd7d4..480239f05 100644
--- a/pkg/api/server/idle/tracker.go
+++ b/pkg/api/server/idle/tracker.go
@@ -1,6 +1,7 @@
package idle
import (
+ "fmt"
"net"
"net/http"
"sync"
@@ -39,7 +40,10 @@ func (t *Tracker) ConnState(conn net.Conn, state http.ConnState) {
t.mux.Lock()
defer t.mux.Unlock()
- logrus.Debugf("IdleTracker %p:%v %dm+%dh/%dt connection(s)", conn, state, len(t.managed), t.hijacked, t.TotalConnections())
+ logrus.WithFields(logrus.Fields{
+ "X-Reference-Id": fmt.Sprintf("%p", conn),
+ }).Debugf("IdleTracker:%v %dm+%dh/%dt connection(s)", state, len(t.managed), t.hijacked, t.TotalConnections())
+
switch state {
case http.StateNew:
t.total++
@@ -68,7 +72,9 @@ func (t *Tracker) ConnState(conn net.Conn, state http.ConnState) {
if _, found := t.managed[conn]; found {
delete(t.managed, conn)
} else {
- logrus.Warnf("IdleTracker %p: StateClosed transition by un-managed connection", conn)
+ logrus.WithFields(logrus.Fields{
+ "X-Reference-Id": fmt.Sprintf("%p", conn),
+ }).Warnf("IdleTracker: StateClosed transition by connection marked un-managed")
}
}
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index 2a32966cc..8dcea1301 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -1124,11 +1124,9 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// - application/json
// responses:
// 200:
- // description: no error
+ // $ref: "#/responses/ContainerStats"
// 404:
// $ref: "#/responses/NoSuchContainer"
- // 409:
- // $ref: "#/responses/ConflictError"
// 500:
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/stats"), s.APIHandler(libpod.StatsContainer)).Methods(http.MethodGet)
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 72ae27276..34d0fa246 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -7,7 +7,7 @@ import (
"net"
"net/http"
"os"
- goRuntime "runtime"
+ "runtime"
"strings"
"sync"
"syscall"
@@ -17,11 +17,11 @@ import (
"github.com/containers/podman/v3/libpod/shutdown"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/server/idle"
+ "github.com/containers/podman/v3/pkg/api/types"
"github.com/coreos/go-systemd/v22/activation"
"github.com/coreos/go-systemd/v22/daemon"
"github.com/gorilla/mux"
"github.com/gorilla/schema"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -44,8 +44,10 @@ const (
UnlimitedServiceDuration = 0 * time.Second
)
-// shutdownOnce ensures Shutdown() may safely be called from several go routines
-var shutdownOnce sync.Once
+var (
+ // shutdownOnce ensures Shutdown() may safely be called from several go routines
+ shutdownOnce sync.Once
+)
type Options struct {
Timeout time.Duration
@@ -66,15 +68,15 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
// If listener not provided try socket activation protocol
if listener == nil {
if _, found := os.LookupEnv("LISTEN_PID"); !found {
- return nil, errors.Errorf("Cannot create API Server, no listener provided and socket activation protocol is not active.")
+ return nil, fmt.Errorf("no service listener provided and socket activation protocol is not active")
}
listeners, err := activation.Listeners()
if err != nil {
- return nil, errors.Wrap(err, "Cannot retrieve file descriptors from systemd")
+ return nil, fmt.Errorf("cannot retrieve file descriptors from systemd: %w", err)
}
if len(listeners) != 1 {
- return nil, errors.Errorf("Wrong number of file descriptors for socket activation protocol (%d != 1)", len(listeners))
+ return nil, fmt.Errorf("wrong number of file descriptors for socket activation protocol (%d != 1)", len(listeners))
}
listener = &listeners[0]
}
@@ -84,24 +86,35 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
logrus.Debugf("CORS Headers were set to %s", corsHeaders)
}
- logrus.Infof("API server listening on %q", (*listener).Addr())
+ logrus.Infof("API service listening on %q", (*listener).Addr())
router := mux.NewRouter().UseEncodedPath()
- idle := idle.NewTracker(duration)
+ tracker := idle.NewTracker(duration)
server := APIServer{
Server: http.Server{
+ ConnContext: func(ctx context.Context, c net.Conn) context.Context {
+ return context.WithValue(ctx, types.ConnKey, c)
+ },
+ ConnState: tracker.ConnState,
+ ErrorLog: log.New(logrus.StandardLogger().Out, "", 0),
Handler: router,
IdleTimeout: duration * 2,
- ConnState: idle.ConnState,
- ErrorLog: log.New(logrus.StandardLogger().Out, "", 0),
},
- Decoder: handlers.NewAPIDecoder(),
- idleTracker: idle,
- Listener: *listener,
- Runtime: runtime,
CorsHeaders: corsHeaders,
+ Listener: *listener,
+ idleTracker: tracker,
+ }
+
+ server.BaseContext = func(l net.Listener) context.Context {
+ ctx := context.WithValue(context.Background(), types.DecoderKey, handlers.NewAPIDecoder())
+ ctx = context.WithValue(ctx, types.RuntimeKey, runtime)
+ ctx = context.WithValue(ctx, types.IdleTrackerKey, tracker)
+ return ctx
}
+ // Capture panics and print stack traces for diagnostics,
+ // additionally process X-Reference-Id Header to support event correlation
+ router.Use(panicHandler(), referenceIDHandler())
router.NotFoundHandler = http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
// We can track user errors...
@@ -149,6 +162,8 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
}
if logrus.IsLevelEnabled(logrus.TraceLevel) {
+ // If in trace mode log request and response bodies
+ router.Use(loggingHandler())
router.Walk(func(route *mux.Route, r *mux.Router, ancestors []*mux.Route) error { // nolint
path, err := route.GetPathTemplate()
if err != nil {
@@ -177,13 +192,13 @@ func setupSystemd() {
payload := fmt.Sprintf("MAINPID=%d\n", os.Getpid())
payload += daemon.SdNotifyReady
if sent, err := daemon.SdNotify(true, payload); err != nil {
- logrus.Errorf("Error notifying systemd of Conmon PID: %s", err.Error())
+ logrus.Error("API service error notifying systemd of Conmon PID: " + err.Error())
} else if !sent {
- logrus.Warn("SDNotify not sent successfully")
+ logrus.Warn("API service unable to successfully send SDNotify")
}
if err := os.Unsetenv("INVOCATION_ID"); err != nil {
- logrus.Errorf("Error unsetting INVOCATION_ID: %s", err.Error())
+ logrus.Error("API service failed unsetting INVOCATION_ID: " + err.Error())
}
}
@@ -205,7 +220,7 @@ func (s *APIServer) Serve() error {
go func() {
<-s.idleTracker.Done()
- logrus.Debugf("API Server idle for %s", s.idleTracker.Duration.Round(time.Second).String())
+ logrus.Debug("API service shutting down, idle for " + s.idleTracker.Duration.Round(time.Second).String())
_ = s.Shutdown()
}()
@@ -213,12 +228,12 @@ func (s *APIServer) Serve() error {
go func() {
pprofMux := mux.NewRouter()
pprofMux.PathPrefix("/debug/pprof").Handler(http.DefaultServeMux)
- goRuntime.SetMutexProfileFraction(1)
- goRuntime.SetBlockProfileRate(1)
+ runtime.SetMutexProfileFraction(1)
+ runtime.SetBlockProfileRate(1)
s.pprof = &http.Server{Addr: "localhost:8888", Handler: pprofMux}
err := s.pprof.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
- logrus.Warn("Profiler Service failed: " + err.Error())
+ logrus.Warn("API profiler service failed: " + err.Error())
}
}()
}
@@ -230,7 +245,7 @@ func (s *APIServer) Serve() error {
go func() {
err := s.Server.Serve(s.Listener)
if err != nil && err != http.ErrServerClosed {
- errChan <- errors.Wrap(err, "failed to start API server")
+ errChan <- fmt.Errorf("failed to start API service: %w", err)
return
}
errChan <- nil
@@ -242,14 +257,14 @@ func (s *APIServer) Serve() error {
// Shutdown is a clean shutdown waiting on existing clients
func (s *APIServer) Shutdown() error {
if s.idleTracker.Duration == UnlimitedServiceDuration {
- logrus.Debug("APIServer.Shutdown ignored as Duration is UnlimitedService")
+ logrus.Debug("API service shutdown ignored as Duration is UnlimitedService")
return nil
}
shutdownOnce.Do(func() {
if logrus.IsLevelEnabled(logrus.DebugLevel) {
- _, file, line, _ := goRuntime.Caller(1)
- logrus.Debugf("APIServer.Shutdown by %s:%d, %d/%d connection(s)",
+ _, file, line, _ := runtime.Caller(1)
+ logrus.Debugf("API service shutdown by %s:%d, %d/%d connection(s)",
file, line, s.idleTracker.ActiveConnections(), s.idleTracker.TotalConnections())
go func() {
@@ -257,8 +272,7 @@ func (s *APIServer) Shutdown() error {
go func() {
defer cancel()
if err := s.pprof.Shutdown(ctx); err != nil {
- logrus.Warn(
- errors.Wrapf(err, "failed to cleanly shutdown pprof Server"))
+ logrus.Warn("Failed to cleanly shutdown API pprof service: " + err.Error())
}
}()
<-ctx.Done()
@@ -272,8 +286,7 @@ func (s *APIServer) Shutdown() error {
err := s.Server.Shutdown(ctx)
if err != nil && err != context.Canceled && err != http.ErrServerClosed {
- logrus.Error(
- errors.Wrapf(err, "failed to cleanly shutdown APIServer"))
+ logrus.Error("Failed to cleanly shutdown API service: " + err.Error())
}
}()
<-ctx.Done()
diff --git a/pkg/api/types/types.go b/pkg/api/types/types.go
index 1b91364e3..d5067cc54 100644
--- a/pkg/api/types/types.go
+++ b/pkg/api/types/types.go
@@ -1,9 +1,18 @@
package types
const (
- // DefaultAPIVersion is the version of the API the server defaults to.
+ // DefaultAPIVersion is the version of the compatible API the server defaults to
DefaultAPIVersion = "1.40" // See https://docs.docker.com/engine/api/v1.40/
- // DefaultAPIVersion is the minimal required version of the API.
+ // MinimalAPIVersion is the minimal required version of the compatible API
MinimalAPIVersion = "1.24"
)
+
+type APIContextKey int
+
+const (
+ DecoderKey APIContextKey = iota
+ RuntimeKey
+ IdleTrackerKey
+ ConnKey
+)
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index 4d1361746..b9ed67255 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -326,11 +326,11 @@ var _ = Describe("Podman containers ", func() {
// TODO for the life of me, i cannot get this to work. maybe another set
// of eyes will
// successful healthcheck
- //status := "healthy"
+ //status := define.HealthCheckHealthy
//for i:=0; i < 10; i++ {
// result, err := containers.RunHealthCheck(connText, "hc")
// Expect(err).To(BeNil())
- // if result.Status != "healthy" {
+ // if result.Status != define.HealthCheckHealthy {
// fmt.Println("Healthcheck container still starting, retrying in 1 second")
// time.Sleep(1 * time.Second)
// continue
@@ -338,7 +338,7 @@ var _ = Describe("Podman containers ", func() {
// status = result.Status
// break
//}
- //Expect(status).To(Equal("healthy"))
+ //Expect(status).To(Equal(define.HealthCheckHealthy))
// TODO enable this when wait is working
// healthcheck on a stopped container should be a 409
diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go
index 77329e328..f630b3f24 100644
--- a/pkg/domain/entities/play.go
+++ b/pkg/domain/entities/play.go
@@ -51,6 +51,8 @@ type PlayKubePod struct {
ID string
// Containers - the IDs of the containers running in the created pod.
Containers []string
+ // InitContainers - the IDs of the init containers to be run in the created pod.
+ InitContainers []string
// Logs - non-fatal errors and log messages while processing.
Logs []string
// ContainerErrors - any errors that occurred while starting containers
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index c6d5dcc3d..87506f70c 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -304,76 +304,59 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers))
+ initContainers := make([]*libpod.Container, 0, len(podYAML.Spec.InitContainers))
cwd, err := os.Getwd()
if err != nil {
return nil, err
}
+
+ for _, initCtr := range podYAML.Spec.InitContainers {
+ // Init containers cannot have either of lifecycle, livenessProbe, readinessProbe, or startupProbe set
+ if initCtr.Lifecycle != nil || initCtr.LivenessProbe != nil || initCtr.ReadinessProbe != nil || initCtr.StartupProbe != nil {
+ return nil, errors.Errorf("cannot create an init container that has either of lifecycle, livenessProbe, readinessProbe, or startupProbe set")
+ }
+ pulledImage, labels, err := ic.getImageAndLabelInfo(ctx, cwd, annotations, writer, initCtr, options)
+ if err != nil {
+ return nil, err
+ }
+
+ specgenOpts := kube.CtrSpecGenOptions{
+ Container: initCtr,
+ Image: pulledImage,
+ Volumes: volumes,
+ PodID: pod.ID(),
+ PodName: podName,
+ PodInfraID: podInfraID,
+ ConfigMaps: configMaps,
+ SeccompPaths: seccompPaths,
+ RestartPolicy: ctrRestartPolicy,
+ NetNSIsHost: p.NetNS.IsHost(),
+ SecretsManager: secretsManager,
+ LogDriver: options.LogDriver,
+ Labels: labels,
+ InitContainerType: define.AlwaysInitContainer,
+ }
+ specGen, err := kube.ToSpecGen(ctx, &specgenOpts)
+ if err != nil {
+ return nil, err
+ }
+ rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen)
+ if err != nil {
+ return nil, err
+ }
+ ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ initContainers = append(initContainers, ctr)
+ }
for _, container := range podYAML.Spec.Containers {
if !strings.Contains("infra", container.Name) {
- // Contains all labels obtained from kube
- labels := make(map[string]string)
- var pulledImage *libimage.Image
- buildFile, err := getBuildFile(container.Image, cwd)
+ pulledImage, labels, err := ic.getImageAndLabelInfo(ctx, cwd, annotations, writer, container, options)
if err != nil {
return nil, err
}
- existsLocally, err := ic.Libpod.LibimageRuntime().Exists(container.Image)
- if err != nil {
- return nil, err
- }
- if (len(buildFile) > 0 && !existsLocally) || (len(buildFile) > 0 && options.Build) {
- buildOpts := new(buildahDefine.BuildOptions)
- commonOpts := new(buildahDefine.CommonBuildOptions)
- buildOpts.ConfigureNetwork = buildahDefine.NetworkDefault
- buildOpts.Isolation = buildahDefine.IsolationChroot
- buildOpts.CommonBuildOpts = commonOpts
- buildOpts.Output = container.Image
- if _, _, err := ic.Libpod.Build(ctx, *buildOpts, []string{buildFile}...); err != nil {
- return nil, err
- }
- i, _, err := ic.Libpod.LibimageRuntime().LookupImage(container.Image, new(libimage.LookupImageOptions))
- if err != nil {
- return nil, err
- }
- pulledImage = i
- } else {
- // NOTE: set the pull policy to "newer". This will cover cases
- // where the "latest" tag requires a pull and will also
- // transparently handle "localhost/" prefixed files which *may*
- // refer to a locally built image OR an image running a
- // registry on localhost.
- pullPolicy := config.PullPolicyNewer
- if len(container.ImagePullPolicy) > 0 {
- // Make sure to lower the strings since K8s pull policy
- // may be capitalized (see bugzilla.redhat.com/show_bug.cgi?id=1985905).
- rawPolicy := string(container.ImagePullPolicy)
- pullPolicy, err = config.ParsePullPolicy(strings.ToLower(rawPolicy))
- if err != nil {
- return nil, err
- }
- }
- pulledImages, err := pullImage(ic, writer, container.Image, options, pullPolicy)
- if err != nil {
- return nil, err
- }
- pulledImage = pulledImages[0]
- }
-
- // Handle kube annotations
- for k, v := range annotations {
- switch k {
- // Auto update annotation without container name will apply to
- // all containers within the pod
- case autoupdate.Label, autoupdate.AuthfileLabel:
- labels[k] = v
- // Auto update annotation with container name will apply only
- // to the specified container
- case fmt.Sprintf("%s/%s", autoupdate.Label, container.Name),
- fmt.Sprintf("%s/%s", autoupdate.AuthfileLabel, container.Name):
- prefixAndCtr := strings.Split(k, "/")
- labels[prefixAndCtr[0]] = v
- }
- }
specgenOpts := kube.CtrSpecGenOptions{
Container: container,
@@ -394,7 +377,6 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
if err != nil {
return nil, err
}
-
rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen)
if err != nil {
return nil, err
@@ -423,12 +405,96 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
for _, ctr := range containers {
playKubePod.Containers = append(playKubePod.Containers, ctr.ID())
}
+ for _, initCtr := range initContainers {
+ playKubePod.InitContainers = append(playKubePod.InitContainers, initCtr.ID())
+ }
report.Pods = append(report.Pods, playKubePod)
return &report, nil
}
+// getImageAndLabelInfo returns the image information and how the image should be pulled plus as well as labels to be used for the container in the pod.
+// Moved this to a separate function so that it can be used for both init and regular containers when playing a kube yaml.
+func (ic *ContainerEngine) getImageAndLabelInfo(ctx context.Context, cwd string, annotations map[string]string, writer io.Writer, container v1.Container, options entities.PlayKubeOptions) (*libimage.Image, map[string]string, error) {
+ // Contains all labels obtained from kube
+ labels := make(map[string]string)
+ var pulledImage *libimage.Image
+ buildFile, err := getBuildFile(container.Image, cwd)
+ if err != nil {
+ return nil, nil, err
+ }
+ existsLocally, err := ic.Libpod.LibimageRuntime().Exists(container.Image)
+ if err != nil {
+ return nil, nil, err
+ }
+ if (len(buildFile) > 0 && !existsLocally) || (len(buildFile) > 0 && options.Build) {
+ buildOpts := new(buildahDefine.BuildOptions)
+ commonOpts := new(buildahDefine.CommonBuildOptions)
+ buildOpts.ConfigureNetwork = buildahDefine.NetworkDefault
+ buildOpts.Isolation = buildahDefine.IsolationChroot
+ buildOpts.CommonBuildOpts = commonOpts
+ buildOpts.Output = container.Image
+ if _, _, err := ic.Libpod.Build(ctx, *buildOpts, []string{buildFile}...); err != nil {
+ return nil, nil, err
+ }
+ i, _, err := ic.Libpod.LibimageRuntime().LookupImage(container.Image, new(libimage.LookupImageOptions))
+ if err != nil {
+ return nil, nil, err
+ }
+ pulledImage = i
+ } else {
+ // NOTE: set the pull policy to "newer". This will cover cases
+ // where the "latest" tag requires a pull and will also
+ // transparently handle "localhost/" prefixed files which *may*
+ // refer to a locally built image OR an image running a
+ // registry on localhost.
+ pullPolicy := config.PullPolicyNewer
+ if len(container.ImagePullPolicy) > 0 {
+ // Make sure to lower the strings since K8s pull policy
+ // may be capitalized (see bugzilla.redhat.com/show_bug.cgi?id=1985905).
+ rawPolicy := string(container.ImagePullPolicy)
+ pullPolicy, err = config.ParsePullPolicy(strings.ToLower(rawPolicy))
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+ // This ensures the image is the image store
+ pullOptions := &libimage.PullOptions{}
+ pullOptions.AuthFilePath = options.Authfile
+ pullOptions.CertDirPath = options.CertDir
+ pullOptions.SignaturePolicyPath = options.SignaturePolicy
+ pullOptions.Writer = writer
+ pullOptions.Username = options.Username
+ pullOptions.Password = options.Password
+ pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
+
+ pulledImages, err := ic.Libpod.LibimageRuntime().Pull(ctx, container.Image, pullPolicy, pullOptions)
+ if err != nil {
+ return nil, nil, err
+ }
+ pulledImage = pulledImages[0]
+ }
+
+ // Handle kube annotations
+ for k, v := range annotations {
+ switch k {
+ // Auto update annotation without container name will apply to
+ // all containers within the pod
+ case autoupdate.Label, autoupdate.AuthfileLabel:
+ labels[k] = v
+ // Auto update annotation with container name will apply only
+ // to the specified container
+ case fmt.Sprintf("%s/%s", autoupdate.Label, container.Name),
+ fmt.Sprintf("%s/%s", autoupdate.AuthfileLabel, container.Name):
+ prefixAndCtr := strings.Split(k, "/")
+ labels[prefixAndCtr[0]] = v
+ }
+ }
+
+ return pulledImage, labels, nil
+}
+
// playKubePVC creates a podman volume from a kube persistent volume claim.
func (ic *ContainerEngine) playKubePVC(ctx context.Context, pvcYAML *v1.PersistentVolumeClaim, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
var report entities.PlayKubeReport
diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go
index a9289d6b3..89b556b14 100644
--- a/pkg/machine/ignition.go
+++ b/pkg/machine/ignition.go
@@ -135,10 +135,25 @@ func getDirs(usrName string) []Directory {
Path: d,
User: getNodeUsr(usrName),
},
- DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(493)},
+ DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)},
}
dirs[i] = newDir
}
+
+ // Issue #11489: make sure that we can inject a custom registries.conf
+ // file on the system level to force a single search registry.
+ // The remote client does not yet support prompting for short-name
+ // resolution, so we enforce a single search registry (i.e., docker.io)
+ // as a workaround.
+ dirs = append(dirs, Directory{
+ Node: Node{
+ Group: getNodeGrp("root"),
+ Path: "/etc/containers/registries.conf.d",
+ User: getNodeUsr("root"),
+ },
+ DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)},
+ })
+
return dirs
}
@@ -158,7 +173,7 @@ func getFiles(usrName string) []File {
Contents: Resource{
Source: strToPtr("data:,%5BUnit%5D%0ADescription%3DA%20systemd%20user%20unit%20demo%0AAfter%3Dnetwork-online.target%0AWants%3Dnetwork-online.target%20podman.socket%0A%5BService%5D%0AExecStart%3D%2Fusr%2Fbin%2Fsleep%20infinity%0A"),
},
- Mode: intToPtr(484),
+ Mode: intToPtr(0744),
},
})
@@ -175,7 +190,7 @@ func getFiles(usrName string) []File {
Contents: Resource{
Source: strToPtr("data:,%5Bcontainers%5D%0D%0Anetns%3D%22bridge%22%0D%0Arootless_networking%3D%22cni%22"),
},
- Mode: intToPtr(484),
+ Mode: intToPtr(0744),
},
})
// Add a file into linger
@@ -185,7 +200,7 @@ func getFiles(usrName string) []File {
Path: "/var/lib/systemd/linger/core",
User: getNodeUsr(usrName),
},
- FileEmbedded1: FileEmbedded1{Mode: intToPtr(420)},
+ FileEmbedded1: FileEmbedded1{Mode: intToPtr(0644)},
})
// Set machine_enabled to true to indicate we're in a VM
@@ -200,9 +215,30 @@ func getFiles(usrName string) []File {
Contents: Resource{
Source: strToPtr("data:,%5Bengine%5D%0Amachine_enabled%3Dtrue%0A"),
},
- Mode: intToPtr(420),
+ Mode: intToPtr(0644),
+ },
+ })
+
+ // Issue #11489: make sure that we can inject a custom registries.conf
+ // file on the system level to force a single search registry.
+ // The remote client does not yet support prompting for short-name
+ // resolution, so we enforce a single search registry (i.e., docker.io)
+ // as a workaround.
+ files = append(files, File{
+ Node: Node{
+ Group: getNodeGrp("root"),
+ Path: "/etc/containers/registries.conf.d/999-podman-machine.conf",
+ User: getNodeUsr("root"),
+ },
+ FileEmbedded1: FileEmbedded1{
+ Append: nil,
+ Contents: Resource{
+ Source: strToPtr("data:,unqualified-search-registries%3D%5B%22docker.io%22%5D"),
+ },
+ Mode: intToPtr(0644),
},
})
+
return files
}
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index 5188abc3a..c01d7a1f0 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -114,6 +114,9 @@ type CtrSpecGenOptions struct {
Labels map[string]string
//
IsInfra bool
+ // InitContainerType sets what type the init container is
+ // Note: When playing a kube yaml, the inti container type will be set to "always" only
+ InitContainerType string
}
func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGenerator, error) {
@@ -135,6 +138,8 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
Driver: opts.LogDriver,
}
+ s.InitContainerType = opts.InitContainerType
+
setupSecurityContext(s, opts.Container)
err := setupLivenessProbe(s, opts.Container, opts.RestartPolicy)
if err != nil {
diff --git a/test/apiv2/python/rest_api/test_v2_0_0_system.py b/test/apiv2/python/rest_api/test_v2_0_0_system.py
index 3dfd08525..2d3935c9c 100644
--- a/test/apiv2/python/rest_api/test_v2_0_0_system.py
+++ b/test/apiv2/python/rest_api/test_v2_0_0_system.py
@@ -1,5 +1,6 @@
import json
import unittest
+import uuid
import requests
from .fixtures import APITestCase
@@ -92,6 +93,18 @@ class SystemTestCase(APITestCase):
r = requests.get(self.uri("/system/df"))
self.assertEqual(r.status_code, 200, r.text)
+ def test_reference_id(self):
+ rid = str(uuid.uuid4())
+ r = requests.get(self.uri("/info"), headers={"X-Reference-Id": rid})
+ self.assertEqual(r.status_code, 200, r.text)
+
+ self.assertIn("X-Reference-Id", r.headers)
+ self.assertEqual(r.headers["X-Reference-Id"], rid)
+
+ r = requests.get(self.uri("/info"))
+ self.assertIn("X-Reference-Id", r.headers)
+ self.assertNotEqual(r.headers["X-Reference-Id"], rid)
+
if __name__ == "__main__":
unittest.main()
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 8996bf6a0..bf89a0708 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -174,6 +174,78 @@ var _ = Describe("Podman generate kube", func() {
Expect(string(kube.Out.Contents())).To(ContainSubstring(`name: pod2`))
})
+ It("podman generate kube on pod with init containers", func() {
+ session := podmanTest.Podman([]string{"create", "--pod", "new:toppod", "--init-ctr", "always", ALPINE, "echo", "hello"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"create", "--pod", "toppod", "--init-ctr", "always", ALPINE, "echo", "world"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"create", "--pod", "toppod", ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", "toppod"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ pod := new(v1.Pod)
+ err := yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+ Expect(pod.Spec.HostNetwork).To(Equal(false))
+
+ numContainers := len(pod.Spec.Containers) + len(pod.Spec.InitContainers)
+ Expect(numContainers).To(Equal(3))
+
+ // Init container should be in the generated kube yaml if created with "once" type and the pod has not been started
+ session = podmanTest.Podman([]string{"create", "--pod", "new:toppod-2", "--init-ctr", "once", ALPINE, "echo", "using once type"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"create", "--pod", "toppod-2", ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ kube = podmanTest.Podman([]string{"generate", "kube", "toppod-2"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ pod = new(v1.Pod)
+ err = yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+ Expect(pod.Spec.HostNetwork).To(Equal(false))
+
+ numContainers = len(pod.Spec.Containers) + len(pod.Spec.InitContainers)
+ Expect(numContainers).To(Equal(2))
+
+ // Init container should not be in the generated kube yaml if created with "once" type and the pod has been started
+ session = podmanTest.Podman([]string{"create", "--pod", "new:toppod-3", "--init-ctr", "once", ALPINE, "echo", "using once type"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"create", "--pod", "toppod-3", ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"pod", "start", "toppod-3"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ kube = podmanTest.Podman([]string{"generate", "kube", "toppod-3"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ pod = new(v1.Pod)
+ err = yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+ Expect(pod.Spec.HostNetwork).To(Equal(false))
+
+ numContainers = len(pod.Spec.Containers) + len(pod.Spec.InitContainers)
+ Expect(numContainers).To(Equal(1))
+ })
+
It("podman generate kube on pod with host network", func() {
podSession := podmanTest.Podman([]string{"pod", "create", "--name", "testHostNetwork", "--network", "host"})
podSession.WaitWithDefaultTimeout()
diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go
index 899c84a14..87f042ed9 100644
--- a/test/e2e/healthcheck_run_test.go
+++ b/test/e2e/healthcheck_run_test.go
@@ -5,6 +5,7 @@ import (
"os"
"time"
+ define "github.com/containers/podman/v3/libpod/define"
. "github.com/containers/podman/v3/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -157,7 +158,7 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(hc).Should(Exit(1))
inspect = podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal("unhealthy"))
+ Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckUnhealthy))
})
@@ -171,7 +172,7 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(hc).Should(Exit(0))
inspect := podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal("healthy"))
+ Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckHealthy))
})
It("podman healthcheck unhealthy but valid arguments check", func() {
@@ -201,7 +202,7 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(hc).Should(Exit(1))
inspect = podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal("unhealthy"))
+ Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckUnhealthy))
foo := podmanTest.Podman([]string{"exec", "hc", "touch", "/foo"})
foo.WaitWithDefaultTimeout()
@@ -212,6 +213,6 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(hc).Should(Exit(0))
inspect = podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal("healthy"))
+ Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckHealthy))
})
})
diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go
index ea7a96428..2e5e07de9 100644
--- a/test/e2e/pause_test.go
+++ b/test/e2e/pause_test.go
@@ -79,6 +79,11 @@ var _ = Describe("Podman pause", func() {
Expect(result).To(ExitWithError())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(strings.ToLower(podmanTest.GetContainerStatus())).To(ContainSubstring(createdState))
+
+ // check we can read stats for a paused container
+ result = podmanTest.Podman([]string{"stats", "--no-stream", cid})
+ result.WaitWithDefaultTimeout()
+ Expect(result).To(ExitWithError())
})
It("podman pause a running container by id", func() {
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index fa30f068c..fcda89fbc 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -12,6 +12,7 @@ import (
"time"
"github.com/containers/common/pkg/config"
+ "github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/util"
. "github.com/containers/podman/v3/test/utils"
"github.com/containers/storage/pkg/stringid"
@@ -263,6 +264,17 @@ spec:
{{ end }}
ip: {{ .IP }}
{{ end }}
+ initContainers:
+{{ with .InitCtrs }}
+ {{ range . }}
+ - command:
+ {{ range .Cmd }}
+ - {{.}}
+ {{ end }}
+ image: {{ .Image }}
+ name: {{ .Name }}
+ {{ end }}
+{{ end }}
containers:
{{ with .Ctrs }}
{{ range . }}
@@ -665,6 +677,7 @@ type Pod struct {
HostNetwork bool
HostAliases []HostAlias
Ctrs []*Ctr
+ InitCtrs []*Ctr
Volumes []*Volume
Labels map[string]string
Annotations map[string]string
@@ -686,6 +699,7 @@ func getPod(options ...podOption) *Pod {
HostNetwork: false,
HostAliases: nil,
Ctrs: make([]*Ctr, 0),
+ InitCtrs: make([]*Ctr, 0),
Volumes: make([]*Volume, 0),
Labels: make(map[string]string),
Annotations: make(map[string]string),
@@ -728,6 +742,12 @@ func withCtr(c *Ctr) podOption {
}
}
+func withPodInitCtr(ic *Ctr) podOption {
+ return func(pod *Pod) {
+ pod.InitCtrs = append(pod.InitCtrs, ic)
+ }
+}
+
func withRestartPolicy(policy string) podOption {
return func(pod *Pod) {
pod.RestartPolicy = policy
@@ -847,6 +867,7 @@ type Ctr struct {
VolumeReadOnly bool
Env []Env
EnvFrom []EnvFrom
+ InitCtrType string
}
// getCtr takes a list of ctrOptions and returns a Ctr with sane defaults
@@ -870,6 +891,7 @@ func getCtr(options ...ctrOption) *Ctr {
VolumeReadOnly: false,
Env: []Env{},
EnvFrom: []EnvFrom{},
+ InitCtrType: "",
}
for _, option := range options {
option(&c)
@@ -885,6 +907,12 @@ func withName(name string) ctrOption {
}
}
+func withInitCtr() ctrOption {
+ return func(c *Ctr) {
+ c.InitCtrType = define.AlwaysInitContainer
+ }
+}
+
func withCmd(cmd []string) ctrOption {
return func(c *Ctr) {
c.Cmd = cmd
@@ -1209,7 +1237,7 @@ var _ = Describe("Podman play kube", func() {
hc := podmanTest.Podman([]string{"healthcheck", "run", "liveness-unhealthy-probe-pod-0-alpine"})
hc.WaitWithDefaultTimeout()
hcoutput := hc.OutputToString()
- Expect(hcoutput).To(ContainSubstring("unhealthy"))
+ Expect(hcoutput).To(ContainSubstring(define.HealthCheckUnhealthy))
})
It("podman play kube fail with nonexistent authfile", func() {
@@ -1294,6 +1322,33 @@ var _ = Describe("Podman play kube", func() {
Expect(inspect.OutputToString()).To(ContainSubstring(`[]`))
})
+ // If you have an init container in the pod yaml, podman should create and run the init container with play kube
+ It("podman play kube test with init containers", func() {
+ pod := getPod(withPodInitCtr(getCtr(withImage(ALPINE), withCmd([]string{"echo", "hello"}), withInitCtr(), withName("init-test"))), withCtr(getCtr(withImage(ALPINE), withCmd([]string{"top"}))))
+ err := generateKubeYaml("pod", pod, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ // Expect the number of containers created to be 3, one init, infra, and regular container
+ numOfCtrs := podmanTest.NumberOfContainers()
+ Expect(numOfCtrs).To(Equal(3))
+
+ // Init container should have exited after running
+ inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-init-test"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring("exited"))
+
+ // Regular container should be in running state
+ inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring("running"))
+ })
+
// If you supply only args for a Container, the default Entrypoint defined in the Docker image is run with the args that you supplied.
It("podman play kube test correct command with only set args in yaml file", func() {
pod := getPod(withCtr(getCtr(withImage(registry), withCmd(nil), withArg([]string{"echo", "hello"}))))
diff --git a/test/e2e/unshare_test.go b/test/e2e/unshare_test.go
index eacdda68a..79ce68e89 100644
--- a/test/e2e/unshare_test.go
+++ b/test/e2e/unshare_test.go
@@ -47,8 +47,7 @@ var _ = Describe("Podman unshare", func() {
session := podmanTest.Podman([]string{"unshare", "readlink", "/proc/self/ns/user"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- ok, _ := session.GrepString(userNS)
- Expect(ok).To(BeFalse())
+ Expect(session.OutputToString()).ToNot(ContainSubstring(userNS))
})
It("podman unshare --rootles-cni", func() {
@@ -57,4 +56,36 @@ var _ = Describe("Podman unshare", func() {
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("tap0"))
})
+
+ It("podman unshare exit codes", func() {
+ session := podmanTest.Podman([]string{"unshare", "false"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(1))
+ Expect(session.OutputToString()).Should(Equal(""))
+ Expect(session.ErrorToString()).Should(Equal(""))
+
+ session = podmanTest.Podman([]string{"unshare", "/usr/bin/bogus"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(127))
+ Expect(session.OutputToString()).Should(Equal(""))
+ Expect(session.ErrorToString()).Should(ContainSubstring("no such file or directory"))
+
+ session = podmanTest.Podman([]string{"unshare", "bogus"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(127))
+ Expect(session.OutputToString()).Should(Equal(""))
+ Expect(session.ErrorToString()).Should(ContainSubstring("executable file not found in $PATH"))
+
+ session = podmanTest.Podman([]string{"unshare", "/usr"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(126))
+ Expect(session.OutputToString()).Should(Equal(""))
+ Expect(session.ErrorToString()).Should(ContainSubstring("permission denied"))
+
+ session = podmanTest.Podman([]string{"unshare", "--bogus"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(125))
+ Expect(session.OutputToString()).Should(Equal(""))
+ Expect(session.ErrorToString()).Should(ContainSubstring("unknown flag: --bogus"))
+ })
})
diff --git a/test/system/075-exec.bats b/test/system/075-exec.bats
index 3e8c3c1ea..b7367d153 100644
--- a/test/system/075-exec.bats
+++ b/test/system/075-exec.bats
@@ -101,4 +101,32 @@ load helpers
run_podman rm $cid
}
+# #11496: podman-remote loses output
+@test "podman exec/run - missing output" {
+ local bigfile=${PODMAN_TMPDIR}/bigfile
+ local newfile=${PODMAN_TMPDIR}/newfile
+ # create a big file, bigger than the 8K buffer size
+ base64 /dev/urandom | head -c 20K > $bigfile
+
+ run_podman run --rm -v $bigfile:/tmp/test:Z $IMAGE cat /tmp/test
+ printf "%s" "$output" > $newfile
+ # use cmp to compare the files, this is very helpful since it will
+ # tell us the first wrong byte in case this fails
+ run cmp $bigfile $newfile
+ is "$output" "" "run output is identical with the file"
+
+ run_podman run -d --stop-timeout 0 -v $bigfile:/tmp/test:Z $IMAGE sleep inf
+ cid="$output"
+
+ run_podman exec $cid cat /tmp/test
+ printf "%s" "$output" > $newfile
+ # use cmp to compare the files, this is very helpful since it will
+ # tell us the first wrong byte in case this fails
+ run cmp $bigfile $newfile
+ is "$output" "" "exec output is identical with the file"
+
+ # Clean up
+ run_podman rm -f $cid
+}
+
# vim: filetype=sh
diff --git a/test/system/125-import.bats b/test/system/125-import.bats
index c53711618..5995d71bf 100644
--- a/test/system/125-import.bats
+++ b/test/system/125-import.bats
@@ -43,3 +43,66 @@ load helpers
is "$output" "$random_content" "tagged import via stdin"
run_podman rmi -f $fqin
}
+
+@test "podman export, alter tarball, re-import" {
+
+ # Create a test file following test
+ mkdir $PODMAN_TMPDIR/tmp
+ touch $PODMAN_TMPDIR/testfile1
+ echo "modified tar file" >> $PODMAN_TMPDIR/tmp/testfile2
+
+ # Create Dockerfile for test
+ dockerfile=$PODMAN_TMPDIR/Dockerfile
+
+ cat >$dockerfile <<EOF
+FROM $IMAGE
+ADD testfile1 /tmp
+WORKDIR /tmp
+EOF
+
+ b_img=before_change_img
+ b_cnt=before_change_cnt
+ a_img=after_change_img
+ a_cnt=after_change_cnt
+
+ # Build from Dockerfile FROM non-existing local image
+ run_podman build -t $b_img $PODMAN_TMPDIR
+ run_podman create --name $b_cnt $b_img
+
+ # Export built container as tarball
+ run_podman export -o $PODMAN_TMPDIR/$b_cnt.tar $b_cnt
+ run_podman rm -f $b_cnt
+
+ # Modify tarball contents
+ tar --delete -f $PODMAN_TMPDIR/$b_cnt.tar tmp/testfile1
+ tar -C $PODMAN_TMPDIR -rf $PODMAN_TMPDIR/$b_cnt.tar tmp/testfile2
+
+ # Import tarball and Tag imported image
+ run_podman import -q $PODMAN_TMPDIR/$b_cnt.tar \
+ --change "CMD sh -c \
+ \"trap 'exit 33' 2;
+ while true; do sleep 0.05;done\"" $a_img
+
+ # Run imported image to confirm tarball modification, block on non-special signal
+ run_podman run --name $a_cnt -d $a_img
+
+ # Confirm testfile1 is deleted from tarball
+ run_podman 1 exec $a_cnt cat /tmp/testfile1
+ is "$output" ".*can't open '/tmp/testfile1': No such file or directory"
+
+ # Confirm testfile2 is added to tarball
+ run_podman exec $a_cnt cat /tmp/testfile2
+ is "$output" "modified tar file" "modify tarball content"
+
+ # Kill can send non-TERM/KILL signal to container to exit
+ run_podman kill --signal 2 $a_cnt
+ run_podman wait $a_cnt
+
+ # Confirm exit within timeout
+ run_podman ps -a --filter name=$a_cnt --format '{{.Status}}'
+ is "$output" "Exited (33)" "Exit by non-TERM/KILL"
+
+ run_podman rm -f $a_cnt
+ run_podman rmi $b_img $a_img
+
+}
diff --git a/test/system/220-healthcheck.bats b/test/system/220-healthcheck.bats
index f929c6770..e416629e6 100644
--- a/test/system/220-healthcheck.bats
+++ b/test/system/220-healthcheck.bats
@@ -74,7 +74,7 @@ EOF
#
# So, just force a healthcheck run, then confirm that it's running.
run_podman healthcheck run healthcheck_c
- is "$output" "healthy" "output from 'podman healthcheck run'"
+ is "$output" "" "output from 'podman healthcheck run'"
_check_health "All healthy" "
Status | healthy
diff --git a/vendor/github.com/containers/psgo/go.mod b/vendor/github.com/containers/psgo/go.mod
index 5f3341aa9..699874cf7 100644
--- a/vendor/github.com/containers/psgo/go.mod
+++ b/vendor/github.com/containers/psgo/go.mod
@@ -1,11 +1,10 @@
module github.com/containers/psgo
-go 1.12
+go 1.13
require (
- github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4
- github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9
- github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe
- github.com/stretchr/testify v1.5.1
- golang.org/x/sys v0.0.0-20190425145619-16072639606e
+ github.com/opencontainers/runc v1.0.2
+ github.com/sirupsen/logrus v1.8.1
+ github.com/stretchr/testify v1.7.0
+ golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2
)
diff --git a/vendor/github.com/containers/psgo/go.sum b/vendor/github.com/containers/psgo/go.sum
index 781b26f2b..0ba04956f 100644
--- a/vendor/github.com/containers/psgo/go.sum
+++ b/vendor/github.com/containers/psgo/go.sum
@@ -1,27 +1,78 @@
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
+github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
+github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
+github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
+github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4 h1:y5PMn9UW9cD5xvjoMs9pJ77zs5DgGkiDv0BI/Qew51o=
-github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
-github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9 h1:dIsTcVF0w9viTLHXUEkDI7cXITMe+M/MRRM2MwisVow=
-github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
+github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
+github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg=
+github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
+github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe h1:PBQLA9wc7FrXiUBnlfs/diNlg3ZdrP21tzcgL3OlVhU=
-github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190425145619-16072639606e h1:4ktJgTV34+N3qOZUc5fAaG3Pb11qzMm3PkAoTAgUZ2I=
-golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
+github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
+github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
+golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo=
+golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/vendor/github.com/containers/psgo/internal/proc/ns.go b/vendor/github.com/containers/psgo/internal/proc/ns.go
index 53e5ebda0..4778048f2 100644
--- a/vendor/github.com/containers/psgo/internal/proc/ns.go
+++ b/vendor/github.com/containers/psgo/internal/proc/ns.go
@@ -19,8 +19,6 @@ import (
"fmt"
"io"
"os"
-
- "github.com/pkg/errors"
)
type IDMap struct {
@@ -51,7 +49,7 @@ func ParseUserNamespace(pid string) (string, error) {
func ReadMappings(path string) ([]IDMap, error) {
file, err := os.Open(path)
if err != nil {
- return nil, errors.Wrapf(err, "cannot open %s", path)
+ return nil, err
}
defer file.Close()
@@ -64,7 +62,7 @@ func ReadMappings(path string) ([]IDMap, error) {
if err == io.EOF {
return mappings, nil
}
- return nil, errors.Wrapf(err, "cannot read line from %s", path)
+ return nil, fmt.Errorf("cannot read line from %s: %w", path, err)
}
if line == nil {
return mappings, nil
@@ -72,7 +70,7 @@ func ReadMappings(path string) ([]IDMap, error) {
containerID, hostID, size := 0, 0, 0
if _, err := fmt.Sscanf(string(line), "%d %d %d", &containerID, &hostID, &size); err != nil {
- return nil, errors.Wrapf(err, "cannot parse %s", string(line))
+ return nil, fmt.Errorf("cannot parse %s: %w", string(line), err)
}
mappings = append(mappings, IDMap{ContainerID: containerID, HostID: hostID, Size: size})
}
diff --git a/vendor/github.com/containers/psgo/internal/proc/status.go b/vendor/github.com/containers/psgo/internal/proc/status.go
index df31139f8..2753915fd 100644
--- a/vendor/github.com/containers/psgo/internal/proc/status.go
+++ b/vendor/github.com/containers/psgo/internal/proc/status.go
@@ -20,8 +20,6 @@ import (
"os"
"os/exec"
"strings"
-
- "github.com/pkg/errors"
)
// Status is a direct translation of a `/proc/[pid]/status`, which provides much
@@ -251,12 +249,12 @@ func parseStatus(pid string, lines []string) (*Status, error) {
s.TracerPid = fields[1]
case "Uid:":
if len(fields) != 5 {
- return nil, errors.Wrap(errUnexpectedInput, line)
+ return nil, fmt.Errorf(line+": %w", errUnexpectedInput)
}
s.Uids = []string{fields[1], fields[2], fields[3], fields[4]}
case "Gid:":
if len(fields) != 5 {
- return nil, errors.Wrap(errUnexpectedInput, line)
+ return nil, fmt.Errorf(line+": %w", errUnexpectedInput)
}
s.Gids = []string{fields[1], fields[2], fields[3], fields[4]}
case "FDSize:":
diff --git a/vendor/github.com/containers/psgo/internal/process/process.go b/vendor/github.com/containers/psgo/internal/process/process.go
index a581921d5..8fd49e416 100644
--- a/vendor/github.com/containers/psgo/internal/process/process.go
+++ b/vendor/github.com/containers/psgo/internal/process/process.go
@@ -15,6 +15,8 @@
package process
import (
+ "errors"
+ "fmt"
"os"
"strconv"
"time"
@@ -22,7 +24,6 @@ import (
"github.com/containers/psgo/internal/host"
"github.com/containers/psgo/internal/proc"
"github.com/opencontainers/runc/libcontainer/user"
- "github.com/pkg/errors"
)
// Process includes process-related from the /proc FS.
@@ -50,7 +51,7 @@ type Process struct {
func LookupGID(gid string) (string, error) {
gidNum, err := strconv.Atoi(gid)
if err != nil {
- return "", errors.Wrap(err, "error parsing group ID")
+ return "", fmt.Errorf("error parsing group ID: %w", err)
}
g, err := user.LookupGid(gidNum)
if err != nil {
@@ -64,7 +65,7 @@ func LookupGID(gid string) (string, error) {
func LookupUID(uid string) (string, error) {
uidNum, err := strconv.Atoi(uid)
if err != nil {
- return "", errors.Wrap(err, "error parsing user ID")
+ return "", fmt.Errorf("error parsing user ID: %w", err)
}
u, err := user.LookupUid(uidNum)
if err != nil {
@@ -107,7 +108,7 @@ func FromPIDs(pids []string, joinUserNS bool) ([]*Process, error) {
for _, pid := range pids {
p, err := New(pid, joinUserNS)
if err != nil {
- if os.IsNotExist(errors.Cause(err)) {
+ if errors.Is(err, os.ErrNotExist) {
// proc parsing is racy
// Let's ignore "does not exist" errors
continue
diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go
index 7c74fd716..b0569fa1c 100644
--- a/vendor/github.com/containers/psgo/psgo.go
+++ b/vendor/github.com/containers/psgo/psgo.go
@@ -27,6 +27,7 @@
package psgo
import (
+ "errors"
"fmt"
"io/ioutil"
"os"
@@ -40,7 +41,6 @@ import (
"github.com/containers/psgo/internal/dev"
"github.com/containers/psgo/internal/proc"
"github.com/containers/psgo/internal/process"
- "github.com/pkg/errors"
"golang.org/x/sys/unix"
)
@@ -109,7 +109,7 @@ func findID(idStr string, mapping []IDMap, lookupFunc func(uid string) (string,
id, err := strconv.ParseInt(idStr, 10, 0)
if err != nil {
- return "", errors.Wrapf(err, "cannot parse %s", idStr)
+ return "", fmt.Errorf("cannot parse ID: %w", err)
}
for _, m := range mapping {
if int(id) >= m.ContainerID && int(id) < m.ContainerID+m.Size {
@@ -122,7 +122,7 @@ func findID(idStr string, mapping []IDMap, lookupFunc func(uid string) (string,
// User not found, read the overflow
overflow, err := ioutil.ReadFile(overflowFile)
if err != nil {
- return "", errors.Wrapf(err, "cannot read %s", overflowFile)
+ return "", err
}
return string(overflow), nil
}
@@ -147,7 +147,7 @@ func translateDescriptors(descriptors []string) ([]aixFormatDescriptor, error) {
}
}
if !found {
- return nil, errors.Wrapf(ErrUnknownDescriptor, "'%s'", d)
+ return nil, fmt.Errorf("'%s': %w", d, ErrUnknownDescriptor)
}
}
@@ -412,13 +412,13 @@ func JoinNamespaceAndProcessInfoWithOptions(pid string, descriptors []string, op
// extract user namespaces prior to joining the mount namespace
currentUserNs, err := proc.ParseUserNamespace("self")
if err != nil {
- dataErr = errors.Wrapf(err, "error determining user namespace")
+ dataErr = fmt.Errorf("error determining user namespace: %w", err)
return
}
pidUserNs, err := proc.ParseUserNamespace(pid)
if err != nil {
- dataErr = errors.Wrapf(err, "error determining user namespace of PID %s", pid)
+ dataErr = fmt.Errorf("error determining user namespace of PID %s: %w", pid, err)
}
// join the mount namespace of pid
@@ -478,11 +478,11 @@ func JoinNamespaceAndProcessInfoByPidsWithOptions(pids []string, descriptors []s
for _, pid := range pids {
ns, err := proc.ParsePIDNamespace(pid)
if err != nil {
- if os.IsNotExist(errors.Cause(err)) {
+ if errors.Is(err, os.ErrNotExist) {
// catch race conditions
continue
}
- return nil, errors.Wrapf(err, "error extracting PID namespace")
+ return nil, fmt.Errorf("error extracting PID namespace: %w", err)
}
if _, exists := nsMap[ns]; !exists {
nsMap[ns] = true
@@ -493,7 +493,7 @@ func JoinNamespaceAndProcessInfoByPidsWithOptions(pids []string, descriptors []s
data := [][]string{}
for i, pid := range pidList {
pidData, err := JoinNamespaceAndProcessInfoWithOptions(pid, descriptors, options)
- if os.IsNotExist(errors.Cause(err)) {
+ if errors.Is(err, os.ErrNotExist) {
// catch race conditions
continue
}
diff --git a/vendor/github.com/containers/psgo/vendor.conf b/vendor/github.com/containers/psgo/vendor.conf
deleted file mode 100644
index 1fba46ec1..000000000
--- a/vendor/github.com/containers/psgo/vendor.conf
+++ /dev/null
@@ -1,8 +0,0 @@
-github.com/davecgh/go-spew master
-github.com/opencontainers/runc master
-github.com/pkg/errors master
-github.com/pmezard/go-difflib master
-github.com/sirupsen/logrus master
-github.com/stretchr/testify master
-golang.org/x/crypto master
-golang.org/x/sys master
diff --git a/vendor/github.com/godbus/dbus/v5/README.markdown b/vendor/github.com/godbus/dbus/v5/README.md
index 1fb2eacaa..5c2412583 100644
--- a/vendor/github.com/godbus/dbus/v5/README.markdown
+++ b/vendor/github.com/godbus/dbus/v5/README.md
@@ -14,14 +14,12 @@ D-Bus message bus system.
### Installation
-This packages requires Go 1.7. If you installed it and set up your GOPATH, just run:
+This packages requires Go 1.12 or later. It can be installed by running the command below:
```
-go get github.com/godbus/dbus
+go get github.com/godbus/dbus/v5
```
-If you want to use the subpackages, you can install them the same way.
-
### Usage
The complete package documentation and some simple examples are available at
@@ -30,10 +28,12 @@ The complete package documentation and some simple examples are available at
gives a short overview over the basic usage.
#### Projects using godbus
-- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
+- [fyne](https://github.com/fyne-io/fyne) a cross platform GUI in Go inspired by Material Design.
+- [fynedesk](https://github.com/fyne-io/fynedesk) a full desktop environment for Linux/Unix using Fyne.
- [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API.
-- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
- [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd".
+- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
+- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
Please note that the API is considered unstable for now and may change without
further notice.
diff --git a/vendor/github.com/godbus/dbus/v5/auth.go b/vendor/github.com/godbus/dbus/v5/auth.go
index 283487a0e..eb0b2f434 100644
--- a/vendor/github.com/godbus/dbus/v5/auth.go
+++ b/vendor/github.com/godbus/dbus/v5/auth.go
@@ -75,9 +75,9 @@ func (conn *Conn) Auth(methods []Auth) error {
s = s[1:]
for _, v := range s {
for _, m := range methods {
- if name, data, status := m.FirstData(); bytes.Equal(v, name) {
+ if name, _, status := m.FirstData(); bytes.Equal(v, name) {
var ok bool
- err = authWriteLine(conn.transport, []byte("AUTH"), v, data)
+ err = authWriteLine(conn.transport, []byte("AUTH"), v)
if err != nil {
return err
}
@@ -194,11 +194,14 @@ func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, boo
}
conn.uuid = string(s[1])
return nil, true
+ case state == waitingForOk && string(s[0]) == "DATA":
+ err = authWriteLine(conn.transport, []byte("DATA"))
+ if err != nil {
+ return err, false
+ }
case state == waitingForOk && string(s[0]) == "REJECTED":
return nil, false
- case state == waitingForOk && (string(s[0]) == "DATA" ||
- string(s[0]) == "ERROR"):
-
+ case state == waitingForOk && string(s[0]) == "ERROR":
err = authWriteLine(conn.transport, []byte("CANCEL"))
if err != nil {
return err, false
diff --git a/vendor/github.com/godbus/dbus/v5/conn.go b/vendor/github.com/godbus/dbus/v5/conn.go
index 29fe018ad..cb8966a74 100644
--- a/vendor/github.com/godbus/dbus/v5/conn.go
+++ b/vendor/github.com/godbus/dbus/v5/conn.go
@@ -478,14 +478,24 @@ func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) {
conn.outInt(msg)
}
err := conn.outHandler.sendAndIfClosed(msg, ifClosed)
- conn.calls.handleSendError(msg, err)
if err != nil {
- conn.serialGen.RetireSerial(msg.serial)
+ conn.handleSendError(msg, err)
} else if msg.Type != TypeMethodCall {
conn.serialGen.RetireSerial(msg.serial)
}
}
+func (conn *Conn) handleSendError(msg *Message, err error) {
+ if msg.Type == TypeMethodCall {
+ conn.calls.handleSendError(msg, err)
+ } else if msg.Type == TypeMethodReply {
+ if _, ok := err.(FormatError); ok {
+ conn.sendError(err, msg.Headers[FieldDestination].value.(string), msg.Headers[FieldReplySerial].value.(uint32))
+ }
+ }
+ conn.serialGen.RetireSerial(msg.serial)
+}
+
// Send sends the given message to the message bus. You usually don't need to
// use this; use the higher-level equivalents (Call / Go, Emit and Export)
// instead. If msg is a method call and NoReplyExpected is not set, a non-nil
diff --git a/vendor/github.com/godbus/dbus/v5/decoder.go b/vendor/github.com/godbus/dbus/v5/decoder.go
index ede91575b..89bfed9d1 100644
--- a/vendor/github.com/godbus/dbus/v5/decoder.go
+++ b/vendor/github.com/godbus/dbus/v5/decoder.go
@@ -10,14 +10,16 @@ type decoder struct {
in io.Reader
order binary.ByteOrder
pos int
+ fds []int
}
// newDecoder returns a new decoder that reads values from in. The input is
// expected to be in the given byte order.
-func newDecoder(in io.Reader, order binary.ByteOrder) *decoder {
+func newDecoder(in io.Reader, order binary.ByteOrder, fds []int) *decoder {
dec := new(decoder)
dec.in = in
dec.order = order
+ dec.fds = fds
return dec
}
@@ -53,7 +55,7 @@ func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {
vs = make([]interface{}, 0)
s := sig.str
for s != "" {
- err, rem := validSingle(s, 0)
+ err, rem := validSingle(s, &depthCounter{})
if err != nil {
return nil, err
}
@@ -150,7 +152,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
if len(sig.str) == 0 {
panic(FormatError("variant signature is empty"))
}
- err, rem := validSingle(sig.str, 0)
+ err, rem := validSingle(sig.str, &depthCounter{})
if err != nil {
panic(err)
}
@@ -161,7 +163,11 @@ func (dec *decoder) decode(s string, depth int) interface{} {
variant.value = dec.decode(sig.str, depth+1)
return variant
case 'h':
- return UnixFDIndex(dec.decode("u", depth).(uint32))
+ idx := dec.decode("u", depth).(uint32)
+ if int(idx) < len(dec.fds) {
+ return UnixFD(dec.fds[idx])
+ }
+ return UnixFDIndex(idx)
case 'a':
if len(s) > 1 && s[1] == '{' {
ksig := s[2:3]
@@ -219,7 +225,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
v := make([]interface{}, 0)
s = s[1 : len(s)-1]
for s != "" {
- err, rem := validSingle(s, 0)
+ err, rem := validSingle(s, &depthCounter{})
if err != nil {
panic(err)
}
diff --git a/vendor/github.com/godbus/dbus/v5/encoder.go b/vendor/github.com/godbus/dbus/v5/encoder.go
index adfbb75c5..015b26cd5 100644
--- a/vendor/github.com/godbus/dbus/v5/encoder.go
+++ b/vendor/github.com/godbus/dbus/v5/encoder.go
@@ -5,28 +5,33 @@ import (
"encoding/binary"
"io"
"reflect"
+ "strings"
+ "unicode/utf8"
)
// An encoder encodes values to the D-Bus wire format.
type encoder struct {
out io.Writer
+ fds []int
order binary.ByteOrder
pos int
}
// NewEncoder returns a new encoder that writes to out in the given byte order.
-func newEncoder(out io.Writer, order binary.ByteOrder) *encoder {
- return newEncoderAtOffset(out, 0, order)
+func newEncoder(out io.Writer, order binary.ByteOrder, fds []int) *encoder {
+ enc := newEncoderAtOffset(out, 0, order, fds)
+ return enc
}
// newEncoderAtOffset returns a new encoder that writes to out in the given
// byte order. Specify the offset to initialize pos for proper alignment
// computation.
-func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder) *encoder {
+func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder, fds []int) *encoder {
enc := new(encoder)
enc.out = out
enc.order = order
enc.pos = offset
+ enc.fds = fds
return enc
}
@@ -75,6 +80,9 @@ func (enc *encoder) Encode(vs ...interface{}) (err error) {
// encode encodes the given value to the writer and panics on error. depth holds
// the depth of the container nesting.
func (enc *encoder) encode(v reflect.Value, depth int) {
+ if depth > 64 {
+ panic(FormatError("input exceeds depth limitation"))
+ }
enc.align(alignment(v.Type()))
switch v.Kind() {
case reflect.Uint8:
@@ -97,7 +105,14 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
enc.binwrite(uint16(v.Uint()))
enc.pos += 2
case reflect.Int, reflect.Int32:
- enc.binwrite(int32(v.Int()))
+ if v.Type() == unixFDType {
+ fd := v.Int()
+ idx := len(enc.fds)
+ enc.fds = append(enc.fds, int(fd))
+ enc.binwrite(uint32(idx))
+ } else {
+ enc.binwrite(int32(v.Int()))
+ }
enc.pos += 4
case reflect.Uint, reflect.Uint32:
enc.binwrite(uint32(v.Uint()))
@@ -112,9 +127,21 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
enc.binwrite(v.Float())
enc.pos += 8
case reflect.String:
- enc.encode(reflect.ValueOf(uint32(len(v.String()))), depth)
+ str := v.String()
+ if !utf8.ValidString(str) {
+ panic(FormatError("input has a not-utf8 char in string"))
+ }
+ if strings.IndexByte(str, byte(0)) != -1 {
+ panic(FormatError("input has a null char('\\000') in string"))
+ }
+ if v.Type() == objectPathType {
+ if !ObjectPath(str).IsValid() {
+ panic(FormatError("invalid object path"))
+ }
+ }
+ enc.encode(reflect.ValueOf(uint32(len(str))), depth)
b := make([]byte, v.Len()+1)
- copy(b, v.String())
+ copy(b, str)
b[len(b)-1] = 0
n, err := enc.out.Write(b)
if err != nil {
@@ -124,20 +151,23 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
case reflect.Ptr:
enc.encode(v.Elem(), depth)
case reflect.Slice, reflect.Array:
- if depth >= 64 {
- panic(FormatError("input exceeds container depth limit"))
- }
// Lookahead offset: 4 bytes for uint32 length (with alignment),
// plus alignment for elements.
n := enc.padding(0, 4) + 4
offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem()))
var buf bytes.Buffer
- bufenc := newEncoderAtOffset(&buf, offset, enc.order)
+ bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
for i := 0; i < v.Len(); i++ {
bufenc.encode(v.Index(i), depth+1)
}
+
+ if buf.Len() > 1<<26 {
+ panic(FormatError("input exceeds array size limitation"))
+ }
+
+ enc.fds = bufenc.fds
enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
length := buf.Len()
enc.align(alignment(v.Type().Elem()))
@@ -146,13 +176,10 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
}
enc.pos += length
case reflect.Struct:
- if depth >= 64 && v.Type() != signatureType {
- panic(FormatError("input exceeds container depth limit"))
- }
switch t := v.Type(); t {
case signatureType:
str := v.Field(0)
- enc.encode(reflect.ValueOf(byte(str.Len())), depth+1)
+ enc.encode(reflect.ValueOf(byte(str.Len())), depth)
b := make([]byte, str.Len()+1)
copy(b, str.String())
b[len(b)-1] = 0
@@ -176,9 +203,6 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
case reflect.Map:
// Maps are arrays of structures, so they actually increase the depth by
// 2.
- if depth >= 63 {
- panic(FormatError("input exceeds container depth limit"))
- }
if !isKeyType(v.Type().Key()) {
panic(InvalidTypeError{v.Type()})
}
@@ -189,12 +213,13 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
offset := enc.pos + n + enc.padding(n, 8)
var buf bytes.Buffer
- bufenc := newEncoderAtOffset(&buf, offset, enc.order)
+ bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
for _, k := range keys {
bufenc.align(8)
bufenc.encode(k, depth+2)
bufenc.encode(v.MapIndex(k), depth+2)
}
+ enc.fds = bufenc.fds
enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
length := buf.Len()
enc.align(8)
diff --git a/vendor/github.com/godbus/dbus/v5/export.go b/vendor/github.com/godbus/dbus/v5/export.go
index 2447b51d4..522334715 100644
--- a/vendor/github.com/godbus/dbus/v5/export.go
+++ b/vendor/github.com/godbus/dbus/v5/export.go
@@ -26,6 +26,27 @@ var (
}
)
+func MakeNoObjectError(path ObjectPath) Error {
+ return Error{
+ "org.freedesktop.DBus.Error.NoSuchObject",
+ []interface{}{fmt.Sprintf("No such object '%s'", string(path))},
+ }
+}
+
+func MakeUnknownMethodError(methodName string) Error {
+ return Error{
+ "org.freedesktop.DBus.Error.UnknownMethod",
+ []interface{}{fmt.Sprintf("Unknown / invalid method '%s'", methodName)},
+ }
+}
+
+func MakeUnknownInterfaceError(ifaceName string) Error {
+ return Error{
+ "org.freedesktop.DBus.Error.UnknownInterface",
+ []interface{}{fmt.Sprintf("Object does not implement the interface '%s'", ifaceName)},
+ }
+}
+
func MakeFailedError(err error) *Error {
return &Error{
"org.freedesktop.DBus.Error.Failed",
@@ -128,6 +149,11 @@ func (conn *Conn) handleCall(msg *Message) {
ifaceName, _ := msg.Headers[FieldInterface].value.(string)
sender, hasSender := msg.Headers[FieldSender].value.(string)
serial := msg.serial
+
+ if len(name) == 0 {
+ conn.sendError(ErrMsgUnknownMethod, sender, serial)
+ }
+
if ifaceName == "org.freedesktop.DBus.Peer" {
switch name {
case "Ping":
@@ -135,29 +161,26 @@ func (conn *Conn) handleCall(msg *Message) {
case "GetMachineId":
conn.sendReply(sender, serial, conn.uuid)
default:
- conn.sendError(ErrMsgUnknownMethod, sender, serial)
+ conn.sendError(MakeUnknownMethodError(name), sender, serial)
}
return
}
- if len(name) == 0 {
- conn.sendError(ErrMsgUnknownMethod, sender, serial)
- }
object, ok := conn.handler.LookupObject(path)
if !ok {
- conn.sendError(ErrMsgNoObject, sender, serial)
+ conn.sendError(MakeNoObjectError(path), sender, serial)
return
}
iface, exists := object.LookupInterface(ifaceName)
if !exists {
- conn.sendError(ErrMsgUnknownInterface, sender, serial)
+ conn.sendError(MakeUnknownInterfaceError(ifaceName), sender, serial)
return
}
m, exists := iface.LookupMethod(name)
if !exists {
- conn.sendError(ErrMsgUnknownMethod, sender, serial)
+ conn.sendError(MakeUnknownMethodError(name), sender, serial)
return
}
args, err := conn.decodeArguments(m, sender, msg)
diff --git a/vendor/github.com/godbus/dbus/v5/message.go b/vendor/github.com/godbus/dbus/v5/message.go
index 6a925367e..dd86aff4f 100644
--- a/vendor/github.com/godbus/dbus/v5/message.go
+++ b/vendor/github.com/godbus/dbus/v5/message.go
@@ -118,11 +118,7 @@ type header struct {
Variant
}
-// DecodeMessage tries to decode a single message in the D-Bus wire format
-// from the given reader. The byte order is figured out from the first byte.
-// The possibly returned error can be an error of the underlying reader, an
-// InvalidMessageError or a FormatError.
-func DecodeMessage(rd io.Reader) (msg *Message, err error) {
+func DecodeMessageWithFDs(rd io.Reader, fds []int) (msg *Message, err error) {
var order binary.ByteOrder
var hlength, length uint32
var typ, flags, proto byte
@@ -142,7 +138,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
return nil, InvalidMessageError("invalid byte order")
}
- dec := newDecoder(rd, order)
+ dec := newDecoder(rd, order, fds)
dec.pos = 1
msg = new(Message)
@@ -166,7 +162,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
if hlength+length+16 > 1<<27 {
return nil, InvalidMessageError("message is too long")
}
- dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order)
+ dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order, fds)
dec.pos = 12
vs, err = dec.Decode(Signature{"a(yv)"})
if err != nil {
@@ -196,7 +192,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
sig, _ := msg.Headers[FieldSignature].value.(Signature)
if sig.str != "" {
buf := bytes.NewBuffer(body)
- dec = newDecoder(buf, order)
+ dec = newDecoder(buf, order, fds)
vs, err := dec.Decode(sig)
if err != nil {
return nil, err
@@ -207,12 +203,32 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
return
}
-// EncodeTo encodes and sends a message to the given writer. The byte order must
-// be either binary.LittleEndian or binary.BigEndian. If the message is not
-// valid or an error occurs when writing, an error is returned.
-func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
+// DecodeMessage tries to decode a single message in the D-Bus wire format
+// from the given reader. The byte order is figured out from the first byte.
+// The possibly returned error can be an error of the underlying reader, an
+// InvalidMessageError or a FormatError.
+func DecodeMessage(rd io.Reader) (msg *Message, err error) {
+ return DecodeMessageWithFDs(rd, make([]int, 0));
+}
+
+type nullwriter struct{}
+
+func (nullwriter) Write(p []byte) (cnt int, err error) {
+ return len(p), nil
+}
+
+func (msg *Message) CountFds() (int, error) {
+ if len(msg.Body) == 0 {
+ return 0, nil
+ }
+ enc := newEncoder(nullwriter{}, nativeEndian, make([]int, 0))
+ err := enc.Encode(msg.Body...)
+ return len(enc.fds), err
+}
+
+func (msg *Message) EncodeToWithFDs(out io.Writer, order binary.ByteOrder) (fds []int, err error) {
if err := msg.IsValid(); err != nil {
- return err
+ return make([]int, 0), err
}
var vs [7]interface{}
switch order {
@@ -221,12 +237,16 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
case binary.BigEndian:
vs[0] = byte('B')
default:
- return errors.New("dbus: invalid byte order")
+ return make([]int, 0), errors.New("dbus: invalid byte order")
}
body := new(bytes.Buffer)
- enc := newEncoder(body, order)
+ fds = make([]int, 0)
+ enc := newEncoder(body, order, fds)
if len(msg.Body) != 0 {
- enc.Encode(msg.Body...)
+ err = enc.Encode(msg.Body...)
+ if err != nil {
+ return
+ }
}
vs[1] = msg.Type
vs[2] = msg.Flags
@@ -239,17 +259,28 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
}
vs[6] = headers
var buf bytes.Buffer
- enc = newEncoder(&buf, order)
- enc.Encode(vs[:]...)
+ enc = newEncoder(&buf, order, enc.fds)
+ err = enc.Encode(vs[:]...)
+ if err != nil {
+ return
+ }
enc.align(8)
body.WriteTo(&buf)
if buf.Len() > 1<<27 {
- return InvalidMessageError("message is too long")
+ return make([]int, 0), InvalidMessageError("message is too long")
}
if _, err := buf.WriteTo(out); err != nil {
- return err
+ return make([]int, 0), err
}
- return nil
+ return enc.fds, nil
+}
+
+// EncodeTo encodes and sends a message to the given writer. The byte order must
+// be either binary.LittleEndian or binary.BigEndian. If the message is not
+// valid or an error occurs when writing, an error is returned.
+func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) (err error) {
+ _, err = msg.EncodeToWithFDs(out, order);
+ return err;
}
// IsValid checks whether msg is a valid message and returns an
diff --git a/vendor/github.com/godbus/dbus/v5/sig.go b/vendor/github.com/godbus/dbus/v5/sig.go
index 2d326cebc..41a039812 100644
--- a/vendor/github.com/godbus/dbus/v5/sig.go
+++ b/vendor/github.com/godbus/dbus/v5/sig.go
@@ -34,7 +34,7 @@ type Signature struct {
func SignatureOf(vs ...interface{}) Signature {
var s string
for _, v := range vs {
- s += getSignature(reflect.TypeOf(v))
+ s += getSignature(reflect.TypeOf(v), &depthCounter{})
}
return Signature{s}
}
@@ -42,11 +42,19 @@ func SignatureOf(vs ...interface{}) Signature {
// SignatureOfType returns the signature of the given type. It panics if the
// type is not representable in D-Bus.
func SignatureOfType(t reflect.Type) Signature {
- return Signature{getSignature(t)}
+ return Signature{getSignature(t, &depthCounter{})}
}
// getSignature returns the signature of the given type and panics on unknown types.
-func getSignature(t reflect.Type) string {
+func getSignature(t reflect.Type, depth *depthCounter) (sig string) {
+ if !depth.Valid() {
+ panic("container nesting too deep")
+ }
+ defer func() {
+ if len(sig) > 255 {
+ panic("signature exceeds the length limitation")
+ }
+ }()
// handle simple types first
switch t.Kind() {
case reflect.Uint8:
@@ -74,7 +82,7 @@ func getSignature(t reflect.Type) string {
case reflect.Float64:
return "d"
case reflect.Ptr:
- return getSignature(t.Elem())
+ return getSignature(t.Elem(), depth)
case reflect.String:
if t == objectPathType {
return "o"
@@ -90,17 +98,20 @@ func getSignature(t reflect.Type) string {
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
- s += getSignature(t.Field(i).Type)
+ s += getSignature(t.Field(i).Type, depth.EnterStruct())
}
}
+ if len(s) == 0 {
+ panic("empty struct")
+ }
return "(" + s + ")"
case reflect.Array, reflect.Slice:
- return "a" + getSignature(t.Elem())
+ return "a" + getSignature(t.Elem(), depth.EnterArray())
case reflect.Map:
if !isKeyType(t.Key()) {
panic(InvalidTypeError{t})
}
- return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}"
+ return "a{" + getSignature(t.Key(), depth.EnterArray().EnterDictEntry()) + getSignature(t.Elem(), depth.EnterArray().EnterDictEntry()) + "}"
case reflect.Interface:
return "v"
}
@@ -118,7 +129,7 @@ func ParseSignature(s string) (sig Signature, err error) {
}
sig.str = s
for err == nil && len(s) != 0 {
- err, s = validSingle(s, 0)
+ err, s = validSingle(s, &depthCounter{})
}
if err != nil {
sig = Signature{""}
@@ -144,7 +155,7 @@ func (s Signature) Empty() bool {
// Single returns whether the signature represents a single, complete type.
func (s Signature) Single() bool {
- err, r := validSingle(s.str, 0)
+ err, r := validSingle(s.str, &depthCounter{})
return err != nil && r == ""
}
@@ -164,15 +175,38 @@ func (e SignatureError) Error() string {
return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason)
}
+type depthCounter struct {
+ arrayDepth, structDepth, dictEntryDepth int
+}
+
+func (cnt *depthCounter) Valid() bool {
+ return cnt.arrayDepth <= 32 && cnt.structDepth <= 32 && cnt.dictEntryDepth <= 32
+}
+
+func (cnt depthCounter) EnterArray() *depthCounter {
+ cnt.arrayDepth++
+ return &cnt
+}
+
+func (cnt depthCounter) EnterStruct() *depthCounter {
+ cnt.structDepth++
+ return &cnt
+}
+
+func (cnt depthCounter) EnterDictEntry() *depthCounter {
+ cnt.dictEntryDepth++
+ return &cnt
+}
+
// Try to read a single type from this string. If it was successful, err is nil
// and rem is the remaining unparsed part. Otherwise, err is a non-nil
// SignatureError and rem is "". depth is the current recursion depth which may
// not be greater than 64 and should be given as 0 on the first call.
-func validSingle(s string, depth int) (err error, rem string) {
+func validSingle(s string, depth *depthCounter) (err error, rem string) {
if s == "" {
return SignatureError{Sig: s, Reason: "empty signature"}, ""
}
- if depth > 64 {
+ if !depth.Valid() {
return SignatureError{Sig: s, Reason: "container nesting too deep"}, ""
}
switch s[0] {
@@ -187,10 +221,10 @@ func validSingle(s string, depth int) (err error, rem string) {
i++
rem = s[i+1:]
s = s[2:i]
- if err, _ = validSingle(s[:1], depth+1); err != nil {
+ if err, _ = validSingle(s[:1], depth.EnterArray().EnterDictEntry()); err != nil {
return err, ""
}
- err, nr := validSingle(s[1:], depth+1)
+ err, nr := validSingle(s[1:], depth.EnterArray().EnterDictEntry())
if err != nil {
return err, ""
}
@@ -199,7 +233,7 @@ func validSingle(s string, depth int) (err error, rem string) {
}
return nil, rem
}
- return validSingle(s[1:], depth+1)
+ return validSingle(s[1:], depth.EnterArray())
case '(':
i := findMatching(s, '(', ')')
if i == -1 {
@@ -208,7 +242,7 @@ func validSingle(s string, depth int) (err error, rem string) {
rem = s[i+1:]
s = s[1:i]
for err == nil && s != "" {
- err, s = validSingle(s, depth+1)
+ err, s = validSingle(s, depth.EnterStruct())
}
if err != nil {
rem = ""
@@ -236,7 +270,7 @@ func findMatching(s string, left, right rune) int {
// typeFor returns the type of the given signature. It ignores any left over
// characters and panics if s doesn't start with a valid type signature.
func typeFor(s string) (t reflect.Type) {
- err, _ := validSingle(s, 0)
+ err, _ := validSingle(s, &depthCounter{})
if err != nil {
panic(err)
}
diff --git a/vendor/github.com/godbus/dbus/v5/transport_generic.go b/vendor/github.com/godbus/dbus/v5/transport_generic.go
index 718a1ff02..a08e2813c 100644
--- a/vendor/github.com/godbus/dbus/v5/transport_generic.go
+++ b/vendor/github.com/godbus/dbus/v5/transport_generic.go
@@ -41,10 +41,12 @@ func (t genericTransport) ReadMessage() (*Message, error) {
}
func (t genericTransport) SendMessage(msg *Message) error {
- for _, v := range msg.Body {
- if _, ok := v.(UnixFD); ok {
- return errors.New("dbus: unix fd passing not enabled")
- }
+ fds, err := msg.CountFds()
+ if err != nil {
+ return err
+ }
+ if fds != 0 {
+ return errors.New("dbus: unix fd passing not enabled")
}
return msg.EncodeTo(t, nativeEndian)
}
diff --git a/vendor/github.com/godbus/dbus/v5/transport_unix.go b/vendor/github.com/godbus/dbus/v5/transport_unix.go
index c7cd02f97..2212e7fa7 100644
--- a/vendor/github.com/godbus/dbus/v5/transport_unix.go
+++ b/vendor/github.com/godbus/dbus/v5/transport_unix.go
@@ -113,7 +113,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil {
return nil, err
}
- dec := newDecoder(bytes.NewBuffer(headerdata), order)
+ dec := newDecoder(bytes.NewBuffer(headerdata), order, make([]int, 0))
dec.pos = 12
vs, err := dec.Decode(Signature{"a(yv)"})
if err != nil {
@@ -147,7 +147,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
if err != nil {
return nil, err
}
- msg, err := DecodeMessage(bytes.NewBuffer(all))
+ msg, err := DecodeMessageWithFDs(bytes.NewBuffer(all), fds)
if err != nil {
return nil, err
}
@@ -179,21 +179,21 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
}
func (t *unixTransport) SendMessage(msg *Message) error {
- fds := make([]int, 0)
- for i, v := range msg.Body {
- if fd, ok := v.(UnixFD); ok {
- msg.Body[i] = UnixFDIndex(len(fds))
- fds = append(fds, int(fd))
- }
+ fdcnt, err := msg.CountFds()
+ if err != nil {
+ return err
}
- if len(fds) != 0 {
+ if fdcnt != 0 {
if !t.hasUnixFDs {
return errors.New("dbus: unix fd passing not enabled")
}
- msg.Headers[FieldUnixFDs] = MakeVariant(uint32(len(fds)))
- oob := syscall.UnixRights(fds...)
+ msg.Headers[FieldUnixFDs] = MakeVariant(uint32(fdcnt))
buf := new(bytes.Buffer)
- msg.EncodeTo(buf, nativeEndian)
+ fds, err := msg.EncodeToWithFDs(buf, nativeEndian)
+ if err != nil {
+ return err
+ }
+ oob := syscall.UnixRights(fds...)
n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
if err != nil {
return err
diff --git a/vendor/github.com/gorilla/handlers/.travis.yml b/vendor/github.com/gorilla/handlers/.travis.yml
new file mode 100644
index 000000000..354b7f8b2
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/.travis.yml
@@ -0,0 +1,8 @@
+language: go
+
+go:
+ - 1.1
+ - 1.2
+ - 1.3
+ - 1.4
+ - tip
diff --git a/vendor/github.com/gorilla/handlers/LICENSE b/vendor/github.com/gorilla/handlers/LICENSE
new file mode 100644
index 000000000..66ea3c8ae
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2013 The Gorilla Handlers Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/gorilla/handlers/README.md b/vendor/github.com/gorilla/handlers/README.md
new file mode 100644
index 000000000..a340abe08
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/README.md
@@ -0,0 +1,52 @@
+gorilla/handlers
+================
+[![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers) [![Build Status](https://travis-ci.org/gorilla/handlers.svg?branch=master)](https://travis-ci.org/gorilla/handlers)
+
+Package handlers is a collection of handlers (aka "HTTP middleware") for use
+with Go's `net/http` package (or any framework supporting `http.Handler`), including:
+
+* `LoggingHandler` for logging HTTP requests in the Apache [Common Log
+ Format](http://httpd.apache.org/docs/2.2/logs.html#common).
+* `CombinedLoggingHandler` for logging HTTP requests in the Apache [Combined Log
+ Format](http://httpd.apache.org/docs/2.2/logs.html#combined) commonly used by
+ both Apache and nginx.
+* `CompressHandler` for gzipping responses.
+* `ContentTypeHandler` for validating requests against a list of accepted
+ content types.
+* `MethodHandler` for matching HTTP methods against handlers in a
+ `map[string]http.Handler`
+* `ProxyHeaders` for populating `r.RemoteAddr` and `r.URL.Scheme` based on the
+ `X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Proto` and RFC7239 `Forwarded`
+ headers when running a Go server behind a HTTP reverse proxy.
+* `CanonicalHost` for re-directing to the preferred host when handling multiple
+ domains (i.e. multiple CNAME aliases).
+
+Other handlers are documented [on the Gorilla
+website](http://www.gorillatoolkit.org/pkg/handlers).
+
+## Example
+
+A simple example using `handlers.LoggingHandler` and `handlers.CompressHandler`:
+
+```go
+import (
+ "net/http"
+ "github.com/gorilla/handlers"
+)
+
+func main() {
+ r := http.NewServeMux()
+
+ // Only log requests to our admin dashboard to stdout
+ r.Handle("/admin", handlers.LoggingHandler(os.Stdout, http.HandlerFunc(ShowAdminDashboard)))
+ r.HandleFunc("/", ShowIndex)
+
+ // Wrap our server with our gzip handler to gzip compress all responses.
+ http.ListenAndServe(":8000", handlers.CompressHandler(r))
+}
+```
+
+## License
+
+BSD licensed. See the included LICENSE file for details.
+
diff --git a/vendor/github.com/gorilla/handlers/canonical.go b/vendor/github.com/gorilla/handlers/canonical.go
new file mode 100644
index 000000000..3961695c4
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/canonical.go
@@ -0,0 +1,71 @@
+package handlers
+
+import (
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+type canonical struct {
+ h http.Handler
+ domain string
+ code int
+}
+
+// CanonicalHost is HTTP middleware that re-directs requests to the canonical
+// domain. It accepts a domain and a status code (e.g. 301 or 302) and
+// re-directs clients to this domain. The existing request path is maintained.
+//
+// Note: If the provided domain is considered invalid by url.Parse or otherwise
+// returns an empty scheme or host, clients are not re-directed.
+// not re-directed.
+//
+// Example:
+//
+// r := mux.NewRouter()
+// canonical := handlers.CanonicalHost("http://www.gorillatoolkit.org", 302)
+// r.HandleFunc("/route", YourHandler)
+//
+// log.Fatal(http.ListenAndServe(":7000", canonical(r)))
+//
+func CanonicalHost(domain string, code int) func(h http.Handler) http.Handler {
+ fn := func(h http.Handler) http.Handler {
+ return canonical{h, domain, code}
+ }
+
+ return fn
+}
+
+func (c canonical) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ dest, err := url.Parse(c.domain)
+ if err != nil {
+ // Call the next handler if the provided domain fails to parse.
+ c.h.ServeHTTP(w, r)
+ return
+ }
+
+ if dest.Scheme == "" || dest.Host == "" {
+ // Call the next handler if the scheme or host are empty.
+ // Note that url.Parse won't fail on in this case.
+ c.h.ServeHTTP(w, r)
+ return
+ }
+
+ if !strings.EqualFold(cleanHost(r.Host), dest.Host) {
+ // Re-build the destination URL
+ dest := dest.Scheme + "://" + dest.Host + r.URL.Path
+ http.Redirect(w, r, dest, c.code)
+ }
+
+ c.h.ServeHTTP(w, r)
+}
+
+// cleanHost cleans invalid Host headers by stripping anything after '/' or ' '.
+// This is backported from Go 1.5 (in response to issue #11206) and attempts to
+// mitigate malformed Host headers that do not match the format in RFC7230.
+func cleanHost(in string) string {
+ if i := strings.IndexAny(in, " /"); i != -1 {
+ return in[:i]
+ }
+ return in
+}
diff --git a/vendor/github.com/gorilla/handlers/compress.go b/vendor/github.com/gorilla/handlers/compress.go
new file mode 100644
index 000000000..3d90e1914
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/compress.go
@@ -0,0 +1,84 @@
+// Copyright 2013 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package handlers
+
+import (
+ "compress/flate"
+ "compress/gzip"
+ "io"
+ "net/http"
+ "strings"
+)
+
+type compressResponseWriter struct {
+ io.Writer
+ http.ResponseWriter
+ http.Hijacker
+}
+
+func (w *compressResponseWriter) Header() http.Header {
+ return w.ResponseWriter.Header()
+}
+
+func (w *compressResponseWriter) Write(b []byte) (int, error) {
+ h := w.ResponseWriter.Header()
+ if h.Get("Content-Type") == "" {
+ h.Set("Content-Type", http.DetectContentType(b))
+ }
+
+ return w.Writer.Write(b)
+}
+
+// CompressHandler gzip compresses HTTP responses for clients that support it
+// via the 'Accept-Encoding' header.
+func CompressHandler(h http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ L:
+ for _, enc := range strings.Split(r.Header.Get("Accept-Encoding"), ",") {
+ switch strings.TrimSpace(enc) {
+ case "gzip":
+ w.Header().Set("Content-Encoding", "gzip")
+ w.Header().Add("Vary", "Accept-Encoding")
+
+ gw := gzip.NewWriter(w)
+ defer gw.Close()
+
+ h, hok := w.(http.Hijacker)
+ if !hok { /* w is not Hijacker... oh well... */
+ h = nil
+ }
+
+ w = &compressResponseWriter{
+ Writer: gw,
+ ResponseWriter: w,
+ Hijacker: h,
+ }
+
+ break L
+ case "deflate":
+ w.Header().Set("Content-Encoding", "deflate")
+ w.Header().Add("Vary", "Accept-Encoding")
+
+ fw, _ := flate.NewWriter(w, flate.DefaultCompression)
+ defer fw.Close()
+
+ h, hok := w.(http.Hijacker)
+ if !hok { /* w is not Hijacker... oh well... */
+ h = nil
+ }
+
+ w = &compressResponseWriter{
+ Writer: fw,
+ ResponseWriter: w,
+ Hijacker: h,
+ }
+
+ break L
+ }
+ }
+
+ h.ServeHTTP(w, r)
+ })
+}
diff --git a/vendor/github.com/gorilla/handlers/doc.go b/vendor/github.com/gorilla/handlers/doc.go
new file mode 100644
index 000000000..944e5a8ae
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/doc.go
@@ -0,0 +1,9 @@
+/*
+Package handlers is a collection of handlers (aka "HTTP middleware") for use
+with Go's net/http package (or any framework supporting http.Handler).
+
+The package includes handlers for logging in standardised formats, compressing
+HTTP responses, validating content types and other useful tools for manipulating
+requests and responses.
+*/
+package handlers
diff --git a/vendor/github.com/gorilla/handlers/handlers.go b/vendor/github.com/gorilla/handlers/handlers.go
new file mode 100644
index 000000000..c3c20e5b9
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/handlers.go
@@ -0,0 +1,378 @@
+// Copyright 2013 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package handlers
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+// MethodHandler is an http.Handler that dispatches to a handler whose key in the MethodHandler's
+// map matches the name of the HTTP request's method, eg: GET
+//
+// If the request's method is OPTIONS and OPTIONS is not a key in the map then the handler
+// responds with a status of 200 and sets the Allow header to a comma-separated list of
+// available methods.
+//
+// If the request's method doesn't match any of its keys the handler responds with
+// a status of 405, Method not allowed and sets the Allow header to a comma-separated list
+// of available methods.
+type MethodHandler map[string]http.Handler
+
+func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ if handler, ok := h[req.Method]; ok {
+ handler.ServeHTTP(w, req)
+ } else {
+ allow := []string{}
+ for k := range h {
+ allow = append(allow, k)
+ }
+ sort.Strings(allow)
+ w.Header().Set("Allow", strings.Join(allow, ", "))
+ if req.Method == "OPTIONS" {
+ w.WriteHeader(http.StatusOK)
+ } else {
+ http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+ }
+ }
+}
+
+// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
+type loggingHandler struct {
+ writer io.Writer
+ handler http.Handler
+}
+
+// combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
+type combinedLoggingHandler struct {
+ writer io.Writer
+ handler http.Handler
+}
+
+func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ t := time.Now()
+ logger := makeLogger(w)
+ url := *req.URL
+ h.handler.ServeHTTP(logger, req)
+ writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
+}
+
+func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ t := time.Now()
+ logger := makeLogger(w)
+ url := *req.URL
+ h.handler.ServeHTTP(logger, req)
+ writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
+}
+
+func makeLogger(w http.ResponseWriter) loggingResponseWriter {
+ var logger loggingResponseWriter = &responseLogger{w: w}
+ if _, ok := w.(http.Hijacker); ok {
+ logger = &hijackLogger{responseLogger{w: w}}
+ }
+ h, ok1 := logger.(http.Hijacker)
+ c, ok2 := w.(http.CloseNotifier)
+ if ok1 && ok2 {
+ return hijackCloseNotifier{logger, h, c}
+ }
+ if ok2 {
+ return &closeNotifyWriter{logger, c}
+ }
+ return logger
+}
+
+type loggingResponseWriter interface {
+ http.ResponseWriter
+ http.Flusher
+ Status() int
+ Size() int
+}
+
+// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP status
+// code and body size
+type responseLogger struct {
+ w http.ResponseWriter
+ status int
+ size int
+}
+
+func (l *responseLogger) Header() http.Header {
+ return l.w.Header()
+}
+
+func (l *responseLogger) Write(b []byte) (int, error) {
+ if l.status == 0 {
+ // The status will be StatusOK if WriteHeader has not been called yet
+ l.status = http.StatusOK
+ }
+ size, err := l.w.Write(b)
+ l.size += size
+ return size, err
+}
+
+func (l *responseLogger) WriteHeader(s int) {
+ l.w.WriteHeader(s)
+ l.status = s
+}
+
+func (l *responseLogger) Status() int {
+ return l.status
+}
+
+func (l *responseLogger) Size() int {
+ return l.size
+}
+
+func (l *responseLogger) Flush() {
+ f, ok := l.w.(http.Flusher)
+ if ok {
+ f.Flush()
+ }
+}
+
+type hijackLogger struct {
+ responseLogger
+}
+
+func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ h := l.responseLogger.w.(http.Hijacker)
+ conn, rw, err := h.Hijack()
+ if err == nil && l.responseLogger.status == 0 {
+ // The status will be StatusSwitchingProtocols if there was no error and WriteHeader has not been called yet
+ l.responseLogger.status = http.StatusSwitchingProtocols
+ }
+ return conn, rw, err
+}
+
+type closeNotifyWriter struct {
+ loggingResponseWriter
+ http.CloseNotifier
+}
+
+type hijackCloseNotifier struct {
+ loggingResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+}
+
+const lowerhex = "0123456789abcdef"
+
+func appendQuoted(buf []byte, s string) []byte {
+ var runeTmp [utf8.UTFMax]byte
+ for width := 0; len(s) > 0; s = s[width:] {
+ r := rune(s[0])
+ width = 1
+ if r >= utf8.RuneSelf {
+ r, width = utf8.DecodeRuneInString(s)
+ }
+ if width == 1 && r == utf8.RuneError {
+ buf = append(buf, `\x`...)
+ buf = append(buf, lowerhex[s[0]>>4])
+ buf = append(buf, lowerhex[s[0]&0xF])
+ continue
+ }
+ if r == rune('"') || r == '\\' { // always backslashed
+ buf = append(buf, '\\')
+ buf = append(buf, byte(r))
+ continue
+ }
+ if strconv.IsPrint(r) {
+ n := utf8.EncodeRune(runeTmp[:], r)
+ buf = append(buf, runeTmp[:n]...)
+ continue
+ }
+ switch r {
+ case '\a':
+ buf = append(buf, `\a`...)
+ case '\b':
+ buf = append(buf, `\b`...)
+ case '\f':
+ buf = append(buf, `\f`...)
+ case '\n':
+ buf = append(buf, `\n`...)
+ case '\r':
+ buf = append(buf, `\r`...)
+ case '\t':
+ buf = append(buf, `\t`...)
+ case '\v':
+ buf = append(buf, `\v`...)
+ default:
+ switch {
+ case r < ' ':
+ buf = append(buf, `\x`...)
+ buf = append(buf, lowerhex[s[0]>>4])
+ buf = append(buf, lowerhex[s[0]&0xF])
+ case r > utf8.MaxRune:
+ r = 0xFFFD
+ fallthrough
+ case r < 0x10000:
+ buf = append(buf, `\u`...)
+ for s := 12; s >= 0; s -= 4 {
+ buf = append(buf, lowerhex[r>>uint(s)&0xF])
+ }
+ default:
+ buf = append(buf, `\U`...)
+ for s := 28; s >= 0; s -= 4 {
+ buf = append(buf, lowerhex[r>>uint(s)&0xF])
+ }
+ }
+ }
+ }
+ return buf
+
+}
+
+// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
+ username := "-"
+ if url.User != nil {
+ if name := url.User.Username(); name != "" {
+ username = name
+ }
+ }
+
+ host, _, err := net.SplitHostPort(req.RemoteAddr)
+
+ if err != nil {
+ host = req.RemoteAddr
+ }
+
+ uri := url.RequestURI()
+
+ buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
+ buf = append(buf, host...)
+ buf = append(buf, " - "...)
+ buf = append(buf, username...)
+ buf = append(buf, " ["...)
+ buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
+ buf = append(buf, `] "`...)
+ buf = append(buf, req.Method...)
+ buf = append(buf, " "...)
+ buf = appendQuoted(buf, uri)
+ buf = append(buf, " "...)
+ buf = append(buf, req.Proto...)
+ buf = append(buf, `" `...)
+ buf = append(buf, strconv.Itoa(status)...)
+ buf = append(buf, " "...)
+ buf = append(buf, strconv.Itoa(size)...)
+ return buf
+}
+
+// writeLog writes a log entry for req to w in Apache Common Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
+ buf := buildCommonLogLine(req, url, ts, status, size)
+ buf = append(buf, '\n')
+ w.Write(buf)
+}
+
+// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
+ buf := buildCommonLogLine(req, url, ts, status, size)
+ buf = append(buf, ` "`...)
+ buf = appendQuoted(buf, req.Referer())
+ buf = append(buf, `" "`...)
+ buf = appendQuoted(buf, req.UserAgent())
+ buf = append(buf, '"', '\n')
+ w.Write(buf)
+}
+
+// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
+// Apache Combined Log Format.
+//
+// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
+//
+// LoggingHandler always sets the ident field of the log to -
+func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
+ return combinedLoggingHandler{out, h}
+}
+
+// LoggingHandler return a http.Handler that wraps h and logs requests to out in
+// Apache Common Log Format (CLF).
+//
+// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
+//
+// LoggingHandler always sets the ident field of the log to -
+func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
+ return loggingHandler{out, h}
+}
+
+// isContentType validates the Content-Type header
+// is contentType. That is, its type and subtype match.
+func isContentType(h http.Header, contentType string) bool {
+ ct := h.Get("Content-Type")
+ if i := strings.IndexRune(ct, ';'); i != -1 {
+ ct = ct[0:i]
+ }
+ return ct == contentType
+}
+
+// ContentTypeHandler wraps and returns a http.Handler, validating the request content type
+// is acompatible with the contentTypes list.
+// It writes a HTTP 415 error if that fails.
+//
+// Only PUT, POST, and PATCH requests are considered.
+func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if !(r.Method == "PUT" || r.Method == "POST" || r.Method == "PATCH") {
+ h.ServeHTTP(w, r)
+ return
+ }
+
+ for _, ct := range contentTypes {
+ if isContentType(r.Header, ct) {
+ h.ServeHTTP(w, r)
+ return
+ }
+ }
+ http.Error(w, fmt.Sprintf("Unsupported content type %q; expected one of %q", r.Header.Get("Content-Type"), contentTypes), http.StatusUnsupportedMediaType)
+ })
+}
+
+const (
+ // HTTPMethodOverrideHeader is a commonly used
+ // http header to override a request method.
+ HTTPMethodOverrideHeader = "X-HTTP-Method-Override"
+ // HTTPMethodOverrideFormKey is a commonly used
+ // HTML form key to override a request method.
+ HTTPMethodOverrideFormKey = "_method"
+)
+
+// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for the X-HTTP-Method-Override header
+// or the _method form key, and overrides (if valid) request.Method with its value.
+//
+// This is especially useful for http clients that don't support many http verbs.
+// It isn't secure to override e.g a GET to a POST, so only POST requests are considered.
+// Likewise, the override method can only be a "write" method: PUT, PATCH or DELETE.
+//
+// Form method takes precedence over header method.
+func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "POST" {
+ om := r.FormValue(HTTPMethodOverrideFormKey)
+ if om == "" {
+ om = r.Header.Get(HTTPMethodOverrideHeader)
+ }
+ if om == "PUT" || om == "PATCH" || om == "DELETE" {
+ r.Method = om
+ }
+ }
+ h.ServeHTTP(w, r)
+ })
+}
diff --git a/vendor/github.com/gorilla/handlers/proxy_headers.go b/vendor/github.com/gorilla/handlers/proxy_headers.go
new file mode 100644
index 000000000..268de9c6a
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/proxy_headers.go
@@ -0,0 +1,113 @@
+package handlers
+
+import (
+ "net/http"
+ "regexp"
+ "strings"
+)
+
+var (
+ // De-facto standard header keys.
+ xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For")
+ xRealIP = http.CanonicalHeaderKey("X-Real-IP")
+ xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Scheme")
+)
+
+var (
+ // RFC7239 defines a new "Forwarded: " header designed to replace the
+ // existing use of X-Forwarded-* headers.
+ // e.g. Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43
+ forwarded = http.CanonicalHeaderKey("Forwarded")
+ // Allows for a sub-match of the first value after 'for=' to the next
+ // comma, semi-colon or space. The match is case-insensitive.
+ forRegex = regexp.MustCompile(`(?i)(?:for=)([^(;|,| )]+)`)
+ // Allows for a sub-match for the first instance of scheme (http|https)
+ // prefixed by 'proto='. The match is case-insensitive.
+ protoRegex = regexp.MustCompile(`(?i)(?:proto=)(https|http)`)
+)
+
+// ProxyHeaders inspects common reverse proxy headers and sets the corresponding
+// fields in the HTTP request struct. These are X-Forwarded-For and X-Real-IP
+// for the remote (client) IP address, X-Forwarded-Proto for the scheme
+// (http|https) and the RFC7239 Forwarded header, which may include both client
+// IPs and schemes.
+//
+// NOTE: This middleware should only be used when behind a reverse
+// proxy like nginx, HAProxy or Apache. Reverse proxies that don't (or are
+// configured not to) strip these headers from client requests, or where these
+// headers are accepted "as is" from a remote client (e.g. when Go is not behind
+// a proxy), can manifest as a vulnerability if your application uses these
+// headers for validating the 'trustworthiness' of a request.
+func ProxyHeaders(h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ // Set the remote IP with the value passed from the proxy.
+ if fwd := getIP(r); fwd != "" {
+ r.RemoteAddr = fwd
+ }
+
+ // Set the scheme (proto) with the value passed from the proxy.
+ if scheme := getScheme(r); scheme != "" {
+ r.URL.Scheme = scheme
+ }
+
+ // Call the next handler in the chain.
+ h.ServeHTTP(w, r)
+ }
+
+ return http.HandlerFunc(fn)
+}
+
+// getIP retrieves the IP from the X-Forwarded-For, X-Real-IP and RFC7239
+// Forwarded headers (in that order).
+func getIP(r *http.Request) string {
+ var addr string
+
+ if fwd := r.Header.Get(xForwardedFor); fwd != "" {
+ // Only grab the first (client) address. Note that '192.168.0.1,
+ // 10.1.1.1' is a valid key for X-Forwarded-For where addresses after
+ // the first may represent forwarding proxies earlier in the chain.
+ s := strings.Index(fwd, ", ")
+ if s == -1 {
+ s = len(fwd)
+ }
+ addr = fwd[:s]
+ } else if fwd := r.Header.Get(xRealIP); fwd != "" {
+ // X-Real-IP should only contain one IP address (the client making the
+ // request).
+ addr = fwd
+ } else if fwd := r.Header.Get(forwarded); fwd != "" {
+ // match should contain at least two elements if the protocol was
+ // specified in the Forwarded header. The first element will always be
+ // the 'for=' capture, which we ignore. In the case of multiple IP
+ // addresses (for=8.8.8.8, 8.8.4.4,172.16.1.20 is valid) we only
+ // extract the first, which should be the client IP.
+ if match := forRegex.FindStringSubmatch(fwd); len(match) > 1 {
+ // IPv6 addresses in Forwarded headers are quoted-strings. We strip
+ // these quotes.
+ addr = strings.Trim(match[1], `"`)
+ }
+ }
+
+ return addr
+}
+
+// getScheme retrieves the scheme from the X-Forwarded-Proto and RFC7239
+// Forwarded headers (in that order).
+func getScheme(r *http.Request) string {
+ var scheme string
+
+ // Retrieve the scheme from X-Forwarded-Proto.
+ if proto := r.Header.Get(xForwardedProto); proto != "" {
+ scheme = strings.ToLower(proto)
+ } else if proto := r.Header.Get(forwarded); proto != "" {
+ // match should contain at least two elements if the protocol was
+ // specified in the Forwarded header. The first element will always be
+ // the 'proto=' capture, which we ignore. In the case of multiple proto
+ // parameters (invalid) we only extract the first.
+ if match := protoRegex.FindStringSubmatch(proto); len(match) > 1 {
+ scheme = strings.ToLower(match[1])
+ }
+ }
+
+ return scheme
+}
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
index 9ffd77afa..0eedcaa78 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
@@ -38,6 +38,8 @@ var (
// CategoryRange allows the upper bound on the category range to be adjusted
CategoryRange = DefaultCategoryRange
+
+ privContainerMountLabel string
)
// Context is a representation of the SELinux label broken into 4 parts
@@ -280,5 +282,7 @@ func GetDefaultContextWithLevel(user, level, scon string) (string, error) {
// PrivContainerMountLabel returns mount label for privileged containers
func PrivContainerMountLabel() string {
+ // Make sure label is initialized.
+ _ = label("")
return privContainerMountLabel
}
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
index a804473e4..295b2bc4e 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
@@ -12,7 +12,6 @@ import (
"os"
"path"
"path/filepath"
- "regexp"
"strconv"
"strings"
"sync"
@@ -34,8 +33,6 @@ const (
xattrNameSelinux = "security.selinux"
)
-var policyRoot = filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
-
type selinuxState struct {
enabledSet bool
enabled bool
@@ -70,7 +67,6 @@ const (
)
var (
- assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`)
readOnlyFileLabel string
state = selinuxState{
mcsList: make(map[string]bool),
@@ -79,8 +75,24 @@ var (
// for attrPath()
attrPathOnce sync.Once
haveThreadSelf bool
+
+ // for policyRoot()
+ policyRootOnce sync.Once
+ policyRootVal string
+
+ // for label()
+ loadLabelsOnce sync.Once
+ labels map[string]string
)
+func policyRoot() string {
+ policyRootOnce.Do(func() {
+ policyRootVal = filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
+ })
+
+ return policyRootVal
+}
+
func (s *selinuxState) setEnable(enabled bool) bool {
s.Lock()
defer s.Unlock()
@@ -222,7 +234,7 @@ func readConfig(target string) string {
scanner := bufio.NewScanner(in)
for scanner.Scan() {
- line := strings.TrimSpace(scanner.Text())
+ line := bytes.TrimSpace(scanner.Bytes())
if len(line) == 0 {
// Skip blank lines
continue
@@ -231,11 +243,12 @@ func readConfig(target string) string {
// Skip comments
continue
}
- if groups := assignRegex.FindStringSubmatch(line); groups != nil {
- key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
- if key == target {
- return strings.Trim(val, "\"")
- }
+ fields := bytes.SplitN(line, []byte{'='}, 2)
+ if len(fields) != 2 {
+ continue
+ }
+ if bytes.Equal(fields[0], []byte(target)) {
+ return string(bytes.Trim(fields[1], `"`))
}
}
return ""
@@ -274,12 +287,15 @@ func readCon(fpath string) (string, error) {
if err := isProcHandle(in); err != nil {
return "", err
}
+ return readConFd(in)
+}
- var retval string
- if _, err := fmt.Fscanf(in, "%s", &retval); err != nil {
+func readConFd(in *os.File) (string, error) {
+ data, err := ioutil.ReadAll(in)
+ if err != nil {
return "", err
}
- return strings.Trim(retval, "\x00"), nil
+ return string(bytes.TrimSuffix(data, []byte{0})), nil
}
// classIndex returns the int index for an object class in the loaded policy,
@@ -389,7 +405,7 @@ func writeCon(fpath, val string) error {
_, err = out.Write(nil)
}
if err != nil {
- return &os.PathError{Op: "write", Path: fpath, Err: err}
+ return err
}
return nil
}
@@ -664,11 +680,7 @@ func readWriteCon(fpath string, val string) (string, error) {
return "", err
}
- var retval string
- if _, err := fmt.Fscanf(f, "%s", &retval); err != nil {
- return "", err
- }
- return strings.Trim(retval, "\x00"), nil
+ return readConFd(f)
}
// setExecLabel sets the SELinux label that the kernel will use for any programs
@@ -723,10 +735,10 @@ func keyLabel() (string, error) {
// get returns the Context as a string
func (c Context) get() string {
- if c["level"] != "" {
- return fmt.Sprintf("%s:%s:%s:%s", c["user"], c["role"], c["type"], c["level"])
+ if level := c["level"]; level != "" {
+ return c["user"] + ":" + c["role"] + ":" + c["type"] + ":" + level
}
- return fmt.Sprintf("%s:%s:%s", c["user"], c["role"], c["type"])
+ return c["user"] + ":" + c["role"] + ":" + c["type"]
}
// newContext creates a new Context struct from the specified label
@@ -891,24 +903,21 @@ func openContextFile() (*os.File, error) {
if f, err := os.Open(contextFile); err == nil {
return f, nil
}
- lxcPath := filepath.Join(policyRoot, "/contexts/lxc_contexts")
- return os.Open(lxcPath)
+ return os.Open(filepath.Join(policyRoot(), "/contexts/lxc_contexts"))
}
-var labels, privContainerMountLabel = loadLabels()
-
-func loadLabels() (map[string]string, string) {
- labels := make(map[string]string)
+func loadLabels() {
+ labels = make(map[string]string)
in, err := openContextFile()
if err != nil {
- return labels, ""
+ return
}
defer in.Close()
scanner := bufio.NewScanner(in)
for scanner.Scan() {
- line := strings.TrimSpace(scanner.Text())
+ line := bytes.TrimSpace(scanner.Bytes())
if len(line) == 0 {
// Skip blank lines
continue
@@ -917,38 +926,47 @@ func loadLabels() (map[string]string, string) {
// Skip comments
continue
}
- if groups := assignRegex.FindStringSubmatch(line); groups != nil {
- key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
- labels[key] = strings.Trim(val, "\"")
+ fields := bytes.SplitN(line, []byte{'='}, 2)
+ if len(fields) != 2 {
+ continue
}
+ key, val := bytes.TrimSpace(fields[0]), bytes.TrimSpace(fields[1])
+ labels[string(key)] = string(bytes.Trim(val, `"`))
}
con, _ := NewContext(labels["file"])
con["level"] = fmt.Sprintf("s0:c%d,c%d", maxCategory-2, maxCategory-1)
- reserveLabel(con.get())
- return labels, con.get()
+ privContainerMountLabel = con.get()
+ reserveLabel(privContainerMountLabel)
+}
+
+func label(key string) string {
+ loadLabelsOnce.Do(func() {
+ loadLabels()
+ })
+ return labels[key]
}
// kvmContainerLabels returns the default processLabel and mountLabel to be used
// for kvm containers by the calling process.
func kvmContainerLabels() (string, string) {
- processLabel := labels["kvm_process"]
+ processLabel := label("kvm_process")
if processLabel == "" {
- processLabel = labels["process"]
+ processLabel = label("process")
}
- return addMcs(processLabel, labels["file"])
+ return addMcs(processLabel, label("file"))
}
// initContainerLabels returns the default processLabel and file labels to be
// used for containers running an init system like systemd by the calling process.
func initContainerLabels() (string, string) {
- processLabel := labels["init_process"]
+ processLabel := label("init_process")
if processLabel == "" {
- processLabel = labels["process"]
+ processLabel = label("process")
}
- return addMcs(processLabel, labels["file"])
+ return addMcs(processLabel, label("file"))
}
// containerLabels returns an allocated processLabel and fileLabel to be used for
@@ -958,9 +976,9 @@ func containerLabels() (processLabel string, fileLabel string) {
return "", ""
}
- processLabel = labels["process"]
- fileLabel = labels["file"]
- readOnlyFileLabel = labels["ro_file"]
+ processLabel = label("process")
+ fileLabel = label("file")
+ readOnlyFileLabel = label("ro_file")
if processLabel == "" || fileLabel == "" {
return "", fileLabel
@@ -1180,15 +1198,14 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
}
func getDefaultContextWithLevel(user, level, scon string) (string, error) {
- userPath := filepath.Join(policyRoot, selinuxUsersDir, user)
- defaultPath := filepath.Join(policyRoot, defaultContexts)
-
+ userPath := filepath.Join(policyRoot(), selinuxUsersDir, user)
fu, err := os.Open(userPath)
if err != nil {
return "", err
}
defer fu.Close()
+ defaultPath := filepath.Join(policyRoot(), defaultContexts)
fd, err := os.Open(defaultPath)
if err != nil {
return "", err
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
index b7218a0b6..42657759c 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
@@ -2,8 +2,6 @@
package selinux
-const privContainerMountLabel = ""
-
func setDisabled() {
}
@@ -152,3 +150,7 @@ func disableSecOpt() []string {
func getDefaultContextWithLevel(user, level, scon string) (string, error) {
return "", nil
}
+
+func label(_ string) string {
+ return ""
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 2e23df953..26a390863 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -191,7 +191,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7
github.com/containers/ocicrypt/spec
github.com/containers/ocicrypt/utils
github.com/containers/ocicrypt/utils/keyprovider
-# github.com/containers/psgo v1.5.2
+# github.com/containers/psgo v1.6.0
github.com/containers/psgo
github.com/containers/psgo/internal/capabilities
github.com/containers/psgo/internal/cgroups
@@ -348,7 +348,7 @@ github.com/ghodss/yaml
github.com/go-logr/logr
# github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
github.com/go-task/slim-sprig
-# github.com/godbus/dbus/v5 v5.0.4
+# github.com/godbus/dbus/v5 v5.0.5
github.com/godbus/dbus/v5
# github.com/gogo/protobuf v1.3.2
github.com/gogo/protobuf/gogoproto
@@ -379,6 +379,8 @@ github.com/google/gofuzz
github.com/google/shlex
# github.com/google/uuid v1.3.0
github.com/google/uuid
+# github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33
+github.com/gorilla/handlers
# github.com/gorilla/mux v1.8.0
github.com/gorilla/mux
# github.com/gorilla/schema v1.2.0
@@ -524,7 +526,7 @@ github.com/opencontainers/runtime-tools/generate
github.com/opencontainers/runtime-tools/generate/seccomp
github.com/opencontainers/runtime-tools/specerror
github.com/opencontainers/runtime-tools/validate
-# github.com/opencontainers/selinux v1.8.4
+# github.com/opencontainers/selinux v1.8.5
github.com/opencontainers/selinux/go-selinux
github.com/opencontainers/selinux/go-selinux/label
github.com/opencontainers/selinux/pkg/pwalk