summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.golangci.yml11
-rw-r--r--Makefile2
-rw-r--r--RELEASE_NOTES.md32
-rw-r--r--changelog.txt164
-rw-r--r--cmd/podman/commands_remoteclient.go6
-rw-r--r--cmd/podman/main.go4
-rw-r--r--cmd/podman/service.go10
-rw-r--r--cmd/podman/service_dummy.go1
-rw-r--r--cmd/podman/varlink.go2
-rw-r--r--cmd/podman/varlink_dummy.go1
-rw-r--r--cmd/podmanV2/Makefile12
-rw-r--r--cmd/podmanV2/containers/cleanup.go75
-rw-r--r--cmd/podmanV2/containers/init.go60
-rw-r--r--cmd/podmanV2/containers/kill.go7
-rw-r--r--cmd/podmanV2/containers/logs.go108
-rw-r--r--cmd/podmanV2/containers/ps.go146
-rw-r--r--cmd/podmanV2/containers/run.go37
-rw-r--r--cmd/podmanV2/containers/wait.go7
-rw-r--r--cmd/podmanV2/images/history.go48
-rw-r--r--cmd/podmanV2/images/list.go50
-rw-r--r--cmd/podmanV2/images/load.go42
-rw-r--r--cmd/podmanV2/images/tag.go11
-rw-r--r--cmd/podmanV2/pods/create.go15
-rw-r--r--cmd/podmanV2/pods/pod.go30
-rw-r--r--cmd/podmanV2/pods/ps.go83
-rw-r--r--cmd/podmanV2/registry/registry.go6
-rw-r--r--cmd/podmanV2/report/templates.go73
-rw-r--r--cmd/podmanV2/system/service.go124
-rw-r--r--cmd/podmanV2/system/system.go8
-rw-r--r--cmd/podmanV2/system/varlink.go56
-rw-r--r--cmd/podmanV2/system/version.go6
-rw-r--r--contrib/spec/podman.spec.in2
-rw-r--r--go.mod2
-rw-r--r--go.sum13
-rwxr-xr-xhack/golangci-lint.sh15
-rw-r--r--pkg/adapter/client.go10
-rw-r--r--pkg/adapter/containers_remote.go28
-rw-r--r--pkg/adapter/pods_remote.go4
-rw-r--r--pkg/adapter/runtime_remote.go17
-rw-r--r--pkg/api/handlers/compat/containers.go1
-rw-r--r--pkg/api/handlers/compat/events.go19
-rw-r--r--pkg/api/handlers/libpod/containers.go20
-rw-r--r--pkg/api/server/handler_api.go9
-rw-r--r--pkg/api/server/register_containers.go26
-rw-r--r--pkg/api/server/server.go175
-rw-r--r--pkg/bindings/containers/containers.go19
-rw-r--r--pkg/bindings/test/containers_test.go21
-rw-r--r--pkg/domain/entities/container_ps.go171
-rw-r--r--pkg/domain/entities/containers.go52
-rw-r--r--pkg/domain/entities/engine_container.go10
-rw-r--r--pkg/domain/entities/pods.go5
-rw-r--r--pkg/domain/entities/system.go14
-rw-r--r--pkg/domain/infra/abi/containers.go99
-rw-r--r--pkg/domain/infra/abi/images.go14
-rw-r--r--pkg/domain/infra/abi/system.go77
-rw-r--r--pkg/domain/infra/tunnel/containers.go29
-rw-r--r--pkg/domain/infra/tunnel/helpers.go2
-rw-r--r--pkg/domain/infra/tunnel/system.go10
-rw-r--r--pkg/ps/ps.go34
-rw-r--r--pkg/rootless/rootless_linux.c5
-rw-r--r--pkg/signal/signal_linux.go7
-rw-r--r--pkg/specgen/pod_validate.go2
-rw-r--r--pkg/varlinkapi/attach.go2
-rw-r--r--pkg/varlinkapi/config.go9
-rw-r--r--pkg/varlinkapi/containers.go72
-rw-r--r--pkg/varlinkapi/containers_create.go2
-rw-r--r--pkg/varlinkapi/events.go7
-rw-r--r--pkg/varlinkapi/generate.go2
-rw-r--r--pkg/varlinkapi/images.go86
-rw-r--r--pkg/varlinkapi/mount.go6
-rw-r--r--pkg/varlinkapi/pods.go32
-rw-r--r--pkg/varlinkapi/system.go6
-rw-r--r--pkg/varlinkapi/transfers.go7
-rw-r--r--pkg/varlinkapi/volumes.go10
-rw-r--r--test/apiv2/20-containers.at4
-rw-r--r--test/e2e/common_test.go4
-rw-r--r--test/e2e/exec_test.go12
-rw-r--r--test/e2e/libpod_suite_remoteclient_test.go6
-rw-r--r--test/e2e/libpod_suite_test.go8
-rw-r--r--test/system/120-load.bats4
-rw-r--r--test/utils/podmantest_test.go2
-rw-r--r--test/utils/utils.go6
-rw-r--r--vendor/github.com/containers/buildah/CHANGELOG.md8
-rw-r--r--vendor/github.com/containers/buildah/Makefile7
-rw-r--r--vendor/github.com/containers/buildah/buildah.go2
-rw-r--r--vendor/github.com/containers/buildah/changelog.txt8
-rw-r--r--vendor/modules.txt2
-rw-r--r--version/version.go2
88 files changed, 1817 insertions, 648 deletions
diff --git a/.golangci.yml b/.golangci.yml
index 8af8aea91..b04683b7b 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,10 +1,5 @@
---
run:
- build-tags:
- - apparmor
- - seccomp
- - selinux
- - ABISupport
concurrency: 6
deadline: 5m
skip-dirs-use-default: true
@@ -12,6 +7,8 @@ run:
- contrib
- dependencies
- test
+ - pkg/varlink
+ - pkg/varlinkapi
skip-files:
- iopodman.go
- swagger.go
@@ -31,3 +28,7 @@ linters:
- misspell
- prealloc
- unparam
+linters-settings:
+ errcheck:
+ check-blank: false
+ ignore: encoding/json:^Unmarshal,fmt:.*
diff --git a/Makefile b/Makefile
index 0797f3908..9121fae1f 100644
--- a/Makefile
+++ b/Makefile
@@ -159,7 +159,7 @@ endif
.PHONY: golangci-lint
golangci-lint: .gopathok varlink_generate .install.golangci-lint
- $(GOBIN)/golangci-lint run
+ hack/golangci-lint.sh run
.PHONY: gofmt
gofmt: ## Verify the source code gofmt
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 6578f40fd..246a4db04 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,7 +1,37 @@
# Release Notes
-## 1.8.2
+## 1.9.0
+### Features
+- Experimental support has been added for `podman run --userns=auto`, which automatically allocates a unique UID and GID range for the new container's user namespace
+- The `podman play kube` command now has a `--network` flag to place the created pod in one or more CNI networks
+- The `podman commit` command now supports an `--iidfile` flag to write the ID of the committed image to a file
+- Initial support for the new `containers.conf` configuration file has been added. `containers.conf` allows for much more detailed configuration of some Podman functionality
+
+### Changes
+- There has been a major cleanup of the `podman info` command resulting in breaking changes. Many fields have been renamed to better suit usage with APIv2
+- All uses of the `--timeout` flag have been switched to prefer the alternative `--time`. The `--timeout` flag will continue to work, but man pages and `--help` will use the `--time` flag instead
+
+### Bugfixes
+- Fixed a bug where some volume mounts from the host would sometimes not properly determine the flags they should use when mounting
+- Fixed a bug where Podman was not propagating `$PATH` to Conmon and the OCI runtime, causing issues for some OCI runtimes that required it
+- Fixed a bug where rootless Podman would print error messages about missing support for systemd cgroups when run in a container with no cgroup support ([#5488](https://github.com/containers/libpod/issues/5488))
+- Fixed a bug where `podman play kube` would not properly handle container-only port mappings ([#5610](https://github.com/containers/libpod/issues/5610))
+- Fixed a bug where the `podman container prune` command was not pruning containers in the `created` and `configured` states
+- Fixed a bug where Podman was not properly removing CNI IP address allocations after a reboot ([#5433](https://github.com/containers/libpod/issues/5433))
+### HTTP API
+- Many Libpod API endpoints have been added, including `Changes`, `Checkpoint`, and `Restore`
+- Stability overall has greatly improved as we prepare the API for a beta release soon with Podman 2.0
+
+### Misc
+- The default infra image for pods has been upgraded to `k8s.gcr.io/pause:3.2` (from 3.1) to address a bug in the architecture metadata for non-AMD64 images
+- The `slirp4netns` networking utility in rootless Podman now uses Seccomp filtering where available for improved security
+- Updated Buildah to v1.14.8
+- Updated containers/storage to v1.18.2
+- Updated containers/image to v5.4.3
+- Updated containers/common to v0.8.1
+
+## 1.8.2
### Features
- Initial support for automatically updating containers managed via Systemd unit files has been merged. This allows containers to automatically upgrade if a newer version of their image becomes available
diff --git a/changelog.txt b/changelog.txt
index 1e08a8419..cf49971a0 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,167 @@
+- Changelog for v1.9.0-rc1 (2020-04-13)
+ * build(deps): bump github.com/containers/buildah from 1.14.7 to 1.14.8
+ * Update release notes for v1.9.0-RC1
+ * v2podman container cleanup
+ * podmanV2: implement logs
+ * test: enable preserve fds test for crun
+ * test: fix exec preserve-fds test
+ * Set exit codes on errors.
+ * Run (make vendor)
+ * Fix (make vendor)
+ * update the latest version to 1.8.2
+ * add tests for kill and exists
+ * v2podman ps alter formats
+ * run/create were processing options after the image name
+ * V2 podman system service
+ * man page: add note about issue with SELinux
+ * Bump Buildah to v1.14.7
+ * Bump containers/image to v5.4.3
+ * V2 podman diff(changes) support
+ * podman info needs to be run within the user namespace
+ * podmanv2 images user format
+ * podmanv2 info
+ * vendor c/image v5.4.2
+ * Do not error on pids.current stats if ctr.path is empty
+ * fix rootless login/logout tests
+ * v2podman run
+ * refactor info
+ * podmanv2 ps
+ * userns: support --userns=auto
+ * podmanv2 start
+ * build(deps): bump github.com/containers/common from 0.8.0 to 0.8.1
+ * build(deps): bump github.com/containers/storage from 1.18.1 to 1.18.2
+ * build(deps): bump github.com/opencontainers/selinux from 1.4.0 to 1.5.0
+ * v2podman attach and exec
+ * v2podman container create
+ * Cleanup whether to enter user namespace for rootless commands
+ * podmanv2 save image
+ * podmanv2 version
+ * checkpoint: handle XDG_RUNTIME_DIR
+ * checkpoint: change runtime checkpoint support test
+ * Pass path environment down to the OCI runtime
+ * podmanv2 checkpoint and restore
+ * Bump github.com/containers/common from 0.6.1 to 0.8.0
+ * test/e2e/run_volume_test: use unique mount point
+ * test/e2e/run_volume_test.go: mv dockerfile decl
+ * test/e2e/run_volume_test: only create dir once
+ * Fix environment handling from containers.conf
+ * podmanV2: implement push
+ * pkg/spec.InitFSMounts: optimize
+ * utils: delete dead code
+ * attach: skip shutdown on errors
+ * attach: fix hang if control path is deleted
+ * pkg/spec.InitFSMounts: fix mount opts in place
+ * podmanv2 export
+ * podmanv2 import
+ * podmanv2-retry - new helper for testing v2
+ * podmanv2 load
+ * podmanv2 pod inspect
+ * V2 podman inspect
+ * Fix repos for CentOS 7 RPM build
+ * podman v2 image tag and untag
+ * podmanv2 pod ps
+ * Touch up mailing list address in README.md
+ * add systemd build tag to podman builds
+ * Bump github.com/rootless-containers/rootlesskit from 0.9.2 to 0.9.3
+ * Switch to using --time as opposed to --timeout to better match Docker.
+ * podmanV2: implement pull
+ * pkg/spec/initFSMounts: fix
+ * Cirrus: Remove darwin/windows builds in gate-job
+ * Cirrus: Update VM Images
+ * Cirrus: Minor docs update
+ * Revert "Default CPUShares in Inspect are 1024"
+ * fix more swagger inconsistencies
+ * V2 Move varlink home
+ * Bump github.com/containers/conmon
+ * Bump github.com/spf13/cobra from 0.0.6 to 0.0.7
+ * rootless: make cgroup ownership detection not fatal
+ * podmanv2 enable healthcheck run
+ * Update vendor of boltdb and containers/image
+ * swagger: top: remove "Docker" from the identifiers
+ * podmanv2: implement pod top
+ * v2 api: implement pods top endpoint
+ * podmanv2 commit
+ * Bump to buildah v1.14.5
+ * Add support for containers.conf
+ * API v2 tests: usability improvements
+ * Sanitize port parsing for pods in play kube
+ * podmanv2 pod create using podspecgen
+ * use `pause:3.2` image for infra containers
+ * Add support for specifying CNI networks in podman play kube
+ * Fix typo in pod create
+ * podmanV2: implement top
+ * Fix Markdown typo in podman-create.1.md
+ * V2 podman image prune
+ * Support label filters for podman pod ps.
+ * podmanv2 container inspect
+ * podmanv2 pod subcommands
+ * Add bindings for Container Exec Create + Inspect
+ * apiv2 add default network in specgen
+ * slirp: enable seccomp filter
+ * V2 podman image rm | podman rmi [IMAGE]
+ * V2 podman image
+ * podmanv2 add pre-run to each commmand
+ * Ensure that exec sends resize events
+ * enable linting on v2
+ * Bump github.com/rootless-containers/rootlesskit from 0.8.0 to 0.9.2
+ * Bump github.com/containers/storage from 1.16.5 to 1.16.6
+ * V2 podman images/image list
+ * podmanv2 volumes
+ * Combine GlobalFlags and EngineFlags into EngineOptions
+ * Complete podmanV2 history command
+ * rootlessport: use x/sys/unix instead of syscall
+ * podmanv2 exit code
+ * Bump github.com/sirupsen/logrus from 1.4.2 to 1.5.0
+ * Correctly document libpod commit endpoint
+ * Implement APIv2 Exec Create and Inspect Endpoints
+ * apiv2 container commit for libpod
+ * Add image signing with GPG tutorial
+ * podmanv2 add core container commands
+ * Improved readability in image json output
+ * podmanv2 volume create
+ * Add stubs for cmd/podman in non-Linux local mode
+ * Make libpod/lock/shm completely Linux-only
+ * Add stubs for pkg/adapter/terminal_linux.go
+ * Add a stub for libpod.Container.Top
+ * Make cmd/podman/shared.GenerateCommand tests Linux-only
+ * Fix the libpod.LabelVolumePath stub
+ * Only run TestGetImageConfigStopSignal on Linux
+ * Fix the pkg/specgen/SpecGenerator.getSeccompConfig stub
+ * podmanv2 pod exists
+ * when removing networks for tests, force should be used
+ * Add basic structure of a spec generator for pods
+ * [CI:DOCS]fix type issue in pod binding test
+ * podmanv2 enable remote wait
+ * fix remote connection use of context
+ * use boolreport for containerexists response
+ * podmanv2 container exists|wait
+ * Add APIV2 service files
+ * Attempt manual removal of CNI IP allocations on refresh
+ * Implemented --iidfile for podman commit
+ * Add guildline for writing podman V2 CLI commands
+ * Use creds form PullImage remote
+ * Fix docker man page links
+ * Bump to v1.8.3-dev
+ * [CI:DOCS]remove podmanv2 binary
+ * Cirrus: Update VM images
+ * Cirrus-CI: Fix source path of vendor task
+ * Cirrus: Enable future installing buildah packages
+ * Cirrus: Include packages for buildah CI
+ * Cirrus: Update Ubuntu base images
+ * Cirrus: Use opensuse open build Ubuntu packages
+ * Update release notes for v1.8.2 final release
+ * rootlessport: handle SIGPIPE
+ * apiv2 add bindings for logs|events
+ * Bump github.com/containers/common from 0.5.0 to 0.6.1
+ * Add inspect for exec sessions
+ * Add structure for new exec session tracking to DB
+ * Populate ExecSession with all required fields
+ * Fix path of tmp_dir
+ * Cirrus: Disable non-docs release processing
+ * container prune remove state created, configured
+ * Cirrus: Log libseccomp package version
+ * docs: mention that "podman version" prints out Remote API Version
+
- Changelog for v1.8.2 (2020-03-19)
* fix reported compat issues
* Don't include SUBDIR in windows.zip
diff --git a/cmd/podman/commands_remoteclient.go b/cmd/podman/commands_remoteclient.go
index ef523ffb1..11baeb4ae 100644
--- a/cmd/podman/commands_remoteclient.go
+++ b/cmd/podman/commands_remoteclient.go
@@ -14,7 +14,7 @@ func getMainCommands() []*cobra.Command {
}
// commands that only the remoteclient implements
-func getAppCommands() []*cobra.Command {
+func getAppCommands() []*cobra.Command { // nolint:varcheck,deadcode,unused
return []*cobra.Command{}
}
@@ -29,7 +29,7 @@ func getContainerSubCommands() []*cobra.Command {
}
// commands that only the remoteclient implements
-func getGenerateSubCommands() []*cobra.Command {
+func getGenerateSubCommands() []*cobra.Command { // nolint:varcheck,deadcode,unused
return []*cobra.Command{}
}
@@ -126,7 +126,7 @@ func getDefaultPidsDescription() string {
return "Tune container pids limit (set 0 for unlimited, -1 for server defaults)"
}
-func getDefaultShareNetwork() string {
+func getDefaultShareNetwork() string { // nolint:varcheck,deadcode,unused
return ""
}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 5134448da..4435b036e 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -24,8 +24,8 @@ import (
var (
exitCode = define.ExecErrorCodeGeneric
Ctx context.Context
- span opentracing.Span
- closer io.Closer
+ span opentracing.Span // nolint:varcheck,deadcode,unused
+ closer io.Closer // nolint:varcheck,deadcode,unused
)
// Commands that the remote and local client have
diff --git a/cmd/podman/service.go b/cmd/podman/service.go
index bcb37eac5..0280b01a4 100644
--- a/cmd/podman/service.go
+++ b/cmd/podman/service.go
@@ -91,7 +91,7 @@ func resolveApiURI(c *cliconfig.ServiceValues) (string, error) {
if len(c.InputArgs) > 0 {
apiURI = c.InputArgs[0]
- } else if ok := systemd.SocketActivated(); ok {
+ } else if ok := systemd.SocketActivated(); ok { // nolint: gocritic
apiURI = ""
} else if rootless.IsRootless() {
xdg, err := util.GetRuntimeDir()
@@ -155,13 +155,11 @@ func runREST(r *libpod.Runtime, uri string, timeout time.Duration) error {
}
}()
- err = server.Serve()
- logrus.Debugf("%d/%d Active connections/Total connections\n", server.ActiveConnections, server.TotalConnections)
- return err
+ return server.Serve()
}
func runVarlink(r *libpod.Runtime, uri string, timeout time.Duration, c *cliconfig.ServiceValues) error {
- var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(&c.PodmanCommand, r)}
+ var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(c.PodmanCommand.Command, r)}
service, err := varlink.NewService(
"Atomic",
"podman",
@@ -182,7 +180,7 @@ func runVarlink(r *libpod.Runtime, uri string, timeout time.Duration, c *cliconf
if err = service.Listen(uri, timeout); err != nil {
switch err.(type) {
case varlink.ServiceTimeoutError:
- logrus.Infof("varlink service expired (use --timeout to increase session time beyond %d ms, 0 means never timeout)", timeout.String())
+ logrus.Infof("varlink service expired (use --timeout to increase session time beyond %s ms, 0 means never timeout)", timeout.String())
return nil
default:
return errors.Wrapf(err, "unable to start varlink service")
diff --git a/cmd/podman/service_dummy.go b/cmd/podman/service_dummy.go
index a774c34de..a726f21c1 100644
--- a/cmd/podman/service_dummy.go
+++ b/cmd/podman/service_dummy.go
@@ -5,6 +5,7 @@ package main
import "github.com/spf13/cobra"
var (
+ // nolint:varcheck,deadcode,unused
_serviceCommand = &cobra.Command{
Use: "",
}
diff --git a/cmd/podman/varlink.go b/cmd/podman/varlink.go
index 20334ec96..be882d497 100644
--- a/cmd/podman/varlink.go
+++ b/cmd/podman/varlink.go
@@ -85,7 +85,7 @@ func varlinkCmd(c *cliconfig.VarlinkValues) error {
}
defer runtime.DeferredShutdown(false)
- var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(&c.PodmanCommand, runtime)}
+ var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(c.PodmanCommand.Command, runtime)}
// Register varlink service. The metadata can be retrieved with:
// $ varlink info [varlink address URI]
service, err := varlink.NewService(
diff --git a/cmd/podman/varlink_dummy.go b/cmd/podman/varlink_dummy.go
index 430511d72..0c7981f1a 100644
--- a/cmd/podman/varlink_dummy.go
+++ b/cmd/podman/varlink_dummy.go
@@ -5,6 +5,7 @@ package main
import "github.com/spf13/cobra"
var (
+ // nolint:varcheck,deadcode,unused
_varlinkCommand = &cobra.Command{
Use: "",
}
diff --git a/cmd/podmanV2/Makefile b/cmd/podmanV2/Makefile
index b847a9385..01d551212 100644
--- a/cmd/podmanV2/Makefile
+++ b/cmd/podmanV2/Makefile
@@ -1,2 +1,10 @@
-all:
- CGO_ENABLED=1 GO111MODULE=off go build -tags 'ABISupport systemd seccomp'
+all: podman podman-remote
+
+podman:
+ CGO_ENABLED=1 GO111MODULE=off go build -tags 'ABISupport systemd varlink seccomp'
+
+podman-remote:
+ CGO_ENABLED=1 GO111MODULE=off go build -tags '!ABISupport systemd seccomp' -o podmanV2-remote
+
+clean:
+ rm podmanV2 podmanV2-remote
diff --git a/cmd/podmanV2/containers/cleanup.go b/cmd/podmanV2/containers/cleanup.go
new file mode 100644
index 000000000..3f45db160
--- /dev/null
+++ b/cmd/podmanV2/containers/cleanup.go
@@ -0,0 +1,75 @@
+package containers
+
+import (
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podmanV2/parse"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/cmd/podmanV2/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ cleanupDescription = `
+ podman container cleanup
+
+ Cleans up mount points and network stacks on one or more containers from the host. The container name or ID can be used. This command is used internally when running containers, but can also be used if container cleanup has failed when a container exits.
+`
+ cleanupCommand = &cobra.Command{
+ Use: "cleanup [flags] CONTAINER [CONTAINER...]",
+ Short: "Cleanup network and mountpoints of one or more containers",
+ Long: cleanupDescription,
+ RunE: cleanup,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman container cleanup --latest
+ podman container cleanup ctrID1 ctrID2 ctrID3
+ podman container cleanup --all`,
+ }
+)
+
+var (
+ cleanupOptions entities.ContainerCleanupOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Parent: containerCmd,
+ Command: cleanupCommand,
+ })
+ flags := cleanupCommand.Flags()
+ flags.BoolVarP(&cleanupOptions.All, "all", "a", false, "Cleans up all containers")
+ flags.BoolVarP(&cleanupOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ flags.BoolVar(&cleanupOptions.Remove, "rm", false, "After cleanup, remove the container entirely")
+ flags.BoolVar(&cleanupOptions.RemoveImage, "rmi", false, "After cleanup, remove the image entirely")
+
+}
+
+func cleanup(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ responses, err := registry.ContainerEngine().ContainerCleanup(registry.GetContext(), args, cleanupOptions)
+ if err != nil {
+ return err
+ }
+ for _, r := range responses {
+ if r.CleanErr == nil && r.RmErr == nil && r.RmiErr == nil {
+ fmt.Println(r.Id)
+ continue
+ }
+ if r.RmErr != nil {
+ errs = append(errs, r.RmErr)
+ }
+ if r.RmiErr != nil {
+ errs = append(errs, r.RmiErr)
+ }
+ if r.CleanErr != nil {
+ errs = append(errs, r.CleanErr)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/cmd/podmanV2/containers/init.go b/cmd/podmanV2/containers/init.go
new file mode 100644
index 000000000..dd1e1d21b
--- /dev/null
+++ b/cmd/podmanV2/containers/init.go
@@ -0,0 +1,60 @@
+package containers
+
+import (
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podmanV2/parse"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/cmd/podmanV2/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ initDescription = `Initialize one or more containers, creating the OCI spec and mounts for inspection. Container names or IDs can be used.`
+
+ initCommand = &cobra.Command{
+ Use: "init [flags] CONTAINER [CONTAINER...]",
+ Short: "Initialize one or more containers",
+ Long: initDescription,
+ PreRunE: preRunE,
+ RunE: initContainer,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman init --latest
+ podman init 3c45ef19d893
+ podman init test1`,
+ }
+)
+
+var (
+ initOptions entities.ContainerInitOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: initCommand,
+ })
+ flags := initCommand.Flags()
+ flags.BoolVarP(&initOptions.All, "all", "a", false, "Initialize all containers")
+ flags.BoolVarP(&initOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ _ = flags.MarkHidden("latest")
+}
+
+func initContainer(cmd *cobra.Command, args []string) error {
+ var errs utils.OutputErrors
+ report, err := registry.ContainerEngine().ContainerInit(registry.GetContext(), args, initOptions)
+ if err != nil {
+ return err
+ }
+ for _, r := range report {
+ if r.Err == nil {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Err)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/cmd/podmanV2/containers/kill.go b/cmd/podmanV2/containers/kill.go
index 6e6debfec..3155d1f34 100644
--- a/cmd/podmanV2/containers/kill.go
+++ b/cmd/podmanV2/containers/kill.go
@@ -2,6 +2,7 @@ package containers
import (
"context"
+ "errors"
"fmt"
"github.com/containers/libpod/cmd/podmanV2/parse"
@@ -54,9 +55,13 @@ func kill(cmd *cobra.Command, args []string) error {
)
// Check if the signalString provided by the user is valid
// Invalid signals will return err
- if _, err = signal.ParseSignalNameOrNumber(killOptions.Signal); err != nil {
+ sig, err := signal.ParseSignalNameOrNumber(killOptions.Signal)
+ if err != nil {
return err
}
+ if sig < 1 || sig > 64 {
+ return errors.New("valid signals are 1 through 64")
+ }
responses, err := registry.ContainerEngine().ContainerKill(context.Background(), args, killOptions)
if err != nil {
return err
diff --git a/cmd/podmanV2/containers/logs.go b/cmd/podmanV2/containers/logs.go
new file mode 100644
index 000000000..d1a179495
--- /dev/null
+++ b/cmd/podmanV2/containers/logs.go
@@ -0,0 +1,108 @@
+package containers
+
+import (
+ "os"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+// logsOptionsWrapper wraps entities.LogsOptions and prevents leaking
+// CLI-only fields into the API types.
+type logsOptionsWrapper struct {
+ entities.ContainerLogsOptions
+
+ SinceRaw string
+}
+
+var (
+ logsOptions logsOptionsWrapper
+ logsDescription = `Retrieves logs for one or more containers.
+
+ This does not guarantee execution order when combined with podman run (i.e., your run may not have generated any logs at the time you execute podman logs).
+`
+ logsCommand = &cobra.Command{
+ Use: "logs [flags] CONTAINER [CONTAINER...]",
+ Short: "Fetch the logs of one or more container",
+ Long: logsDescription,
+ RunE: logs,
+ PreRunE: preRunE,
+ Example: `podman logs ctrID
+ podman logs --names ctrID1 ctrID2
+ podman logs --tail 2 mywebserver
+ podman logs --follow=true --since 10m ctrID
+ podman logs mywebserver mydbserver`,
+ }
+
+ containerLogsCommand = &cobra.Command{
+ Use: logsCommand.Use,
+ Short: logsCommand.Short,
+ Long: logsCommand.Long,
+ PreRunE: logsCommand.PreRunE,
+ RunE: logsCommand.RunE,
+ Example: `podman container logs ctrID
+ podman container logs --names ctrID1 ctrID2
+ podman container logs --tail 2 mywebserver
+ podman container logs --follow=true --since 10m ctrID
+ podman container logs mywebserver mydbserver`,
+ }
+)
+
+func init() {
+ // logs
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: logsCommand,
+ })
+
+ logsCommand.SetHelpTemplate(registry.HelpTemplate())
+ logsCommand.SetUsageTemplate(registry.UsageTemplate())
+
+ flags := logsCommand.Flags()
+ logsFlags(flags)
+
+ // container logs
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: containerLogsCommand,
+ Parent: containerCmd,
+ })
+
+ containerLogsFlags := containerLogsCommand.Flags()
+ logsFlags(containerLogsFlags)
+}
+
+func logsFlags(flags *pflag.FlagSet) {
+ flags.BoolVar(&logsOptions.Details, "details", false, "Show extra details provided to the logs")
+ flags.BoolVarP(&logsOptions.Follow, "follow", "f", false, "Follow log output. The default is false")
+ flags.BoolVarP(&logsOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ flags.StringVar(&logsOptions.SinceRaw, "since", "", "Show logs since TIMESTAMP")
+ flags.Int64Var(&logsOptions.Tail, "tail", -1, "Output the specified number of LINES at the end of the logs. Defaults to -1, which prints all lines")
+ flags.BoolVarP(&logsOptions.Timestamps, "timestamps", "t", false, "Output the timestamps in the log")
+ flags.BoolVarP(&logsOptions.Names, "names", "n", false, "Output the container name in the log")
+ flags.SetInterspersed(false)
+ _ = flags.MarkHidden("details")
+}
+
+func logs(cmd *cobra.Command, args []string) error {
+ if len(args) > 0 && logsOptions.Latest {
+ return errors.New("no containers can be specified when using 'latest'")
+ }
+ if !logsOptions.Latest && len(args) < 1 {
+ return errors.New("specify at least one container name or ID to log")
+ }
+ if logsOptions.SinceRaw != "" {
+ // parse time, error out if something is wrong
+ since, err := util.ParseInputTime(logsOptions.SinceRaw)
+ if err != nil {
+ return errors.Wrapf(err, "error parsing --since %q", logsOptions.SinceRaw)
+ }
+ logsOptions.Since = since
+ }
+ logsOptions.Writer = os.Stdout
+ return registry.ContainerEngine().ContainerLogs(registry.GetContext(), args, logsOptions.ContainerLogsOptions)
+}
diff --git a/cmd/podmanV2/containers/ps.go b/cmd/podmanV2/containers/ps.go
index 2397eb8c0..8c1d44842 100644
--- a/cmd/podmanV2/containers/ps.go
+++ b/cmd/podmanV2/containers/ps.go
@@ -4,8 +4,6 @@ import (
"encoding/json"
"fmt"
"os"
- "sort"
- "strconv"
"strings"
"text/tabwriter"
"text/template"
@@ -13,12 +11,8 @@ import (
tm "github.com/buger/goterm"
"github.com/containers/buildah/pkg/formats"
- "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/cmd/podmanV2/registry"
- "github.com/containers/libpod/cmd/podmanV2/report"
"github.com/containers/libpod/pkg/domain/entities"
- "github.com/cri-o/ocicni/pkg/ocicni"
- "github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -44,9 +38,6 @@ var (
filters []string
noTrunc bool
defaultHeaders string = "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES"
-
-// CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
-
)
func init() {
@@ -143,7 +134,6 @@ func getResponses() ([]entities.ListContainer, error) {
}
func ps(cmd *cobra.Command, args []string) error {
- // []string to map[string][]string
for _, f := range filters {
split := strings.SplitN(f, "=", 2)
if len(split) == 1 {
@@ -178,8 +168,7 @@ func ps(cmd *cobra.Command, args []string) error {
if !listOpts.Quiet && !cmd.Flag("format").Changed {
format = headers + format
}
- funcs := report.AppendFuncMap(psFuncMap)
- tmpl, err := template.New("listPods").Funcs(funcs).Parse(format)
+ tmpl, err := template.New("listContainers").Parse(format)
if err != nil {
return err
}
@@ -217,7 +206,7 @@ func createPsOut() (string, string) {
var row string
if listOpts.Namespace {
headers := "CONTAINER ID\tNAMES\tPID\tCGROUPNS\tIPC\tMNT\tNET\tPIDN\tUSERNS\tUTS\n"
- row := "{{.ID}}\t{{names .Names}}\t{{.Pid}}\t{{.Namespaces.Cgroup}}\t{{.Namespaces.IPC}}\t{{.Namespaces.MNT}}\t{{.Namespaces.NET}}\t{{.Namespaces.PIDNS}}\t{{.Namespaces.User}}\t{{.Namespaces.UTS}}\n"
+ row := "{{.ID}}\t{{.Names}}\t{{.Pid}}\t{{.Namespaces.Cgroup}}\t{{.Namespaces.IPC}}\t{{.Namespaces.MNT}}\t{{.Namespaces.NET}}\t{{.Namespaces.PIDNS}}\t{{.Namespaces.User}}\t{{.Namespaces.UTS}}\n"
return headers, row
}
headers := defaultHeaders
@@ -226,7 +215,7 @@ func createPsOut() (string, string) {
} else {
row += "{{slice .ID 0 12}}"
}
- row += "\t{{.Image}}\t{{cmd .Command}}\t{{humanDuration .Created}}\t{{state .}}\t{{ports .Ports}}\t{{names .Names}}"
+ row += "\t{{.Image}}\t{{.Command}}\t{{.CreatedHuman}}\t{{.State}}\t{{.Ports}}\t{{.Names}}"
if listOpts.Pod {
headers += "\tPOD ID\tPODNAME"
@@ -240,7 +229,7 @@ func createPsOut() (string, string) {
if listOpts.Size {
headers += "\tSIZE"
- row += "\t{{consize .Size}}"
+ row += "\t{{.Size}}"
}
if !strings.HasSuffix(headers, "\n") {
headers += "\n"
@@ -250,130 +239,3 @@ func createPsOut() (string, string) {
}
return headers, row
}
-
-var psFuncMap = template.FuncMap{
- "cmd": func(conCommand []string) string {
- return strings.Join(conCommand, " ")
- },
- "state": func(con entities.ListContainer) string {
- var state string
- switch con.State {
- case "running":
- t := units.HumanDuration(time.Since(time.Unix(con.StartedAt, 0)))
- state = "Up " + t + " ago"
- case "configured":
- state = "Created"
- case "exited":
- t := units.HumanDuration(time.Since(time.Unix(con.ExitedAt, 0)))
- state = fmt.Sprintf("Exited (%d) %s ago", con.ExitCode, t)
- default:
- state = con.State
- }
- return state
- },
- "ports": func(ports []ocicni.PortMapping) string {
- if len(ports) == 0 {
- return ""
- }
- return portsToString(ports)
- },
- "names": func(names []string) string {
- return names[0]
- },
- "consize": func(csize shared.ContainerSize) string {
- virt := units.HumanSizeWithPrecision(float64(csize.RootFsSize), 3)
- s := units.HumanSizeWithPrecision(float64(csize.RwSize), 3)
- return fmt.Sprintf("%s (virtual %s)", s, virt)
- },
-}
-
-// portsToString converts the ports used to a string of the from "port1, port2"
-// and also groups a continuous list of ports into a readable format.
-func portsToString(ports []ocicni.PortMapping) string {
- type portGroup struct {
- first int32
- last int32
- }
- var portDisplay []string
- if len(ports) == 0 {
- return ""
- }
- //Sort the ports, so grouping continuous ports become easy.
- sort.Slice(ports, func(i, j int) bool {
- return comparePorts(ports[i], ports[j])
- })
-
- // portGroupMap is used for grouping continuous ports.
- portGroupMap := make(map[string]*portGroup)
- var groupKeyList []string
-
- for _, v := range ports {
-
- hostIP := v.HostIP
- if hostIP == "" {
- hostIP = "0.0.0.0"
- }
- // If hostPort and containerPort are not same, consider as individual port.
- if v.ContainerPort != v.HostPort {
- portDisplay = append(portDisplay, fmt.Sprintf("%s:%d->%d/%s", hostIP, v.HostPort, v.ContainerPort, v.Protocol))
- continue
- }
-
- portMapKey := fmt.Sprintf("%s/%s", hostIP, v.Protocol)
-
- portgroup, ok := portGroupMap[portMapKey]
- if !ok {
- portGroupMap[portMapKey] = &portGroup{first: v.ContainerPort, last: v.ContainerPort}
- // This list is required to traverse portGroupMap.
- groupKeyList = append(groupKeyList, portMapKey)
- continue
- }
-
- if portgroup.last == (v.ContainerPort - 1) {
- portgroup.last = v.ContainerPort
- continue
- }
- }
- // For each portMapKey, format group list and appned to output string.
- for _, portKey := range groupKeyList {
- group := portGroupMap[portKey]
- portDisplay = append(portDisplay, formatGroup(portKey, group.first, group.last))
- }
- return strings.Join(portDisplay, ", ")
-}
-
-func comparePorts(i, j ocicni.PortMapping) bool {
- if i.ContainerPort != j.ContainerPort {
- return i.ContainerPort < j.ContainerPort
- }
-
- if i.HostIP != j.HostIP {
- return i.HostIP < j.HostIP
- }
-
- if i.HostPort != j.HostPort {
- return i.HostPort < j.HostPort
- }
-
- return i.Protocol < j.Protocol
-}
-
-// formatGroup returns the group as <IP:startPort:lastPort->startPort:lastPort/Proto>
-// e.g 0.0.0.0:1000-1006->1000-1006/tcp.
-func formatGroup(key string, start, last int32) string {
- parts := strings.Split(key, "/")
- groupType := parts[0]
- var ip string
- if len(parts) > 1 {
- ip = parts[0]
- groupType = parts[1]
- }
- group := strconv.Itoa(int(start))
- if start != last {
- group = fmt.Sprintf("%s-%d", group, last)
- }
- if ip != "" {
- group = fmt.Sprintf("%s:%s->%s", ip, group, group)
- }
- return fmt.Sprintf("%s/%s", group, groupType)
-}
diff --git a/cmd/podmanV2/containers/run.go b/cmd/podmanV2/containers/run.go
index f839c358d..0bf0f90f8 100644
--- a/cmd/podmanV2/containers/run.go
+++ b/cmd/podmanV2/containers/run.go
@@ -5,15 +5,14 @@ import (
"os"
"strings"
- "github.com/sirupsen/logrus"
-
- "github.com/containers/libpod/pkg/domain/entities"
-
+ "github.com/containers/common/pkg/config"
"github.com/containers/libpod/cmd/podmanV2/common"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/specgen"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -75,6 +74,30 @@ func run(cmd *cobra.Command, args []string) error {
return err
}
+ ie, err := registry.NewImageEngine(cmd, args)
+ if err != nil {
+ return err
+ }
+ br, err := ie.Exists(registry.GetContext(), args[0])
+ if err != nil {
+ return err
+ }
+ pullPolicy, err := config.ValidatePullPolicy(cliVals.Pull)
+ if err != nil {
+ return err
+ }
+ if !br.Value || pullPolicy == config.PullImageAlways {
+ if pullPolicy == config.PullImageNever {
+ return errors.New("unable to find a name and tag match for busybox in repotags: no such image")
+ }
+ _, pullErr := ie.Pull(registry.GetContext(), args[0], entities.ImagePullOptions{
+ Authfile: cliVals.Authfile,
+ Quiet: cliVals.Quiet,
+ })
+ if pullErr != nil {
+ return pullErr
+ }
+ }
// If -i is not set, clear stdin
if !cliVals.Interactive {
runOpts.InputStream = nil
@@ -110,7 +133,9 @@ func run(cmd *cobra.Command, args []string) error {
runOpts.Spec = s
report, err := registry.ContainerEngine().ContainerRun(registry.GetContext(), runOpts)
// report.ExitCode is set by ContainerRun even it it returns an error
- registry.SetExitCode(report.ExitCode)
+ if report != nil {
+ registry.SetExitCode(report.ExitCode)
+ }
if err != nil {
return err
}
@@ -118,7 +143,7 @@ func run(cmd *cobra.Command, args []string) error {
fmt.Println(report.Id)
}
if runRmi {
- _, err := registry.ImageEngine().Delete(registry.GetContext(), []string{report.Id}, entities.ImageDeleteOptions{})
+ _, err := registry.ImageEngine().Delete(registry.GetContext(), []string{args[0]}, entities.ImageDeleteOptions{})
if err != nil {
logrus.Errorf("%s", errors.Wrapf(err, "failed removing image"))
}
diff --git a/cmd/podmanV2/containers/wait.go b/cmd/podmanV2/containers/wait.go
index bf3c86200..2171f2073 100644
--- a/cmd/podmanV2/containers/wait.go
+++ b/cmd/podmanV2/containers/wait.go
@@ -5,7 +5,6 @@ import (
"fmt"
"time"
- "github.com/containers/libpod/cmd/podmanV2/parse"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/cmd/podmanV2/utils"
"github.com/containers/libpod/libpod/define"
@@ -23,9 +22,7 @@ var (
Long: waitDescription,
RunE: wait,
PersistentPreRunE: preRunE,
- Args: func(cmd *cobra.Command, args []string) error {
- return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
- },
+ Args: registry.IdOrLatestArgs,
Example: `podman wait --latest
podman wait --interval 5000 ctrID
podman wait ctrID1 ctrID2`,
@@ -73,7 +70,7 @@ func wait(cmd *cobra.Command, args []string) error {
}
for _, r := range responses {
if r.Error == nil {
- fmt.Println(r.Id)
+ fmt.Println(r.ExitCode)
} else {
errs = append(errs, r.Error)
}
diff --git a/cmd/podmanV2/images/history.go b/cmd/podmanV2/images/history.go
index f6f15e2f2..48575b33a 100644
--- a/cmd/podmanV2/images/history.go
+++ b/cmd/podmanV2/images/history.go
@@ -8,10 +8,11 @@ import (
"text/tabwriter"
"text/template"
"time"
+ "unicode"
"github.com/containers/libpod/cmd/podmanV2/registry"
- "github.com/containers/libpod/cmd/podmanV2/report"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/docker/go-units"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -86,10 +87,13 @@ func history(cmd *cobra.Command, args []string) error {
}
return err
}
-
+ var hr []historyreporter
+ for _, l := range results.Layers {
+ hr = append(hr, historyreporter{l})
+ }
// Defaults
hdr := "ID\tCREATED\tCREATED BY\tSIZE\tCOMMENT\n"
- row := "{{slice .ID 0 12}}\t{{humanDuration .Created}}\t{{ellipsis .CreatedBy 45}}\t{{.Size}}\t{{.Comment}}\n"
+ row := "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n"
if len(opts.format) > 0 {
hdr = ""
@@ -100,9 +104,9 @@ func history(cmd *cobra.Command, args []string) error {
} else {
switch {
case opts.human:
- row = "{{slice .ID 0 12}}\t{{humanDuration .Created}}\t{{ellipsis .CreatedBy 45}}\t{{humanSize .Size}}\t{{.Comment}}\n"
+ row = "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n"
case opts.noTrunc:
- row = "{{.ID}}\t{{humanDuration .Created}}\t{{.CreatedBy}}\t{{humanSize .Size}}\t{{.Comment}}\n"
+ row = "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n"
case opts.quiet:
hdr = ""
row = "{{.ID}}\n"
@@ -110,14 +114,40 @@ func history(cmd *cobra.Command, args []string) error {
}
format := hdr + "{{range . }}" + row + "{{end}}"
- tmpl := template.Must(template.New("report").Funcs(report.PodmanTemplateFuncs()).Parse(format))
+ tmpl := template.Must(template.New("report").Parse(format))
w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
-
- _, _ = w.Write(report.ReportHeader("id", "created", "created by", "size", "comment"))
- err = tmpl.Execute(w, results.Layers)
+ err = tmpl.Execute(w, hr)
if err != nil {
fmt.Fprintln(os.Stderr, errors.Wrapf(err, "Failed to print report"))
}
w.Flush()
return nil
}
+
+type historyreporter struct {
+ entities.ImageHistoryLayer
+}
+
+func (h historyreporter) Created() string {
+ return units.HumanDuration(time.Since(time.Unix(h.ImageHistoryLayer.Created, 0))) + " ago"
+}
+
+func (h historyreporter) Size() string {
+ s := units.HumanSizeWithPrecision(float64(h.ImageHistoryLayer.Size), 3)
+ i := strings.LastIndexFunc(s, unicode.IsNumber)
+ return s[:i+1] + " " + s[i+1:]
+}
+
+func (h historyreporter) CreatedBy() string {
+ if len(h.ImageHistoryLayer.CreatedBy) > 45 {
+ return h.ImageHistoryLayer.CreatedBy[:45-3] + "..."
+ }
+ return h.ImageHistoryLayer.CreatedBy
+}
+
+func (h historyreporter) ID() string {
+ if !opts.noTrunc && len(h.ImageHistoryLayer.ID) >= 12 {
+ return h.ImageHistoryLayer.ID[0:12]
+ }
+ return h.ImageHistoryLayer.ID
+}
diff --git a/cmd/podmanV2/images/list.go b/cmd/podmanV2/images/list.go
index 6b02e239e..d594a4323 100644
--- a/cmd/podmanV2/images/list.go
+++ b/cmd/podmanV2/images/list.go
@@ -9,10 +9,11 @@ import (
"text/tabwriter"
"text/template"
"time"
+ "unicode"
"github.com/containers/libpod/cmd/podmanV2/registry"
- "github.com/containers/libpod/cmd/podmanV2/report"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/docker/go-units"
jsoniter "github.com/json-iterator/go"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
@@ -133,16 +134,10 @@ func writeTemplate(imageS []*entities.ImageSummary, err error) error {
var (
hdr, row string
)
- type image struct {
- entities.ImageSummary
- Repository string `json:"repository,omitempty"`
- Tag string `json:"tag,omitempty"`
- }
-
- imgs := make([]image, 0, len(imageS))
+ imgs := make([]imageReporter, 0, len(imageS))
for _, e := range imageS {
for _, tag := range e.RepoTags {
- var h image
+ var h imageReporter
h.ImageSummary = *e
h.Repository, h.Tag = tokenRepoTag(tag)
imgs = append(imgs, h)
@@ -160,7 +155,7 @@ func writeTemplate(imageS []*entities.ImageSummary, err error) error {
}
}
format := hdr + "{{range . }}" + row + "{{end}}"
- tmpl := template.Must(template.New("list").Funcs(report.PodmanTemplateFuncs()).Parse(format))
+ tmpl := template.Must(template.New("list").Parse(format))
w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
defer w.Flush()
return tmpl.Execute(w, imgs)
@@ -208,7 +203,7 @@ func sortFunc(key string, data []*entities.ImageSummary) func(i, j int) bool {
func imageListFormat(flags listFlagType) (string, string) {
if flags.quiet {
- return "", "{{slice .ID 0 12}}\n"
+ return "", "{{.ID}}\n"
}
// Defaults
@@ -224,15 +219,15 @@ func imageListFormat(flags listFlagType) (string, string) {
if flags.noTrunc {
row += "\tsha256:{{.ID}}"
} else {
- row += "\t{{slice .ID 0 12}}"
+ row += "\t{{.ID}}"
}
hdr += "\tCREATED\tSIZE"
- row += "\t{{humanDuration .Created}}\t{{humanSize .Size}}"
+ row += "\t{{.Created}}\t{{.Size}}"
if flags.history {
hdr += "\tHISTORY"
- row += "\t{{if .History}}{{join .History \", \"}}{{else}}<none>{{end}}"
+ row += "\t{{if .History}}{{.History}}{{else}}<none>{{end}}"
}
if flags.readOnly {
@@ -249,3 +244,30 @@ func imageListFormat(flags listFlagType) (string, string) {
row += "\n"
return hdr, row
}
+
+type imageReporter struct {
+ Repository string `json:"repository,omitempty"`
+ Tag string `json:"tag,omitempty"`
+ entities.ImageSummary
+}
+
+func (i imageReporter) ID() string {
+ if !listFlag.noTrunc && len(i.ImageSummary.ID) >= 12 {
+ return i.ImageSummary.ID[0:12]
+ }
+ return i.ImageSummary.ID
+}
+
+func (i imageReporter) Created() string {
+ return units.HumanDuration(time.Since(time.Unix(i.ImageSummary.Created, 0))) + " ago"
+}
+
+func (i imageReporter) Size() string {
+ s := units.HumanSizeWithPrecision(float64(i.ImageSummary.Size), 3)
+ j := strings.LastIndexFunc(s, unicode.IsNumber)
+ return s[:j+1] + " " + s[j+1:]
+}
+
+func (i imageReporter) History() string {
+ return strings.Join(i.ImageSummary.History, ", ")
+}
diff --git a/cmd/podmanV2/images/load.go b/cmd/podmanV2/images/load.go
index f60dc4908..315dbed3a 100644
--- a/cmd/podmanV2/images/load.go
+++ b/cmd/podmanV2/images/load.go
@@ -3,11 +3,18 @@ package images
import (
"context"
"fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "github.com/containers/image/v5/docker/reference"
+ "github.com/containers/libpod/cmd/podmanV2/parse"
"github.com/containers/libpod/cmd/podmanV2/registry"
- "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/pkg/errors"
"github.com/spf13/cobra"
+ "golang.org/x/crypto/ssh/terminal"
)
var (
@@ -46,11 +53,40 @@ func init() {
func load(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
- repo, err := image.NormalizedTag(args[0])
+ ref, err := reference.Parse(args[0])
if err != nil {
return err
}
- loadOpts.Name = repo.Name()
+ if t, ok := ref.(reference.Tagged); ok {
+ loadOpts.Tag = t.Tag()
+ } else {
+ loadOpts.Tag = "latest"
+ }
+ if r, ok := ref.(reference.Named); ok {
+ fmt.Println(r.Name())
+ loadOpts.Name = r.Name()
+ }
+ }
+ if len(loadOpts.Input) > 0 {
+ if err := parse.ValidateFileName(loadOpts.Input); err != nil {
+ return err
+ }
+ } else {
+ if terminal.IsTerminal(int(os.Stdin.Fd())) {
+ return errors.Errorf("cannot read from terminal. Use command-line redirection or the --input flag.")
+ }
+ outFile, err := ioutil.TempFile(util.Tmpdir(), "podman")
+ if err != nil {
+ return errors.Errorf("error creating file %v", err)
+ }
+ defer os.Remove(outFile.Name())
+ defer outFile.Close()
+
+ _, err = io.Copy(outFile, os.Stdin)
+ if err != nil {
+ return errors.Errorf("error copying file %v", err)
+ }
+ loadOpts.Input = outFile.Name()
}
response, err := registry.ImageEngine().Load(context.Background(), loadOpts)
if err != nil {
diff --git a/cmd/podmanV2/images/tag.go b/cmd/podmanV2/images/tag.go
index f66fe7857..f8799d4a7 100644
--- a/cmd/podmanV2/images/tag.go
+++ b/cmd/podmanV2/images/tag.go
@@ -9,11 +9,12 @@ import (
var (
tagDescription = "Adds one or more additional names to locally-stored image."
tagCommand = &cobra.Command{
- Use: "tag [flags] IMAGE TARGET_NAME [TARGET_NAME...]",
- Short: "Add an additional name to a local image",
- Long: tagDescription,
- RunE: tag,
- Args: cobra.MinimumNArgs(2),
+ Use: "tag [flags] IMAGE TARGET_NAME [TARGET_NAME...]",
+ Short: "Add an additional name to a local image",
+ Long: tagDescription,
+ RunE: tag,
+ PreRunE: preRunE,
+ Args: cobra.MinimumNArgs(2),
Example: `podman tag 0e3bbc2 fedora:latest
podman tag imageID:latest myNewImage:newTag
podman tag httpd myregistryhost:5000/fedora/httpd:v2`,
diff --git a/cmd/podmanV2/pods/create.go b/cmd/podmanV2/pods/create.go
index ab8957ee3..2aaf0cd2c 100644
--- a/cmd/podmanV2/pods/create.go
+++ b/cmd/podmanV2/pods/create.go
@@ -123,6 +123,21 @@ func create(cmd *cobra.Command, args []string) error {
}
}
+ if !createOptions.Infra {
+ if cmd.Flag("infra-command").Changed {
+ return errors.New("cannot set infra-command without an infra container")
+ }
+ createOptions.InfraCommand = ""
+ if cmd.Flag("infra-image").Changed {
+ return errors.New("cannot set infra-image without an infra container")
+ }
+ createOptions.InfraImage = ""
+ if cmd.Flag("share").Changed {
+ return errors.New("cannot set share namespaces without an infra container")
+ }
+ createOptions.Share = nil
+ }
+
response, err := registry.ContainerEngine().PodCreate(context.Background(), createOptions)
if err != nil {
return err
diff --git a/cmd/podmanV2/pods/pod.go b/cmd/podmanV2/pods/pod.go
index 3766893bb..81c0d33e1 100644
--- a/cmd/podmanV2/pods/pod.go
+++ b/cmd/podmanV2/pods/pod.go
@@ -1,9 +1,6 @@
package pods
import (
- "strings"
- "text/template"
-
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/spf13/cobra"
@@ -21,33 +18,6 @@ var (
}
)
-var podFuncMap = template.FuncMap{
- "numCons": func(cons []*entities.ListPodContainer) int {
- return len(cons)
- },
- "podcids": func(cons []*entities.ListPodContainer) string {
- var ctrids []string
- for _, c := range cons {
- ctrids = append(ctrids, c.Id[:12])
- }
- return strings.Join(ctrids, ",")
- },
- "podconnames": func(cons []*entities.ListPodContainer) string {
- var ctrNames []string
- for _, c := range cons {
- ctrNames = append(ctrNames, c.Names[:12])
- }
- return strings.Join(ctrNames, ",")
- },
- "podconstatuses": func(cons []*entities.ListPodContainer) string {
- var statuses []string
- for _, c := range cons {
- statuses = append(statuses, c.Status)
- }
- return strings.Join(statuses, ",")
- },
-}
-
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
diff --git a/cmd/podmanV2/pods/ps.go b/cmd/podmanV2/pods/ps.go
index 9875263ac..3dac607df 100644
--- a/cmd/podmanV2/pods/ps.go
+++ b/cmd/podmanV2/pods/ps.go
@@ -9,9 +9,11 @@ import (
"strings"
"text/tabwriter"
"text/template"
+ "time"
+
+ "github.com/docker/go-units"
"github.com/containers/libpod/cmd/podmanV2/registry"
- "github.com/containers/libpod/cmd/podmanV2/report"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -65,6 +67,7 @@ func pods(cmd *cobra.Command, args []string) error {
var (
w io.Writer = os.Stdout
row string
+ lpr []ListPodReporter
)
if cmd.Flag("filter").Changed {
for _, f := range strings.Split(inputFilters, ",") {
@@ -88,6 +91,10 @@ func pods(cmd *cobra.Command, args []string) error {
fmt.Println(string(b))
return nil
}
+
+ for _, r := range responses {
+ lpr = append(lpr, ListPodReporter{r})
+ }
headers, row := createPodPsOut()
if psInput.Quiet {
if noTrunc {
@@ -106,15 +113,14 @@ func pods(cmd *cobra.Command, args []string) error {
if !psInput.Quiet && !cmd.Flag("format").Changed {
format = headers + format
}
- funcs := report.AppendFuncMap(podFuncMap)
- tmpl, err := template.New("listPods").Funcs(funcs).Parse(format)
+ tmpl, err := template.New("listPods").Parse(format)
if err != nil {
return err
}
if !psInput.Quiet {
w = tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
}
- if err := tmpl.Execute(w, responses); err != nil {
+ if err := tmpl.Execute(w, lpr); err != nil {
return err
}
if flusher, ok := w.(interface{ Flush() error }); ok {
@@ -132,20 +138,19 @@ func createPodPsOut() (string, string) {
row += "{{slice .Id 0 12}}"
}
- row += "\t{{.Name}}\t{{.Status}}\t{{humanDurationFromTime .Created}}"
+ row += "\t{{.Name}}\t{{.Status}}\t{{.Created}}"
- //rowFormat string = "{{slice .Id 0 12}}\t{{.Name}}\t{{.Status}}\t{{humanDurationFromTime .Created}}"
if psInput.CtrIds {
headers += "\tIDS"
- row += "\t{{podcids .Containers}}"
+ row += "\t{{.ContainerIds}}"
}
if psInput.CtrNames {
headers += "\tNAMES"
- row += "\t{{podconnames .Containers}}"
+ row += "\t{{.ContainerNames}}"
}
if psInput.CtrStatus {
headers += "\tSTATUS"
- row += "\t{{podconstatuses .Containers}}"
+ row += "\t{{.ContainerStatuses}}"
}
if psInput.Namespace {
headers += "\tCGROUP\tNAMESPACES"
@@ -153,7 +158,7 @@ func createPodPsOut() (string, string) {
}
if !psInput.CtrStatus && !psInput.CtrNames && !psInput.CtrIds {
headers += "\t# OF CONTAINERS"
- row += "\t{{numCons .Containers}}"
+ row += "\t{{.NumberOfContainers}}"
}
headers += "\tINFRA ID\n"
@@ -164,3 +169,61 @@ func createPodPsOut() (string, string) {
}
return headers, row
}
+
+// ListPodReporter is a struct for pod ps output
+type ListPodReporter struct {
+ *entities.ListPodsReport
+}
+
+// Created returns a human readable created time/date
+func (l ListPodReporter) Created() string {
+ return units.HumanDuration(time.Since(l.ListPodsReport.Created)) + " ago"
+}
+
+// NumberofContainers returns an int representation for
+// the number of containers belonging to the pod
+func (l ListPodReporter) NumberOfContainers() int {
+ return len(l.Containers)
+}
+
+// Added for backwards compatibility with podmanv1
+func (l ListPodReporter) InfraID() string {
+ return l.InfraId()
+}
+
+// InfraId returns the infra container id for the pod
+// depending on trunc
+func (l ListPodReporter) InfraId() string {
+ if noTrunc {
+ return l.ListPodsReport.InfraId
+ }
+ return l.ListPodsReport.InfraId[0:12]
+}
+
+func (l ListPodReporter) ContainerIds() string {
+ var ctrids []string
+ for _, c := range l.Containers {
+ id := c.Id
+ if !noTrunc {
+ id = id[0:12]
+ }
+ ctrids = append(ctrids, id)
+ }
+ return strings.Join(ctrids, ",")
+}
+
+func (l ListPodReporter) ContainerNames() string {
+ var ctrNames []string
+ for _, c := range l.Containers {
+ ctrNames = append(ctrNames, c.Names)
+ }
+ return strings.Join(ctrNames, ",")
+}
+
+func (l ListPodReporter) ContainerStatuses() string {
+ var statuses []string
+ for _, c := range l.Containers {
+ statuses = append(statuses, c.Status)
+ }
+ return strings.Join(statuses, ",")
+}
diff --git a/cmd/podmanV2/registry/registry.go b/cmd/podmanV2/registry/registry.go
index 8ff44041f..07c2b33ff 100644
--- a/cmd/podmanV2/registry/registry.go
+++ b/cmd/podmanV2/registry/registry.go
@@ -9,7 +9,11 @@ import (
"github.com/spf13/cobra"
)
-type CobraFuncs func(cmd *cobra.Command, args []string) error
+// DefaultAPIAddress is the default address of the REST socket
+const DefaultAPIAddress = "unix:/run/podman/podman.sock"
+
+// DefaultVarlinkAddress is the default address of the varlink socket
+const DefaultVarlinkAddress = "unix:/run/podman/io.podman"
type CliCommand struct {
Mode []entities.EngineMode
diff --git a/cmd/podmanV2/report/templates.go b/cmd/podmanV2/report/templates.go
deleted file mode 100644
index e46048e97..000000000
--- a/cmd/podmanV2/report/templates.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package report
-
-import (
- "strings"
- "text/template"
- "time"
- "unicode"
-
- "github.com/docker/go-units"
-)
-
-var defaultFuncMap = template.FuncMap{
- "ellipsis": func(s string, length int) string {
- if len(s) > length {
- return s[:length-3] + "..."
- }
- return s
- },
- "humanDuration": func(t int64) string {
- return units.HumanDuration(time.Since(time.Unix(t, 0))) + " ago"
- },
- "humanDurationFromTime": func(t time.Time) string {
- return units.HumanDuration(time.Since(t)) + " ago"
- },
- "humanSize": func(sz int64) string {
- s := units.HumanSizeWithPrecision(float64(sz), 3)
- i := strings.LastIndexFunc(s, unicode.IsNumber)
- return s[:i+1] + " " + s[i+1:]
- },
- "join": strings.Join,
- "lower": strings.ToLower,
- "rfc3339": func(t int64) string {
- return time.Unix(t, 0).Format(time.RFC3339)
- },
- "replace": strings.Replace,
- "split": strings.Split,
- "title": strings.Title,
- "upper": strings.ToUpper,
- // TODO: Remove after Go 1.14 port
- "slice": func(s string, i, j int) string {
- if i > j || len(s) < i {
- return s
- }
- if len(s) < j {
- return s[i:]
- }
- return s[i:j]
- },
-}
-
-func ReportHeader(columns ...string) []byte {
- hdr := make([]string, len(columns))
- for i, h := range columns {
- hdr[i] = strings.ToUpper(h)
- }
- return []byte(strings.Join(hdr, "\t") + "\n")
-}
-
-func AppendFuncMap(funcMap template.FuncMap) template.FuncMap {
- merged := PodmanTemplateFuncs()
- for k, v := range funcMap {
- merged[k] = v
- }
- return merged
-}
-
-func PodmanTemplateFuncs() template.FuncMap {
- merged := make(template.FuncMap)
- for k, v := range defaultFuncMap {
- merged[k] = v
- }
- return merged
-}
diff --git a/cmd/podmanV2/system/service.go b/cmd/podmanV2/system/service.go
new file mode 100644
index 000000000..5573f7039
--- /dev/null
+++ b/cmd/podmanV2/system/service.go
@@ -0,0 +1,124 @@
+package system
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/systemd"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
+)
+
+var (
+ srvDescription = `Run an API service
+
+Enable a listening service for API access to Podman commands.
+`
+
+ srvCmd = &cobra.Command{
+ Use: "service [flags] [URI]",
+ Args: cobra.MaximumNArgs(1),
+ Short: "Run API service",
+ Long: srvDescription,
+ RunE: service,
+ Example: `podman system service --time=0 unix:///tmp/podman.sock
+ podman system service --varlink --time=0 unix:///tmp/podman.sock`,
+ }
+
+ srvArgs = struct {
+ Timeout int64
+ Varlink bool
+ }{}
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: srvCmd,
+ Parent: systemCmd,
+ })
+
+ flags := srvCmd.Flags()
+ flags.Int64VarP(&srvArgs.Timeout, "time", "t", 5, "Time until the service session expires in seconds. Use 0 to disable the timeout")
+ flags.Int64Var(&srvArgs.Timeout, "timeout", 5, "Time until the service session expires in seconds. Use 0 to disable the timeout")
+ flags.BoolVar(&srvArgs.Varlink, "varlink", false, "Use legacy varlink service instead of REST")
+
+ _ = flags.MarkDeprecated("varlink", "valink API is deprecated.")
+}
+
+func service(cmd *cobra.Command, args []string) error {
+ apiURI, err := resolveApiURI(args)
+ if err != nil {
+ return err
+ }
+ logrus.Infof("using API endpoint: \"%s\"", apiURI)
+
+ opts := entities.ServiceOptions{
+ URI: apiURI,
+ Timeout: time.Duration(srvArgs.Timeout) * time.Second,
+ Command: cmd,
+ }
+
+ if srvArgs.Varlink {
+ return registry.ContainerEngine().VarlinkService(registry.GetContext(), opts)
+ }
+
+ logrus.Warn("This function is EXPERIMENTAL")
+ fmt.Fprintf(os.Stderr, "This function is EXPERIMENTAL.\n")
+ return registry.ContainerEngine().RestService(registry.GetContext(), opts)
+}
+
+func resolveApiURI(_url []string) (string, error) {
+
+ // When determining _*THE*_ listening endpoint --
+ // 1) User input wins always
+ // 2) systemd socket activation
+ // 3) rootless honors XDG_RUNTIME_DIR
+ // 4) if varlink -- adapter.DefaultVarlinkAddress
+ // 5) lastly adapter.DefaultAPIAddress
+
+ if _url == nil {
+ if v, found := os.LookupEnv("PODMAN_SOCKET"); found {
+ _url = []string{v}
+ }
+ }
+
+ switch {
+ case len(_url) > 0:
+ return _url[0], nil
+ case systemd.SocketActivated():
+ logrus.Info("using systemd socket activation to determine API endpoint")
+ return "", nil
+ case rootless.IsRootless():
+ xdg, err := util.GetRuntimeDir()
+ if err != nil {
+ return "", err
+ }
+
+ socketName := "podman.sock"
+ if srvArgs.Varlink {
+ socketName = "io.podman"
+ }
+ socketDir := filepath.Join(xdg, "podman", socketName)
+ if _, err := os.Stat(filepath.Dir(socketDir)); err != nil {
+ if os.IsNotExist(err) {
+ if err := os.Mkdir(filepath.Dir(socketDir), 0755); err != nil {
+ return "", err
+ }
+ } else {
+ return "", err
+ }
+ }
+ return "unix:" + socketDir, nil
+ case srvArgs.Varlink:
+ return registry.DefaultVarlinkAddress, nil
+ default:
+ return registry.DefaultAPIAddress, nil
+ }
+}
diff --git a/cmd/podmanV2/system/system.go b/cmd/podmanV2/system/system.go
index 4e805c7bd..b44632187 100644
--- a/cmd/podmanV2/system/system.go
+++ b/cmd/podmanV2/system/system.go
@@ -8,7 +8,7 @@ import (
var (
// Command: podman _system_
- cmd = &cobra.Command{
+ systemCmd = &cobra.Command{
Use: "system",
Short: "Manage podman",
Long: "Manage podman",
@@ -21,10 +21,10 @@ var (
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
- Command: cmd,
+ Command: systemCmd,
})
- cmd.SetHelpTemplate(registry.HelpTemplate())
- cmd.SetUsageTemplate(registry.UsageTemplate())
+ systemCmd.SetHelpTemplate(registry.HelpTemplate())
+ systemCmd.SetUsageTemplate(registry.UsageTemplate())
}
func preRunE(cmd *cobra.Command, args []string) error {
diff --git a/cmd/podmanV2/system/varlink.go b/cmd/podmanV2/system/varlink.go
new file mode 100644
index 000000000..da9af6fe4
--- /dev/null
+++ b/cmd/podmanV2/system/varlink.go
@@ -0,0 +1,56 @@
+package system
+
+import (
+ "time"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ varlinkDescription = `Run varlink interface. Podman varlink listens on the specified unix domain socket for incoming connects.
+
+ Tools speaking varlink protocol can remotely manage pods, containers and images.
+`
+ varlinkCmd = &cobra.Command{
+ Use: "varlink [flags] [URI]",
+ Args: cobra.MinimumNArgs(1),
+ Short: "Run varlink interface",
+ Long: varlinkDescription,
+ PreRunE: preRunE,
+ RunE: varlinkE,
+ Example: `podman varlink unix:/run/podman/io.podman
+ podman varlink --timeout 5000 unix:/run/podman/io.podman`,
+ }
+ varlinkArgs = struct {
+ Timeout int64
+ }{}
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: varlinkCmd,
+ })
+ varlinkCmd.SetHelpTemplate(registry.HelpTemplate())
+ varlinkCmd.SetUsageTemplate(registry.UsageTemplate())
+
+ flags := varlinkCmd.Flags()
+ flags.Int64VarP(&varlinkArgs.Timeout, "time", "t", 1000, "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout")
+ flags.Int64Var(&varlinkArgs.Timeout, "timeout", 1000, "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout")
+
+}
+
+func varlinkE(cmd *cobra.Command, args []string) error {
+ uri := registry.DefaultVarlinkAddress
+ if len(args) > 0 {
+ uri = args[0]
+ }
+ opts := entities.ServiceOptions{
+ URI: uri,
+ Timeout: time.Duration(varlinkArgs.Timeout) * time.Second,
+ Command: cmd,
+ }
+ return registry.ContainerEngine().VarlinkService(registry.GetContext(), opts)
+}
diff --git a/cmd/podmanV2/system/version.go b/cmd/podmanV2/system/version.go
index e8002056b..8d6e8b7a8 100644
--- a/cmd/podmanV2/system/version.go
+++ b/cmd/podmanV2/system/version.go
@@ -24,7 +24,7 @@ var (
RunE: version,
PersistentPreRunE: preRunE,
}
- format string
+ versionFormat string
)
type versionStruct struct {
@@ -38,7 +38,7 @@ func init() {
Command: versionCommand,
})
flags := versionCommand.Flags()
- flags.StringVarP(&format, "format", "f", "", "Change the output format to JSON or a Go template")
+ flags.StringVarP(&versionFormat, "format", "f", "", "Change the output format to JSON or a Go template")
}
func version(cmd *cobra.Command, args []string) error {
@@ -62,7 +62,7 @@ func version(cmd *cobra.Command, args []string) error {
v.Server = v.Client
//}
- versionOutputFormat := format
+ versionOutputFormat := versionFormat
if versionOutputFormat != "" {
if strings.Join(strings.Fields(versionOutputFormat), "") == "{{json.}}" {
versionOutputFormat = formats.JSONString
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index 9641a52e6..a63c15940 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -48,7 +48,7 @@ Epoch: 99
%else
Epoch: 0
%endif
-Version: 1.8.3
+Version: 1.9.0
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
diff --git a/go.mod b/go.mod
index 0dd460680..08e52e83b 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect
github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921
github.com/containernetworking/plugins v0.8.5
- github.com/containers/buildah v1.14.7
+ github.com/containers/buildah v1.14.8
github.com/containers/common v0.8.1
github.com/containers/conmon v2.0.14+incompatible
github.com/containers/image/v5 v5.4.3
diff --git a/go.sum b/go.sum
index e7a0c5e46..2ca41f042 100644
--- a/go.sum
+++ b/go.sum
@@ -63,8 +63,8 @@ github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921 h1:eUMd8
github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/plugins v0.8.5 h1:pCvEMrFf7yzJI8+/D/7jkvE96KD52b7/Eu+jpahihy8=
github.com/containernetworking/plugins v0.8.5/go.mod h1:UZ2539umj8djuRQmBxuazHeJbYrLV8BSBejkk+she6o=
-github.com/containers/buildah v1.14.7 h1:q3uSCb+HWZLF5oLPYJ3wcI8b25/Gy2nqrMuvtjuSiUA=
-github.com/containers/buildah v1.14.7/go.mod h1:ytEjHJQnRXC1ygXMyc0FqYkjcoCydqBQkOdxbH563QU=
+github.com/containers/buildah v1.14.8 h1:JbMI0QSOmyZ30Mr2633uCXAj+Fajgh/EFS9xX/Y14oQ=
+github.com/containers/buildah v1.14.8/go.mod h1:ytEjHJQnRXC1ygXMyc0FqYkjcoCydqBQkOdxbH563QU=
github.com/containers/common v0.8.1 h1:1IUwAtZ4mC7GYRr4AC23cHf2oXCuoLzTUoSzIkSgnYw=
github.com/containers/common v0.8.1/go.mod h1:VxDJbaA1k6N1TNv9Rt6bQEF4hyKVHNfOfGA5L91ADEs=
github.com/containers/conmon v2.0.14+incompatible h1:knU1O1QxXy5YxtjMQVKEyCajROaehizK9FHaICl+P5Y=
@@ -217,6 +217,7 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@@ -258,6 +259,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -270,7 +272,9 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJdNZo6oqSENd4eW8=
github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
github.com/moby/vpnkit v0.3.1-0.20200304131818-6bc1679a048d/go.mod h1:KyjUrL9cb6ZSNNAUwZfqRjhwwgJ3BJN+kXh0t43WTUQ=
@@ -339,6 +343,7 @@ github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsq
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc=
+github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
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=
@@ -393,16 +398,20 @@ github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.7 h1:FfTH+vuMXOas8jmfb5/M7dzEYx7LpcLb7a0LPe34uOU=
github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
+github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
diff --git a/hack/golangci-lint.sh b/hack/golangci-lint.sh
new file mode 100755
index 000000000..385b21f39
--- /dev/null
+++ b/hack/golangci-lint.sh
@@ -0,0 +1,15 @@
+#!/bin/bash -e
+
+# Need to run linter twice to cover all the build tags code paths
+
+declare -A BUILD_TAGS
+BUILD_TAGS[default]="apparmor,seccomp,selinux"
+BUILD_TAGS[abi]="${BUILD_TAGS[default]},ABISupport,varlink,!remoteclient"
+BUILD_TAGS[tunnel]="${BUILD_TAGS[default]},!ABISupport,!varlink,remoteclient"
+
+[[ $1 == run ]] && shift
+
+for i in tunnel abi; do
+ echo Build Tags: ${BUILD_TAGS[$i]}
+ golangci-lint run --build-tags=${BUILD_TAGS[$i]} "$@"
+done
diff --git a/pkg/adapter/client.go b/pkg/adapter/client.go
index 5774ebe72..a1b2bd507 100644
--- a/pkg/adapter/client.go
+++ b/pkg/adapter/client.go
@@ -12,7 +12,7 @@ import (
"github.com/varlink/go/varlink"
)
-var remoteEndpoint *Endpoint
+var remoteEndpoint *Endpoint // nolint: deadcode,unused
func (r RemoteRuntime) RemoteEndpoint() (remoteEndpoint *Endpoint, err error) {
remoteConfigConnections, err := remoteclientconfig.ReadRemoteConfig(r.config)
@@ -26,8 +26,8 @@ func (r RemoteRuntime) RemoteEndpoint() (remoteEndpoint *Endpoint, err error) {
remoteEndpoint, err = newBridgeConnection(bridge, nil, r.cmd.LogLevel)
// if an environment variable for podman_varlink_address is defined,
// we used that as passed
- } else if address := os.Getenv("PODMAN_VARLINK_ADDRESS"); address != "" {
- logrus.Debug("creating a varlink address based on env variable: %s", address)
+ } else if address := os.Getenv("PODMAN_VARLINK_ADDRESS"); address != "" { // nolint:gocritic
+ logrus.Debugf("creating a varlink address based on env variable: %s", address)
remoteEndpoint, err = newSocketConnection(address)
// if the user provides a remote host, we use it to configure a bridge connection
} else if len(r.cmd.RemoteHost) > 0 {
@@ -35,7 +35,7 @@ func (r RemoteRuntime) RemoteEndpoint() (remoteEndpoint *Endpoint, err error) {
if len(r.cmd.RemoteUserName) < 1 {
return nil, errors.New("you must provide a username when providing a remote host name")
}
- rc := remoteclientconfig.RemoteConnection{r.cmd.RemoteHost, r.cmd.RemoteUserName, false, r.cmd.Port, r.cmd.IdentityFile, r.cmd.IgnoreHosts}
+ rc := remoteclientconfig.RemoteConnection{r.cmd.RemoteHost, r.cmd.RemoteUserName, false, r.cmd.Port, r.cmd.IdentityFile, r.cmd.IgnoreHosts} // nolint: govet
remoteEndpoint, err = newBridgeConnection("", &rc, r.cmd.LogLevel)
// if the user has a config file with connections in it
} else if len(remoteConfigConnections.Connections) > 0 {
@@ -59,7 +59,7 @@ func (r RemoteRuntime) RemoteEndpoint() (remoteEndpoint *Endpoint, err error) {
logrus.Debug("creating a varlink address based default root address")
remoteEndpoint, err = newSocketConnection(DefaultVarlinkAddress)
}
- return
+ return // nolint: nakedret
}
// Connect provides a varlink connection
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index fc8b524d6..777605896 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -341,7 +341,7 @@ func (r *LocalRuntime) RemoveContainers(ctx context.Context, cli *cliconfig.RmVa
failures[ctr] = errors.Wrapf(err, "Failed to evict container: %q", id)
continue
}
- ok = append(ok, string(id))
+ ok = append(ok, id)
}
return ok, failures, nil
}
@@ -432,7 +432,7 @@ func BatchContainerOp(ctr *Container, opts shared.PsOptions) (shared.BatchContai
// Log one or more containers over a varlink connection
func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *logs.LogOptions) error {
// GetContainersLogs
- reply, err := iopodman.GetContainersLogs().Send(r.Conn, uint64(varlink.More), c.InputArgs, c.Follow, c.Latest, options.Since.Format(time.RFC3339Nano), int64(c.Tail), c.Timestamps)
+ reply, err := iopodman.GetContainersLogs().Send(r.Conn, uint64(varlink.More), c.InputArgs, c.Follow, c.Latest, options.Since.Format(time.RFC3339Nano), c.Tail, c.Timestamps)
if err != nil {
return errors.Wrapf(err, "failed to get container logs")
}
@@ -753,15 +753,15 @@ func (r *LocalRuntime) attach(ctx context.Context, stdin, stdout *os.File, cid s
return nil, nil, err
}
defer cancel()
- defer restoreTerminal(oldTermState)
+ defer restoreTerminal(oldTermState) // nolint: errcheck
logrus.SetFormatter(&RawTtyFormatter{})
- term.SetRawTerminal(os.Stdin.Fd())
+ term.SetRawTerminal(os.Stdin.Fd()) // nolint: errcheck
}
reply, err := iopodman.Attach().Send(r.Conn, varlink.Upgrade, cid, detachKeys, start)
if err != nil {
- restoreTerminal(oldTermState)
+ restoreTerminal(oldTermState) // nolint: errcheck
return nil, nil, err
}
@@ -769,7 +769,7 @@ func (r *LocalRuntime) attach(ctx context.Context, stdin, stdout *os.File, cid s
_, err = reply()
if err != nil {
- restoreTerminal(oldTermState)
+ restoreTerminal(oldTermState) // nolint: errcheck
return nil, nil, err
}
@@ -857,7 +857,7 @@ func (r *LocalRuntime) Restart(ctx context.Context, c *cliconfig.RestartValues)
useTimeout := c.Flag("timeout").Changed || c.Flag("time").Changed
inputTimeout := c.Timeout
- if c.Latest {
+ if c.Latest { // nolint: gocritic
lastCtr, err := r.GetLatestContainer()
if err != nil {
return nil, nil, errors.Wrapf(err, "unable to get latest container")
@@ -1042,10 +1042,10 @@ func (r *LocalRuntime) ExecContainer(ctx context.Context, cli *cliconfig.ExecVal
return ec, err
}
defer cancel()
- defer restoreTerminal(oldTermState)
+ defer restoreTerminal(oldTermState) // nolint: errcheck
logrus.SetFormatter(&RawTtyFormatter{})
- term.SetRawTerminal(os.Stdin.Fd())
+ term.SetRawTerminal(os.Stdin.Fd()) // nolint: errcheck
}
opts := iopodman.ExecOpts{
@@ -1082,7 +1082,7 @@ func (r *LocalRuntime) ExecContainer(ctx context.Context, cli *cliconfig.ExecVal
return ec, err
}
-func configureVarlinkAttachStdio(reader *bufio.Reader, writer *bufio.Writer, stdin *os.File, stdout *os.File, oldTermState *term.State, resize chan remotecommand.TerminalSize, ecChan chan int) chan error {
+func configureVarlinkAttachStdio(reader *bufio.Reader, writer *bufio.Writer, stdin *os.File, stdout *os.File, oldTermState *term.State, resize chan remotecommand.TerminalSize, ecChan chan int) chan error { // nolint: interfacer
errChan := make(chan error, 1)
// These are the special writers that encode input from the client.
varlinkStdinWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.ToStdin)
@@ -1092,7 +1092,7 @@ func configureVarlinkAttachStdio(reader *bufio.Reader, writer *bufio.Writer, std
go func() {
// Read from the wire and direct to stdout or stderr
err := virtwriter.Reader(reader, stdout, os.Stderr, nil, nil, ecChan)
- defer restoreTerminal(oldTermState)
+ defer restoreTerminal(oldTermState) // nolint: errcheck
sendGenericError(ecChan)
errChan <- err
}()
@@ -1101,13 +1101,13 @@ func configureVarlinkAttachStdio(reader *bufio.Reader, writer *bufio.Writer, std
for termResize := range resize {
b, err := json.Marshal(termResize)
if err != nil {
- defer restoreTerminal(oldTermState)
+ defer restoreTerminal(oldTermState) // nolint: errcheck,staticcheck
sendGenericError(ecChan)
errChan <- err
}
_, err = varlinkResizeWriter.Write(b)
if err != nil {
- defer restoreTerminal(oldTermState)
+ defer restoreTerminal(oldTermState) // nolint: errcheck,staticcheck
sendGenericError(ecChan)
errChan <- err
}
@@ -1117,7 +1117,7 @@ func configureVarlinkAttachStdio(reader *bufio.Reader, writer *bufio.Writer, std
// Takes stdinput and sends it over the wire after being encoded
go func() {
if _, err := io.Copy(varlinkStdinWriter, stdin); err != nil {
- defer restoreTerminal(oldTermState)
+ defer restoreTerminal(oldTermState) // nolint: errcheck
sendGenericError(ecChan)
errChan <- err
}
diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go
index ebd10a92a..4c6eea9a7 100644
--- a/pkg/adapter/pods_remote.go
+++ b/pkg/adapter/pods_remote.go
@@ -515,10 +515,10 @@ func (p *Pod) GetPodStats(previousContainerStats map[string]*libpod.ContainerSta
newStats := varlinkapi.ContainerStatsToLibpodContainerStats(stats)
// If the container wasn't running, don't include it
// but also suppress the error
- if err != nil && errors.Cause(err) != define.ErrCtrStateInvalid {
+ if err != nil && errors.Cause(err) != define.ErrCtrStateInvalid { // nolint: govet
return nil, err
}
- if err == nil {
+ if err == nil { // nolint: govet
newContainerStats[c.ID()] = &newStats
}
}
diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go
index a4ac660ea..c511b70f1 100644
--- a/pkg/adapter/runtime_remote.go
+++ b/pkg/adapter/runtime_remote.go
@@ -180,7 +180,7 @@ type Pod struct {
type remotepod struct {
config *libpod.PodConfig
state *libpod.PodInspectState
- containers []libpod.PodContainerInfo
+ containers []libpod.PodContainerInfo // nolint: structcheck
Runtime *LocalRuntime
}
@@ -627,7 +627,7 @@ func (r *LocalRuntime) SendFileOverVarlink(source string) (string, error) {
return "", err
}
logrus.Debugf("sending %s over varlink connection", source)
- reply, err := iopodman.SendFile().Send(r.Conn, varlink.Upgrade, "", int64(fileInfo.Size()))
+ reply, err := iopodman.SendFile().Send(r.Conn, varlink.Upgrade, "", fileInfo.Size())
if err != nil {
return "", err
}
@@ -754,9 +754,7 @@ func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeIn
volumes = append(volumes, vol.Name())
}
} else {
- for _, arg := range c.InputArgs {
- volumes = append(volumes, arg)
- }
+ volumes = append(volumes, c.InputArgs...)
}
for _, vol := range volumes {
@@ -855,7 +853,7 @@ func (r *LocalRuntime) SaveImage(ctx context.Context, c *cliconfig.SaveValues) e
}
}
- if err != nil {
+ if err != nil { // nolint: govet
return err
}
@@ -927,7 +925,7 @@ func IsImageNotFound(err error) bool {
if errors.Cause(err) == image.ErrNoSuchImage {
return true
}
- switch err.(type) {
+ switch err.(type) { // nolint: gocritic
case *iopodman.ImageNotFound:
return true
}
@@ -991,7 +989,7 @@ func (r *LocalRuntime) Events(c *cliconfig.EventValues) error {
Time: eTime,
Type: eType,
}
- if c.Format == formats.JSONString {
+ if c.Format == formats.JSONString { // nolint: gocritic
jsonStr, err := event.ToJSONString()
if err != nil {
return errors.Wrapf(err, "unable to format json")
@@ -1008,6 +1006,7 @@ func (r *LocalRuntime) Events(c *cliconfig.EventValues) error {
return err
}
}
+
if _, err := w.Write([]byte("\n")); err != nil {
return err
}
@@ -1040,7 +1039,7 @@ func stringToChangeType(change string) archive.ChangeType {
return archive.ChangeAdd
case "D":
return archive.ChangeDelete
- default:
+ default: // nolint: gocritic,stylecheck
logrus.Errorf("'%s' is unknown archive type", change)
fallthrough
case "C":
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index c53af0f26..3f6aca502 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -261,6 +261,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
var until time.Time
if _, found := r.URL.Query()["until"]; found {
+ // FIXME: until != since but the logs backend does not yet support until.
since, err = util.ParseInputTime(query.Until)
if err != nil {
utils.BadRequest(w, "until", query.Until, err)
diff --git a/pkg/api/handlers/compat/events.go b/pkg/api/handlers/compat/events.go
index 0f72ef328..8ef32716d 100644
--- a/pkg/api/handlers/compat/events.go
+++ b/pkg/api/handlers/compat/events.go
@@ -1,7 +1,6 @@
package compat
import (
- "encoding/json"
"fmt"
"net/http"
@@ -10,6 +9,7 @@ import (
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/gorilla/schema"
+ jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -48,14 +48,27 @@ func GetEvents(w http.ResponseWriter, r *http.Request) {
}()
if eventsError != nil {
utils.InternalServerError(w, eventsError)
+ close(eventChannel)
return
}
- coder := json.NewEncoder(w)
- coder.SetEscapeHTML(true)
+ // If client disappears we need to stop listening for events
+ go func(done <-chan struct{}) {
+ <-done
+ close(eventChannel)
+ }(r.Context().Done())
+ // Headers need to be written out before turning Writer() over to json encoder
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
+ if flusher, ok := w.(http.Flusher); ok {
+ flusher.Flush()
+ }
+
+ json := jsoniter.ConfigCompatibleWithStandardLibrary
+ coder := json.NewEncoder(w)
+ coder.SetEscapeHTML(true)
+
for event := range eventChannel {
e := handlers.EventToApiEvent(event)
if err := coder.Encode(e); err != nil {
diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go
index 5cbfb11eb..086bef847 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -285,3 +285,23 @@ func Restore(w http.ResponseWriter, r *http.Request) {
}
utils.WriteResponse(w, http.StatusOK, entities.RestoreReport{Id: ctr.ID()})
}
+
+func InitContainer(w http.ResponseWriter, r *http.Request) {
+ name := utils.GetName(r)
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ utils.ContainerNotFound(w, name, err)
+ return
+ }
+ err = ctr.Init(r.Context())
+ if errors.Cause(err) == define.ErrCtrStateInvalid {
+ utils.Error(w, "container already initialized", http.StatusNotModified, err)
+ return
+ }
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ utils.WriteResponse(w, http.StatusNoContent, "")
+}
diff --git a/pkg/api/server/handler_api.go b/pkg/api/server/handler_api.go
index 30a1680c9..7a7db12f3 100644
--- a/pkg/api/server/handler_api.go
+++ b/pkg/api/server/handler_api.go
@@ -19,7 +19,7 @@ func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc {
if err != nil {
buf := make([]byte, 1<<20)
n := runtime.Stack(buf, true)
- log.Warnf("Recovering from podman handler panic: %v, %s", err, buf[:n])
+ log.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))
}
@@ -27,12 +27,7 @@ func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc {
// Wrapper to hide some boiler plate
fn := func(w http.ResponseWriter, r *http.Request) {
- // Connection counting, ugh. Needed to support the sliding window for idle checking.
- s.ConnectionCh <- EnterHandler
- defer func() { s.ConnectionCh <- ExitHandler }()
-
- log.Debugf("APIHandler -- Method: %s URL: %s (conn %d/%d)",
- r.Method, r.URL.String(), s.ActiveConnections, s.TotalConnections)
+ log.Debugf("APIHandler -- Method: %s URL: %s", r.Method, r.URL.String())
if err := r.ParseForm(); err != nil {
log.Infof("Failed Request: unable to parse form: %q", err)
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index 150cca872..e39e43bfb 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -1377,7 +1377,6 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// 500:
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name}/restore"), s.APIHandler(libpod.Restore)).Methods(http.MethodPost)
-
// swagger:operation GET /containers/{name}/changes libpod libpodChangesContainer
// swagger:operation GET /libpod/containers/{name}/changes compat changesContainer
// ---
@@ -1411,6 +1410,29 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
r.HandleFunc(VersionedPath("/containers/{name}/changes"), s.APIHandler(compat.Changes))
r.HandleFunc("/containers/{name}/changes", s.APIHandler(compat.Changes))
r.HandleFunc(VersionedPath("/libpod/containers/{name}/changes"), s.APIHandler(compat.Changes))
-
+ // swagger:operation POST /libpod/containers/{name}/init libpod libpodInitContainer
+ // ---
+ // tags:
+ // - containers
+ // summary: Initialize a container
+ // description: Performs all tasks necessary for initializing the container but does not start the container.
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name or ID of the container
+ // produces:
+ // - application/json
+ // responses:
+ // 204:
+ // description: no error
+ // 304:
+ // description: container already initialized
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/init"), s.APIHandler(libpod.InitContainer)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 59f1f95cb..5f1a86183 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -2,11 +2,14 @@ package server
import (
"context"
+ "log"
"net"
"net/http"
"os"
"os/signal"
+ "runtime"
"strings"
+ "sync"
"syscall"
"time"
@@ -20,26 +23,19 @@ import (
)
type APIServer struct {
- http.Server // The HTTP work happens here
- *schema.Decoder // Decoder for Query parameters to structs
- context.Context // Context to carry objects to handlers
- *libpod.Runtime // Where the real work happens
- net.Listener // mux for routing HTTP API calls to libpod routines
- context.CancelFunc // Stop APIServer
- *time.Timer // Hold timer for sliding window
- time.Duration // Duration of client access sliding window
- ActiveConnections uint64 // Number of handlers holding a connection
- TotalConnections uint64 // Number of connections handled
- ConnectionCh chan int // Channel for signalling handler enter/exit
+ http.Server // The HTTP work happens here
+ *schema.Decoder // Decoder for Query parameters to structs
+ context.Context // Context to carry objects to handlers
+ *libpod.Runtime // Where the real work happens
+ net.Listener // mux for routing HTTP API calls to libpod routines
+ context.CancelFunc // Stop APIServer
+ idleTracker *IdleTracker // Track connections to support idle shutdown
}
// Number of seconds to wait for next request, if exceeded shutdown server
const (
DefaultServiceDuration = 300 * time.Second
UnlimitedServiceDuration = 0 * time.Second
- EnterHandler = 1
- ExitHandler = -1
- NOOPHandler = 0
)
// NewServer will create and configure a new API server with all defaults
@@ -56,7 +52,7 @@ 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_FDS"); !found {
- return nil, errors.Errorf("Cannot create Server, no listener provided and socket activation protocol is not active.")
+ return nil, errors.Errorf("Cannot create API Server, no listener provided and socket activation protocol is not active.")
}
listeners, err := activation.Listeners()
@@ -70,17 +66,20 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
}
router := mux.NewRouter().UseEncodedPath()
+ idle := NewIdleTracker(duration)
+
server := APIServer{
Server: http.Server{
Handler: router,
ReadHeaderTimeout: 20 * time.Second,
IdleTimeout: duration,
+ ConnState: idle.ConnState,
+ ErrorLog: log.New(logrus.StandardLogger().Out, "", 0),
},
- Decoder: handlers.NewAPIDecoder(),
- Runtime: runtime,
- Listener: *listener,
- Duration: duration,
- ConnectionCh: make(chan int),
+ Decoder: handlers.NewAPIDecoder(),
+ idleTracker: idle,
+ Listener: *listener,
+ Runtime: runtime,
}
router.NotFoundHandler = http.HandlerFunc(
@@ -120,11 +119,11 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
router.Walk(func(route *mux.Route, r *mux.Router, ancestors []*mux.Route) error { // nolint
path, err := route.GetPathTemplate()
if err != nil {
- path = ""
+ path = "<N/A>"
}
methods, err := route.GetMethods()
if err != nil {
- methods = []string{}
+ methods = []string{"<N/A>"}
}
logrus.Debugf("Methods: %s Path: %s", strings.Join(methods, ", "), path)
return nil
@@ -136,24 +135,20 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
// Serve starts responding to HTTP requests
func (s *APIServer) Serve() error {
- // This is initialized here as Timer is not needed until Serve'ing
- if s.Duration > 0 {
- s.Timer = time.AfterFunc(s.Duration, func() {
- s.ConnectionCh <- NOOPHandler
- })
- go s.ReadChannelWithTimeout()
- } else {
- go s.ReadChannelNoTimeout()
- }
-
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
errChan := make(chan error, 1)
go func() {
+ <-s.idleTracker.Done()
+ logrus.Debugf("API Server idle for %v", s.idleTracker.Duration)
+ _ = s.Shutdown()
+ }()
+
+ go func() {
err := s.Server.Serve(s.Listener)
if err != nil && err != http.ErrServerClosed {
- errChan <- errors.Wrap(err, "Failed to start APIServer")
+ errChan <- errors.Wrap(err, "failed to start API server")
return
}
errChan <- nil
@@ -169,72 +164,30 @@ func (s *APIServer) Serve() error {
return nil
}
-func (s *APIServer) ReadChannelWithTimeout() {
- // stalker to count the connections. Should the timer expire it will shutdown the service.
- for delta := range s.ConnectionCh {
- switch delta {
- case EnterHandler:
- s.Timer.Stop()
- s.ActiveConnections += 1
- s.TotalConnections += 1
- case ExitHandler:
- s.Timer.Stop()
- s.ActiveConnections -= 1
- if s.ActiveConnections == 0 {
- // Server will be shutdown iff the timer expires before being reset or stopped
- s.Timer = time.AfterFunc(s.Duration, func() {
- if err := s.Shutdown(); err != nil {
- logrus.Errorf("Failed to shutdown APIServer: %v", err)
- os.Exit(1)
- }
- })
- } else {
- s.Timer.Reset(s.Duration)
- }
- case NOOPHandler:
- // push the check out another duration...
- s.Timer.Reset(s.Duration)
- default:
- logrus.Warnf("ConnectionCh received unsupported input %d", delta)
- }
- }
-}
-
-func (s *APIServer) ReadChannelNoTimeout() {
- // stalker to count the connections.
- for delta := range s.ConnectionCh {
- switch delta {
- case EnterHandler:
- s.ActiveConnections += 1
- s.TotalConnections += 1
- case ExitHandler:
- s.ActiveConnections -= 1
- case NOOPHandler:
- default:
- logrus.Warnf("ConnectionCh received unsupported input %d", delta)
- }
- }
-}
-
// Shutdown is a clean shutdown waiting on existing clients
func (s *APIServer) Shutdown() error {
+ if logrus.IsLevelEnabled(logrus.DebugLevel) {
+ _, file, line, _ := runtime.Caller(1)
+ logrus.Debugf("APIServer.Shutdown by %s:%d, %d/%d connection(s)",
+ file, line, s.idleTracker.ActiveConnections(), s.idleTracker.TotalConnections())
+ }
+
// Duration == 0 flags no auto-shutdown of the server
- if s.Duration == 0 {
+ if s.idleTracker.Duration == 0 {
logrus.Debug("APIServer.Shutdown ignored as Duration == 0")
return nil
}
- logrus.Debugf("APIServer.Shutdown called %v, conn %d/%d", time.Now(), s.ActiveConnections, s.TotalConnections)
- // Gracefully shutdown server
- ctx, cancel := context.WithTimeout(context.Background(), s.Duration)
+ // Gracefully shutdown server, duration of wait same as idle window
+ ctx, cancel := context.WithTimeout(context.Background(), s.idleTracker.Duration)
defer cancel()
-
go func() {
err := s.Server.Shutdown(ctx)
if err != nil && err != context.Canceled && err != http.ErrServerClosed {
logrus.Errorf("Failed to cleanly shutdown APIServer: %s", err.Error())
}
}()
+ <-ctx.Done()
return nil
}
@@ -242,3 +195,55 @@ func (s *APIServer) Shutdown() error {
func (s *APIServer) Close() error {
return s.Server.Close()
}
+
+type IdleTracker struct {
+ active map[net.Conn]struct{}
+ total int
+ mux sync.Mutex
+ timer *time.Timer
+ Duration time.Duration
+}
+
+func NewIdleTracker(idle time.Duration) *IdleTracker {
+ return &IdleTracker{
+ active: make(map[net.Conn]struct{}),
+ Duration: idle,
+ timer: time.NewTimer(idle),
+ }
+}
+
+func (t *IdleTracker) ConnState(conn net.Conn, state http.ConnState) {
+ t.mux.Lock()
+ defer t.mux.Unlock()
+
+ oldActive := len(t.active)
+ logrus.Debugf("IdleTracker %p:%v %d/%d connection(s)", conn, state, t.ActiveConnections(), t.TotalConnections())
+ switch state {
+ case http.StateNew, http.StateActive, http.StateHijacked:
+ t.active[conn] = struct{}{}
+ // stop the timer if we transitioned from idle
+ if oldActive == 0 {
+ t.timer.Stop()
+ }
+ t.total += 1
+ case http.StateIdle, http.StateClosed:
+ delete(t.active, conn)
+ // Restart the timer if we've become idle
+ if oldActive > 0 && len(t.active) == 0 {
+ t.timer.Stop()
+ t.timer.Reset(t.Duration)
+ }
+ }
+}
+
+func (t *IdleTracker) ActiveConnections() int {
+ return len(t.active)
+}
+
+func (t *IdleTracker) TotalConnections() int {
+ return t.total
+}
+
+func (t *IdleTracker) Done() <-chan time.Time {
+ return t.timer.C
+}
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index a188d73a0..963f0ec57 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
)
// List obtains a list of containers in local storage. All parameters to this method are optional.
@@ -316,3 +317,21 @@ func Export(ctx context.Context, nameOrID string, w io.Writer) error {
}
return response.Process(nil)
}
+
+// ContainerInit takes a created container and executes all of the
+// preparations to run the container except it will not start
+// or attach to the container
+func ContainerInit(ctx context.Context, nameOrID string) error {
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/init", nil, nameOrID)
+ if err != nil {
+ return err
+ }
+ if response.StatusCode == http.StatusNotModified {
+ return errors.Wrapf(define.ErrCtrStateInvalid, "container %s has already been created in runtime", nameOrID)
+ }
+ return response.Process(nil)
+}
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index ee5df40a0..c6501ac9e 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -508,8 +508,27 @@ var _ = Describe("Podman containers ", func() {
_, err = bt.RunTopContainer(&name2, &bindings.PFalse, nil)
Expect(err).To(BeNil())
containerLatestList, err := containers.List(bt.conn, nil, nil, &latestContainers, nil, nil, nil)
- err = containers.Kill(bt.conn, containerLatestList[0].Names[0], "SIGTERM")
Expect(err).To(BeNil())
+ err = containers.Kill(bt.conn, containerLatestList[0].Names(), "SIGTERM")
+ Expect(err).To(BeNil())
+ })
+
+ It("container init on a bogus container", func() {
+ err := containers.ContainerInit(bt.conn, "doesnotexist")
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+ })
+
+ It("container init", func() {
+ s := specgen.NewSpecGenerator(alpine.name)
+ ctr, err := containers.CreateWithSpec(bt.conn, s)
+ Expect(err).To(BeNil())
+ err = containers.ContainerInit(bt.conn, ctr.ID)
+ Expect(err).To(BeNil())
+ // trying to init again should be an error
+ err = containers.ContainerInit(bt.conn, ctr.ID)
+ Expect(err).ToNot(BeNil())
})
})
diff --git a/pkg/domain/entities/container_ps.go b/pkg/domain/entities/container_ps.go
index ceafecebc..f07b0364f 100644
--- a/pkg/domain/entities/container_ps.go
+++ b/pkg/domain/entities/container_ps.go
@@ -1,19 +1,23 @@
package entities
import (
+ "fmt"
"sort"
+ "strconv"
"strings"
+ "time"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/cri-o/ocicni/pkg/ocicni"
+ "github.com/docker/go-units"
"github.com/pkg/errors"
)
// Listcontainer describes a container suitable for listing
type ListContainer struct {
// Container command
- Command []string
+ Cmd []string
// Container creation time
Created int64
// If container has exited/stopped
@@ -33,7 +37,7 @@ type ListContainer struct {
// User volume mounts
Mounts []string
// The names assigned to the container
- Names []string
+ ContainerNames []string
// Namespaces the container belongs to. Requires the
// namespace boolean to be true
Namespaces ListContainerNamespaces
@@ -46,13 +50,69 @@ type ListContainer struct {
// boolean to be set
PodName string
// Port mappings
- Ports []ocicni.PortMapping
+ PortMappings []ocicni.PortMapping
// Size of the container rootfs. Requires the size boolean to be true
- Size *shared.ContainerSize
+ ContainerSize *shared.ContainerSize
// Time when container started
StartedAt int64
// State of container
- State string
+ ContainerState string
+}
+
+// State returns the container state in human duration
+func (l ListContainer) State() string {
+ var state string
+ switch l.ContainerState {
+ case "running":
+ t := units.HumanDuration(time.Since(time.Unix(l.StartedAt, 0)))
+ state = "Up " + t + " ago"
+ case "configured":
+ state = "Created"
+ case "exited", "stopped":
+ t := units.HumanDuration(time.Since(time.Unix(l.ExitedAt, 0)))
+ state = fmt.Sprintf("Exited (%d) %s ago", l.ExitCode, t)
+ default:
+ state = l.ContainerState
+ }
+ return state
+}
+
+// Command returns the container command in string format
+func (l ListContainer) Command() string {
+ return strings.Join(l.Cmd, " ")
+}
+
+// Size returns the rootfs and virtual sizes in human duration in
+// and output form (string) suitable for ps
+func (l ListContainer) Size() string {
+ virt := units.HumanSizeWithPrecision(float64(l.ContainerSize.RootFsSize), 3)
+ s := units.HumanSizeWithPrecision(float64(l.ContainerSize.RwSize), 3)
+ return fmt.Sprintf("%s (virtual %s)", s, virt)
+}
+
+// Names returns the container name in string format
+func (l ListContainer) Names() string {
+ return l.ContainerNames[0]
+}
+
+// Ports converts from Portmappings to the string form
+// required by ps
+func (l ListContainer) Ports() string {
+ if len(l.PortMappings) < 1 {
+ return ""
+ }
+ return portsToString(l.PortMappings)
+}
+
+// CreatedAt returns the container creation time in string format. podman
+// and docker both return a timestamped value for createdat
+func (l ListContainer) CreatedAt() string {
+ return time.Unix(l.Created, 0).String()
+}
+
+// CreateHuman allows us to output the created time in human readable format
+func (l ListContainer) CreatedHuman() string {
+ return units.HumanDuration(time.Since(time.Unix(l.Created, 0))) + " ago"
}
// ListContainer Namespaces contains the identifiers of the container's Linux namespaces
@@ -93,7 +153,7 @@ func (a SortListContainers) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
type psSortedCommand struct{ SortListContainers }
func (a psSortedCommand) Less(i, j int) bool {
- return strings.Join(a.SortListContainers[i].Command, " ") < strings.Join(a.SortListContainers[j].Command, " ")
+ return strings.Join(a.SortListContainers[i].Cmd, " ") < strings.Join(a.SortListContainers[j].Cmd, " ")
}
type psSortedId struct{ SortListContainers }
@@ -111,7 +171,7 @@ func (a psSortedImage) Less(i, j int) bool {
type psSortedNames struct{ SortListContainers }
func (a psSortedNames) Less(i, j int) bool {
- return a.SortListContainers[i].Names[0] < a.SortListContainers[j].Names[0]
+ return a.SortListContainers[i].ContainerNames[0] < a.SortListContainers[j].ContainerNames[0]
}
type psSortedPod struct{ SortListContainers }
@@ -129,16 +189,16 @@ func (a psSortedRunningFor) Less(i, j int) bool {
type psSortedStatus struct{ SortListContainers }
func (a psSortedStatus) Less(i, j int) bool {
- return a.SortListContainers[i].State < a.SortListContainers[j].State
+ return a.SortListContainers[i].ContainerState < a.SortListContainers[j].ContainerState
}
type psSortedSize struct{ SortListContainers }
func (a psSortedSize) Less(i, j int) bool {
- if a.SortListContainers[i].Size == nil || a.SortListContainers[j].Size == nil {
+ if a.SortListContainers[i].ContainerSize == nil || a.SortListContainers[j].ContainerSize == nil {
return false
}
- return a.SortListContainers[i].Size.RootFsSize < a.SortListContainers[j].Size.RootFsSize
+ return a.SortListContainers[i].ContainerSize.RootFsSize < a.SortListContainers[j].ContainerSize.RootFsSize
}
type PsSortedCreateTime struct{ SortListContainers }
@@ -172,3 +232,94 @@ func SortPsOutput(sortBy string, psOutput SortListContainers) (SortListContainer
}
return psOutput, nil
}
+
+// portsToString converts the ports used to a string of the from "port1, port2"
+// and also groups a continuous list of ports into a readable format.
+func portsToString(ports []ocicni.PortMapping) string {
+ type portGroup struct {
+ first int32
+ last int32
+ }
+ var portDisplay []string
+ if len(ports) == 0 {
+ return ""
+ }
+ //Sort the ports, so grouping continuous ports become easy.
+ sort.Slice(ports, func(i, j int) bool {
+ return comparePorts(ports[i], ports[j])
+ })
+
+ // portGroupMap is used for grouping continuous ports.
+ portGroupMap := make(map[string]*portGroup)
+ var groupKeyList []string
+
+ for _, v := range ports {
+
+ hostIP := v.HostIP
+ if hostIP == "" {
+ hostIP = "0.0.0.0"
+ }
+ // If hostPort and containerPort are not same, consider as individual port.
+ if v.ContainerPort != v.HostPort {
+ portDisplay = append(portDisplay, fmt.Sprintf("%s:%d->%d/%s", hostIP, v.HostPort, v.ContainerPort, v.Protocol))
+ continue
+ }
+
+ portMapKey := fmt.Sprintf("%s/%s", hostIP, v.Protocol)
+
+ portgroup, ok := portGroupMap[portMapKey]
+ if !ok {
+ portGroupMap[portMapKey] = &portGroup{first: v.ContainerPort, last: v.ContainerPort}
+ // This list is required to traverse portGroupMap.
+ groupKeyList = append(groupKeyList, portMapKey)
+ continue
+ }
+
+ if portgroup.last == (v.ContainerPort - 1) {
+ portgroup.last = v.ContainerPort
+ continue
+ }
+ }
+ // For each portMapKey, format group list and appned to output string.
+ for _, portKey := range groupKeyList {
+ group := portGroupMap[portKey]
+ portDisplay = append(portDisplay, formatGroup(portKey, group.first, group.last))
+ }
+ return strings.Join(portDisplay, ", ")
+}
+
+func comparePorts(i, j ocicni.PortMapping) bool {
+ if i.ContainerPort != j.ContainerPort {
+ return i.ContainerPort < j.ContainerPort
+ }
+
+ if i.HostIP != j.HostIP {
+ return i.HostIP < j.HostIP
+ }
+
+ if i.HostPort != j.HostPort {
+ return i.HostPort < j.HostPort
+ }
+
+ return i.Protocol < j.Protocol
+}
+
+// formatGroup returns the group as <IP:startPort:lastPort->startPort:lastPort/Proto>
+// e.g 0.0.0.0:1000-1006->1000-1006/tcp.
+func formatGroup(key string, start, last int32) string {
+ parts := strings.Split(key, "/")
+ groupType := parts[0]
+ var ip string
+ if len(parts) > 1 {
+ ip = parts[0]
+ groupType = parts[1]
+ }
+ group := strconv.Itoa(int(start))
+ if start != last {
+ group = fmt.Sprintf("%s-%d", group, last)
+ }
+ if ip != "" {
+ group = fmt.Sprintf("%s:%s->%s", ip, group, group)
+ }
+ return fmt.Sprintf("%s/%s", group, groupType)
+}
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index 5d302058b..4508f9c2c 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -172,6 +172,26 @@ type AttachOptions struct {
Stderr *os.File
}
+// ContainerLogsOptions describes the options to extract container logs.
+type ContainerLogsOptions struct {
+ // Show extra details provided to the logs.
+ Details bool
+ // Follow the log output.
+ Follow bool
+ // Display logs for the latest container only. Ignored on the remote client.
+ Latest bool
+ // Show container names in the output.
+ Names bool
+ // Show logs since this timestamp.
+ Since time.Time
+ // Number of lines to display at the end of the output.
+ Tail int64
+ // Show timestamps in the logs.
+ Timestamps bool
+ // Write the logs to Writer.
+ Writer io.Writer
+}
+
// ExecOptions describes the cli values to exec into
// a container
type ExecOptions struct {
@@ -245,3 +265,35 @@ type ContainerRunReport struct {
ExitCode int
Id string
}
+
+// ContainerCleanupOptions are the CLI values for the
+// cleanup command
+type ContainerCleanupOptions struct {
+ All bool
+ Latest bool
+ Remove bool
+ RemoveImage bool
+}
+
+// ContainerCleanupReport describes the response from a
+// container cleanup
+type ContainerCleanupReport struct {
+ CleanErr error
+ Id string
+ RmErr error
+ RmiErr error
+}
+
+// ContainerInitOptions describes input options
+// for the container init cli
+type ContainerInitOptions struct {
+ All bool
+ Latest bool
+}
+
+// ContainerInitReport describes the results of a
+// container init
+type ContainerInitReport struct {
+ Err error
+ Id string
+}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 24b7a9acc..d23006a38 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -10,26 +10,30 @@ import (
type ContainerEngine interface {
ContainerAttach(ctx context.Context, nameOrId string, options AttachOptions) error
ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error)
+ ContainerCleanup(ctx context.Context, namesOrIds []string, options ContainerCleanupOptions) ([]*ContainerCleanupReport, error)
ContainerCommit(ctx context.Context, nameOrId string, options CommitOptions) (*CommitReport, error)
ContainerCreate(ctx context.Context, s *specgen.SpecGenerator) (*ContainerCreateReport, error)
ContainerDiff(ctx context.Context, nameOrId string, options DiffOptions) (*DiffReport, error)
ContainerExec(ctx context.Context, nameOrId string, options ExecOptions) (int, error)
ContainerExists(ctx context.Context, nameOrId string) (*BoolReport, error)
ContainerExport(ctx context.Context, nameOrId string, options ContainerExportOptions) error
+ ContainerInit(ctx context.Context, namesOrIds []string, options ContainerInitOptions) ([]*ContainerInitReport, error)
ContainerInspect(ctx context.Context, namesOrIds []string, options InspectOptions) ([]*ContainerInspectReport, error)
ContainerKill(ctx context.Context, namesOrIds []string, options KillOptions) ([]*KillReport, error)
ContainerList(ctx context.Context, options ContainerListOptions) ([]ListContainer, error)
ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
+ ContainerLogs(ctx context.Context, containers []string, options ContainerLogsOptions) error
ContainerRestart(ctx context.Context, namesOrIds []string, options RestartOptions) ([]*RestartReport, error)
ContainerRestore(ctx context.Context, namesOrIds []string, options RestoreOptions) ([]*RestoreReport, error)
ContainerRm(ctx context.Context, namesOrIds []string, options RmOptions) ([]*RmReport, error)
- ContainerStart(ctx context.Context, namesOrIds []string, options ContainerStartOptions) ([]*ContainerStartReport, error)
ContainerRun(ctx context.Context, opts ContainerRunOptions) (*ContainerRunReport, error)
+ ContainerStart(ctx context.Context, namesOrIds []string, options ContainerStartOptions) ([]*ContainerStartReport, error)
ContainerStop(ctx context.Context, namesOrIds []string, options StopOptions) ([]*StopReport, error)
ContainerTop(ctx context.Context, options TopOptions) (*StringSliceReport, error)
ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error)
HealthCheckRun(ctx context.Context, nameOrId string, options HealthCheckOptions) (*define.HealthCheckResults, error)
+ Info(ctx context.Context) (*define.Info, error)
PodCreate(ctx context.Context, opts PodCreateOptions) (*PodCreateReport, error)
PodExists(ctx context.Context, nameOrId string) (*BoolReport, error)
PodInspect(ctx context.Context, options PodInspectOptions) (*PodInspectReport, error)
@@ -42,11 +46,11 @@ type ContainerEngine interface {
PodStop(ctx context.Context, namesOrIds []string, options PodStopOptions) ([]*PodStopReport, error)
PodTop(ctx context.Context, options PodTopOptions) (*StringSliceReport, error)
PodUnpause(ctx context.Context, namesOrIds []string, options PodunpauseOptions) ([]*PodUnpauseReport, error)
+ RestService(ctx context.Context, opts ServiceOptions) error
+ VarlinkService(ctx context.Context, opts ServiceOptions) error
VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IdOrNameResponse, error)
VolumeInspect(ctx context.Context, namesOrIds []string, opts VolumeInspectOptions) ([]*VolumeInspectReport, error)
VolumeList(ctx context.Context, opts VolumeListOptions) ([]*VolumeListReport, error)
VolumePrune(ctx context.Context, opts VolumePruneOptions) ([]*VolumePruneReport, error)
VolumeRm(ctx context.Context, namesOrIds []string, opts VolumeRmOptions) ([]*VolumeRmReport, error)
-
- Info(ctx context.Context) (*define.Info, error)
}
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index cd2e79961..9ca8ff43c 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -1,6 +1,7 @@
package entities
import (
+ "strings"
"time"
"github.com/containers/libpod/libpod"
@@ -121,7 +122,9 @@ func (p PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) {
s.Hostname = p.Hostname
s.Labels = p.Labels
s.NoInfra = !p.Infra
- s.InfraCommand = []string{p.InfraCommand}
+ if len(p.InfraCommand) > 0 {
+ s.InfraCommand = strings.Split(p.InfraCommand, " ")
+ }
s.InfraImage = p.InfraImage
s.SharedNamespaces = p.Share
diff --git a/pkg/domain/entities/system.go b/pkg/domain/entities/system.go
new file mode 100644
index 000000000..3ddc04293
--- /dev/null
+++ b/pkg/domain/entities/system.go
@@ -0,0 +1,14 @@
+package entities
+
+import (
+ "time"
+
+ "github.com/spf13/cobra"
+)
+
+// ServiceOptions provides the input for starting an API Service
+type ServiceOptions struct {
+ URI string // Path to unix domain socket service should listen on
+ Timeout time.Duration // duration of inactivity the service should wait before shutting down
+ Command *cobra.Command // CLI command provided. Used in V1 code
+}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index ccbe6d4fd..a3a0a8202 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -4,9 +4,11 @@ package abi
import (
"context"
+ "fmt"
"io/ioutil"
"strconv"
"strings"
+ "sync"
"github.com/containers/buildah"
"github.com/containers/image/v5/manifest"
@@ -14,6 +16,7 @@ import (
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/libpod/logs"
"github.com/containers/libpod/pkg/checkpoint"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/infra/abi/terminal"
@@ -709,3 +712,99 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
}
return &report, nil
}
+
+func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []string, options entities.ContainerLogsOptions) error {
+ if options.Writer == nil {
+ return errors.New("no io.Writer set for container logs")
+ }
+
+ var wg sync.WaitGroup
+
+ ctrs, err := getContainersByContext(false, options.Latest, containers, ic.Libpod)
+ if err != nil {
+ return err
+ }
+
+ logOpts := &logs.LogOptions{
+ Multi: len(ctrs) > 1,
+ Details: options.Details,
+ Follow: options.Follow,
+ Since: options.Since,
+ Tail: options.Tail,
+ Timestamps: options.Timestamps,
+ UseName: options.Names,
+ WaitGroup: &wg,
+ }
+
+ chSize := len(ctrs) * int(options.Tail)
+ if chSize <= 0 {
+ chSize = 1
+ }
+ logChannel := make(chan *logs.LogLine, chSize)
+
+ if err := ic.Libpod.Log(ctrs, logOpts, logChannel); err != nil {
+ return err
+ }
+
+ go func() {
+ wg.Wait()
+ close(logChannel)
+ }()
+
+ for line := range logChannel {
+ fmt.Fprintln(options.Writer, line.String(logOpts))
+ }
+
+ return nil
+}
+
+func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []string, options entities.ContainerCleanupOptions) ([]*entities.ContainerCleanupReport, error) {
+ var reports []*entities.ContainerCleanupReport
+ ctrs, err := getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
+ if err != nil {
+ return nil, err
+ }
+ for _, ctr := range ctrs {
+ var err error
+ report := entities.ContainerCleanupReport{Id: ctr.ID()}
+ if options.Remove {
+ err = ic.Libpod.RemoveContainer(ctx, ctr, false, true)
+ if err != nil {
+ report.RmErr = errors.Wrapf(err, "failed to cleanup and remove container %v", ctr.ID())
+ }
+ } else {
+ err := ctr.Cleanup(ctx)
+ if err != nil {
+ report.CleanErr = errors.Wrapf(err, "failed to cleanup container %v", ctr.ID())
+ }
+ }
+
+ if options.RemoveImage {
+ _, imageName := ctr.Image()
+ ctrImage, err := ic.Libpod.ImageRuntime().NewFromLocal(imageName)
+ if err != nil {
+ report.RmiErr = err
+ reports = append(reports, &report)
+ continue
+ }
+ _, err = ic.Libpod.RemoveImage(ctx, ctrImage, false)
+ report.RmiErr = err
+ }
+ reports = append(reports, &report)
+ }
+ return reports, nil
+}
+
+func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []string, options entities.ContainerInitOptions) ([]*entities.ContainerInitReport, error) {
+ var reports []*entities.ContainerInitReport
+ ctrs, err := getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
+ if err != nil {
+ return nil, err
+ }
+ for _, ctr := range ctrs {
+ report := entities.ContainerInitReport{Id: ctr.ID()}
+ report.Err = ctr.Init(ctx)
+ reports = append(reports, &report)
+ }
+ return reports, nil
+}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 13abfa2e3..402bbb45e 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -15,6 +15,7 @@ import (
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/image"
libpodImage "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/domain/entities"
@@ -27,10 +28,11 @@ import (
)
func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) {
- if _, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId); err != nil {
- return &entities.BoolReport{}, nil
+ _, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
+ if err != nil && errors.Cause(err) != define.ErrNoSuchImage {
+ return nil, err
}
- return &entities.BoolReport{Value: true}, nil
+ return &entities.BoolReport{Value: err == nil}, nil
}
func (ir *ImageEngine) Delete(ctx context.Context, nameOrId []string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) {
@@ -392,8 +394,10 @@ func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions)
if err != nil {
return nil, errors.Wrap(err, "image loaded but no additional tags were created")
}
- if err := newImage.TagImage(opts.Name); err != nil {
- return nil, errors.Wrapf(err, "error adding %q to image %q", opts.Name, newImage.InputName)
+ if len(opts.Name) > 0 {
+ if err := newImage.TagImage(fmt.Sprintf("%s:%s", opts.Name, opts.Tag)); err != nil {
+ return nil, errors.Wrapf(err, "error adding %q to image %q", opts.Name, newImage.InputName)
+ }
}
return &entities.ImageLoadReport{Name: name}, nil
}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 8aaa69847..adec94f6c 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -4,10 +4,87 @@ package abi
import (
"context"
+ "net"
+ "strings"
"github.com/containers/libpod/libpod/define"
+ api "github.com/containers/libpod/pkg/api/server"
+ "github.com/containers/libpod/pkg/domain/entities"
+ iopodman "github.com/containers/libpod/pkg/varlink"
+ iopodmanAPI "github.com/containers/libpod/pkg/varlinkapi"
+ "github.com/containers/libpod/version"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "github.com/varlink/go/varlink"
)
func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) {
return ic.Libpod.Info()
}
+
+func (ic *ContainerEngine) RestService(_ context.Context, opts entities.ServiceOptions) error {
+ var (
+ listener net.Listener
+ err error
+ )
+
+ if opts.URI != "" {
+ fields := strings.Split(opts.URI, ":")
+ if len(fields) == 1 {
+ return errors.Errorf("%s is an invalid socket destination", opts.URI)
+ }
+ address := strings.Join(fields[1:], ":")
+ listener, err = net.Listen(fields[0], address)
+ if err != nil {
+ return errors.Wrapf(err, "unable to create socket %s", opts.URI)
+ }
+ }
+
+ server, err := api.NewServerWithSettings(ic.Libpod, opts.Timeout, &listener)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err := server.Shutdown(); err != nil {
+ logrus.Warnf("Error when stopping API service: %s", err)
+ }
+ }()
+
+ err = server.Serve()
+ _ = listener.Close()
+ return err
+}
+
+func (ic *ContainerEngine) VarlinkService(_ context.Context, opts entities.ServiceOptions) error {
+ var varlinkInterfaces = []*iopodman.VarlinkInterface{
+ iopodmanAPI.New(opts.Command, ic.Libpod),
+ }
+
+ service, err := varlink.NewService(
+ "Atomic",
+ "podman",
+ version.Version,
+ "https://github.com/containers/libpod",
+ )
+ if err != nil {
+ return errors.Wrapf(err, "unable to create new varlink service")
+ }
+
+ for _, i := range varlinkInterfaces {
+ if err := service.RegisterInterface(i); err != nil {
+ return errors.Errorf("unable to register varlink interface %v", i)
+ }
+ }
+
+ // Run the varlink server at the given address
+ if err = service.Listen(opts.URI, opts.Timeout); err != nil {
+ switch err.(type) {
+ case varlink.ServiceTimeoutError:
+ logrus.Infof("varlink service expired (use --timeout to increase session time beyond %s ms, 0 means never timeout)", opts.Timeout.String())
+ return nil
+ default:
+ return errors.Wrapf(err, "unable to start varlink service")
+ }
+ }
+ return nil
+}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index b22c6e3ba..1a430e3d0 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -242,7 +242,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
}
// narrow the list to running only
for _, c := range allCtrs {
- if c.State == define.ContainerStateRunning.String() {
+ if c.ContainerState == define.ContainerStateRunning.String() {
ctrs = append(ctrs, c)
}
}
@@ -276,7 +276,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
}
// narrow the list to exited only
for _, c := range allCtrs {
- if c.State == define.ContainerStateExited.String() {
+ if c.ContainerState == define.ContainerStateExited.String() {
ctrs = append(ctrs, c)
}
}
@@ -305,6 +305,11 @@ func (ic *ContainerEngine) ContainerCreate(ctx context.Context, s *specgen.SpecG
return &entities.ContainerCreateReport{Id: response.ID}, nil
}
+func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []string, options entities.ContainerLogsOptions) error {
+ // The endpoint is not ready yet and requires some more work.
+ return errors.New("not implemented yet")
+}
+
func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string, options entities.AttachOptions) error {
return errors.New("not implemented")
}
@@ -329,3 +334,23 @@ func (ic *ContainerEngine) ContainerDiff(ctx context.Context, nameOrId string, _
changes, err := containers.Diff(ic.ClientCxt, nameOrId)
return &entities.DiffReport{Changes: changes}, err
}
+
+func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []string, options entities.ContainerCleanupOptions) ([]*entities.ContainerCleanupReport, error) {
+ return nil, errors.New("not implemented")
+}
+
+func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []string, options entities.ContainerInitOptions) ([]*entities.ContainerInitReport, error) {
+ var reports []*entities.ContainerInitReport
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
+ if err != nil {
+ return nil, err
+ }
+ for _, ctr := range ctrs {
+ err := containers.ContainerInit(ic.ClientCxt, ctr.ID)
+ reports = append(reports, &entities.ContainerInitReport{
+ Err: err,
+ Id: ctr.ID,
+ })
+ }
+ return reports, nil
+}
diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go
index 682d60d6a..4d7e45897 100644
--- a/pkg/domain/infra/tunnel/helpers.go
+++ b/pkg/domain/infra/tunnel/helpers.go
@@ -30,7 +30,7 @@ func getContainersByContext(contextWithConnection context.Context, all bool, nam
for _, id := range namesOrIds {
var found bool
for _, con := range c {
- if id == con.ID || strings.HasPrefix(con.ID, id) || util.StringInSlice(id, con.Names) {
+ if id == con.ID || strings.HasPrefix(con.ID, id) || util.StringInSlice(id, con.ContainerNames) {
cons = append(cons, con)
found = true
break
diff --git a/pkg/domain/infra/tunnel/system.go b/pkg/domain/infra/tunnel/system.go
index 5d6346234..7c7a55c05 100644
--- a/pkg/domain/infra/tunnel/system.go
+++ b/pkg/domain/infra/tunnel/system.go
@@ -2,11 +2,21 @@ package tunnel
import (
"context"
+ "errors"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/bindings/system"
+ "github.com/containers/libpod/pkg/domain/entities"
)
func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) {
return system.Info(ic.ClientCxt)
}
+
+func (ic *ContainerEngine) RestService(_ context.Context, _ entities.ServiceOptions) error {
+ panic(errors.New("rest service is not supported when tunneling"))
+}
+
+func (ic *ContainerEngine) VarlinkService(_ context.Context, _ entities.ServiceOptions) error {
+ panic(errors.New("varlink service is not supported when tunneling"))
+}
diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go
index 58fcc2c21..9217fa595 100644
--- a/pkg/ps/ps.go
+++ b/pkg/ps/ps.go
@@ -148,23 +148,23 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
}
ps := entities.ListContainer{
- Command: conConfig.Command,
- Created: conConfig.CreatedTime.Unix(),
- Exited: exited,
- ExitCode: exitCode,
- ExitedAt: exitedTime.Unix(),
- ID: conConfig.ID,
- Image: conConfig.RootfsImageName,
- IsInfra: conConfig.IsInfra,
- Labels: conConfig.Labels,
- Mounts: ctr.UserVolumes(),
- Names: []string{conConfig.Name},
- Pid: pid,
- Pod: conConfig.Pod,
- Ports: conConfig.PortMappings,
- Size: size,
- StartedAt: startedTime.Unix(),
- State: conState.String(),
+ Cmd: conConfig.Command,
+ Created: conConfig.CreatedTime.Unix(),
+ Exited: exited,
+ ExitCode: exitCode,
+ ExitedAt: exitedTime.Unix(),
+ ID: conConfig.ID,
+ Image: conConfig.RootfsImageName,
+ IsInfra: conConfig.IsInfra,
+ Labels: conConfig.Labels,
+ Mounts: ctr.UserVolumes(),
+ ContainerNames: []string{conConfig.Name},
+ Pid: pid,
+ Pod: conConfig.Pod,
+ PortMappings: conConfig.PortMappings,
+ ContainerSize: size,
+ StartedAt: startedTime.Unix(),
+ ContainerState: conState.String(),
}
if opts.Pod && len(conConfig.Pod) > 0 {
pod, err := rt.GetPod(conConfig.Pod)
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 6643bfbbf..da52a7217 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -288,6 +288,7 @@ static void __attribute__((constructor)) init()
char *cwd = getcwd (NULL, 0);
char uid_fmt[16];
char gid_fmt[16];
+ size_t len;
if (cwd == NULL)
{
@@ -295,13 +296,13 @@ static void __attribute__((constructor)) init()
_exit (EXIT_FAILURE);
}
- if (strlen (xdg_runtime_dir) >= PATH_MAX - strlen (suffix))
+ len = snprintf (path, PATH_MAX, "%s%s", xdg_runtime_dir, suffix);
+ if (len >= PATH_MAX)
{
fprintf (stderr, "invalid value for XDG_RUNTIME_DIR: %s", strerror (ENAMETOOLONG));
exit (EXIT_FAILURE);
}
- sprintf (path, "%s%s", xdg_runtime_dir, suffix);
fd = open (path, O_RDONLY);
if (fd < 0)
{
diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go
index 76ab16ec7..e6e0f1ca1 100644
--- a/pkg/signal/signal_linux.go
+++ b/pkg/signal/signal_linux.go
@@ -129,14 +129,15 @@ func StopCatch(sigc chan os.Signal) {
// ParseSignalNameOrNumber translates a string to a valid syscall signal. Input
// can be a name or number representation i.e. "KILL" "9"
func ParseSignalNameOrNumber(rawSignal string) (syscall.Signal, error) {
- s, err := ParseSignal(rawSignal)
+ basename := strings.TrimPrefix(rawSignal, "-")
+ s, err := ParseSignal(basename)
if err == nil {
return s, nil
}
for k, v := range signalMap {
- if k == strings.ToUpper(rawSignal) {
+ if k == strings.ToUpper(basename) {
return v, nil
}
}
- return -1, fmt.Errorf("invalid signal: %s", rawSignal)
+ return -1, fmt.Errorf("invalid signal: %s", basename)
}
diff --git a/pkg/specgen/pod_validate.go b/pkg/specgen/pod_validate.go
index 50309f096..92026309f 100644
--- a/pkg/specgen/pod_validate.go
+++ b/pkg/specgen/pod_validate.go
@@ -25,7 +25,7 @@ func (p *PodSpecGenerator) validate() error {
return exclusivePodOptions("NoInfra", "InfraImage")
}
if len(p.SharedNamespaces) > 0 {
- return exclusivePodOptions("NoInfo", "SharedNamespaces")
+ return exclusivePodOptions("NoInfra", "SharedNamespaces")
}
}
diff --git a/pkg/varlinkapi/attach.go b/pkg/varlinkapi/attach.go
index 34f351669..db977ee5c 100644
--- a/pkg/varlinkapi/attach.go
+++ b/pkg/varlinkapi/attach.go
@@ -44,7 +44,7 @@ func setupStreams(call iopodman.VarlinkCall) (*bufio.Reader, *bufio.Writer, *io.
}
// Attach connects to a containers console
-func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys string, start bool) error {
+func (i *VarlinkAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys string, start bool) error {
var finalErr error
resize := make(chan remotecommand.TerminalSize)
errChan := make(chan error)
diff --git a/pkg/varlinkapi/config.go b/pkg/varlinkapi/config.go
index c69dc794a..cc787eca2 100644
--- a/pkg/varlinkapi/config.go
+++ b/pkg/varlinkapi/config.go
@@ -3,21 +3,20 @@
package varlinkapi
import (
- "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/spf13/cobra"
)
-// LibpodAPI is the basic varlink struct for libpod
-type LibpodAPI struct {
+// VarlinkAPI is the basic varlink struct for libpod
+type VarlinkAPI struct {
Cli *cobra.Command
iopodman.VarlinkInterface
Runtime *libpod.Runtime
}
// New creates a new varlink client
-func New(cli *cliconfig.PodmanCommand, runtime *libpod.Runtime) *iopodman.VarlinkInterface {
- lp := LibpodAPI{Cli: cli.Command, Runtime: runtime}
+func New(cli *cobra.Command, runtime *libpod.Runtime) *iopodman.VarlinkInterface {
+ lp := VarlinkAPI{Cli: cli, Runtime: runtime}
return iopodman.VarlinkNew(&lp)
}
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index 2d051470f..66b3e4095 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -30,7 +30,7 @@ import (
)
// ListContainers ...
-func (i *LibpodAPI) ListContainers(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) ListContainers(call iopodman.VarlinkCall) error {
var (
listContainers []iopodman.Container
)
@@ -54,7 +54,7 @@ func (i *LibpodAPI) ListContainers(call iopodman.VarlinkCall) error {
return call.ReplyListContainers(listContainers)
}
-func (i *LibpodAPI) Ps(call iopodman.VarlinkCall, opts iopodman.PsOpts) error {
+func (i *VarlinkAPI) Ps(call iopodman.VarlinkCall, opts iopodman.PsOpts) error {
var (
containers []iopodman.PsContainer
)
@@ -106,7 +106,7 @@ func (i *LibpodAPI) Ps(call iopodman.VarlinkCall, opts iopodman.PsOpts) error {
}
// GetContainer ...
-func (i *LibpodAPI) GetContainer(call iopodman.VarlinkCall, id string) error {
+func (i *VarlinkAPI) GetContainer(call iopodman.VarlinkCall, id string) error {
ctr, err := i.Runtime.LookupContainer(id)
if err != nil {
return call.ReplyContainerNotFound(id, err.Error())
@@ -123,7 +123,7 @@ func (i *LibpodAPI) GetContainer(call iopodman.VarlinkCall, id string) error {
}
// GetContainersByContext returns a slice of container ids based on all, latest, or a list
-func (i *LibpodAPI) GetContainersByContext(call iopodman.VarlinkCall, all, latest bool, input []string) error {
+func (i *VarlinkAPI) GetContainersByContext(call iopodman.VarlinkCall, all, latest bool, input []string) error {
var ids []string
ctrs, err := shortcuts.GetContainersByContext(all, latest, input, i.Runtime)
@@ -141,7 +141,7 @@ func (i *LibpodAPI) GetContainersByContext(call iopodman.VarlinkCall, all, lates
}
// GetContainersByStatus returns a slice of containers filtered by a libpod status
-func (i *LibpodAPI) GetContainersByStatus(call iopodman.VarlinkCall, statuses []string) error {
+func (i *VarlinkAPI) GetContainersByStatus(call iopodman.VarlinkCall, statuses []string) error {
var (
filterFuncs []libpod.ContainerFilter
containers []iopodman.Container
@@ -172,7 +172,7 @@ func (i *LibpodAPI) GetContainersByStatus(call iopodman.VarlinkCall, statuses []
}
// InspectContainer ...
-func (i *LibpodAPI) InspectContainer(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) InspectContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -189,7 +189,7 @@ func (i *LibpodAPI) InspectContainer(call iopodman.VarlinkCall, name string) err
}
// ListContainerProcesses ...
-func (i *LibpodAPI) ListContainerProcesses(call iopodman.VarlinkCall, name string, opts []string) error {
+func (i *VarlinkAPI) ListContainerProcesses(call iopodman.VarlinkCall, name string, opts []string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -216,7 +216,7 @@ func (i *LibpodAPI) ListContainerProcesses(call iopodman.VarlinkCall, name strin
}
// GetContainerLogs ...
-func (i *LibpodAPI) GetContainerLogs(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) GetContainerLogs(call iopodman.VarlinkCall, name string) error {
var logs []string
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
@@ -277,7 +277,7 @@ func (i *LibpodAPI) GetContainerLogs(call iopodman.VarlinkCall, name string) err
}
// ListContainerChanges ...
-func (i *LibpodAPI) ListContainerChanges(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) ListContainerChanges(call iopodman.VarlinkCall, name string) error {
changes, err := i.Runtime.GetDiff("", name)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -297,7 +297,7 @@ func (i *LibpodAPI) ListContainerChanges(call iopodman.VarlinkCall, name string)
}
// ExportContainer ...
-func (i *LibpodAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath string) error {
+func (i *VarlinkAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -319,7 +319,7 @@ func (i *LibpodAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath str
}
// GetContainerStats ...
-func (i *LibpodAPI) GetContainerStats(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) GetContainerStats(call iopodman.VarlinkCall, name string) error {
if rootless.IsRootless() {
cgroupv2, err := cgroups.IsCgroup2UnifiedMode()
if err != nil {
@@ -359,7 +359,7 @@ func (i *LibpodAPI) GetContainerStats(call iopodman.VarlinkCall, name string) er
}
// StartContainer ...
-func (i *LibpodAPI) StartContainer(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) StartContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -382,7 +382,7 @@ func (i *LibpodAPI) StartContainer(call iopodman.VarlinkCall, name string) error
}
// InitContainer initializes the container given by Varlink.
-func (i *LibpodAPI) InitContainer(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) InitContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -397,7 +397,7 @@ func (i *LibpodAPI) InitContainer(call iopodman.VarlinkCall, name string) error
}
// StopContainer ...
-func (i *LibpodAPI) StopContainer(call iopodman.VarlinkCall, name string, timeout int64) error {
+func (i *VarlinkAPI) StopContainer(call iopodman.VarlinkCall, name string, timeout int64) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -415,7 +415,7 @@ func (i *LibpodAPI) StopContainer(call iopodman.VarlinkCall, name string, timeou
}
// RestartContainer ...
-func (i *LibpodAPI) RestartContainer(call iopodman.VarlinkCall, name string, timeout int64) error {
+func (i *VarlinkAPI) RestartContainer(call iopodman.VarlinkCall, name string, timeout int64) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -427,7 +427,7 @@ func (i *LibpodAPI) RestartContainer(call iopodman.VarlinkCall, name string, tim
}
// ContainerExists looks in local storage for the existence of a container
-func (i *LibpodAPI) ContainerExists(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) ContainerExists(call iopodman.VarlinkCall, name string) error {
_, err := i.Runtime.LookupContainer(name)
if errors.Cause(err) == define.ErrNoSuchCtr {
return call.ReplyContainerExists(1)
@@ -440,7 +440,7 @@ func (i *LibpodAPI) ContainerExists(call iopodman.VarlinkCall, name string) erro
// KillContainer kills a running container. If you want to use the default SIGTERM signal, just send a -1
// for the signal arg.
-func (i *LibpodAPI) KillContainer(call iopodman.VarlinkCall, name string, signal int64) error {
+func (i *VarlinkAPI) KillContainer(call iopodman.VarlinkCall, name string, signal int64) error {
killSignal := uint(syscall.SIGTERM)
if signal != -1 {
killSignal = uint(signal)
@@ -456,7 +456,7 @@ func (i *LibpodAPI) KillContainer(call iopodman.VarlinkCall, name string, signal
}
// PauseContainer ...
-func (i *LibpodAPI) PauseContainer(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) PauseContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -468,7 +468,7 @@ func (i *LibpodAPI) PauseContainer(call iopodman.VarlinkCall, name string) error
}
// UnpauseContainer ...
-func (i *LibpodAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -480,7 +480,7 @@ func (i *LibpodAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) err
}
// WaitContainer ...
-func (i *LibpodAPI) WaitContainer(call iopodman.VarlinkCall, name string, interval int64) error {
+func (i *VarlinkAPI) WaitContainer(call iopodman.VarlinkCall, name string, interval int64) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -493,7 +493,7 @@ func (i *LibpodAPI) WaitContainer(call iopodman.VarlinkCall, name string, interv
}
// RemoveContainer ...
-func (i *LibpodAPI) RemoveContainer(call iopodman.VarlinkCall, name string, force bool, removeVolumes bool) error {
+func (i *VarlinkAPI) RemoveContainer(call iopodman.VarlinkCall, name string, force bool, removeVolumes bool) error {
ctx := getContext()
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
@@ -512,7 +512,7 @@ func (i *LibpodAPI) RemoveContainer(call iopodman.VarlinkCall, name string, forc
}
// EvictContainer ...
-func (i *LibpodAPI) EvictContainer(call iopodman.VarlinkCall, name string, removeVolumes bool) error {
+func (i *VarlinkAPI) EvictContainer(call iopodman.VarlinkCall, name string, removeVolumes bool) error {
ctx := getContext()
id, err := i.Runtime.EvictContainer(ctx, name, removeVolumes)
if err != nil {
@@ -522,7 +522,7 @@ func (i *LibpodAPI) EvictContainer(call iopodman.VarlinkCall, name string, remov
}
// DeleteStoppedContainers ...
-func (i *LibpodAPI) DeleteStoppedContainers(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) DeleteStoppedContainers(call iopodman.VarlinkCall) error {
ctx := getContext()
var deletedContainers []string
containers, err := i.Runtime.GetAllContainers()
@@ -545,7 +545,7 @@ func (i *LibpodAPI) DeleteStoppedContainers(call iopodman.VarlinkCall) error {
}
// GetAttachSockets ...
-func (i *LibpodAPI) GetAttachSockets(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) GetAttachSockets(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -578,7 +578,7 @@ func (i *LibpodAPI) GetAttachSockets(call iopodman.VarlinkCall, name string) err
}
// ContainerCheckpoint ...
-func (i *LibpodAPI) ContainerCheckpoint(call iopodman.VarlinkCall, name string, keep, leaveRunning, tcpEstablished bool) error {
+func (i *VarlinkAPI) ContainerCheckpoint(call iopodman.VarlinkCall, name string, keep, leaveRunning, tcpEstablished bool) error {
ctx := getContext()
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
@@ -597,7 +597,7 @@ func (i *LibpodAPI) ContainerCheckpoint(call iopodman.VarlinkCall, name string,
}
// ContainerRestore ...
-func (i *LibpodAPI) ContainerRestore(call iopodman.VarlinkCall, name string, keep, tcpEstablished bool) error {
+func (i *VarlinkAPI) ContainerRestore(call iopodman.VarlinkCall, name string, keep, tcpEstablished bool) error {
ctx := getContext()
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
@@ -615,7 +615,7 @@ func (i *LibpodAPI) ContainerRestore(call iopodman.VarlinkCall, name string, kee
}
// ContainerConfig returns just the container.config struct
-func (i *LibpodAPI) ContainerConfig(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) ContainerConfig(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -629,7 +629,7 @@ func (i *LibpodAPI) ContainerConfig(call iopodman.VarlinkCall, name string) erro
}
// ContainerArtifacts returns an untouched container's artifact in string format
-func (i *LibpodAPI) ContainerArtifacts(call iopodman.VarlinkCall, name, artifactName string) error {
+func (i *VarlinkAPI) ContainerArtifacts(call iopodman.VarlinkCall, name, artifactName string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -646,7 +646,7 @@ func (i *LibpodAPI) ContainerArtifacts(call iopodman.VarlinkCall, name, artifact
}
// ContainerInspectData returns the inspect data of a container in string format
-func (i *LibpodAPI) ContainerInspectData(call iopodman.VarlinkCall, name string, size bool) error {
+func (i *VarlinkAPI) ContainerInspectData(call iopodman.VarlinkCall, name string, size bool) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -664,7 +664,7 @@ func (i *LibpodAPI) ContainerInspectData(call iopodman.VarlinkCall, name string,
}
// ContainerStateData returns a container's state data in string format
-func (i *LibpodAPI) ContainerStateData(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) ContainerStateData(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -682,7 +682,7 @@ func (i *LibpodAPI) ContainerStateData(call iopodman.VarlinkCall, name string) e
// GetContainerStatsWithHistory is a varlink endpoint that returns container stats based on current and
// previous statistics
-func (i *LibpodAPI) GetContainerStatsWithHistory(call iopodman.VarlinkCall, prevStats iopodman.ContainerStats) error {
+func (i *VarlinkAPI) GetContainerStatsWithHistory(call iopodman.VarlinkCall, prevStats iopodman.ContainerStats) error {
con, err := i.Runtime.LookupContainer(prevStats.Id)
if err != nil {
return call.ReplyContainerNotFound(prevStats.Id, err.Error())
@@ -711,7 +711,7 @@ func (i *LibpodAPI) GetContainerStatsWithHistory(call iopodman.VarlinkCall, prev
}
// Spec ...
-func (i *LibpodAPI) Spec(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) Spec(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -727,7 +727,7 @@ func (i *LibpodAPI) Spec(call iopodman.VarlinkCall, name string) error {
}
// GetContainersLogs is the varlink endpoint to obtain one or more container logs
-func (i *LibpodAPI) GetContainersLogs(call iopodman.VarlinkCall, names []string, follow, latest bool, since string, tail int64, timestamps bool) error {
+func (i *VarlinkAPI) GetContainersLogs(call iopodman.VarlinkCall, names []string, follow, latest bool, since string, tail int64, timestamps bool) error {
var wg sync.WaitGroup
if call.WantsMore() {
call.Continues = true
@@ -784,7 +784,7 @@ func newPodmanLogLine(line *logs.LogLine) iopodman.LogLine {
}
// Top displays information about a container's running processes
-func (i *LibpodAPI) Top(call iopodman.VarlinkCall, nameOrID string, descriptors []string) error {
+func (i *VarlinkAPI) Top(call iopodman.VarlinkCall, nameOrID string, descriptors []string) error {
ctr, err := i.Runtime.LookupContainer(nameOrID)
if err != nil {
return call.ReplyContainerNotFound(ctr.ID(), err.Error())
@@ -797,7 +797,7 @@ func (i *LibpodAPI) Top(call iopodman.VarlinkCall, nameOrID string, descriptors
}
// ExecContainer is the varlink endpoint to execute a command in a container
-func (i *LibpodAPI) ExecContainer(call iopodman.VarlinkCall, opts iopodman.ExecOpts) error {
+func (i *VarlinkAPI) ExecContainer(call iopodman.VarlinkCall, opts iopodman.ExecOpts) error {
if !call.WantsUpgrade() {
return call.ReplyErrorOccurred("client must use upgraded connection to exec")
}
@@ -901,7 +901,7 @@ func (i *LibpodAPI) ExecContainer(call iopodman.VarlinkCall, opts iopodman.ExecO
}
// HealthCheckRun executes defined container's healthcheck command and returns the container's health status.
-func (i *LibpodAPI) HealthCheckRun(call iopodman.VarlinkCall, nameOrID string) error {
+func (i *VarlinkAPI) HealthCheckRun(call iopodman.VarlinkCall, nameOrID string) error {
hcStatus, err := i.Runtime.HealthCheck(nameOrID)
if err != nil && hcStatus != libpod.HealthCheckFailure {
return call.ReplyErrorOccurred(err.Error())
diff --git a/pkg/varlinkapi/containers_create.go b/pkg/varlinkapi/containers_create.go
index bbd4d59f1..c1c1f6674 100644
--- a/pkg/varlinkapi/containers_create.go
+++ b/pkg/varlinkapi/containers_create.go
@@ -8,7 +8,7 @@ import (
)
// CreateContainer ...
-func (i *LibpodAPI) CreateContainer(call iopodman.VarlinkCall, config iopodman.Create) error {
+func (i *VarlinkAPI) CreateContainer(call iopodman.VarlinkCall, config iopodman.Create) error {
generic := shared.VarlinkCreateToGeneric(config)
ctr, _, err := shared.CreateContainer(getContext(), &generic, i.Runtime)
if err != nil {
diff --git a/pkg/varlinkapi/events.go b/pkg/varlinkapi/events.go
index 4ae2d1cb2..33938f08b 100644
--- a/pkg/varlinkapi/events.go
+++ b/pkg/varlinkapi/events.go
@@ -3,7 +3,6 @@
package varlinkapi
import (
- "fmt"
"time"
"github.com/containers/libpod/libpod/events"
@@ -11,7 +10,7 @@ import (
)
// GetEvents is a remote endpoint to get events from the event log
-func (i *LibpodAPI) GetEvents(call iopodman.VarlinkCall, filter []string, since string, until string) error {
+func (i *VarlinkAPI) GetEvents(call iopodman.VarlinkCall, filter []string, since string, until string) error {
var (
fromStart bool
eventsError error
@@ -43,9 +42,9 @@ func (i *LibpodAPI) GetEvents(call iopodman.VarlinkCall, filter []string, since
Id: event.ID,
Image: event.Image,
Name: event.Name,
- Status: fmt.Sprintf("%s", event.Status),
+ Status: string(event.Status),
Time: event.Time.Format(time.RFC3339Nano),
- Type: fmt.Sprintf("%s", event.Type),
+ Type: string(event.Type),
})
if !call.Continues {
// For a one-shot on events, we break out here
diff --git a/pkg/varlinkapi/generate.go b/pkg/varlinkapi/generate.go
index c19c8dede..81a0df68e 100644
--- a/pkg/varlinkapi/generate.go
+++ b/pkg/varlinkapi/generate.go
@@ -10,7 +10,7 @@ import (
)
// GenerateKube ...
-func (i *LibpodAPI) GenerateKube(call iopodman.VarlinkCall, name string, service bool) error {
+func (i *VarlinkAPI) GenerateKube(call iopodman.VarlinkCall, name string, service bool) error {
pod, serv, err := shared.GenerateKube(name, service, i.Runtime)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
index c3b4bd9ae..49bd0b0cb 100644
--- a/pkg/varlinkapi/images.go
+++ b/pkg/varlinkapi/images.go
@@ -35,14 +35,14 @@ import (
)
// ListImagesWithFilters returns a list of images that have been filtered
-func (i *LibpodAPI) ListImagesWithFilters(call iopodman.VarlinkCall, filters []string) error {
+func (i *VarlinkAPI) ListImagesWithFilters(call iopodman.VarlinkCall, filters []string) error {
images, err := i.Runtime.ImageRuntime().GetImagesWithFilters(filters)
if err != nil {
return call.ReplyErrorOccurred(fmt.Sprintf("unable to get list of images %q", err))
}
imageList, err := imagesToImageList(images)
if err != nil {
- return call.ReplyErrorOccurred(fmt.Sprintf("unable to parse response", err))
+ return call.ReplyErrorOccurred("unable to parse response " + err.Error())
}
return call.ReplyListImagesWithFilters(imageList)
}
@@ -50,34 +50,34 @@ func (i *LibpodAPI) ListImagesWithFilters(call iopodman.VarlinkCall, filters []s
// imagesToImageList converts a slice of Images to an imagelist for varlink responses
func imagesToImageList(images []*image.Image) ([]iopodman.Image, error) {
var imageList []iopodman.Image
- for _, image := range images {
- labels, _ := image.Labels(getContext())
- containers, _ := image.Containers()
- repoDigests, err := image.RepoDigests()
+ for _, img := range images {
+ labels, _ := img.Labels(getContext())
+ containers, _ := img.Containers()
+ repoDigests, err := img.RepoDigests()
if err != nil {
return nil, err
}
- size, _ := image.Size(getContext())
- isParent, err := image.IsParent(context.TODO())
+ size, _ := img.Size(getContext())
+ isParent, err := img.IsParent(context.TODO())
if err != nil {
return nil, err
}
i := iopodman.Image{
- Id: image.ID(),
- Digest: string(image.Digest()),
- ParentId: image.Parent,
- RepoTags: image.Names(),
+ Id: img.ID(),
+ Digest: string(img.Digest()),
+ ParentId: img.Parent,
+ RepoTags: img.Names(),
RepoDigests: repoDigests,
- Created: image.Created().Format(time.RFC3339),
+ Created: img.Created().Format(time.RFC3339),
Size: int64(*size),
- VirtualSize: image.VirtualSize,
+ VirtualSize: img.VirtualSize,
Containers: int64(len(containers)),
Labels: labels,
IsParent: isParent,
- ReadOnly: image.IsReadOnly(),
- History: image.NamesHistory(),
+ ReadOnly: img.IsReadOnly(),
+ History: img.NamesHistory(),
}
imageList = append(imageList, i)
}
@@ -86,20 +86,20 @@ func imagesToImageList(images []*image.Image) ([]iopodman.Image, error) {
// ListImages lists all the images in the store
// It requires no inputs.
-func (i *LibpodAPI) ListImages(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) ListImages(call iopodman.VarlinkCall) error {
images, err := i.Runtime.ImageRuntime().GetImages()
if err != nil {
- return call.ReplyErrorOccurred(fmt.Sprintf("unable to get list of images %q", err))
+ return call.ReplyErrorOccurred("unable to get list of images " + err.Error())
}
imageList, err := imagesToImageList(images)
if err != nil {
- return call.ReplyErrorOccurred(fmt.Sprintf("unable to parse response", err))
+ return call.ReplyErrorOccurred("unable to parse response " + err.Error())
}
return call.ReplyListImages(imageList)
}
// GetImage returns a single image in the form of a Image
-func (i *LibpodAPI) GetImage(call iopodman.VarlinkCall, id string) error {
+func (i *VarlinkAPI) GetImage(call iopodman.VarlinkCall, id string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(id)
if err != nil {
return call.ReplyImageNotFound(id, err.Error())
@@ -139,7 +139,7 @@ func (i *LibpodAPI) GetImage(call iopodman.VarlinkCall, id string) error {
}
// BuildImage ...
-func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildInfo) error {
+func (i *VarlinkAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildInfo) error {
var (
namespace []buildah.NamespaceOption
imageID string
@@ -302,7 +302,7 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI
// InspectImage returns an image's inspect information as a string that can be serialized.
// Requires an image ID or name
-func (i *LibpodAPI) InspectImage(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) InspectImage(call iopodman.VarlinkCall, name string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
return call.ReplyImageNotFound(name, err.Error())
@@ -320,7 +320,7 @@ func (i *LibpodAPI) InspectImage(call iopodman.VarlinkCall, name string) error {
// HistoryImage returns the history of the image's layers
// Requires an image or name
-func (i *LibpodAPI) HistoryImage(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) HistoryImage(call iopodman.VarlinkCall, name string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
return call.ReplyImageNotFound(name, err.Error())
@@ -345,7 +345,7 @@ func (i *LibpodAPI) HistoryImage(call iopodman.VarlinkCall, name string) error {
}
// PushImage pushes an local image to registry
-func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, compress bool, format string, removeSignatures bool, signBy string) error {
+func (i *VarlinkAPI) PushImage(call iopodman.VarlinkCall, name, tag string, compress bool, format string, removeSignatures bool, signBy string) error {
var (
manifestType string
)
@@ -437,7 +437,7 @@ func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, compr
}
// TagImage accepts an image name and tag as strings and tags an image in the local store.
-func (i *LibpodAPI) TagImage(call iopodman.VarlinkCall, name, tag string) error {
+func (i *VarlinkAPI) TagImage(call iopodman.VarlinkCall, name, tag string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
return call.ReplyImageNotFound(name, err.Error())
@@ -449,7 +449,7 @@ func (i *LibpodAPI) TagImage(call iopodman.VarlinkCall, name, tag string) error
}
// UntagImage accepts an image name and tag as strings and removes the tag from the local store.
-func (i *LibpodAPI) UntagImage(call iopodman.VarlinkCall, name, tag string) error {
+func (i *VarlinkAPI) UntagImage(call iopodman.VarlinkCall, name, tag string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
return call.ReplyImageNotFound(name, err.Error())
@@ -462,7 +462,7 @@ func (i *LibpodAPI) UntagImage(call iopodman.VarlinkCall, name, tag string) erro
// RemoveImage accepts a image name or ID as a string and force bool to determine if it should
// remove the image even if being used by stopped containers
-func (i *LibpodAPI) RemoveImage(call iopodman.VarlinkCall, name string, force bool) error {
+func (i *VarlinkAPI) RemoveImage(call iopodman.VarlinkCall, name string, force bool) error {
ctx := getContext()
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
@@ -477,7 +477,7 @@ func (i *LibpodAPI) RemoveImage(call iopodman.VarlinkCall, name string, force bo
// RemoveImageWithResponse accepts an image name and force bool. It returns details about what
// was done in removeimageresponse struct.
-func (i *LibpodAPI) RemoveImageWithResponse(call iopodman.VarlinkCall, name string, force bool) error {
+func (i *VarlinkAPI) RemoveImageWithResponse(call iopodman.VarlinkCall, name string, force bool) error {
ir := iopodman.RemoveImageResponse{}
ctx := getContext()
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
@@ -495,7 +495,7 @@ func (i *LibpodAPI) RemoveImageWithResponse(call iopodman.VarlinkCall, name stri
// SearchImages searches all registries configured in /etc/containers/registries.conf for an image
// Requires an image name and a search limit as int
-func (i *LibpodAPI) SearchImages(call iopodman.VarlinkCall, query string, limit *int64, filter iopodman.ImageSearchFilter) error {
+func (i *VarlinkAPI) SearchImages(call iopodman.VarlinkCall, query string, limit *int64, filter iopodman.ImageSearchFilter) error {
// Transform all arguments to proper types first
argLimit := 0
argIsOfficial := types.OptionalBoolUndefined
@@ -543,7 +543,7 @@ func (i *LibpodAPI) SearchImages(call iopodman.VarlinkCall, query string, limit
// DeleteUnusedImages deletes any images that do not have containers associated with it.
// TODO Filters are not implemented
-func (i *LibpodAPI) DeleteUnusedImages(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) DeleteUnusedImages(call iopodman.VarlinkCall) error {
images, err := i.Runtime.ImageRuntime().GetImages()
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -565,7 +565,7 @@ func (i *LibpodAPI) DeleteUnusedImages(call iopodman.VarlinkCall) error {
}
// Commit ...
-func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, changes []string, author, message string, pause bool, manifestType string) error {
+func (i *VarlinkAPI) Commit(call iopodman.VarlinkCall, name, imageName string, changes []string, author, message string, pause bool, manifestType string) error {
var (
newImage *image.Image
log []string
@@ -643,7 +643,7 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch
}
// ImportImage imports an image from a tarball to the image store
-func (i *LibpodAPI) ImportImage(call iopodman.VarlinkCall, source, reference, message string, changes []string, delete bool) error {
+func (i *VarlinkAPI) ImportImage(call iopodman.VarlinkCall, source, reference, message string, changes []string, delete bool) error {
configChanges, err := util.GetImageConfig(changes)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -670,7 +670,7 @@ func (i *LibpodAPI) ImportImage(call iopodman.VarlinkCall, source, reference, me
// ExportImage exports an image to the provided destination
// destination must have the transport type!!
-func (i *LibpodAPI) ExportImage(call iopodman.VarlinkCall, name, destination string, compress bool, tags []string) error {
+func (i *VarlinkAPI) ExportImage(call iopodman.VarlinkCall, name, destination string, compress bool, tags []string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
return call.ReplyImageNotFound(name, err.Error())
@@ -688,7 +688,7 @@ func (i *LibpodAPI) ExportImage(call iopodman.VarlinkCall, name, destination str
}
// PullImage pulls an image from a registry to the image store.
-func (i *LibpodAPI) PullImage(call iopodman.VarlinkCall, name string, creds iopodman.AuthConfig) error {
+func (i *VarlinkAPI) PullImage(call iopodman.VarlinkCall, name string, creds iopodman.AuthConfig) error {
var (
imageID string
err error
@@ -760,7 +760,7 @@ func (i *LibpodAPI) PullImage(call iopodman.VarlinkCall, name string, creds iopo
}
// ImageExists returns bool as to whether the input image exists in local storage
-func (i *LibpodAPI) ImageExists(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) ImageExists(call iopodman.VarlinkCall, name string) error {
_, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if errors.Cause(err) == image.ErrNoSuchImage {
return call.ReplyImageExists(1)
@@ -772,7 +772,7 @@ func (i *LibpodAPI) ImageExists(call iopodman.VarlinkCall, name string) error {
}
// ContainerRunlabel ...
-func (i *LibpodAPI) ContainerRunlabel(call iopodman.VarlinkCall, input iopodman.Runlabel) error {
+func (i *VarlinkAPI) ContainerRunlabel(call iopodman.VarlinkCall, input iopodman.Runlabel) error {
ctx := getContext()
dockerRegistryOptions := image.DockerRegistryOptions{}
stdErr := os.Stderr
@@ -798,7 +798,7 @@ func (i *LibpodAPI) ContainerRunlabel(call iopodman.VarlinkCall, input iopodman.
}
// ImagesPrune ....
-func (i *LibpodAPI) ImagesPrune(call iopodman.VarlinkCall, all bool, filter []string) error {
+func (i *VarlinkAPI) ImagesPrune(call iopodman.VarlinkCall, all bool, filter []string) error {
prunedImages, err := i.Runtime.ImageRuntime().PruneImages(context.TODO(), all, []string{})
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -807,7 +807,7 @@ func (i *LibpodAPI) ImagesPrune(call iopodman.VarlinkCall, all bool, filter []st
}
// ImageSave ....
-func (i *LibpodAPI) ImageSave(call iopodman.VarlinkCall, options iopodman.ImageSaveOptions) error {
+func (i *VarlinkAPI) ImageSave(call iopodman.VarlinkCall, options iopodman.ImageSaveOptions) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(options.Name)
if err != nil {
if errors.Cause(err) == define.ErrNoSuchImage {
@@ -905,7 +905,7 @@ func (i *LibpodAPI) ImageSave(call iopodman.VarlinkCall, options iopodman.ImageS
}
// LoadImage ...
-func (i *LibpodAPI) LoadImage(call iopodman.VarlinkCall, name, inputFile string, deleteInputFile, quiet bool) error {
+func (i *VarlinkAPI) LoadImage(call iopodman.VarlinkCall, name, inputFile string, deleteInputFile, quiet bool) error {
var (
names string
writer io.Writer
@@ -974,7 +974,7 @@ func (i *LibpodAPI) LoadImage(call iopodman.VarlinkCall, name, inputFile string,
}
// Diff ...
-func (i *LibpodAPI) Diff(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) Diff(call iopodman.VarlinkCall, name string) error {
var response []iopodman.DiffInfo
changes, err := i.Runtime.GetDiff("", name)
if err != nil {
@@ -987,7 +987,7 @@ func (i *LibpodAPI) Diff(call iopodman.VarlinkCall, name string) error {
}
// GetLayersMapWithImageInfo is a development only endpoint to obtain layer information for an image.
-func (i *LibpodAPI) GetLayersMapWithImageInfo(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) GetLayersMapWithImageInfo(call iopodman.VarlinkCall) error {
layerInfo, err := image.GetLayersMapWithImageInfo(i.Runtime.ImageRuntime())
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -1000,7 +1000,7 @@ func (i *LibpodAPI) GetLayersMapWithImageInfo(call iopodman.VarlinkCall) error {
}
// BuildImageHierarchyMap ...
-func (i *LibpodAPI) BuildImageHierarchyMap(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) BuildImageHierarchyMap(call iopodman.VarlinkCall, name string) error {
img, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -1024,7 +1024,7 @@ func (i *LibpodAPI) BuildImageHierarchyMap(call iopodman.VarlinkCall, name strin
}
// ImageTree returns the image tree string for the provided image name or ID
-func (i *LibpodAPI) ImageTree(call iopodman.VarlinkCall, nameOrID string, whatRequires bool) error {
+func (i *VarlinkAPI) ImageTree(call iopodman.VarlinkCall, nameOrID string, whatRequires bool) error {
img, err := i.Runtime.ImageRuntime().NewFromLocal(nameOrID)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
diff --git a/pkg/varlinkapi/mount.go b/pkg/varlinkapi/mount.go
index 2450f6fd9..6e1eed644 100644
--- a/pkg/varlinkapi/mount.go
+++ b/pkg/varlinkapi/mount.go
@@ -5,7 +5,7 @@ package varlinkapi
import iopodman "github.com/containers/libpod/pkg/varlink"
// ListContainerMounts ...
-func (i *LibpodAPI) ListContainerMounts(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) ListContainerMounts(call iopodman.VarlinkCall) error {
mounts := make(map[string]string)
allContainers, err := i.Runtime.GetAllContainers()
if err != nil {
@@ -24,7 +24,7 @@ func (i *LibpodAPI) ListContainerMounts(call iopodman.VarlinkCall) error {
}
// MountContainer ...
-func (i *LibpodAPI) MountContainer(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) MountContainer(call iopodman.VarlinkCall, name string) error {
container, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -37,7 +37,7 @@ func (i *LibpodAPI) MountContainer(call iopodman.VarlinkCall, name string) error
}
// UnmountContainer ...
-func (i *LibpodAPI) UnmountContainer(call iopodman.VarlinkCall, name string, force bool) error {
+func (i *VarlinkAPI) UnmountContainer(call iopodman.VarlinkCall, name string, force bool) error {
container, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go
index 79ffb6677..94add1b6c 100644
--- a/pkg/varlinkapi/pods.go
+++ b/pkg/varlinkapi/pods.go
@@ -14,7 +14,7 @@ import (
)
// CreatePod ...
-func (i *LibpodAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCreate) error {
+func (i *VarlinkAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCreate) error {
var options []libpod.PodCreateOption
if create.Infra {
options = append(options, libpod.WithInfraContainer())
@@ -61,7 +61,7 @@ func (i *LibpodAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCrea
}
// ListPods ...
-func (i *LibpodAPI) ListPods(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) ListPods(call iopodman.VarlinkCall) error {
var (
listPods []iopodman.ListPodData
)
@@ -82,7 +82,7 @@ func (i *LibpodAPI) ListPods(call iopodman.VarlinkCall) error {
}
// GetPod ...
-func (i *LibpodAPI) GetPod(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) GetPod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
return call.ReplyPodNotFound(name, err.Error())
@@ -98,7 +98,7 @@ func (i *LibpodAPI) GetPod(call iopodman.VarlinkCall, name string) error {
}
// GetPodsByStatus returns a slice of pods filtered by a libpod status
-func (i *LibpodAPI) GetPodsByStatus(call iopodman.VarlinkCall, statuses []string) error {
+func (i *VarlinkAPI) GetPodsByStatus(call iopodman.VarlinkCall, statuses []string) error {
filterFuncs := func(p *libpod.Pod) bool {
state, _ := shared.GetPodStatus(p)
for _, status := range statuses {
@@ -120,7 +120,7 @@ func (i *LibpodAPI) GetPodsByStatus(call iopodman.VarlinkCall, statuses []string
}
// InspectPod ...
-func (i *LibpodAPI) InspectPod(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) InspectPod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
return call.ReplyPodNotFound(name, err.Error())
@@ -137,7 +137,7 @@ func (i *LibpodAPI) InspectPod(call iopodman.VarlinkCall, name string) error {
}
// StartPod ...
-func (i *LibpodAPI) StartPod(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) StartPod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
return call.ReplyPodNotFound(name, err.Error())
@@ -158,7 +158,7 @@ func (i *LibpodAPI) StartPod(call iopodman.VarlinkCall, name string) error {
}
// StopPod ...
-func (i *LibpodAPI) StopPod(call iopodman.VarlinkCall, name string, timeout int64) error {
+func (i *VarlinkAPI) StopPod(call iopodman.VarlinkCall, name string, timeout int64) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
return call.ReplyPodNotFound(name, err.Error())
@@ -172,7 +172,7 @@ func (i *LibpodAPI) StopPod(call iopodman.VarlinkCall, name string, timeout int6
}
// RestartPod ...
-func (i *LibpodAPI) RestartPod(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) RestartPod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
return call.ReplyPodNotFound(name, err.Error())
@@ -194,7 +194,7 @@ func (i *LibpodAPI) RestartPod(call iopodman.VarlinkCall, name string) error {
// KillPod kills the running containers in a pod. If you want to use the default SIGTERM signal,
// just send a -1 for the signal arg.
-func (i *LibpodAPI) KillPod(call iopodman.VarlinkCall, name string, signal int64) error {
+func (i *VarlinkAPI) KillPod(call iopodman.VarlinkCall, name string, signal int64) error {
killSignal := uint(syscall.SIGTERM)
if signal != -1 {
killSignal = uint(signal)
@@ -213,7 +213,7 @@ func (i *LibpodAPI) KillPod(call iopodman.VarlinkCall, name string, signal int64
}
// PausePod ...
-func (i *LibpodAPI) PausePod(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) PausePod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
return call.ReplyPodNotFound(name, err.Error())
@@ -227,7 +227,7 @@ func (i *LibpodAPI) PausePod(call iopodman.VarlinkCall, name string) error {
}
// UnpausePod ...
-func (i *LibpodAPI) UnpausePod(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) UnpausePod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
return call.ReplyPodNotFound(name, err.Error())
@@ -241,7 +241,7 @@ func (i *LibpodAPI) UnpausePod(call iopodman.VarlinkCall, name string) error {
}
// RemovePod ...
-func (i *LibpodAPI) RemovePod(call iopodman.VarlinkCall, name string, force bool) error {
+func (i *VarlinkAPI) RemovePod(call iopodman.VarlinkCall, name string, force bool) error {
ctx := getContext()
pod, err := i.Runtime.LookupPod(name)
if err != nil {
@@ -255,7 +255,7 @@ func (i *LibpodAPI) RemovePod(call iopodman.VarlinkCall, name string, force bool
}
// GetPodStats ...
-func (i *LibpodAPI) GetPodStats(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) GetPodStats(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
return call.ReplyPodNotFound(name, err.Error())
@@ -291,7 +291,7 @@ func (i *LibpodAPI) GetPodStats(call iopodman.VarlinkCall, name string) error {
}
// GetPodsByContext returns a slice of pod ids based on all, latest, or a list
-func (i *LibpodAPI) GetPodsByContext(call iopodman.VarlinkCall, all, latest bool, input []string) error {
+func (i *VarlinkAPI) GetPodsByContext(call iopodman.VarlinkCall, all, latest bool, input []string) error {
var podids []string
pods, err := shortcuts.GetPodsByContext(all, latest, input, i.Runtime)
@@ -305,7 +305,7 @@ func (i *LibpodAPI) GetPodsByContext(call iopodman.VarlinkCall, all, latest bool
}
// PodStateData returns a container's state data in string format
-func (i *LibpodAPI) PodStateData(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) PodStateData(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -322,7 +322,7 @@ func (i *LibpodAPI) PodStateData(call iopodman.VarlinkCall, name string) error {
}
// TopPod provides the top stats for a given or latest pod
-func (i *LibpodAPI) TopPod(call iopodman.VarlinkCall, name string, latest bool, descriptors []string) error {
+func (i *VarlinkAPI) TopPod(call iopodman.VarlinkCall, name string, latest bool, descriptors []string) error {
var (
pod *libpod.Pod
err error
diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go
index 7bee643c2..82efe9b5d 100644
--- a/pkg/varlinkapi/system.go
+++ b/pkg/varlinkapi/system.go
@@ -16,7 +16,7 @@ import (
)
// GetVersion ...
-func (i *LibpodAPI) GetVersion(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) GetVersion(call iopodman.VarlinkCall) error {
versionInfo, err := define.GetVersion()
if err != nil {
return err
@@ -33,7 +33,7 @@ func (i *LibpodAPI) GetVersion(call iopodman.VarlinkCall) error {
}
// GetInfo returns details about the podman host and its stores
-func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) GetInfo(call iopodman.VarlinkCall) error {
versionInfo, err := define.GetVersion()
if err != nil {
return err
@@ -106,7 +106,7 @@ func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error {
}
// GetVersion ...
-func (i *LibpodAPI) Reset(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) Reset(call iopodman.VarlinkCall) error {
if err := i.Runtime.Reset(context.TODO()); err != nil {
logrus.Errorf("Reset Failed: %v", err)
if err := call.ReplyErrorOccurred(err.Error()); err != nil {
diff --git a/pkg/varlinkapi/transfers.go b/pkg/varlinkapi/transfers.go
index 654da276e..9df8ffcdc 100644
--- a/pkg/varlinkapi/transfers.go
+++ b/pkg/varlinkapi/transfers.go
@@ -4,7 +4,6 @@ package varlinkapi
import (
"bufio"
- "fmt"
"io"
"io/ioutil"
"os"
@@ -14,7 +13,7 @@ import (
)
// SendFile allows a client to send a file to the varlink server
-func (i *LibpodAPI) SendFile(call iopodman.VarlinkCall, ftype string, length int64) error {
+func (i *VarlinkAPI) SendFile(call iopodman.VarlinkCall, ftype string, length int64) error {
if !call.WantsUpgrade() {
return call.ReplyErrorOccurred("client must use upgraded connection to send files")
}
@@ -40,14 +39,14 @@ func (i *LibpodAPI) SendFile(call iopodman.VarlinkCall, ftype string, length int
logrus.Debugf("successfully received %s", outputFile.Name())
// Send an ACK to the client
- call.Call.Writer.WriteString(fmt.Sprintf("%s:", outputFile.Name()))
+ call.Call.Writer.WriteString(outputFile.Name())
call.Call.Writer.Flush()
return nil
}
// ReceiveFile allows the varlink server to send a file to a client
-func (i *LibpodAPI) ReceiveFile(call iopodman.VarlinkCall, filepath string, delete bool) error {
+func (i *VarlinkAPI) ReceiveFile(call iopodman.VarlinkCall, filepath string, delete bool) error {
if !call.WantsUpgrade() {
return call.ReplyErrorOccurred("client must use upgraded connection to send files")
}
diff --git a/pkg/varlinkapi/volumes.go b/pkg/varlinkapi/volumes.go
index b0c3608c4..ff72c3869 100644
--- a/pkg/varlinkapi/volumes.go
+++ b/pkg/varlinkapi/volumes.go
@@ -11,7 +11,7 @@ import (
)
// VolumeCreate creates a libpod volume based on input from a varlink connection
-func (i *LibpodAPI) VolumeCreate(call iopodman.VarlinkCall, options iopodman.VolumeCreateOpts) error {
+func (i *VarlinkAPI) VolumeCreate(call iopodman.VarlinkCall, options iopodman.VolumeCreateOpts) error {
var volumeOptions []libpod.VolumeCreateOption
if len(options.VolumeName) > 0 {
@@ -38,7 +38,7 @@ func (i *LibpodAPI) VolumeCreate(call iopodman.VarlinkCall, options iopodman.Vol
}
// VolumeRemove removes volumes by options.All or options.Volumes
-func (i *LibpodAPI) VolumeRemove(call iopodman.VarlinkCall, options iopodman.VolumeRemoveOpts) error {
+func (i *VarlinkAPI) VolumeRemove(call iopodman.VarlinkCall, options iopodman.VolumeRemoveOpts) error {
success, failed, err := shared.SharedRemoveVolumes(getContext(), i.Runtime, options.Volumes, options.All, options.Force)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -52,7 +52,7 @@ func (i *LibpodAPI) VolumeRemove(call iopodman.VarlinkCall, options iopodman.Vol
}
// GetVolumes returns all the volumes known to the remote system
-func (i *LibpodAPI) GetVolumes(call iopodman.VarlinkCall, args []string, all bool) error {
+func (i *VarlinkAPI) GetVolumes(call iopodman.VarlinkCall, args []string, all bool) error {
var (
err error
reply []*libpod.Volume
@@ -87,7 +87,7 @@ func (i *LibpodAPI) GetVolumes(call iopodman.VarlinkCall, args []string, all boo
}
// InspectVolume inspects a single volume, returning its JSON as a string.
-func (i *LibpodAPI) InspectVolume(call iopodman.VarlinkCall, name string) error {
+func (i *VarlinkAPI) InspectVolume(call iopodman.VarlinkCall, name string) error {
vol, err := i.Runtime.LookupVolume(name)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -104,7 +104,7 @@ func (i *LibpodAPI) InspectVolume(call iopodman.VarlinkCall, name string) error
}
// VolumesPrune removes unused images via a varlink call
-func (i *LibpodAPI) VolumesPrune(call iopodman.VarlinkCall) error {
+func (i *VarlinkAPI) VolumesPrune(call iopodman.VarlinkCall) error {
var (
prunedErrors []string
prunedNames []string
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index 7fb39b221..04e2fa64c 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -21,8 +21,8 @@ t GET libpod/containers/json?all=true 200 \
length=1 \
.[0].Id~[0-9a-f]\\{12\\} \
.[0].Image=$IMAGE \
- .[0].Command[0]="true" \
- .[0].State~\\\(exited\\\|stopped\\\) \
+ .[0].Cmd[0]="true" \
+ .[0].ContainerState~\\\(exited\\\|stopped\\\) \
.[0].ExitCode=0 \
.[0].IsInfra=false
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 8c4fe9223..d93ee8d3a 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -221,8 +221,8 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
ociRuntime := os.Getenv("OCI_RUNTIME")
if ociRuntime == "" {
var err error
- ociRuntime, err = exec.LookPath("runc")
- // If we cannot find the runc binary, setting to something static as we have no way
+ ociRuntime, err = exec.LookPath("crun")
+ // If we cannot find the crun binary, setting to something static as we have no way
// to return an error. The tests will fail and point out that the runc binary could
// not be found nicely.
if err != nil {
diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go
index 5d0d6e689..8b95794d2 100644
--- a/test/e2e/exec_test.go
+++ b/test/e2e/exec_test.go
@@ -244,15 +244,17 @@ var _ = Describe("Podman exec", func() {
})
It("podman exec preserve fds sanity check", func() {
- // TODO: add this test once crun adds the --preserve-fds flag for exec
- if strings.Contains(podmanTest.OCIRuntime, "crun") {
- Skip("Test only works on crun")
- }
setup := podmanTest.RunTopContainer("test1")
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
- session := podmanTest.Podman([]string{"exec", "--preserve-fds", "1", "test1", "ls"})
+ devNull, err := os.Open("/dev/null")
+ Expect(err).To(BeNil())
+ defer devNull.Close()
+ files := []*os.File{
+ devNull,
+ }
+ session := podmanTest.PodmanExtraFiles([]string{"exec", "--preserve-fds", "1", "test1", "ls"}, files)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
diff --git a/test/e2e/libpod_suite_remoteclient_test.go b/test/e2e/libpod_suite_remoteclient_test.go
index c87ff016a..b5da041ab 100644
--- a/test/e2e/libpod_suite_remoteclient_test.go
+++ b/test/e2e/libpod_suite_remoteclient_test.go
@@ -34,6 +34,12 @@ func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration
return &PodmanSessionIntegration{podmanSession}
}
+// PodmanExtraFiles is the exec call to podman on the filesystem and passes down extra files
+func (p *PodmanTestIntegration) PodmanExtraFiles(args []string, extraFiles []*os.File) *PodmanSessionIntegration {
+ podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, nil, extraFiles)
+ return &PodmanSessionIntegration{podmanSession}
+}
+
// PodmanNoCache calls podman with out adding the imagecache
func (p *PodmanTestIntegration) PodmanNoCache(args []string) *PodmanSessionIntegration {
podmanSession := p.PodmanBase(args, false, true)
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index dc5e91c72..29a55980c 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -27,6 +27,12 @@ func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration
return &PodmanSessionIntegration{podmanSession}
}
+// PodmanExtraFiles is the exec call to podman on the filesystem and passes down extra files
+func (p *PodmanTestIntegration) PodmanExtraFiles(args []string, extraFiles []*os.File) *PodmanSessionIntegration {
+ podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, extraFiles)
+ return &PodmanSessionIntegration{podmanSession}
+}
+
// PodmanNoCache calls the podman command with no configured imagecache
func (p *PodmanTestIntegration) PodmanNoCache(args []string) *PodmanSessionIntegration {
podmanSession := p.PodmanBase(args, false, true)
@@ -42,7 +48,7 @@ func (p *PodmanTestIntegration) PodmanNoEvents(args []string) *PodmanSessionInte
// PodmanAsUser is the exec call to podman on the filesystem with the specified uid/gid and environment
func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, cwd string, env []string) *PodmanSessionIntegration {
- podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env, false, false)
+ podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env, false, false, nil)
return &PodmanSessionIntegration{podmanSession}
}
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index f2dedb73f..15df6adec 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -10,7 +10,7 @@ load helpers
#
# initialize, read image ID and name
get_iid_and_name() {
- run_podman images --format '{{.ID}} {{.Repository}}:{{.Tag}}'
+ run_podman images -a --format '{{.ID}} {{.Repository}}:{{.Tag}}'
read iid img_name < <(echo "$output")
archive=$PODMAN_TMPDIR/myimage-$(random_string 8).tar
@@ -18,7 +18,7 @@ get_iid_and_name() {
# Simple verification of image ID and name
verify_iid_and_name() {
- run_podman images --format '{{.ID}} {{.Repository}}:{{.Tag}}'
+ run_podman images -a --format '{{.ID}} {{.Repository}}:{{.Tag}}'
read new_iid new_img_name < <(echo "$output")
# Verify
diff --git a/test/utils/podmantest_test.go b/test/utils/podmantest_test.go
index 9620898af..387c8747c 100644
--- a/test/utils/podmantest_test.go
+++ b/test/utils/podmantest_test.go
@@ -23,7 +23,7 @@ var _ = Describe("PodmanTest test", func() {
FakeOutputs["check"] = []string{"check"}
os.Setenv("HOOK_OPTION", "hook_option")
env := os.Environ()
- session := podmanTest.PodmanAsUserBase([]string{"check"}, 1000, 1000, "", env, true, false)
+ session := podmanTest.PodmanAsUserBase([]string{"check"}, 1000, 1000, "", env, true, false, nil)
os.Unsetenv("HOOK_OPTION")
session.WaitWithDefaultTimeout()
Expect(session.Command.Process).ShouldNot(BeNil())
diff --git a/test/utils/utils.go b/test/utils/utils.go
index ad78d9792..6ab8604a4 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -65,7 +65,7 @@ func (p *PodmanTest) MakeOptions(args []string, noEvents, noCache bool) []string
// PodmanAsUserBase exec podman as user. uid and gid is set for credentials usage. env is used
// to record the env for debugging
-func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string, env []string, noEvents, noCache bool) *PodmanSession {
+func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string, env []string, noEvents, noCache bool, extraFiles []*os.File) *PodmanSession {
var command *exec.Cmd
podmanOptions := p.MakeOptions(args, noEvents, noCache)
podmanBinary := p.PodmanBinary
@@ -93,6 +93,8 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string
command.Dir = cwd
}
+ command.ExtraFiles = extraFiles
+
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
if err != nil {
Fail(fmt.Sprintf("unable to run podman command: %s\n%v", strings.Join(podmanOptions, " "), err))
@@ -102,7 +104,7 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string
// PodmanBase exec podman with default env.
func (p *PodmanTest) PodmanBase(args []string, noEvents, noCache bool) *PodmanSession {
- return p.PodmanAsUserBase(args, 0, 0, "", nil, noEvents, noCache)
+ return p.PodmanAsUserBase(args, 0, 0, "", nil, noEvents, noCache, nil)
}
// WaitForContainer waits on a started container
diff --git a/vendor/github.com/containers/buildah/CHANGELOG.md b/vendor/github.com/containers/buildah/CHANGELOG.md
index 941a35535..ed4ba3967 100644
--- a/vendor/github.com/containers/buildah/CHANGELOG.md
+++ b/vendor/github.com/containers/buildah/CHANGELOG.md
@@ -2,6 +2,14 @@
# Changelog
+## v1.14.8 (2020-04-09)
+ Run (make vendor)
+ Run (make -C tests/tools vendor)
+ Run (go mod tidy) before (go mod vendor) again
+ Fix (make vendor)
+ Bump validation
+ Bump back to v1.15.0-dev
+
## v1.14.7 (2020-04-07)
Bump github.com/containers/image/v5 from 5.3.1 to 5.4.3
make vendor: run `tidy` after `vendor`
diff --git a/vendor/github.com/containers/buildah/Makefile b/vendor/github.com/containers/buildah/Makefile
index 371cefa7f..ced48a95a 100644
--- a/vendor/github.com/containers/buildah/Makefile
+++ b/vendor/github.com/containers/buildah/Makefile
@@ -142,10 +142,9 @@ vendor-in-container:
.PHONY: vendor
vendor:
- export GO111MODULE=on \
- $(GO) mod vendor && \
- $(GO) mod tidy && \
- $(GO) mod verify
+ GO111MODULE=on $(GO) mod tidy
+ GO111MODULE=on $(GO) mod vendor
+ GO111MODULE=on $(GO) mod verify
.PHONY: lint
lint: install.tools
diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go
index 059f0edd8..6cfbbb73f 100644
--- a/vendor/github.com/containers/buildah/buildah.go
+++ b/vendor/github.com/containers/buildah/buildah.go
@@ -27,7 +27,7 @@ const (
Package = "buildah"
// Version for the Package. Bump version in contrib/rpm/buildah.spec
// too.
- Version = "1.14.7"
+ Version = "1.14.8"
// The value we use to identify what type of information, currently a
// serialized Builder structure, we are using as per-container state.
// This should only be changed when we make incompatible changes to
diff --git a/vendor/github.com/containers/buildah/changelog.txt b/vendor/github.com/containers/buildah/changelog.txt
index ebbfa5a64..4cd9a18df 100644
--- a/vendor/github.com/containers/buildah/changelog.txt
+++ b/vendor/github.com/containers/buildah/changelog.txt
@@ -1,3 +1,11 @@
+- Changelog for v1.14.8 (2020-04-09)
+ * Run (make vendor)
+ * Run (make -C tests/tools vendor)
+ * Run (go mod tidy) before (go mod vendor) again
+ * Fix (make vendor)
+ * Bump validation
+ * Bump back to v1.15.0-dev
+
- Changelog for v1.14.7 (2020-04-07)
* Bump github.com/containers/image/v5 from 5.3.1 to 5.4.3
* make vendor: run `tidy` after `vendor`
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 73c9d45ac..535090e81 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -64,7 +64,7 @@ github.com/containernetworking/plugins/pkg/ns
github.com/containernetworking/plugins/pkg/utils/hwaddr
github.com/containernetworking/plugins/plugins/ipam/host-local/backend
github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator
-# github.com/containers/buildah v1.14.7
+# github.com/containers/buildah v1.14.8
github.com/containers/buildah
github.com/containers/buildah/bind
github.com/containers/buildah/chroot
diff --git a/version/version.go b/version/version.go
index 0d0b0b422..06457e3ea 100644
--- a/version/version.go
+++ b/version/version.go
@@ -4,7 +4,7 @@ package version
// NOTE: remember to bump the version at the top
// of the top-level README.md file when this is
// bumped.
-const Version = "1.8.3-dev"
+const Version = "1.9.0-dev"
// RemoteAPIVersion is the version for the remote
// client API. It is used to determine compatibility