summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Containerfile-testvol10
-rw-r--r--Makefile37
-rw-r--r--README.md14
-rw-r--r--cmd/podman/containers/rename.go56
-rw-r--r--contrib/cirrus/required_host_ports.txt10
-rw-r--r--docs/source/Commands.rst2
-rw-r--r--docs/source/managecontainers.rst2
-rw-r--r--docs/source/markdown/podman-container.1.md3
-rw-r--r--docs/source/markdown/podman-rename.1.md38
-rw-r--r--docs/source/markdown/podman-volume-create.1.md10
-rw-r--r--docs/source/markdown/podman.1.md3
-rw-r--r--go.mod4
-rw-r--r--go.sum8
-rw-r--r--libpod/boltdb_state.go1
-rw-r--r--libpod/boltdb_state_internal.go15
-rw-r--r--libpod/container_api.go10
-rw-r--r--libpod/container_inspect.go7
-rw-r--r--libpod/container_internal.go66
-rw-r--r--libpod/container_internal_linux.go39
-rw-r--r--libpod/define/containerstate.go5
-rw-r--r--libpod/define/errors.go4
-rw-r--r--libpod/define/volume_inspect.go51
-rw-r--r--libpod/options.go11
-rw-r--r--libpod/plugin/volume_api.go55
-rw-r--r--libpod/rootless_cni_linux.go2
-rw-r--r--libpod/runtime.go16
-rw-r--r--libpod/runtime_ctr.go149
-rw-r--r--libpod/runtime_volume_linux.go130
-rw-r--r--libpod/volume.go57
-rw-r--r--libpod/volume_inspect.go87
-rw-r--r--libpod/volume_internal.go13
-rw-r--r--libpod/volume_internal_linux.go46
-rw-r--r--pkg/api/handlers/compat/containers.go31
-rw-r--r--pkg/api/handlers/compat/volumes.go28
-rw-r--r--pkg/api/handlers/libpod/volumes.go51
-rw-r--r--pkg/api/server/register_containers.go62
-rw-r--r--pkg/bindings/containers/types_attach_options.go4
-rw-r--r--pkg/bindings/containers/types_checkpoint_options.go4
-rw-r--r--pkg/bindings/containers/types_commit_options.go4
-rw-r--r--pkg/bindings/containers/types_create_options.go4
-rw-r--r--pkg/bindings/containers/types_diff_options.go4
-rw-r--r--pkg/bindings/containers/types_execinspect_options.go4
-rw-r--r--pkg/bindings/containers/types_execstart_options.go4
-rw-r--r--pkg/bindings/containers/types_execstartandattach_options.go4
-rw-r--r--pkg/bindings/containers/types_export_options.go4
-rw-r--r--pkg/bindings/containers/types_healthcheck_options.go4
-rw-r--r--pkg/bindings/containers/types_init_options.go4
-rw-r--r--pkg/bindings/containers/types_inspect_options.go4
-rw-r--r--pkg/bindings/containers/types_kill_options.go4
-rw-r--r--pkg/bindings/containers/types_list_options.go2
-rw-r--r--pkg/bindings/containers/types_log_options.go4
-rw-r--r--pkg/bindings/containers/types_mount_options.go4
-rw-r--r--pkg/bindings/containers/types_mountedcontainerpaths_options.go4
-rw-r--r--pkg/bindings/containers/types_pause_options.go4
-rw-r--r--pkg/bindings/containers/types_prune_options.go4
-rw-r--r--pkg/bindings/containers/types_remove_options.go4
-rw-r--r--pkg/bindings/containers/types_resizeexectty_options.go4
-rw-r--r--pkg/bindings/containers/types_resizetty_options.go4
-rw-r--r--pkg/bindings/containers/types_restart_options.go4
-rw-r--r--pkg/bindings/containers/types_restore_options.go4
-rw-r--r--pkg/bindings/containers/types_shouldrestart_options.go4
-rw-r--r--pkg/bindings/containers/types_start_options.go4
-rw-r--r--pkg/bindings/containers/types_stats_options.go4
-rw-r--r--pkg/bindings/containers/types_stop_options.go4
-rw-r--r--pkg/bindings/containers/types_top_options.go4
-rw-r--r--pkg/bindings/containers/types_unmount_options.go4
-rw-r--r--pkg/bindings/containers/types_unpause_options.go4
-rw-r--r--pkg/bindings/containers/types_wait_options.go4
-rw-r--r--pkg/bindings/generate/types_kube_options.go4
-rw-r--r--pkg/bindings/generate/types_systemd_options.go4
-rw-r--r--pkg/bindings/generator/generator.go6
-rw-r--r--pkg/bindings/images/types_diff_options.go4
-rw-r--r--pkg/bindings/images/types_export_options.go4
-rw-r--r--pkg/bindings/images/types_get_options.go4
-rw-r--r--pkg/bindings/images/types_history_options.go4
-rw-r--r--pkg/bindings/images/types_import_options.go4
-rw-r--r--pkg/bindings/images/types_list_options.go4
-rw-r--r--pkg/bindings/images/types_load_options.go4
-rw-r--r--pkg/bindings/images/types_prune_options.go4
-rw-r--r--pkg/bindings/images/types_pull_options.go4
-rw-r--r--pkg/bindings/images/types_push_options.go4
-rw-r--r--pkg/bindings/images/types_remove_options.go4
-rw-r--r--pkg/bindings/images/types_search_options.go4
-rw-r--r--pkg/bindings/images/types_tag_options.go4
-rw-r--r--pkg/bindings/images/types_tree_options.go4
-rw-r--r--pkg/bindings/images/types_untag_options.go4
-rw-r--r--pkg/bindings/manifests/types_add_options.go4
-rw-r--r--pkg/bindings/manifests/types_create_options.go4
-rw-r--r--pkg/bindings/manifests/types_inspect_options.go4
-rw-r--r--pkg/bindings/manifests/types_push_options.go4
-rw-r--r--pkg/bindings/manifests/types_remove_options.go4
-rw-r--r--pkg/bindings/network/types_connect_options.go4
-rw-r--r--pkg/bindings/network/types_create_options.go8
-rw-r--r--pkg/bindings/network/types_disconnect_options.go4
-rw-r--r--pkg/bindings/network/types_inspect_options.go4
-rw-r--r--pkg/bindings/network/types_list_options.go4
-rw-r--r--pkg/bindings/network/types_remove_options.go4
-rw-r--r--pkg/bindings/play/types_kube_options.go4
-rw-r--r--pkg/bindings/pods/types_create_options.go4
-rw-r--r--pkg/bindings/pods/types_inspect_options.go4
-rw-r--r--pkg/bindings/pods/types_kill_options.go4
-rw-r--r--pkg/bindings/pods/types_list_options.go4
-rw-r--r--pkg/bindings/pods/types_pause_options.go4
-rw-r--r--pkg/bindings/pods/types_prune_options.go4
-rw-r--r--pkg/bindings/pods/types_remove_options.go4
-rw-r--r--pkg/bindings/pods/types_restart_options.go4
-rw-r--r--pkg/bindings/pods/types_start_options.go4
-rw-r--r--pkg/bindings/pods/types_stats_options.go4
-rw-r--r--pkg/bindings/pods/types_stop_options.go4
-rw-r--r--pkg/bindings/pods/types_top_options.go4
-rw-r--r--pkg/bindings/pods/types_unpause_options.go4
-rw-r--r--pkg/bindings/system/types_disk_options.go4
-rw-r--r--pkg/bindings/system/types_events_options.go4
-rw-r--r--pkg/bindings/system/types_info_options.go4
-rw-r--r--pkg/bindings/system/types_prune_options.go4
-rw-r--r--pkg/bindings/system/types_version_options.go4
-rw-r--r--pkg/bindings/volumes/types_create_options.go4
-rw-r--r--pkg/bindings/volumes/types_inspect_options.go4
-rw-r--r--pkg/bindings/volumes/types_list_options.go4
-rw-r--r--pkg/bindings/volumes/types_prune_options.go4
-rw-r--r--pkg/bindings/volumes/types_remove_options.go4
-rw-r--r--pkg/domain/entities/containers.go6
-rw-r--r--pkg/domain/entities/engine_container.go1
-rw-r--r--pkg/domain/entities/volumes.go35
-rw-r--r--pkg/domain/infra/abi/containers.go16
-rw-r--r--pkg/domain/infra/abi/containers_stat.go17
-rw-r--r--pkg/domain/infra/abi/system.go12
-rw-r--r--pkg/domain/infra/abi/volumes.go34
-rw-r--r--pkg/domain/infra/tunnel/containers.go5
-rw-r--r--test/apiv2/30-volumes.at2
-rw-r--r--test/apiv2/45-system.at2
-rw-r--r--test/e2e/checkpoint_test.go2
-rw-r--r--test/e2e/common_test.go10
-rw-r--r--test/e2e/config.go1
-rw-r--r--test/e2e/config/containers.conf14
-rw-r--r--test/e2e/rename_test.go93
-rw-r--r--test/e2e/volume_plugin_test.go184
-rw-r--r--test/python/docker/test_containers.py8
-rw-r--r--test/system/050-stop.bats28
-rw-r--r--test/testvol/main.go309
-rw-r--r--vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go32
-rw-r--r--vendor/modules.txt4
143 files changed, 1791 insertions, 502 deletions
diff --git a/.gitignore b/.gitignore
index f87c8974f..6a5ae509c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,6 +29,7 @@ release.txt
/test/checkseccomp/checkseccomp
/test/copyimg/copyimg
/test/goecho/goecho
+/test/testvol/testvol
.vscode*
result
# Necessary to prevent hack/tree-status.sh false-positive
diff --git a/Containerfile-testvol b/Containerfile-testvol
new file mode 100644
index 000000000..6ff45064b
--- /dev/null
+++ b/Containerfile-testvol
@@ -0,0 +1,10 @@
+FROM golang:1.15-alpine AS build-img
+COPY ./test/testvol/ /go/src/github.com/containers/podman/cmd/testvol/
+COPY ./vendor /go/src/github.com/containers/podman/vendor/
+WORKDIR /go/src/github.com/containers/podman
+RUN go build -o /testvol ./cmd/testvol
+
+FROM alpine
+COPY --from=build-img /testvol /usr/local/bin
+WORKDIR /
+ENTRYPOINT ["/usr/local/bin/testvol"]
diff --git a/Makefile b/Makefile
index 085af6d80..cc7d9f0ff 100644
--- a/Makefile
+++ b/Makefile
@@ -180,6 +180,14 @@ gofmt: ## Verify the source code gofmt
test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go)
$(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp
+.PHONY: test/testvol/testvol
+test/testvol/testvol: .gopathok $(wildcard test/testvol/*.go)
+ $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol
+
+.PHONY: volume-plugin-test-image
+volume-plugin-test-img:
+ podman build -t quay.io/libpod/volume-plugin-test-img -f Containerfile-testvol .
+
.PHONY: test/goecho/goecho
test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go)
$(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho
@@ -198,7 +206,7 @@ endif
podman: bin/podman
.PHONY: bin/podman-remote
-bin/podman-remote: .gopathok $(SOURCES) go.mod go.sum ## Build with podman on remote environment
+bin/podman-remote: .gopathok .generate-bindings $(SOURCES) go.mod go.sum ## Build with podman on remote environment
$(GO) build $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "${REMOTETAGS}" -o $@ ./cmd/podman
.PHONY: bin/podman-remote-static
@@ -268,6 +276,8 @@ clean: ## Clean artifacts
libpod/pod_ffjson.go \
libpod/container_easyjson.go \
libpod/pod_easyjson.go \
+ .install.goimports \
+ .generate-bindings \
docs/build
make -C docs clean
@@ -407,7 +417,7 @@ release.txt:
# X-RELEASE-INFO format depended upon by automated tooling
echo -n "X-RELEASE-INFO:" > "$@"
for field in "$(RELEASE_BASENAME)" "$(RELEASE_VERSION)" \
- "$(RELEASE_DIST)" "$(RELEASE_DIST_VER)" "$(RELEASE_ARCH)"; do \
+ "$(RELEASE_DIST)" "$(RELEASE_DIST_VER)" "$(RELEASE_ARCH)"; do \
echo -n " $$field"; done >> "$@"
echo "" >> "$@"
@@ -449,6 +459,21 @@ podman-remote-%-release:
rm -f release.txt
$(MAKE) podman-remote-release-$*.zip
+BINDINGS_SOURCE = $(wildcard pkg/bindings/**/types.go)
+.generate-bindings: $(BINDINGS_SOURCE)
+ifneq ($(shell uname -s), Darwin)
+ for i in $(BINDINGS_SOURCE); do \
+ dirname=$$(dirname $${i}); \
+ shortname=$$(basename $${dirname}); \
+ pushd $${dirname}>/dev/null; \
+ echo $${dirname}; \
+ echo $(GO) generate; \
+ $(GO) generate; \
+ popd > /dev/null; \
+ done;
+endif
+ touch .generate-bindings
+
.PHONY: docker-docs
docker-docs: docs
(cd docs; ./dckrman.sh ./build/man/*.1)
@@ -565,13 +590,19 @@ uninstall:
GIT_CHECK_EXCLUDE="./vendor:docs/make.bat" $(GOBIN)/git-validation -run DCO,short-subject,dangling-whitespace -range $(EPOCH_TEST_COMMIT)..$(HEAD)
.PHONY: install.tools
-install.tools: .install.gitvalidation .install.md2man .install.ginkgo .install.golangci-lint .install.bats ## Install needed tools
+install.tools: .install.goimports .install.gitvalidation .install.md2man .install.ginkgo .install.golangci-lint .install.bats ## Install needed tools
define go-get
env GO111MODULE=off \
$(GO) get -u ${1}
endef
+.install.goimports: .gopathok
+ if [ ! -x "$(GOBIN)/goimports" ]; then \
+ $(call go-get,golang.org/x/tools/cmd/goimports); \
+ fi
+ touch .install.goimports
+
.PHONY: .install.ginkgo
.install.ginkgo: .gopathok
if [ ! -x "$(GOBIN)/ginkgo" ]; then \
diff --git a/README.md b/README.md
index 89dd012c7..4dd34d366 100644
--- a/README.md
+++ b/README.md
@@ -71,20 +71,6 @@ A little configuration by an administrator is required before rootless Podman ca
See [Skopeo](https://github.com/containers/skopeo/) for those tasks.
* Support for the Kubernetes CRI interface for container management.
The [CRI-O](https://github.com/cri-o/cri-o) daemon specializes in that.
-* Supporting `docker-compose`. We believe that Kubernetes is the defacto
- standard for composing Pods and for orchestrating containers, making
- Kubernetes YAML a defacto standard file format. Hence, Podman allows the
- creation and execution of Pods from a Kubernetes YAML file (see
- [podman-play-kube](https://github.com/containers/podman/blob/master/docs/source/markdown/podman-play-kube.1.md)).
- Podman can also generate Kubernetes YAML based on a container or Pod (see
- [podman-generate-kube](https://github.com/containers/podman/blob/master/docs/source/markdown/podman-generate-kube.1.md)),
- which allows for an easy transition from a local development environment
- to a production Kubernetes cluster. If Kubernetes does not fit your requirements,
- there are other third-party tools that support the docker-compose format such as
- [kompose](https://github.com/kubernetes/kompose/) and
- [podman-compose](https://github.com/muayyad-alsadi/podman-compose)
- that might be appropriate for your environment. This situation may change with
- the addition of the REST API.
## OCI Projects Plans
diff --git a/cmd/podman/containers/rename.go b/cmd/podman/containers/rename.go
new file mode 100644
index 000000000..9c94e6272
--- /dev/null
+++ b/cmd/podman/containers/rename.go
@@ -0,0 +1,56 @@
+package containers
+
+import (
+ "github.com/containers/podman/v2/cmd/podman/common"
+ "github.com/containers/podman/v2/cmd/podman/registry"
+ "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ renameDescription = "The podman rename command allows you to rename an existing container"
+ renameCommand = &cobra.Command{
+ Use: "rename CONTAINER NAME",
+ Short: "Rename an existing container",
+ Long: renameDescription,
+ RunE: rename,
+ Args: cobra.ExactArgs(2),
+ ValidArgsFunction: common.AutocompletePortCommand,
+ Example: "podman rename containerA newName",
+ }
+
+ containerRenameCommand = &cobra.Command{
+ Use: renameCommand.Use,
+ Short: renameCommand.Short,
+ Long: renameCommand.Long,
+ RunE: renameCommand.RunE,
+ Args: renameCommand.Args,
+ ValidArgsFunction: renameCommand.ValidArgsFunction,
+ Example: "podman container rename containerA newName",
+ }
+)
+
+func init() {
+ // TODO: Once bindings are done, add this to TunnelMode
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: renameCommand,
+ })
+
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: containerRenameCommand,
+ Parent: containerCmd,
+ })
+}
+
+func rename(cmd *cobra.Command, args []string) error {
+ if len(args) > 2 {
+ return errors.Errorf("must provide at least two arguments to rename")
+ }
+ renameOpts := entities.ContainerRenameOptions{
+ NewName: args[1],
+ }
+ return registry.ContainerEngine().ContainerRename(registry.GetContext(), args[0], renameOpts)
+}
diff --git a/contrib/cirrus/required_host_ports.txt b/contrib/cirrus/required_host_ports.txt
index 140e2c32f..9248e497a 100644
--- a/contrib/cirrus/required_host_ports.txt
+++ b/contrib/cirrus/required_host_ports.txt
@@ -2,13 +2,3 @@ github.com 22
docker.io 443
quay.io 443
registry.fedoraproject.org 443
-mirrors.fedoraproject.org 443
-dl.fedoraproject.org 443
-ewr.edge.kernel.org 443
-mirror.clarkson.edu 443
-mirror.umd.edu 443
-mirror.vcu.edu 443
-mirrors.cat.pdx.edu 443
-pubmirror1.math.uh.edu 443
-pubmirror2.math.uh.edu 443
-sjc.edge.kernel.org 443
diff --git a/docs/source/Commands.rst b/docs/source/Commands.rst
index cd5d894da..563462377 100644
--- a/docs/source/Commands.rst
+++ b/docs/source/Commands.rst
@@ -75,6 +75,8 @@ Commands
:doc:`push <markdown/podman-push.1>` Push an image to a specified destination
+:doc:`rename <markdown/podman-rename.1>` Rename an existing container
+
:doc:`restart <markdown/podman-restart.1>` Restart one or more containers
:doc:`rm <markdown/podman-rm.1>` Remove one or more containers
diff --git a/docs/source/managecontainers.rst b/docs/source/managecontainers.rst
index 9926f9996..9b3978f25 100644
--- a/docs/source/managecontainers.rst
+++ b/docs/source/managecontainers.rst
@@ -41,6 +41,8 @@ Manage Containers
:doc:`ps <markdown/podman-ps.1>` List containers
+:doc:`rename <markdown/podman-rename.1>` Rename an existing container
+
:doc:`restart <markdown/podman-restart.1>` Restart one or more containers
:doc:`restore <markdown/podman-container-restore.1>` Restores one or more containers from a checkpoint
diff --git a/docs/source/markdown/podman-container.1.md b/docs/source/markdown/podman-container.1.md
index 9da5db601..e85d69c59 100644
--- a/docs/source/markdown/podman-container.1.md
+++ b/docs/source/markdown/podman-container.1.md
@@ -33,6 +33,7 @@ The container command allows you to manage containers
| port | [podman-port(1)](podman-port.1.md) | List port mappings for the container. |
| prune | [podman-container-prune(1)](podman-container-prune.1.md)| Remove all stopped containers from local storage. |
| ps | [podman-ps(1)](podman-ps.1.md) | Prints out information about containers. |
+| rename | [podman-rename(1)](podman-rename.1.md) | Rename an existing container. |
| restart | [podman-restart(1)](podman-restart.1.md) | Restart one or more containers. |
| restore | [podman-container-restore(1)](podman-container-restore.1.md) | Restores one or more containers from a checkpoint. |
| rm | [podman-rm(1)](podman-rm.1.md) | Remove one or more containers. |
@@ -42,7 +43,7 @@ The container command allows you to manage containers
| stats | [podman-stats(1)](podman-stats.1.md) | Display a live stream of one or more container's resource usage statistics. |
| stop | [podman-stop(1)](podman-stop.1.md) | Stop one or more running containers. |
| top | [podman-top(1)](podman-top.1.md) | Display the running processes of a container. |
-| unmount | [podman-unmount(1)](podman-unmount.1.md) | Unmount a working container's root filesystem.(Alias unmount) |
+| unmount | [podman-unmount(1)](podman-unmount.1.md) | Unmount a working container's root filesystem.(Alias unmount) |
| unpause | [podman-unpause(1)](podman-unpause.1.md) | Unpause one or more containers. |
| wait | [podman-wait(1)](podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes. |
diff --git a/docs/source/markdown/podman-rename.1.md b/docs/source/markdown/podman-rename.1.md
new file mode 100644
index 000000000..fdb0dac89
--- /dev/null
+++ b/docs/source/markdown/podman-rename.1.md
@@ -0,0 +1,38 @@
+% podman-rename(1)
+
+## NAME
+podman\-rename - Rename an existing container
+
+## SYNOPSIS
+**podman rename** *container* *newname*
+
+**podman container rename** *container* *newname*
+
+## DESCRIPTION
+Rename changes the name of an existing container.
+The old name will be freed, and will be available for use.
+This command can be run on containers in any state.
+However, running containers may not fully receive the effects until they are restarted - for example, a running container may still use the old name in its logs.
+At present, only containers are supported; pods and volumes cannot be renamed.
+
+## OPTIONS
+
+## EXAMPLES
+
+```
+# Rename a container by name
+$ podman rename oldContainer aNewName
+```
+
+```
+# Rename a container by ID
+$ podman rename 717716c00a6b testcontainer
+```
+
+```
+# Use the container rename alias
+$ podman container rename 6e7514b47180 databaseCtr
+```
+
+## SEE ALSO
+podman(1), podman-create(1), podman-run(1)
diff --git a/docs/source/markdown/podman-volume-create.1.md b/docs/source/markdown/podman-volume-create.1.md
index 118f024df..a06411000 100644
--- a/docs/source/markdown/podman-volume-create.1.md
+++ b/docs/source/markdown/podman-volume-create.1.md
@@ -17,7 +17,7 @@ driver options can be set using the **--opt** flag.
#### **--driver**=*driver*
-Specify the volume driver name (default local).
+Specify the volume driver name (default **local**). Setting this to a value other than **local** Podman will attempt to create the volume using a volume plugin with the given name. Such plugins must be defined in the **volume_plugins** section of the **containers.conf**(5) configuration file.
#### **--help**
@@ -30,13 +30,14 @@ Set metadata for a volume (e.g., --label mykey=value).
#### **--opt**=*option*, **-o**
Set driver specific options.
-For the default driver, `local`, this allows a volume to be configured to mount a filesystem on the host.
+For the default driver, **local**, this allows a volume to be configured to mount a filesystem on the host.
For the `local` driver the following options are supported: `type`, `device`, and `o`.
The `type` option sets the type of the filesystem to be mounted, and is equivalent to the `-t` flag to **mount(8)**.
The `device` option sets the device to be mounted, and is equivalent to the `device` argument to **mount(8)**.
The `o` option sets options for the mount, and is equivalent to the `-o` flag to **mount(8)** with two exceptions.
The `o` option supports `uid` and `gid` options to set the UID and GID of the created volume that are not normally supported by **mount(8)**.
-Using volume options with the `local` driver requires root privileges.
+Using volume options with the **local** driver requires root privileges.
+When not using the **local** driver, the given options will be passed directly to the volume plugin. In this case, supported options will be dictated by the plugin in question, not Podman.
## EXAMPLES
@@ -53,7 +54,8 @@ $ podman volume create --label foo=bar myvol
```
## SEE ALSO
-podman-volume(1), mount(8)
+**podman-volume**(1), **mount**(8), **containers.conf**(5)
## HISTORY
+January 2020, updated with information on volume plugins by Matthew Heon <mheon@redhat.com>
November 2018, Originally compiled by Urvashi Mohnani <umohnani@redhat.com>
diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md
index 42054d075..67484c3ec 100644
--- a/docs/source/markdown/podman.1.md
+++ b/docs/source/markdown/podman.1.md
@@ -247,6 +247,7 @@ the exit codes follow the `chroot` standard, see below:
| [podman-ps(1)](podman-ps.1.md) | Prints out information about containers. |
| [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. |
| [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. |
+| [podman-rename(1)](podman-rename.1.md) | Rename an existing container. |
| [podman-restart(1)](podman-restart.1.md) | Restart one or more containers. |
| [podman-rm(1)](podman-rm.1.md) | Remove one or more containers. |
| [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. |
@@ -259,7 +260,7 @@ the exit codes follow the `chroot` standard, see below:
| [podman-system(1)](podman-system.1.md) | Manage podman. |
| [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. |
| [podman-top(1)](podman-top.1.md) | Display the running processes of a container. |
-| [podman-unmount(1)](podman-unmount.1.md) | Unmount a working container's root filesystem. |
+| [podman-unmount(1)](podman-unmount.1.md) | Unmount a working container's root filesystem. |
| [podman-unpause(1)](podman-unpause.1.md) | Unpause one or more containers. |
| [podman-unshare(1)](podman-unshare.1.md) | Run a command inside of a modified user namespace. |
| [podman-untag(1)](podman-untag.1.md) | Removes one or more names from a locally-stored image. |
diff --git a/go.mod b/go.mod
index d3af0a71a..9f3bf4042 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
github.com/containers/psgo v1.5.2
github.com/containers/storage v1.24.5
github.com/coreos/go-systemd/v22 v22.1.0
- github.com/cri-o/ocicni v0.2.1-0.20201125151022-df072ea5421c
+ github.com/cri-o/ocicni v0.2.1-0.20201204103948-b6cbe99b9756
github.com/cyphar/filepath-securejoin v0.2.2
github.com/davecgh/go-spew v1.1.1
github.com/docker/distribution v2.7.1+incompatible
@@ -62,7 +62,7 @@ require (
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
- golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
+ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3
google.golang.org/appengine v1.6.6 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
diff --git a/go.sum b/go.sum
index 2bc32ba79..3a050bb5b 100644
--- a/go.sum
+++ b/go.sum
@@ -131,8 +131,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/cri-o/ocicni v0.2.1-0.20201125151022-df072ea5421c h1:iGaCU6d3oVT0pl8tmvyDhoA/vTDL3IX08akfsKZIy9o=
-github.com/cri-o/ocicni v0.2.1-0.20201125151022-df072ea5421c/go.mod h1:vingr1ztOAzP2WyTgGbpMov9dFhbjNxdLtDv0+PhAvY=
+github.com/cri-o/ocicni v0.2.1-0.20201204103948-b6cbe99b9756 h1:4T3rzrCSvMgVTR+fm526d+Ed0BurAHGjOaaNFOVoK6E=
+github.com/cri-o/ocicni v0.2.1-0.20201204103948-b6cbe99b9756/go.mod h1:vingr1ztOAzP2WyTgGbpMov9dFhbjNxdLtDv0+PhAvY=
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
@@ -666,8 +666,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
-golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index dcb2ff751..b2ee63b08 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -304,6 +304,7 @@ func (s *BoltState) Refresh() error {
// Reset mount count to 0
oldState.MountCount = 0
+ oldState.MountPoint = ""
newState, err := json.Marshal(oldState)
if err != nil {
diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go
index c06fedd3e..6014fbef3 100644
--- a/libpod/boltdb_state_internal.go
+++ b/libpod/boltdb_state_internal.go
@@ -497,6 +497,21 @@ func (s *BoltState) getVolumeFromDB(name []byte, volume *Volume, volBkt *bolt.Bu
}
}
+ // Retrieve volume driver
+ if volume.UsesVolumeDriver() {
+ plugin, err := s.runtime.getVolumePlugin(volume.config.Driver)
+ if err != nil {
+ // We want to fail gracefully here, to ensure that we
+ // can still remove volumes even if their plugin is
+ // missing. Otherwise, we end up with volumes that
+ // cannot even be retrieved from the database and will
+ // cause things like `volume ls` to fail.
+ logrus.Errorf("Volume %s uses volume plugin %s, but it cannot be accessed - some functionality may not be available: %v", volume.Name(), volume.config.Driver, err)
+ } else {
+ volume.plugin = plugin
+ }
+ }
+
// Get the lock
lock, err := s.runtime.lockManager.RetrieveLock(volume.config.LockID)
if err != nil {
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 87ff764e3..0d62a2dd7 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -210,7 +210,13 @@ func (c *Container) Kill(signal uint) error {
}
// TODO: Is killing a paused container OK?
- if c.state.State != define.ContainerStateRunning {
+ switch c.state.State {
+ case define.ContainerStateRunning, define.ContainerStateStopping:
+ // Note that killing containers in "stopping" state is okay.
+ // In that state, the Podman is waiting for the runtime to
+ // stop the container and if that is taking too long, a user
+ // may have decided to kill the container after all.
+ default:
return errors.Wrapf(define.ErrCtrStateInvalid, "can only kill running containers. %s is in state %s", c.ID(), c.state.State.String())
}
@@ -539,7 +545,7 @@ func (c *Container) Cleanup(ctx context.Context) error {
}
// Check if state is good
- if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateCreated, define.ContainerStateStopped, define.ContainerStateExited) {
+ if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateCreated, define.ContainerStateStopped, define.ContainerStateStopping, define.ContainerStateExited) {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, refusing to clean up", c.ID())
}
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 870d92ca9..ac7eae56b 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -212,7 +212,12 @@ func (c *Container) getInspectMounts(namedVolumes []*ContainerNamedVolume, image
return nil, errors.Wrapf(err, "error looking up volume %s in container %s config", volume.Name, c.ID())
}
mountStruct.Driver = volFromDB.Driver()
- mountStruct.Source = volFromDB.MountPoint()
+
+ mountPoint, err := volFromDB.MountPoint()
+ if err != nil {
+ return nil, err
+ }
+ mountStruct.Source = mountPoint
parseMountOptionsForInspect(volume.Options, &mountStruct)
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index f4cdb749f..b9ea50783 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -764,7 +764,7 @@ func (c *Container) isStopped() (bool, error) {
return true, err
}
- return !c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused), nil
+ return !c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused, define.ContainerStateStopping), nil
}
// save container state to the database
@@ -1290,10 +1290,49 @@ func (c *Container) stop(timeout uint) error {
return err
}
+ // Set the container state to "stopping" and unlock the container
+ // before handing it over to conmon to unblock other commands. #8501
+ // demonstrates nicely that a high stop timeout will block even simple
+ // commands such as `podman ps` from progressing if the container lock
+ // is held when busy-waiting for the container to be stopped.
+ c.state.State = define.ContainerStateStopping
+ if err := c.save(); err != nil {
+ return errors.Wrapf(err, "error saving container %s state before stopping", c.ID())
+ }
+ if !c.batched {
+ c.lock.Unlock()
+ }
+
if err := c.ociRuntime.StopContainer(c, timeout, all); err != nil {
return err
}
+ if !c.batched {
+ c.lock.Lock()
+ if err := c.syncContainer(); err != nil {
+ switch errors.Cause(err) {
+ // If the container has already been removed (e.g., via
+ // the cleanup process), there's nothing left to do.
+ case define.ErrNoSuchCtr, define.ErrCtrRemoved:
+ return nil
+ default:
+ return err
+ }
+ }
+ }
+
+ // Since we're now subject to a race condition with other processes who
+ // may have altered the state (and other data), let's check if the
+ // state has changed. If so, we should return immediately and log a
+ // warning.
+ if c.state.State != define.ContainerStateStopping {
+ logrus.Warnf(
+ "Container %q state changed from %q to %q while waiting for it to be stopped: discontinuing stop procedure as another process interfered",
+ c.ID(), define.ContainerStateStopping, c.state.State,
+ )
+ return nil
+ }
+
c.newContainerEvent(events.Stop)
c.state.PID = 0
@@ -1541,8 +1580,18 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
return nil, err
}
+ // HACK HACK HACK - copy up into a volume driver is 100% broken
+ // right now.
+ if vol.UsesVolumeDriver() {
+ logrus.Infof("Not copying up into volume %s as it uses a volume driver", vol.Name())
+ return vol, nil
+ }
+
// If the volume is not empty, we should not copy up.
- volMount := vol.MountPoint()
+ volMount, err := vol.MountPoint()
+ if err != nil {
+ return nil, err
+ }
contents, err := ioutil.ReadDir(volMount)
if err != nil {
return nil, errors.Wrapf(err, "error listing contents of volume %s mountpoint when copying up from container %s", vol.Name(), c.ID())
@@ -1580,7 +1629,11 @@ func (c *Container) chownVolume(volumeName string) error {
return err
}
- if vol.state.NeedsChown {
+ // TODO: For now, I've disabled chowning volumes owned by non-Podman
+ // drivers. This may be safe, but it's really going to be a case-by-case
+ // thing, I think - safest to leave disabled now and reenable later if
+ // there is a demand.
+ if vol.state.NeedsChown && !vol.UsesVolumeDriver() {
vol.state.NeedsChown = false
uid := int(c.config.Spec.Process.User.UID)
@@ -1607,7 +1660,10 @@ func (c *Container) chownVolume(volumeName string) error {
return err
}
- mountPoint := vol.MountPoint()
+ mountPoint, err := vol.MountPoint()
+ if err != nil {
+ return err
+ }
if err := os.Lchown(mountPoint, uid, gid); err != nil {
return err
@@ -2116,7 +2172,7 @@ func (c *Container) sortUserVolumes(ctrSpec *spec.Spec) ([]*ContainerNamedVolume
// Check for an exit file, and handle one if present
func (c *Container) checkExitFile() error {
// If the container's not running, nothing to do.
- if !c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) {
+ if !c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused, define.ContainerStateStopping) {
return nil
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index ce2b52234..0553cc59c 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -341,7 +341,10 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
if err != nil {
return nil, errors.Wrapf(err, "error retrieving volume %s to add to container %s", namedVol.Name, c.ID())
}
- mountPoint := volume.MountPoint()
+ mountPoint, err := volume.MountPoint()
+ if err != nil {
+ return nil, err
+ }
volMount := spec.Mount{
Type: "bind",
Source: mountPoint,
@@ -903,7 +906,15 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
return err
}
- input, err := archive.TarWithOptions(volume.MountPoint(), &archive.TarOptions{
+ mp, err := volume.MountPoint()
+ if err != nil {
+ return err
+ }
+ if mp == "" {
+ return errors.Wrapf(define.ErrInternal, "volume %s is not mounted, cannot export", volume.Name())
+ }
+
+ input, err := archive.TarWithOptions(mp, &archive.TarOptions{
Compression: archive.Uncompressed,
IncludeSourceDir: true,
})
@@ -958,10 +969,10 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
func (c *Container) checkpointRestoreSupported() error {
if !criu.CheckForCriu() {
- return errors.Errorf("Checkpoint/Restore requires at least CRIU %d", criu.MinCriuVersion)
+ return errors.Errorf("checkpoint/restore requires at least CRIU %d", criu.MinCriuVersion)
}
if !c.ociRuntime.SupportsCheckpoint() {
- return errors.Errorf("Configured runtime does not support checkpoint/restore")
+ return errors.Errorf("configured runtime does not support checkpoint/restore")
}
return nil
}
@@ -993,7 +1004,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
}
if c.AutoRemove() && options.TargetFile == "" {
- return errors.Errorf("Cannot checkpoint containers that have been started with '--rm' unless '--export' is used")
+ return errors.Errorf("cannot checkpoint containers that have been started with '--rm' unless '--export' is used")
}
if err := c.checkpointRestoreLabelLog("dump.log"); err != nil {
@@ -1079,13 +1090,13 @@ func (c *Container) importCheckpoint(input string) error {
}
err = archive.Untar(archiveFile, c.bundlePath(), options)
if err != nil {
- return errors.Wrapf(err, "Unpacking of checkpoint archive %s failed", input)
+ return errors.Wrapf(err, "unpacking of checkpoint archive %s failed", input)
}
// Make sure the newly created config.json exists on disk
g := generate.Generator{Config: c.config.Spec}
if err = c.saveSpec(g.Config); err != nil {
- return errors.Wrap(err, "Saving imported container specification for restore failed")
+ return errors.Wrap(err, "saving imported container specification for restore failed")
}
return nil
@@ -1130,7 +1141,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
// Let's try to stat() CRIU's inventory file. If it does not exist, it makes
// no sense to try a restore. This is a minimal check if a checkpoint exist.
if _, err := os.Stat(filepath.Join(c.CheckpointPath(), "inventory.img")); os.IsNotExist(err) {
- return errors.Wrapf(err, "A complete checkpoint for this container cannot be found, cannot restore")
+ return errors.Wrapf(err, "a complete checkpoint for this container cannot be found, cannot restore")
}
if err := c.checkpointRestoreLabelLog("restore.log"); err != nil {
@@ -1286,16 +1297,22 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
volumeFile, err := os.Open(volumeFilePath)
if err != nil {
- return errors.Wrapf(err, "Failed to open volume file %s", volumeFilePath)
+ return errors.Wrapf(err, "failed to open volume file %s", volumeFilePath)
}
defer volumeFile.Close()
volume, err := c.runtime.GetVolume(v.Name)
if err != nil {
- return errors.Wrapf(err, "Failed to retrieve volume %s", v.Name)
+ return errors.Wrapf(err, "failed to retrieve volume %s", v.Name)
}
- mountPoint := volume.MountPoint()
+ mountPoint, err := volume.MountPoint()
+ if err != nil {
+ return err
+ }
+ if mountPoint == "" {
+ return errors.Wrapf(err, "unable to import volume %s as it is not mounted", volume.Name())
+ }
if err := archive.UntarUncompressed(volumeFile, mountPoint, nil); err != nil {
return errors.Wrapf(err, "Failed to extract volume %s to %s", volumeFilePath, mountPoint)
}
diff --git a/libpod/define/containerstate.go b/libpod/define/containerstate.go
index 825e77387..5d2bc9099 100644
--- a/libpod/define/containerstate.go
+++ b/libpod/define/containerstate.go
@@ -28,6 +28,9 @@ const (
// ContainerStateRemoving indicates the container is in the process of
// being removed.
ContainerStateRemoving ContainerStatus = iota
+ // ContainerStateStopping indicates the container is in the process of
+ // being stopped.
+ ContainerStateStopping ContainerStatus = iota
)
// ContainerStatus returns a string representation for users
@@ -50,6 +53,8 @@ func (t ContainerStatus) String() string {
return "exited"
case ContainerStateRemoving:
return "removing"
+ case ContainerStateStopping:
+ return "stopping"
}
return "bad state"
}
diff --git a/libpod/define/errors.go b/libpod/define/errors.go
index 568f8e88d..d37bc397e 100644
--- a/libpod/define/errors.go
+++ b/libpod/define/errors.go
@@ -35,6 +35,10 @@ var (
// aliases.
ErrNoAliases = errors.New("no aliases for container")
+ // ErrMissingPlugin indicates that the requested operation requires a
+ // plugin that is not present on the system or in the configuration.
+ ErrMissingPlugin = errors.New("required plugin missing")
+
// ErrCtrExists indicates a container with the same name or ID already
// exists
ErrCtrExists = errors.New("container already exists")
diff --git a/libpod/define/volume_inspect.go b/libpod/define/volume_inspect.go
new file mode 100644
index 000000000..20602ea16
--- /dev/null
+++ b/libpod/define/volume_inspect.go
@@ -0,0 +1,51 @@
+package define
+
+import (
+ "time"
+)
+
+// InspectVolumeData is the output of Inspect() on a volume. It is matched to
+// the format of 'docker volume inspect'.
+type InspectVolumeData struct {
+ // Name is the name of the volume.
+ Name string `json:"Name"`
+ // Driver is the driver used to create the volume.
+ // If set to "local" or "", the Local driver (Podman built-in code) is
+ // used to service the volume; otherwise, a volume plugin with the given
+ // name is used to mount and manage the volume.
+ Driver string `json:"Driver"`
+ // Mountpoint is the path on the host where the volume is mounted.
+ Mountpoint string `json:"Mountpoint"`
+ // CreatedAt is the date and time the volume was created at. This is not
+ // stored for older Libpod volumes; if so, it will be omitted.
+ CreatedAt time.Time `json:"CreatedAt,omitempty"`
+ // Status is used to return information on the volume's current state,
+ // if the volume was created using a volume plugin (uses a Driver that
+ // is not the local driver).
+ // Status is provided to us by an external program, so no guarantees are
+ // made about its format or contents. Further, it is an optional field,
+ // so it may not be set even in cases where a volume plugin is in use.
+ Status map[string]interface{} `json:"Status,omitempty"`
+ // Labels includes the volume's configured labels, key:value pairs that
+ // can be passed during volume creation to provide information for third
+ // party tools.
+ Labels map[string]string `json:"Labels"`
+ // Scope is unused and provided solely for Docker compatibility. It is
+ // unconditionally set to "local".
+ Scope string `json:"Scope"`
+ // Options is a set of options that were used when creating the volume.
+ // For the Local driver, these are mount options that will be used to
+ // determine how a local filesystem is mounted; they are handled as
+ // parameters to Mount in a manner described in the volume create
+ // manpage.
+ // For non-local drivers, these are passed as-is to the volume plugin.
+ Options map[string]string `json:"Options"`
+ // UID is the UID that the volume was created with.
+ UID int `json:"UID,omitempty"`
+ // GID is the GID that the volume was created with.
+ GID int `json:"GID,omitempty"`
+ // Anonymous indicates that the volume was created as an anonymous
+ // volume for a specific container, and will be be removed when any
+ // container using it is removed.
+ Anonymous bool `json:"Anonymous,omitempty"`
+}
diff --git a/libpod/options.go b/libpod/options.go
index 31c0b9ac9..c7bac7e1f 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1549,17 +1549,6 @@ func WithVolumeDriver(driver string) VolumeCreateOption {
return define.ErrVolumeFinalized
}
- // Uncomment when volume plugins are ready for use.
- // if driver != define.VolumeDriverLocal {
- // if _, err := plugin.GetVolumePlugin(driver); err != nil {
- // return err
- // }
- // }
-
- if driver != define.VolumeDriverLocal {
- return define.ErrNotImplemented
- }
-
volume.config.Driver = driver
return nil
}
diff --git a/libpod/plugin/volume_api.go b/libpod/plugin/volume_api.go
index 2500a4f36..c5dec651c 100644
--- a/libpod/plugin/volume_api.go
+++ b/libpod/plugin/volume_api.go
@@ -2,8 +2,9 @@ package plugin
import (
"bytes"
- "fmt"
+ "context"
"io/ioutil"
+ "net"
"net/http"
"os"
"path/filepath"
@@ -43,7 +44,6 @@ var (
const (
defaultTimeout = 5 * time.Second
- defaultPath = "/run/docker/plugins"
volumePluginType = "VolumeDriver"
)
@@ -64,6 +64,8 @@ type VolumePlugin struct {
Name string
// SocketPath is the unix socket at which the plugin is accessed.
SocketPath string
+ // Client is the HTTP client we use to connect to the plugin.
+ Client *http.Client
}
// This is the response from the activate endpoint of the API.
@@ -76,7 +78,7 @@ type activateResponse struct {
func validatePlugin(newPlugin *VolumePlugin) error {
// It's a socket. Is it a plugin?
// Hit the Activate endpoint to find out if it is, and if so what kind
- req, err := http.NewRequest("POST", activatePath, nil)
+ req, err := http.NewRequest("POST", "http://plugin"+activatePath, nil)
if err != nil {
return errors.Wrapf(err, "error making request to volume plugin %s activation endpoint", newPlugin.Name)
}
@@ -84,9 +86,7 @@ func validatePlugin(newPlugin *VolumePlugin) error {
req.Header.Set("Host", newPlugin.getURI())
req.Header.Set("Content-Type", sdk.DefaultContentTypeV1_1)
- client := new(http.Client)
- client.Timeout = defaultTimeout
- resp, err := client.Do(req)
+ resp, err := newPlugin.Client.Do(req)
if err != nil {
return errors.Wrapf(err, "error sending request to plugin %s activation endpoint", newPlugin.Name)
}
@@ -121,22 +121,28 @@ func validatePlugin(newPlugin *VolumePlugin) error {
return errors.Wrapf(ErrNotVolumePlugin, "plugin %s does not implement volume plugin, instead provides %s", newPlugin.Name, strings.Join(respStruct.Implements, ", "))
}
+ if plugins == nil {
+ plugins = make(map[string]*VolumePlugin)
+ }
+
plugins[newPlugin.Name] = newPlugin
return nil
}
-// GetVolumePlugin gets a single volume plugin by path.
-// TODO: We should not be auto-completing based on a default path; we should
-// require volumes to have been pre-specified in containers.conf (will need a
-// function to pre-populate the plugins list, and we should probably do a lazy
-// initialization there to not slow things down too much).
-func GetVolumePlugin(name string) (*VolumePlugin, error) {
+// GetVolumePlugin gets a single volume plugin, with the given name, at the
+// given path.
+func GetVolumePlugin(name string, path string) (*VolumePlugin, error) {
pluginsLock.Lock()
defer pluginsLock.Unlock()
plugin, exists := plugins[name]
if exists {
+ // This shouldn't be possible, but just in case...
+ if plugin.SocketPath != filepath.Clean(path) {
+ return nil, errors.Wrapf(define.ErrInvalidArg, "requested path %q for volume plugin %s does not match pre-existing path for plugin, %q", path, name, plugin.SocketPath)
+ }
+
return plugin, nil
}
@@ -144,7 +150,20 @@ func GetVolumePlugin(name string) (*VolumePlugin, error) {
newPlugin := new(VolumePlugin)
newPlugin.Name = name
- newPlugin.SocketPath = filepath.Join(defaultPath, fmt.Sprintf("%s.sock", name))
+ newPlugin.SocketPath = filepath.Clean(path)
+
+ // Need an HTTP client to force a Unix connection.
+ // And since we can reuse it, might as well cache it.
+ client := new(http.Client)
+ client.Timeout = defaultTimeout
+ // This bit borrowed from pkg/bindings/connection.go
+ client.Transport = &http.Transport{
+ DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
+ return (&net.Dialer{}).DialContext(ctx, "unix", newPlugin.SocketPath)
+ },
+ DisableCompression: true,
+ }
+ newPlugin.Client = client
stat, err := os.Stat(newPlugin.SocketPath)
if err != nil {
@@ -183,6 +202,7 @@ func (p *VolumePlugin) verifyReachable() error {
}
// Send a request to the volume plugin for handling.
+// Callers *MUST* close the response when they are done.
func (p *VolumePlugin) sendRequest(toJSON interface{}, hasBody bool, endpoint string) (*http.Response, error) {
var (
reqJSON []byte
@@ -196,7 +216,7 @@ func (p *VolumePlugin) sendRequest(toJSON interface{}, hasBody bool, endpoint st
}
}
- req, err := http.NewRequest("POST", endpoint, bytes.NewReader(reqJSON))
+ req, err := http.NewRequest("POST", "http://plugin"+endpoint, bytes.NewReader(reqJSON))
if err != nil {
return nil, errors.Wrapf(err, "error making request to volume plugin %s endpoint %s", p.Name, endpoint)
}
@@ -204,13 +224,12 @@ func (p *VolumePlugin) sendRequest(toJSON interface{}, hasBody bool, endpoint st
req.Header.Set("Host", p.getURI())
req.Header.Set("Content-Type", sdk.DefaultContentTypeV1_1)
- client := new(http.Client)
- client.Timeout = defaultTimeout
- resp, err := client.Do(req)
+ resp, err := p.Client.Do(req)
if err != nil {
return nil, errors.Wrapf(err, "error sending request to volume plugin %s endpoint %s", p.Name, endpoint)
}
- defer resp.Body.Close()
+ // We are *deliberately not closing* response here. It is the
+ // responsibility of the caller to do so after reading the response.
return resp, nil
}
diff --git a/libpod/rootless_cni_linux.go b/libpod/rootless_cni_linux.go
index ce8a87759..9a980750f 100644
--- a/libpod/rootless_cni_linux.go
+++ b/libpod/rootless_cni_linux.go
@@ -110,6 +110,8 @@ func DeallocRootlessCNI(ctx context.Context, c *Container) error {
logrus.Warn(err)
}
logrus.Debugf("rootless CNI: removing infra container %q", infra.ID())
+ infra.lock.Lock()
+ defer infra.lock.Unlock()
if err := c.runtime.removeContainer(ctx, infra, true, false, true); err != nil {
return err
}
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 1004e4fa7..34c737a67 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -17,6 +17,7 @@ import (
"github.com/containers/podman/v2/libpod/events"
"github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/libpod/lock"
+ "github.com/containers/podman/v2/libpod/plugin"
"github.com/containers/podman/v2/libpod/shutdown"
"github.com/containers/podman/v2/pkg/cgroups"
"github.com/containers/podman/v2/pkg/registries"
@@ -888,3 +889,18 @@ func (r *Runtime) reloadStorageConf() error {
logrus.Infof("applied new storage configuration: %v", r.storageConfig)
return nil
}
+
+// getVolumePlugin gets a specific volume plugin given its name.
+func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) {
+ // There is no plugin for local.
+ if name == define.VolumeDriverLocal || name == "" {
+ return nil, nil
+ }
+
+ pluginPath, ok := r.config.Engine.VolumePlugins[name]
+ if !ok {
+ return nil, errors.Wrapf(define.ErrMissingPlugin, "no volume plugin with name %s available", name)
+ }
+
+ return plugin.GetVolumePlugin(name, pluginPath)
+}
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index f22e48746..d2bcd8db3 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -72,6 +72,140 @@ func (r *Runtime) RestoreContainer(ctx context.Context, rSpec *spec.Spec, config
return r.setupContainer(ctx, ctr)
}
+// RenameContainer renames the given container.
+// The given container object will be rendered unusable, and a new, renamed
+// Container will be returned.
+func (r *Runtime) RenameContainer(ctx context.Context, ctr *Container, newName string) (*Container, error) {
+ ctr.lock.Lock()
+ defer ctr.lock.Unlock()
+
+ if err := ctr.syncContainer(); err != nil {
+ return nil, err
+ }
+
+ if newName == "" || !define.NameRegex.MatchString(newName) {
+ return nil, define.RegexError
+ }
+
+ // Check if the name is available.
+ // This is *100% NOT ATOMIC* so any failures in-flight will do
+ // *VERY BAD THINGS* to the state. So we have to try and catch all we
+ // can before starting.
+ if _, err := r.state.LookupContainerID(newName); err == nil {
+ return nil, errors.Wrapf(define.ErrCtrExists, "name %s is already in use by another container", newName)
+ }
+ if _, err := r.state.LookupPod(newName); err == nil {
+ return nil, errors.Wrapf(define.ErrPodExists, "name %s is already in use by another pod", newName)
+ }
+
+ // TODO: Investigate if it is possible to remove this limitation.
+ depCtrs, err := r.state.ContainerInUse(ctr)
+ if err != nil {
+ return nil, err
+ }
+ if len(depCtrs) > 0 {
+ return nil, errors.Wrapf(define.ErrCtrExists, "cannot rename container %s as it is in use by other containers: %v", ctr.ID(), strings.Join(depCtrs, ","))
+ }
+
+ // We need to pull an updated config, in case another rename fired and
+ // the config was re-written.
+ newConf, err := r.state.GetContainerConfig(ctr.ID())
+ if err != nil {
+ return nil, errors.Wrapf(err, "error retrieving container %s configuration from DB to remove", ctr.ID())
+ }
+ ctr.config = newConf
+
+ // TODO: This is going to fail if we have active exec sessions, too.
+ // Investigate fixing that at a later date.
+
+ var pod *Pod
+ if ctr.config.Pod != "" {
+ tmpPod, err := r.state.Pod(ctr.config.Pod)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error retrieving container %s pod", ctr.ID())
+ }
+ pod = tmpPod
+ // Lock pod to ensure it's not removed while we're working
+ pod.lock.Lock()
+ defer pod.lock.Unlock()
+ }
+
+ // Lock all volumes to ensure they are not removed while we're working
+ volsLocked := make(map[string]bool)
+ for _, namedVol := range ctr.config.NamedVolumes {
+ if volsLocked[namedVol.Name] {
+ continue
+ }
+ vol, err := r.state.Volume(namedVol.Name)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error retrieving volume used by container %s", ctr.ID())
+ }
+
+ volsLocked[vol.Name()] = true
+ vol.lock.Lock()
+ defer vol.lock.Unlock()
+ }
+
+ logrus.Infof("Going to rename container %s from %q to %q", ctr.ID(), ctr.Name(), newName)
+
+ // Step 1: remove the old container.
+ if pod != nil {
+ if err := r.state.RemoveContainerFromPod(pod, ctr); err != nil {
+ return nil, errors.Wrapf(err, "error renaming container %s", ctr.ID())
+ }
+ } else {
+ if err := r.state.RemoveContainer(ctr); err != nil {
+ return nil, errors.Wrapf(err, "error renaming container %s", ctr.ID())
+ }
+ }
+
+ // Step 2: Make a new container based on the old one.
+ // TODO: Should we deep-copy the container config and state, to be safe?
+ newCtr := new(Container)
+ newCtr.config = ctr.config
+ newCtr.state = ctr.state
+ newCtr.lock = ctr.lock
+ newCtr.ociRuntime = ctr.ociRuntime
+ newCtr.runtime = r
+ newCtr.rootlessSlirpSyncR = ctr.rootlessSlirpSyncR
+ newCtr.rootlessSlirpSyncW = ctr.rootlessSlirpSyncW
+ newCtr.rootlessPortSyncR = ctr.rootlessPortSyncR
+ newCtr.rootlessPortSyncW = ctr.rootlessPortSyncW
+
+ newCtr.valid = true
+ newCtr.config.Name = newName
+
+ // Step 3: Add that new container to the DB
+ if pod != nil {
+ if err := r.state.AddContainerToPod(pod, newCtr); err != nil {
+ return nil, errors.Wrapf(err, "error renaming container %s", newCtr.ID())
+ }
+ } else {
+ if err := r.state.AddContainer(newCtr); err != nil {
+ return nil, errors.Wrapf(err, "error renaming container %s", newCtr.ID())
+ }
+ }
+
+ // Step 4: Save the new container, to force the state to be written to
+ // the DB. This may not be necessary, depending on DB implementation,
+ // but let's do it to be safe.
+ if err := newCtr.save(); err != nil {
+ return nil, err
+ }
+
+ // Step 5: rename the container in c/storage.
+ // This can fail if the name is already in use by a non-Podman
+ // container. This puts us in a bad spot - we've already renamed the
+ // container in Podman. We can swap the order, but then we have the
+ // opposite problem. Atomicity is a real problem here, with no easy
+ // solution.
+ if err := r.store.SetNames(newCtr.ID(), []string{newCtr.Name()}); err != nil {
+ return nil, err
+ }
+
+ return newCtr, nil
+}
+
func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConfig) (*Container, error) {
if rSpec == nil {
return nil, errors.Wrapf(define.ErrInvalidArg, "must provide a valid runtime spec to create container")
@@ -393,7 +527,7 @@ func (r *Runtime) RemoveContainer(ctx context.Context, c *Container, force bool,
// removePod is used only when removing pods. It instructs Podman to ignore
// infra container protections, and *not* remove from the database (as pod
// remove will handle that).
-func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool, removeVolume bool, removePod bool) error {
+func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, removeVolume, removePod bool) error {
span, _ := opentracing.StartSpanFromContext(ctx, "removeContainer")
span.SetTag("type", "runtime")
defer span.Finish()
@@ -406,6 +540,18 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool,
}
}
+ // We need to refresh container config from the DB, to ensure that any
+ // changes (e.g. a rename) are picked up before we start removing.
+ // Since HasContainer above succeeded, we can safely assume the
+ // container exists.
+ // This is *very iffy* but it should be OK because the container won't
+ // exist once we're done.
+ newConf, err := r.state.GetContainerConfig(c.ID())
+ if err != nil {
+ return errors.Wrapf(err, "error retrieving container %s configuration from DB to remove", c.ID())
+ }
+ c.config = newConf
+
logrus.Debugf("Removing container %s", c.ID())
// We need to lock the pod before we lock the container.
@@ -413,7 +559,6 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool,
// Don't need to do this in pod removal case - we're evicting the entire
// pod.
var pod *Pod
- var err error
runtime := c.runtime
if c.config.Pod != "" && !removePod {
pod, err = r.state.Pod(c.config.Pod)
diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go
index 9bf0fd108..4a29f01aa 100644
--- a/libpod/runtime_volume_linux.go
+++ b/libpod/runtime_volume_linux.go
@@ -11,7 +11,9 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/events"
+ volplugin "github.com/containers/podman/v2/libpod/plugin"
"github.com/containers/storage/pkg/stringid"
+ pluginapi "github.com/docker/go-plugins-helpers/volume"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -53,6 +55,14 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption)
return nil, errors.Wrapf(define.ErrVolumeExists, "volume with name %s already exists", volume.config.Name)
}
+ // Plugin can be nil if driver is local, but that's OK - superfluous
+ // assignment doesn't hurt much.
+ plugin, err := r.getVolumePlugin(volume.config.Driver)
+ if err != nil {
+ return nil, errors.Wrapf(err, "volume %s uses volume plugin %s but it could not be retrieved", volume.config.Name, volume.config.Driver)
+ }
+ volume.plugin = plugin
+
if volume.config.Driver == define.VolumeDriverLocal {
logrus.Debugf("Validating options for local driver")
// Validate options
@@ -66,25 +76,38 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption)
}
}
- // Create the mountpoint of this volume
- volPathRoot := filepath.Join(r.config.Engine.VolumePath, volume.config.Name)
- if err := os.MkdirAll(volPathRoot, 0700); err != nil {
- return nil, errors.Wrapf(err, "error creating volume directory %q", volPathRoot)
- }
- if err := os.Chown(volPathRoot, volume.config.UID, volume.config.GID); err != nil {
- return nil, errors.Wrapf(err, "error chowning volume directory %q to %d:%d", volPathRoot, volume.config.UID, volume.config.GID)
- }
- fullVolPath := filepath.Join(volPathRoot, "_data")
- if err := os.MkdirAll(fullVolPath, 0755); err != nil {
- return nil, errors.Wrapf(err, "error creating volume directory %q", fullVolPath)
- }
- if err := os.Chown(fullVolPath, volume.config.UID, volume.config.GID); err != nil {
- return nil, errors.Wrapf(err, "error chowning volume directory %q to %d:%d", fullVolPath, volume.config.UID, volume.config.GID)
- }
- if err := LabelVolumePath(fullVolPath); err != nil {
- return nil, err
+ // Now we get conditional: we either need to make the volume in the
+ // volume plugin, or on disk if not using a plugin.
+ if volume.plugin != nil {
+ // We can't chown, or relabel, or similar the path the volume is
+ // using, because it's not managed by us.
+ // TODO: reevaluate this once we actually have volume plugins in
+ // use in production - it may be safe, but I can't tell without
+ // knowing what the actual plugin does...
+ if err := makeVolumeInPluginIfNotExist(volume.config.Name, volume.config.Options, volume.plugin); err != nil {
+ return nil, err
+ }
+ } else {
+ // Create the mountpoint of this volume
+ volPathRoot := filepath.Join(r.config.Engine.VolumePath, volume.config.Name)
+ if err := os.MkdirAll(volPathRoot, 0700); err != nil {
+ return nil, errors.Wrapf(err, "error creating volume directory %q", volPathRoot)
+ }
+ if err := os.Chown(volPathRoot, volume.config.UID, volume.config.GID); err != nil {
+ return nil, errors.Wrapf(err, "error chowning volume directory %q to %d:%d", volPathRoot, volume.config.UID, volume.config.GID)
+ }
+ fullVolPath := filepath.Join(volPathRoot, "_data")
+ if err := os.MkdirAll(fullVolPath, 0755); err != nil {
+ return nil, errors.Wrapf(err, "error creating volume directory %q", fullVolPath)
+ }
+ if err := os.Chown(fullVolPath, volume.config.UID, volume.config.GID); err != nil {
+ return nil, errors.Wrapf(err, "error chowning volume directory %q to %d:%d", fullVolPath, volume.config.UID, volume.config.GID)
+ }
+ if err := LabelVolumePath(fullVolPath); err != nil {
+ return nil, err
+ }
+ volume.config.MountPoint = fullVolPath
}
- volume.config.MountPoint = fullVolPath
lock, err := r.lockManager.AllocateLock()
if err != nil {
@@ -111,6 +134,39 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption)
return volume, nil
}
+// makeVolumeInPluginIfNotExist makes a volume in the given volume plugin if it
+// does not already exist.
+func makeVolumeInPluginIfNotExist(name string, options map[string]string, plugin *volplugin.VolumePlugin) error {
+ // Ping the volume plugin to see if it exists first.
+ // If it does, use the existing volume in the plugin.
+ // Options may not match exactly, but not much we can do about
+ // that. Not complaining avoids a lot of the sync issues we see
+ // with c/storage and libpod DB.
+ needsCreate := true
+ getReq := new(pluginapi.GetRequest)
+ getReq.Name = name
+ if resp, err := plugin.GetVolume(getReq); err == nil {
+ // TODO: What do we do if we get a 200 response, but the
+ // Volume is nil? The docs on the Plugin API are very
+ // nonspecific, so I don't know if this is valid or
+ // not...
+ if resp != nil {
+ needsCreate = false
+ logrus.Infof("Volume %q already exists in plugin %q, using existing volume", name, plugin.Name)
+ }
+ }
+ if needsCreate {
+ createReq := new(pluginapi.CreateRequest)
+ createReq.Name = name
+ createReq.Options = options
+ if err := plugin.CreateVolume(createReq); err != nil {
+ return errors.Wrapf(err, "error creating volume %q in plugin %s", name, plugin.Name)
+ }
+ }
+
+ return nil
+}
+
// removeVolume removes the specified volume from state as well tears down its mountpoint and storage
func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error {
if !v.valid {
@@ -185,9 +241,43 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
var removalErr error
+ // If we use a volume plugin, we need to remove from the plugin.
+ if v.UsesVolumeDriver() {
+ canRemove := true
+
+ // Do we have a volume driver?
+ if v.plugin == nil {
+ canRemove = false
+ removalErr = errors.Wrapf(define.ErrMissingPlugin, "cannot remove volume %s from plugin %s, but it has been removed from Podman", v.Name(), v.Driver())
+ } else {
+ // Ping the plugin first to verify the volume still
+ // exists.
+ // We're trying to be very tolerant of missing volumes
+ // in the backend, to avoid the problems we see with
+ // sync between c/storage and the Libpod DB.
+ getReq := new(pluginapi.GetRequest)
+ getReq.Name = v.Name()
+ if _, err := v.plugin.GetVolume(getReq); err != nil {
+ canRemove = false
+ removalErr = errors.Wrapf(err, "volume %s could not be retrieved from plugin %s, but it has been removed from Podman", v.Name(), v.Driver())
+ }
+ }
+ if canRemove {
+ req := new(pluginapi.RemoveRequest)
+ req.Name = v.Name()
+ if err := v.plugin.RemoveVolume(req); err != nil {
+ removalErr = errors.Wrapf(err, "volume %s could not be removed from plugin %s, but it has been removed from Podman", v.Name(), v.Driver())
+ }
+ }
+ }
+
// Free the volume's lock
if err := v.lock.Free(); err != nil {
- removalErr = errors.Wrapf(err, "error freeing lock for volume %s", v.Name())
+ if removalErr == nil {
+ removalErr = errors.Wrapf(err, "error freeing lock for volume %s", v.Name())
+ } else {
+ logrus.Errorf("Error freeing lock for volume %q: %v", v.Name(), err)
+ }
}
// Delete the mountpoint path of the volume, that is delete the volume
@@ -196,7 +286,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
if removalErr == nil {
removalErr = errors.Wrapf(err, "error cleaning up volume storage for %q", v.Name())
} else {
- logrus.Errorf("error cleaning up volume storage for volume %q: %v", v.Name(), err)
+ logrus.Errorf("Error cleaning up volume storage for volume %q: %v", v.Name(), err)
}
}
diff --git a/libpod/volume.go b/libpod/volume.go
index ed08d375f..4c137cb8e 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/lock"
+ "github.com/containers/podman/v2/libpod/plugin"
)
// Volume is a libpod named volume.
@@ -18,6 +19,7 @@ type Volume struct {
state *VolumeState
valid bool
+ plugin *plugin.VolumePlugin
runtime *Runtime
lock lock.Locker
}
@@ -31,7 +33,7 @@ type VolumeConfig struct {
// Labels for the volume.
Labels map[string]string `json:"labels"`
// The volume driver. Empty string or local does not activate a volume
- // driver, all other volumes will.
+ // driver, all other values will.
Driver string `json:"volumeDriver"`
// The location the volume is mounted at.
MountPoint string `json:"mountPoint"`
@@ -53,6 +55,10 @@ type VolumeConfig struct {
// Volumes are not guaranteed to have a state. Only volumes using the Local
// driver that have mount options set will create a state.
type VolumeState struct {
+ // Mountpoint is the location where the volume was mounted.
+ // This is only used for volumes using a volume plugin, which will mount
+ // at non-standard locations.
+ MountPoint string `json:"mountPoint,omitempty"`
// MountCount is the number of times this volume has been requested to
// be mounted.
// It is incremented on mount() and decremented on unmount().
@@ -115,8 +121,20 @@ func (v *Volume) Labels() map[string]string {
}
// MountPoint returns the volume's mountpoint on the host
-func (v *Volume) MountPoint() string {
- return v.config.MountPoint
+func (v *Volume) MountPoint() (string, error) {
+ // For the sake of performance, avoid locking unless we have to.
+ if v.UsesVolumeDriver() {
+ v.lock.Lock()
+ defer v.lock.Unlock()
+
+ if err := v.update(); err != nil {
+ return "", err
+ }
+
+ return v.state.MountPoint, nil
+ }
+
+ return v.config.MountPoint, nil
}
// Options return the volume's options
@@ -139,14 +157,19 @@ func (v *Volume) UID() (int, error) {
v.lock.Lock()
defer v.lock.Unlock()
- if !v.valid {
- return -1, define.ErrVolumeRemoved
+ if err := v.update(); err != nil {
+ return -1, err
}
+ return v.uid(), nil
+}
+
+// Internal, unlocked accessor for UID.
+func (v *Volume) uid() int {
if v.state.UIDChowned > 0 {
- return v.state.UIDChowned, nil
+ return v.state.UIDChowned
}
- return v.config.UID, nil
+ return v.config.UID
}
// GID returns the GID the volume will be created as.
@@ -154,14 +177,19 @@ func (v *Volume) GID() (int, error) {
v.lock.Lock()
defer v.lock.Unlock()
- if !v.valid {
- return -1, define.ErrVolumeRemoved
+ if err := v.update(); err != nil {
+ return -1, err
}
+ return v.gid(), nil
+}
+
+// Internal, unlocked accessor for GID.
+func (v *Volume) gid() int {
if v.state.GIDChowned > 0 {
- return v.state.GIDChowned, nil
+ return v.state.GIDChowned
}
- return v.config.GID, nil
+ return v.config.GID
}
// CreatedTime returns the time the volume was created at. It was not tracked
@@ -198,3 +226,10 @@ func (v *Volume) IsDangling() (bool, error) {
}
return len(ctrs) == 0, nil
}
+
+// UsesVolumeDriver determines whether the volume uses a volume driver. Volume
+// drivers are pluggable backends for volumes that will manage the storage and
+// mounting.
+func (v *Volume) UsesVolumeDriver() bool {
+ return !(v.config.Driver == define.VolumeDriverLocal || v.config.Driver == "")
+}
diff --git a/libpod/volume_inspect.go b/libpod/volume_inspect.go
index c8b20b8f1..2448d1bb5 100644
--- a/libpod/volume_inspect.go
+++ b/libpod/volume_inspect.go
@@ -1,60 +1,52 @@
package libpod
import (
- "time"
-
"github.com/containers/podman/v2/libpod/define"
+ pluginapi "github.com/docker/go-plugins-helpers/volume"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
-// InspectVolumeData is the output of Inspect() on a volume. It is matched to
-// the format of 'docker volume inspect'.
-type InspectVolumeData struct {
- // Name is the name of the volume.
- Name string `json:"Name"`
- // Driver is the driver used to create the volume.
- // This will be properly implemented in a future version.
- Driver string `json:"Driver"`
- // Mountpoint is the path on the host where the volume is mounted.
- Mountpoint string `json:"Mountpoint"`
- // CreatedAt is the date and time the volume was created at. This is not
- // stored for older Libpod volumes; if so, it will be omitted.
- CreatedAt time.Time `json:"CreatedAt,omitempty"`
- // Status is presently unused and provided only for Docker compatibility.
- // In the future it will be used to return information on the volume's
- // current state.
- Status map[string]string `json:"Status,omitempty"`
- // Labels includes the volume's configured labels, key:value pairs that
- // can be passed during volume creation to provide information for third
- // party tools.
- Labels map[string]string `json:"Labels"`
- // Scope is unused and provided solely for Docker compatibility. It is
- // unconditionally set to "local".
- Scope string `json:"Scope"`
- // Options is a set of options that were used when creating the volume.
- // It is presently not used.
- Options map[string]string `json:"Options"`
- // UID is the UID that the volume was created with.
- UID int `json:"UID,omitempty"`
- // GID is the GID that the volume was created with.
- GID int `json:"GID,omitempty"`
- // Anonymous indicates that the volume was created as an anonymous
- // volume for a specific container, and will be be removed when any
- // container using it is removed.
- Anonymous bool `json:"Anonymous,omitempty"`
-}
-
// Inspect provides detailed information about the configuration of the given
// volume.
-func (v *Volume) Inspect() (*InspectVolumeData, error) {
+func (v *Volume) Inspect() (*define.InspectVolumeData, error) {
if !v.valid {
return nil, define.ErrVolumeRemoved
}
- data := new(InspectVolumeData)
+ v.lock.Lock()
+ defer v.lock.Unlock()
+
+ if err := v.update(); err != nil {
+ return nil, err
+ }
+
+ data := new(define.InspectVolumeData)
+
+ data.Mountpoint = v.config.MountPoint
+ if v.UsesVolumeDriver() {
+ logrus.Debugf("Querying volume plugin %s for status", v.config.Driver)
+ data.Mountpoint = v.state.MountPoint
+
+ if v.plugin == nil {
+ return nil, errors.Wrapf(define.ErrMissingPlugin, "volume %s uses volume plugin %s but it is not available, cannot inspect", v.Name(), v.config.Driver)
+ }
+
+ // Retrieve status for the volume.
+ // Need to query the volume driver.
+ req := new(pluginapi.GetRequest)
+ req.Name = v.Name()
+ resp, err := v.plugin.GetVolume(req)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error retrieving volume %s information from plugin %s", v.Name(), v.Driver())
+ }
+ if resp != nil {
+ data.Status = resp.Status
+ }
+ }
data.Name = v.config.Name
data.Driver = v.config.Driver
- data.Mountpoint = v.config.MountPoint
data.CreatedAt = v.config.CreatedTime
data.Labels = make(map[string]string)
for k, v := range v.config.Labels {
@@ -65,15 +57,8 @@ func (v *Volume) Inspect() (*InspectVolumeData, error) {
for k, v := range v.config.Options {
data.Options[k] = v
}
- var err error
- data.UID, err = v.UID()
- if err != nil {
- return nil, err
- }
- data.GID, err = v.GID()
- if err != nil {
- return nil, err
- }
+ data.UID = v.uid()
+ data.GID = v.gid()
data.Anonymous = v.config.IsAnon
return data, nil
diff --git a/libpod/volume_internal.go b/libpod/volume_internal.go
index 95cb752e0..88d940370 100644
--- a/libpod/volume_internal.go
+++ b/libpod/volume_internal.go
@@ -22,13 +22,24 @@ func newVolume(runtime *Runtime) *Volume {
// teardownStorage deletes the volume from volumePath
func (v *Volume) teardownStorage() error {
+ if v.UsesVolumeDriver() {
+ return nil
+ }
+
+ // TODO: Should this be converted to use v.config.MountPoint?
return os.RemoveAll(filepath.Join(v.runtime.config.Engine.VolumePath, v.Name()))
}
// Volumes with options set, or a filesystem type, or a device to mount need to
// be mounted and unmounted.
func (v *Volume) needsMount() bool {
- return len(v.config.Options) > 0 && v.config.Driver == define.VolumeDriverLocal
+ // Non-local driver always needs mount
+ if v.UsesVolumeDriver() {
+ return true
+ }
+
+ // Local driver with options needs mount
+ return len(v.config.Options) > 0
}
// update() updates the volume state from the DB.
diff --git a/libpod/volume_internal_linux.go b/libpod/volume_internal_linux.go
index bbf47f124..e184505e7 100644
--- a/libpod/volume_internal_linux.go
+++ b/libpod/volume_internal_linux.go
@@ -8,11 +8,17 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/rootless"
+ pluginapi "github.com/docker/go-plugins-helpers/volume"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
+// This is a pseudo-container ID to use when requesting a mount or unmount from
+// the volume plugins.
+// This is the shas256 of the string "placeholder\n".
+const pseudoCtrID = "2f73349cfc4630255319c6c8dfc1b46a8996ace9d14d8e07563b165915918ec2"
+
// mount mounts the volume if necessary.
// A mount is necessary if a volume has any options set.
// If a mount is necessary, v.state.MountCount will be incremented.
@@ -20,7 +26,7 @@ import (
// host. Otherwise, we assume it is already mounted.
// Must be done while the volume is locked.
// Is a no-op on volumes that do not require a mount (as defined by
-// volumeNeedsMount())
+// volumeNeedsMount()).
func (v *Volume) mount() error {
if !v.needsMount() {
return nil
@@ -44,6 +50,28 @@ func (v *Volume) mount() error {
return v.save()
}
+ // Volume plugins implement their own mount counter, based on the ID of
+ // the mounting container. But we already have one, and honestly I trust
+ // ours more. So hardcode container ID to something reasonable, and use
+ // the same one for everything.
+ if v.UsesVolumeDriver() {
+ if v.plugin == nil {
+ return errors.Wrapf(define.ErrMissingPlugin, "volume plugin %s (needed by volume %s) missing", v.Driver(), v.Name())
+ }
+
+ req := new(pluginapi.MountRequest)
+ req.Name = v.Name()
+ req.ID = pseudoCtrID
+ mountPoint, err := v.plugin.MountVolume(req)
+ if err != nil {
+ return err
+ }
+
+ v.state.MountCount += 1
+ v.state.MountPoint = mountPoint
+ return v.save()
+ }
+
volDevice := v.config.Options["device"]
volType := v.config.Options["type"]
volOptions := v.config.Options["o"]
@@ -132,6 +160,22 @@ func (v *Volume) unmount(force bool) error {
logrus.Debugf("Volume %s mount count now at %d", v.Name(), v.state.MountCount)
if v.state.MountCount == 0 {
+ if v.UsesVolumeDriver() {
+ if v.plugin == nil {
+ return errors.Wrapf(define.ErrMissingPlugin, "volume plugin %s (needed by volume %s) missing", v.Driver(), v.Name())
+ }
+
+ req := new(pluginapi.UnmountRequest)
+ req.Name = v.Name()
+ req.ID = pseudoCtrID
+ if err := v.plugin.UnmountVolume(req); err != nil {
+ return err
+ }
+
+ v.state.MountPoint = ""
+ return v.save()
+ }
+
// Unmount the volume
if err := unix.Unmount(v.config.MountPoint, unix.MNT_DETACH); err != nil {
if err == unix.EINVAL {
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 0f89c859e..6e1945db1 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -465,3 +465,34 @@ func formatCapabilities(slice []string) {
slice[i] = strings.TrimPrefix(slice[i], "CAP_")
}
}
+
+func RenameContainer(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+
+ name := utils.GetName(r)
+ query := struct {
+ Name string `schema:"name"`
+ }{}
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ utils.ContainerNotFound(w, name, err)
+ return
+ }
+
+ if _, err := runtime.RenameContainer(r.Context(), ctr, query.Name); err != nil {
+ if errors.Cause(err) == define.ErrPodExists || errors.Cause(err) == define.ErrCtrExists {
+ utils.Error(w, "Something went wrong.", http.StatusConflict, err)
+ return
+ }
+ utils.InternalServerError(w, err)
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusNoContent, nil)
+}
diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go
index 4903bbad4..82e70eb90 100644
--- a/pkg/api/handlers/compat/volumes.go
+++ b/pkg/api/handlers/compat/volumes.go
@@ -58,10 +58,15 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
}
volumeConfigs := make([]*docker_api_types.Volume, 0, len(vols))
for _, v := range vols {
+ mp, err := v.MountPoint()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
config := docker_api_types.Volume{
Name: v.Name(),
Driver: v.Driver(),
- Mountpoint: v.MountPoint(),
+ Mountpoint: mp,
CreatedAt: v.CreatedTime().Format(time.RFC3339),
Labels: v.Labels(),
Scope: v.Scope(),
@@ -106,11 +111,16 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
// if using the compat layer and the volume already exists, we
// must return a 201 with the same information as create
if existingVolume != nil && !utils.IsLibpodRequest(r) {
+ mp, err := existingVolume.MountPoint()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
response := docker_api_types.Volume{
CreatedAt: existingVolume.CreatedTime().Format(time.RFC3339),
Driver: existingVolume.Driver(),
Labels: existingVolume.Labels(),
- Mountpoint: existingVolume.MountPoint(),
+ Mountpoint: mp,
Name: existingVolume.Name(),
Options: existingVolume.Options(),
Scope: existingVolume.Scope(),
@@ -146,10 +156,15 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
+ mp, err := vol.MountPoint()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
volResponse := docker_api_types.Volume{
Name: config.Name,
Driver: config.Driver,
- Mountpoint: config.MountPoint,
+ Mountpoint: mp,
CreatedAt: config.CreatedTime.Format(time.RFC3339),
Labels: config.Labels,
Options: config.Options,
@@ -173,10 +188,15 @@ func InspectVolume(w http.ResponseWriter, r *http.Request) {
utils.VolumeNotFound(w, name, err)
return
}
+ mp, err := vol.MountPoint()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
volResponse := docker_api_types.Volume{
Name: vol.Name(),
Driver: vol.Driver(),
- Mountpoint: vol.MountPoint(),
+ Mountpoint: mp,
CreatedAt: vol.CreatedTime().Format(time.RFC3339),
Labels: vol.Labels(),
Options: vol.Options(),
diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go
index 6f9537515..38fdf1b4d 100644
--- a/pkg/api/handlers/libpod/volumes.go
+++ b/pkg/api/handlers/libpod/volumes.go
@@ -60,20 +60,13 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
- config, err := vol.Config()
+ inspectOut, err := vol.Inspect()
if err != nil {
utils.InternalServerError(w, err)
return
}
volResponse := entities.VolumeConfigResponse{
- Name: config.Name,
- Driver: config.Driver,
- Mountpoint: config.MountPoint,
- CreatedAt: config.CreatedTime,
- Labels: config.Labels,
- Options: config.Options,
- UID: config.UID,
- GID: config.GID,
+ InspectVolumeData: *inspectOut,
}
utils.WriteResponse(w, http.StatusCreated, volResponse)
}
@@ -88,27 +81,13 @@ func InspectVolume(w http.ResponseWriter, r *http.Request) {
utils.VolumeNotFound(w, name, err)
return
}
- var uid, gid int
- uid, err = vol.UID()
+ inspectOut, err := vol.Inspect()
if err != nil {
- utils.Error(w, "Error fetching volume UID", http.StatusInternalServerError, err)
- return
- }
- gid, err = vol.GID()
- if err != nil {
- utils.Error(w, "Error fetching volume GID", http.StatusInternalServerError, err)
+ utils.InternalServerError(w, err)
return
}
volResponse := entities.VolumeConfigResponse{
- Name: vol.Name(),
- Driver: vol.Driver(),
- Mountpoint: vol.MountPoint(),
- CreatedAt: vol.CreatedTime(),
- Labels: vol.Labels(),
- Scope: vol.Scope(),
- Options: vol.Options(),
- UID: uid,
- GID: gid,
+ InspectVolumeData: *inspectOut,
}
utils.WriteResponse(w, http.StatusOK, volResponse)
}
@@ -143,27 +122,13 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
}
volumeConfigs := make([]*entities.VolumeListReport, 0, len(vols))
for _, v := range vols {
- var uid, gid int
- uid, err = v.UID()
+ inspectOut, err := v.Inspect()
if err != nil {
- utils.Error(w, "Error fetching volume UID", http.StatusInternalServerError, err)
- return
- }
- gid, err = v.GID()
- if err != nil {
- utils.Error(w, "Error fetching volume GID", http.StatusInternalServerError, err)
+ utils.InternalServerError(w, err)
return
}
config := entities.VolumeConfigResponse{
- Name: v.Name(),
- Driver: v.Driver(),
- Mountpoint: v.MountPoint(),
- CreatedAt: v.CreatedTime(),
- Labels: v.Labels(),
- Scope: v.Scope(),
- Options: v.Options(),
- UID: uid,
- GID: gid,
+ InspectVolumeData: *inspectOut,
}
volumeConfigs = append(volumeConfigs, &entities.VolumeListReport{VolumeConfigResponse: config})
}
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index b80dea545..74a04b2e6 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -291,9 +291,6 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
r.HandleFunc(VersionedPath("/containers/{name}/pause"), s.APIHandler(compat.PauseContainer)).Methods(http.MethodPost)
// Added non version path to URI to support docker non versioned paths
r.HandleFunc("/containers/{name}/pause", s.APIHandler(compat.PauseContainer)).Methods(http.MethodPost)
- r.HandleFunc(VersionedPath("/containers/{name}/rename"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
- // Added non version path to URI to support docker non versioned paths
- r.HandleFunc("/containers/{name}/rename", s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
// swagger:operation POST /containers/{name}/restart compat restartContainer
// ---
// tags:
@@ -610,6 +607,36 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/{name}/export"), s.APIHandler(compat.ExportContainer)).Methods(http.MethodGet)
r.HandleFunc("/containers/{name}/export", s.APIHandler(compat.ExportContainer)).Methods(http.MethodGet)
+ // swagger:operation POST /containers/{name}/rename compat renameContainer
+ // ---
+ // tags:
+ // - containers (compat)
+ // summary: Rename an existing container
+ // description: Change the name of an existing container.
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: Full or partial ID or full name of the container to rename
+ // - in: query
+ // name: name
+ // type: string
+ // required: true
+ // description: New name for the container
+ // produces:
+ // - application/json
+ // responses:
+ // 204:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 409:
+ // $ref: "#/responses/ConflictError"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/containers/{name}/rename"), s.APIHandler(compat.RenameContainer)).Methods(http.MethodPost)
+ r.HandleFunc("/containers/{name}/rename", s.APIHandler(compat.RenameContainer)).Methods(http.MethodPost)
/*
libpod endpoints
@@ -1463,5 +1490,34 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// 500:
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name}/init"), s.APIHandler(libpod.InitContainer)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/containers/{name}/rename libpod libpodRenameContainer
+ // ---
+ // tags:
+ // - containers
+ // summary: Rename an existing container
+ // description: Change the name of an existing container.
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: Full or partial ID or full name of the container to rename
+ // - in: query
+ // name: name
+ // type: string
+ // required: true
+ // description: New name for the container
+ // produces:
+ // - application/json
+ // responses:
+ // 204:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 409:
+ // $ref: "#/responses/ConflictError"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/rename"), s.APIHandler(compat.RenameContainer)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/bindings/containers/types_attach_options.go b/pkg/bindings/containers/types_attach_options.go
index 4ffb8ab17..6d8c1cb01 100644
--- a/pkg/bindings/containers/types_attach_options.go
+++ b/pkg/bindings/containers/types_attach_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:18.566804404 -0600 CST m=+0.000258831
*/
// Changed
@@ -39,6 +38,7 @@ func (o *AttachOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_checkpoint_options.go b/pkg/bindings/containers/types_checkpoint_options.go
index d03dc8231..ec766de4a 100644
--- a/pkg/bindings/containers/types_checkpoint_options.go
+++ b/pkg/bindings/containers/types_checkpoint_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:18.714853285 -0600 CST m=+0.000319103
*/
// Changed
@@ -39,6 +38,7 @@ func (o *CheckpointOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_commit_options.go b/pkg/bindings/containers/types_commit_options.go
index a8b215141..b745bebe2 100644
--- a/pkg/bindings/containers/types_commit_options.go
+++ b/pkg/bindings/containers/types_commit_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:18.420656951 -0600 CST m=+0.000259662
*/
// Changed
@@ -39,6 +38,7 @@ func (o *CommitOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_create_options.go b/pkg/bindings/containers/types_create_options.go
index 4dbce0203..4b9574cf1 100644
--- a/pkg/bindings/containers/types_create_options.go
+++ b/pkg/bindings/containers/types_create_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:19.011789618 -0600 CST m=+0.000259413
*/
// Changed
@@ -39,6 +38,7 @@ func (o *CreateOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_diff_options.go b/pkg/bindings/containers/types_diff_options.go
index be3bbf554..55fa6930d 100644
--- a/pkg/bindings/containers/types_diff_options.go
+++ b/pkg/bindings/containers/types_diff_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:19.159128927 -0600 CST m=+0.000255635
*/
// Changed
@@ -39,6 +38,7 @@ func (o *DiffOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_execinspect_options.go b/pkg/bindings/containers/types_execinspect_options.go
index 3c4c870be..c5d1f931a 100644
--- a/pkg/bindings/containers/types_execinspect_options.go
+++ b/pkg/bindings/containers/types_execinspect_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:19.303239014 -0600 CST m=+0.000256861
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ExecInspectOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_execstart_options.go b/pkg/bindings/containers/types_execstart_options.go
index 66fdc82cb..9ecb70a3e 100644
--- a/pkg/bindings/containers/types_execstart_options.go
+++ b/pkg/bindings/containers/types_execstart_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:19.447714428 -0600 CST m=+0.000257278
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ExecStartOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_execstartandattach_options.go b/pkg/bindings/containers/types_execstartandattach_options.go
index 43900d29d..a5a691e35 100644
--- a/pkg/bindings/containers/types_execstartandattach_options.go
+++ b/pkg/bindings/containers/types_execstartandattach_options.go
@@ -6,6 +6,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -13,8 +14,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:22.827903078 -0600 CST m=+0.000269906
*/
// Changed
@@ -41,6 +40,7 @@ func (o *ExecStartAndAttachOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_export_options.go b/pkg/bindings/containers/types_export_options.go
index e325bd2cd..55e413c72 100644
--- a/pkg/bindings/containers/types_export_options.go
+++ b/pkg/bindings/containers/types_export_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:22.101679998 -0600 CST m=+0.000261669
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ExportOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_healthcheck_options.go b/pkg/bindings/containers/types_healthcheck_options.go
index 8c4300366..9d8b25bf4 100644
--- a/pkg/bindings/containers/types_healthcheck_options.go
+++ b/pkg/bindings/containers/types_healthcheck_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:19.593883686 -0600 CST m=+0.000289845
*/
// Changed
@@ -39,6 +38,7 @@ func (o *HealthCheckOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_init_options.go b/pkg/bindings/containers/types_init_options.go
index 655362f62..6fb5795c0 100644
--- a/pkg/bindings/containers/types_init_options.go
+++ b/pkg/bindings/containers/types_init_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:22.245077233 -0600 CST m=+0.000255461
*/
// Changed
@@ -39,6 +38,7 @@ func (o *InitOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_inspect_options.go b/pkg/bindings/containers/types_inspect_options.go
index 884f5524d..722372414 100644
--- a/pkg/bindings/containers/types_inspect_options.go
+++ b/pkg/bindings/containers/types_inspect_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:20.635987603 -0600 CST m=+0.000260270
*/
// Changed
@@ -39,6 +38,7 @@ func (o *InspectOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_kill_options.go b/pkg/bindings/containers/types_kill_options.go
index 3d6fa6224..dd84f0d9f 100644
--- a/pkg/bindings/containers/types_kill_options.go
+++ b/pkg/bindings/containers/types_kill_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:20.781581076 -0600 CST m=+0.000259040
*/
// Changed
@@ -39,6 +38,7 @@ func (o *KillOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_list_options.go b/pkg/bindings/containers/types_list_options.go
index dd74d37b7..43326fa59 100644
--- a/pkg/bindings/containers/types_list_options.go
+++ b/pkg/bindings/containers/types_list_options.go
@@ -12,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:20.199081744 -0600 CST m=+0.000270626
*/
// Changed
diff --git a/pkg/bindings/containers/types_log_options.go b/pkg/bindings/containers/types_log_options.go
index a6958242f..364f29de4 100644
--- a/pkg/bindings/containers/types_log_options.go
+++ b/pkg/bindings/containers/types_log_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:18.273264471 -0600 CST m=+0.000274536
*/
// Changed
@@ -39,6 +38,7 @@ func (o *LogOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_mount_options.go b/pkg/bindings/containers/types_mount_options.go
index c0e253094..6f4349b73 100644
--- a/pkg/bindings/containers/types_mount_options.go
+++ b/pkg/bindings/containers/types_mount_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:19.740822464 -0600 CST m=+0.000250074
*/
// Changed
@@ -39,6 +38,7 @@ func (o *MountOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_mountedcontainerpaths_options.go b/pkg/bindings/containers/types_mountedcontainerpaths_options.go
index e368ff131..0d8b69654 100644
--- a/pkg/bindings/containers/types_mountedcontainerpaths_options.go
+++ b/pkg/bindings/containers/types_mountedcontainerpaths_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:20.048233253 -0600 CST m=+0.000307223
*/
// Changed
@@ -39,6 +38,7 @@ func (o *MountedContainerPathsOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_pause_options.go b/pkg/bindings/containers/types_pause_options.go
index 26ad86793..0cc65f64e 100644
--- a/pkg/bindings/containers/types_pause_options.go
+++ b/pkg/bindings/containers/types_pause_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:20.929891294 -0600 CST m=+0.000261081
*/
// Changed
@@ -39,6 +38,7 @@ func (o *PauseOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_prune_options.go b/pkg/bindings/containers/types_prune_options.go
index e3c0f4de7..10adf0a2a 100644
--- a/pkg/bindings/containers/types_prune_options.go
+++ b/pkg/bindings/containers/types_prune_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:20.344278799 -0600 CST m=+0.000263499
*/
// Changed
@@ -39,6 +38,7 @@ func (o *PruneOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_remove_options.go b/pkg/bindings/containers/types_remove_options.go
index 6f59f0ed5..e21fb41f7 100644
--- a/pkg/bindings/containers/types_remove_options.go
+++ b/pkg/bindings/containers/types_remove_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:20.489968735 -0600 CST m=+0.000264450
*/
// Changed
@@ -39,6 +38,7 @@ func (o *RemoveOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_resizeexectty_options.go b/pkg/bindings/containers/types_resizeexectty_options.go
index 33bb4e78b..0212adeb2 100644
--- a/pkg/bindings/containers/types_resizeexectty_options.go
+++ b/pkg/bindings/containers/types_resizeexectty_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:22.680735758 -0600 CST m=+0.000267081
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ResizeExecTTYOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_resizetty_options.go b/pkg/bindings/containers/types_resizetty_options.go
index 29ec54988..cee607902 100644
--- a/pkg/bindings/containers/types_resizetty_options.go
+++ b/pkg/bindings/containers/types_resizetty_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:22.535788375 -0600 CST m=+0.000266528
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ResizeTTYOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_restart_options.go b/pkg/bindings/containers/types_restart_options.go
index 13ac099b1..8dcc6b5b7 100644
--- a/pkg/bindings/containers/types_restart_options.go
+++ b/pkg/bindings/containers/types_restart_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:21.076709643 -0600 CST m=+0.000303354
*/
// Changed
@@ -39,6 +38,7 @@ func (o *RestartOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_restore_options.go b/pkg/bindings/containers/types_restore_options.go
index be6e94736..491d678a5 100644
--- a/pkg/bindings/containers/types_restore_options.go
+++ b/pkg/bindings/containers/types_restore_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:18.861536405 -0600 CST m=+0.000300026
*/
// Changed
@@ -39,6 +38,7 @@ func (o *RestoreOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_shouldrestart_options.go b/pkg/bindings/containers/types_shouldrestart_options.go
index c833d0d8b..30ab618c7 100644
--- a/pkg/bindings/containers/types_shouldrestart_options.go
+++ b/pkg/bindings/containers/types_shouldrestart_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:22.388596051 -0600 CST m=+0.000253693
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ShouldRestartOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_start_options.go b/pkg/bindings/containers/types_start_options.go
index 5918af89b..4050a8993 100644
--- a/pkg/bindings/containers/types_start_options.go
+++ b/pkg/bindings/containers/types_start_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:21.221364502 -0600 CST m=+0.000276575
*/
// Changed
@@ -39,6 +38,7 @@ func (o *StartOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_stats_options.go b/pkg/bindings/containers/types_stats_options.go
index f821ea1cd..74f419913 100644
--- a/pkg/bindings/containers/types_stats_options.go
+++ b/pkg/bindings/containers/types_stats_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:21.370213399 -0600 CST m=+0.000264334
*/
// Changed
@@ -39,6 +38,7 @@ func (o *StatsOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_stop_options.go b/pkg/bindings/containers/types_stop_options.go
index 14d7633a0..db692dbf0 100644
--- a/pkg/bindings/containers/types_stop_options.go
+++ b/pkg/bindings/containers/types_stop_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:21.95469621 -0600 CST m=+0.000261399
*/
// Changed
@@ -39,6 +38,7 @@ func (o *StopOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_top_options.go b/pkg/bindings/containers/types_top_options.go
index 95a1ee686..5f2717c28 100644
--- a/pkg/bindings/containers/types_top_options.go
+++ b/pkg/bindings/containers/types_top_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:21.515867629 -0600 CST m=+0.000257106
*/
// Changed
@@ -39,6 +38,7 @@ func (o *TopOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_unmount_options.go b/pkg/bindings/containers/types_unmount_options.go
index a29bd8216..060327c4a 100644
--- a/pkg/bindings/containers/types_unmount_options.go
+++ b/pkg/bindings/containers/types_unmount_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:19.891657824 -0600 CST m=+0.000326668
*/
// Changed
@@ -39,6 +38,7 @@ func (o *UnmountOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_unpause_options.go b/pkg/bindings/containers/types_unpause_options.go
index 44c077df2..e02bf2c95 100644
--- a/pkg/bindings/containers/types_unpause_options.go
+++ b/pkg/bindings/containers/types_unpause_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:21.661356277 -0600 CST m=+0.000262608
*/
// Changed
@@ -39,6 +38,7 @@ func (o *UnpauseOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/containers/types_wait_options.go b/pkg/bindings/containers/types_wait_options.go
index 18d36c377..470d67611 100644
--- a/pkg/bindings/containers/types_wait_options.go
+++ b/pkg/bindings/containers/types_wait_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
"github.com/containers/podman/v2/libpod/define"
jsoniter "github.com/json-iterator/go"
@@ -12,8 +13,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 13:33:21.809397978 -0600 CST m=+0.000267049
*/
// Changed
@@ -40,6 +39,7 @@ func (o *WaitOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/generate/types_kube_options.go b/pkg/bindings/generate/types_kube_options.go
index 68488aaee..5fb965c9f 100644
--- a/pkg/bindings/generate/types_kube_options.go
+++ b/pkg/bindings/generate/types_kube_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:20.522950566 -0600 CST m=+0.000154384
*/
// Changed
@@ -39,6 +38,7 @@ func (o *KubeOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/generate/types_systemd_options.go b/pkg/bindings/generate/types_systemd_options.go
index 0e8a46aa0..ce7286b3a 100644
--- a/pkg/bindings/generate/types_systemd_options.go
+++ b/pkg/bindings/generate/types_systemd_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:20.661450253 -0600 CST m=+0.000135779
*/
// Changed
@@ -39,6 +38,7 @@ func (o *SystemdOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/generator/generator.go b/pkg/bindings/generator/generator.go
index 8c79aebae..6a7f600a8 100644
--- a/pkg/bindings/generator/generator.go
+++ b/pkg/bindings/generator/generator.go
@@ -19,13 +19,10 @@ var bodyTmpl = `package {{.PackageName}}
import (
{{range $import := .Imports}} {{$import}}
{{end}}
-
)
/*
This file is generated automatically by go generate. Do not edit.
-
-Created {{.Date}}
*/
// Changed
@@ -52,6 +49,7 @@ func (o *{{.StructName}}) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
@@ -239,7 +237,7 @@ func main() {
closed = true
// go fmt file
- gofmt := exec.Command("gofmt", "-w", "-s", out.Name())
+ gofmt := exec.Command("go", "fmt", out.Name())
gofmt.Stderr = os.Stdout
if err := gofmt.Run(); err != nil {
fmt.Println(err)
diff --git a/pkg/bindings/images/types_diff_options.go b/pkg/bindings/images/types_diff_options.go
index d27c8945e..34a5bf2df 100644
--- a/pkg/bindings/images/types_diff_options.go
+++ b/pkg/bindings/images/types_diff_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:26.320022698 -0600 CST m=+0.000277796
*/
// Changed
@@ -39,6 +38,7 @@ func (o *DiffOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_export_options.go b/pkg/bindings/images/types_export_options.go
index 078b27fc0..172cb2b5c 100644
--- a/pkg/bindings/images/types_export_options.go
+++ b/pkg/bindings/images/types_export_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:27.173810543 -0600 CST m=+0.000239871
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ExportOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_get_options.go b/pkg/bindings/images/types_get_options.go
index 1161657f7..c91ddb170 100644
--- a/pkg/bindings/images/types_get_options.go
+++ b/pkg/bindings/images/types_get_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:26.609005517 -0600 CST m=+0.000241828
*/
// Changed
@@ -39,6 +38,7 @@ func (o *GetOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_history_options.go b/pkg/bindings/images/types_history_options.go
index 6f9854e03..bd4224cd8 100644
--- a/pkg/bindings/images/types_history_options.go
+++ b/pkg/bindings/images/types_history_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:26.890854681 -0600 CST m=+0.000243668
*/
// Changed
@@ -39,6 +38,7 @@ func (o *HistoryOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_import_options.go b/pkg/bindings/images/types_import_options.go
index f5e6c8f7e..81eda946e 100644
--- a/pkg/bindings/images/types_import_options.go
+++ b/pkg/bindings/images/types_import_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:27.740585278 -0600 CST m=+0.000340441
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ImportOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_list_options.go b/pkg/bindings/images/types_list_options.go
index 209d72e34..5dc4242fc 100644
--- a/pkg/bindings/images/types_list_options.go
+++ b/pkg/bindings/images/types_list_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:26.462967928 -0600 CST m=+0.000289760
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ListOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_load_options.go b/pkg/bindings/images/types_load_options.go
index 6bba573d4..7bbd56c09 100644
--- a/pkg/bindings/images/types_load_options.go
+++ b/pkg/bindings/images/types_load_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:27.031848205 -0600 CST m=+0.000279409
*/
// Changed
@@ -39,6 +38,7 @@ func (o *LoadOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_prune_options.go b/pkg/bindings/images/types_prune_options.go
index c29fdae12..c290bb379 100644
--- a/pkg/bindings/images/types_prune_options.go
+++ b/pkg/bindings/images/types_prune_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:27.316938584 -0600 CST m=+0.000239843
*/
// Changed
@@ -39,6 +38,7 @@ func (o *PruneOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_pull_options.go b/pkg/bindings/images/types_pull_options.go
index 07f3e079d..5163a6341 100644
--- a/pkg/bindings/images/types_pull_options.go
+++ b/pkg/bindings/images/types_pull_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
"github.com/containers/common/pkg/config"
jsoniter "github.com/json-iterator/go"
@@ -12,8 +13,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:28.164648348 -0600 CST m=+0.000243264
*/
// Changed
@@ -40,6 +39,7 @@ func (o *PullOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_push_options.go b/pkg/bindings/images/types_push_options.go
index f9ce1b835..15210f30b 100644
--- a/pkg/bindings/images/types_push_options.go
+++ b/pkg/bindings/images/types_push_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:27.881232044 -0600 CST m=+0.000242458
*/
// Changed
@@ -39,6 +38,7 @@ func (o *PushOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_remove_options.go b/pkg/bindings/images/types_remove_options.go
index c9692c2b7..66a6bea7d 100644
--- a/pkg/bindings/images/types_remove_options.go
+++ b/pkg/bindings/images/types_remove_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:26.180391541 -0600 CST m=+0.000290244
*/
// Changed
@@ -39,6 +38,7 @@ func (o *RemoveOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_search_options.go b/pkg/bindings/images/types_search_options.go
index e6168ac33..299d27505 100644
--- a/pkg/bindings/images/types_search_options.go
+++ b/pkg/bindings/images/types_search_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:28.023569573 -0600 CST m=+0.000245548
*/
// Changed
@@ -39,6 +38,7 @@ func (o *SearchOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_tag_options.go b/pkg/bindings/images/types_tag_options.go
index f6396e590..40cd4a35b 100644
--- a/pkg/bindings/images/types_tag_options.go
+++ b/pkg/bindings/images/types_tag_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:27.457906682 -0600 CST m=+0.000245071
*/
// Changed
@@ -39,6 +38,7 @@ func (o *TagOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_tree_options.go b/pkg/bindings/images/types_tree_options.go
index fb2493f85..a671fa4e0 100644
--- a/pkg/bindings/images/types_tree_options.go
+++ b/pkg/bindings/images/types_tree_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:26.749625305 -0600 CST m=+0.000267624
*/
// Changed
@@ -39,6 +38,7 @@ func (o *TreeOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/images/types_untag_options.go b/pkg/bindings/images/types_untag_options.go
index 8faf5c14e..e38c5f18e 100644
--- a/pkg/bindings/images/types_untag_options.go
+++ b/pkg/bindings/images/types_untag_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:27.600379913 -0600 CST m=+0.000251449
*/
// Changed
@@ -39,6 +38,7 @@ func (o *UntagOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/manifests/types_add_options.go b/pkg/bindings/manifests/types_add_options.go
index d45effedc..1e588c668 100644
--- a/pkg/bindings/manifests/types_add_options.go
+++ b/pkg/bindings/manifests/types_add_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:57:55.92237379 -0600 CST m=+0.000150701
*/
// Changed
@@ -39,6 +38,7 @@ func (o *AddOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/manifests/types_create_options.go b/pkg/bindings/manifests/types_create_options.go
index da07f1abf..3a564a92b 100644
--- a/pkg/bindings/manifests/types_create_options.go
+++ b/pkg/bindings/manifests/types_create_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:57:55.784206871 -0600 CST m=+0.000157049
*/
// Changed
@@ -39,6 +38,7 @@ func (o *CreateOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/manifests/types_inspect_options.go b/pkg/bindings/manifests/types_inspect_options.go
index 0d32d5bb9..2af4190d4 100644
--- a/pkg/bindings/manifests/types_inspect_options.go
+++ b/pkg/bindings/manifests/types_inspect_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:57:55.631746481 -0600 CST m=+0.000143104
*/
// Changed
@@ -39,6 +38,7 @@ func (o *InspectOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/manifests/types_push_options.go b/pkg/bindings/manifests/types_push_options.go
index 4226733c9..1d689f699 100644
--- a/pkg/bindings/manifests/types_push_options.go
+++ b/pkg/bindings/manifests/types_push_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:57:56.197438009 -0600 CST m=+0.000149060
*/
// Changed
@@ -39,6 +38,7 @@ func (o *PushOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/manifests/types_remove_options.go b/pkg/bindings/manifests/types_remove_options.go
index f99220f6c..3b35c38b8 100644
--- a/pkg/bindings/manifests/types_remove_options.go
+++ b/pkg/bindings/manifests/types_remove_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:57:56.059954408 -0600 CST m=+0.000146015
*/
// Changed
@@ -39,6 +38,7 @@ func (o *RemoveOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/network/types_connect_options.go b/pkg/bindings/network/types_connect_options.go
index 6fcc4536e..b6081ba57 100644
--- a/pkg/bindings/network/types_connect_options.go
+++ b/pkg/bindings/network/types_connect_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:34.075822786 -0600 CST m=+0.000167237
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ConnectOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/network/types_create_options.go b/pkg/bindings/network/types_create_options.go
index daec6a254..5b0abe870 100644
--- a/pkg/bindings/network/types_create_options.go
+++ b/pkg/bindings/network/types_create_options.go
@@ -5,6 +5,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -12,8 +13,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:33.37307678 -0600 CST m=+0.000176739
*/
// Changed
@@ -40,6 +39,7 @@ func (o *CreateOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
@@ -193,9 +193,9 @@ func (o *CreateOptions) WithIPRange(value net.IPNet) *CreateOptions {
// GetIPRange
func (o *CreateOptions) GetIPRange() net.IPNet {
- var ipRange net.IPNet
+ var iPRange net.IPNet
if o.IPRange == nil {
- return ipRange
+ return iPRange
}
return *o.IPRange
}
diff --git a/pkg/bindings/network/types_disconnect_options.go b/pkg/bindings/network/types_disconnect_options.go
index 821279976..8b2a9cb71 100644
--- a/pkg/bindings/network/types_disconnect_options.go
+++ b/pkg/bindings/network/types_disconnect_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:33.936088242 -0600 CST m=+0.000168680
*/
// Changed
@@ -39,6 +38,7 @@ func (o *DisconnectOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/network/types_inspect_options.go b/pkg/bindings/network/types_inspect_options.go
index 7704904ce..cec5ef7b2 100644
--- a/pkg/bindings/network/types_inspect_options.go
+++ b/pkg/bindings/network/types_inspect_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:33.520438264 -0600 CST m=+0.000172934
*/
// Changed
@@ -39,6 +38,7 @@ func (o *InspectOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/network/types_list_options.go b/pkg/bindings/network/types_list_options.go
index bbd2a71db..6a33fb7b6 100644
--- a/pkg/bindings/network/types_list_options.go
+++ b/pkg/bindings/network/types_list_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:33.796794129 -0600 CST m=+0.000180368
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ListOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/network/types_remove_options.go b/pkg/bindings/network/types_remove_options.go
index b24835ae4..861fe1f2c 100644
--- a/pkg/bindings/network/types_remove_options.go
+++ b/pkg/bindings/network/types_remove_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:33.658228151 -0600 CST m=+0.000172527
*/
// Changed
@@ -39,6 +38,7 @@ func (o *RemoveOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/play/types_kube_options.go b/pkg/bindings/play/types_kube_options.go
index 91cdd30aa..5aec4b479 100644
--- a/pkg/bindings/play/types_kube_options.go
+++ b/pkg/bindings/play/types_kube_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:02.386833736 -0600 CST m=+0.000171080
*/
// Changed
@@ -39,6 +38,7 @@ func (o *KubeOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_create_options.go b/pkg/bindings/pods/types_create_options.go
index b6cf0fc53..b501d1151 100644
--- a/pkg/bindings/pods/types_create_options.go
+++ b/pkg/bindings/pods/types_create_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:40.05490508 -0600 CST m=+0.000156396
*/
// Changed
@@ -39,6 +38,7 @@ func (o *CreateOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_inspect_options.go b/pkg/bindings/pods/types_inspect_options.go
index 1c881ce9c..a2eb25fef 100644
--- a/pkg/bindings/pods/types_inspect_options.go
+++ b/pkg/bindings/pods/types_inspect_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:40.258801519 -0600 CST m=+0.000175055
*/
// Changed
@@ -39,6 +38,7 @@ func (o *InspectOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_kill_options.go b/pkg/bindings/pods/types_kill_options.go
index cb5bdfd01..f9cad3579 100644
--- a/pkg/bindings/pods/types_kill_options.go
+++ b/pkg/bindings/pods/types_kill_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:40.398857339 -0600 CST m=+0.000160135
*/
// Changed
@@ -39,6 +38,7 @@ func (o *KillOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_list_options.go b/pkg/bindings/pods/types_list_options.go
index d095bf3db..02e7adf2d 100644
--- a/pkg/bindings/pods/types_list_options.go
+++ b/pkg/bindings/pods/types_list_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:40.818123838 -0600 CST m=+0.000164328
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ListOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_pause_options.go b/pkg/bindings/pods/types_pause_options.go
index 06ee6f81d..2e4fdb4a6 100644
--- a/pkg/bindings/pods/types_pause_options.go
+++ b/pkg/bindings/pods/types_pause_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:40.538407099 -0600 CST m=+0.000193274
*/
// Changed
@@ -39,6 +38,7 @@ func (o *PauseOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_prune_options.go b/pkg/bindings/pods/types_prune_options.go
index 6610aa7cc..616ad6dc9 100644
--- a/pkg/bindings/pods/types_prune_options.go
+++ b/pkg/bindings/pods/types_prune_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:40.678507342 -0600 CST m=+0.000183891
*/
// Changed
@@ -39,6 +38,7 @@ func (o *PruneOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_remove_options.go b/pkg/bindings/pods/types_remove_options.go
index 8f18e43c9..6960d8839 100644
--- a/pkg/bindings/pods/types_remove_options.go
+++ b/pkg/bindings/pods/types_remove_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:41.80320679 -0600 CST m=+0.000158149
*/
// Changed
@@ -39,6 +38,7 @@ func (o *RemoveOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_restart_options.go b/pkg/bindings/pods/types_restart_options.go
index 9030de1e7..427833044 100644
--- a/pkg/bindings/pods/types_restart_options.go
+++ b/pkg/bindings/pods/types_restart_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:40.958315383 -0600 CST m=+0.000168360
*/
// Changed
@@ -39,6 +38,7 @@ func (o *RestartOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_start_options.go b/pkg/bindings/pods/types_start_options.go
index 0fce21099..e98798459 100644
--- a/pkg/bindings/pods/types_start_options.go
+++ b/pkg/bindings/pods/types_start_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:41.099102916 -0600 CST m=+0.000159629
*/
// Changed
@@ -39,6 +38,7 @@ func (o *StartOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_stats_options.go b/pkg/bindings/pods/types_stats_options.go
index d38a9a115..845a534a3 100644
--- a/pkg/bindings/pods/types_stats_options.go
+++ b/pkg/bindings/pods/types_stats_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:41.658228243 -0600 CST m=+0.000160769
*/
// Changed
@@ -39,6 +38,7 @@ func (o *StatsOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_stop_options.go b/pkg/bindings/pods/types_stop_options.go
index ac698b8c5..86000eb57 100644
--- a/pkg/bindings/pods/types_stop_options.go
+++ b/pkg/bindings/pods/types_stop_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:41.237892781 -0600 CST m=+0.000155040
*/
// Changed
@@ -39,6 +38,7 @@ func (o *StopOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_top_options.go b/pkg/bindings/pods/types_top_options.go
index 895f62957..ada0b1e25 100644
--- a/pkg/bindings/pods/types_top_options.go
+++ b/pkg/bindings/pods/types_top_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:41.375876994 -0600 CST m=+0.000154839
*/
// Changed
@@ -39,6 +38,7 @@ func (o *TopOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/pods/types_unpause_options.go b/pkg/bindings/pods/types_unpause_options.go
index 3d647cf25..6a9ee8fcd 100644
--- a/pkg/bindings/pods/types_unpause_options.go
+++ b/pkg/bindings/pods/types_unpause_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:41.515225789 -0600 CST m=+0.000158667
*/
// Changed
@@ -39,6 +38,7 @@ func (o *UnpauseOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/system/types_disk_options.go b/pkg/bindings/system/types_disk_options.go
index f7d2cca06..c5eb2f94c 100644
--- a/pkg/bindings/system/types_disk_options.go
+++ b/pkg/bindings/system/types_disk_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:08.087362343 -0600 CST m=+0.000150636
*/
// Changed
@@ -39,6 +38,7 @@ func (o *DiskOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/system/types_events_options.go b/pkg/bindings/system/types_events_options.go
index 6dd64b055..2e95339e6 100644
--- a/pkg/bindings/system/types_events_options.go
+++ b/pkg/bindings/system/types_events_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:07.675150173 -0600 CST m=+0.000140977
*/
// Changed
@@ -39,6 +38,7 @@ func (o *EventsOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/system/types_info_options.go b/pkg/bindings/system/types_info_options.go
index 3a8960e1b..263513b0f 100644
--- a/pkg/bindings/system/types_info_options.go
+++ b/pkg/bindings/system/types_info_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:08.233760126 -0600 CST m=+0.000142369
*/
// Changed
@@ -39,6 +38,7 @@ func (o *InfoOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/system/types_prune_options.go b/pkg/bindings/system/types_prune_options.go
index 2cd3c8000..a9a6a6cda 100644
--- a/pkg/bindings/system/types_prune_options.go
+++ b/pkg/bindings/system/types_prune_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:07.812719858 -0600 CST m=+0.000143214
*/
// Changed
@@ -39,6 +38,7 @@ func (o *PruneOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/system/types_version_options.go b/pkg/bindings/system/types_version_options.go
index 4974e8d8f..be07581fa 100644
--- a/pkg/bindings/system/types_version_options.go
+++ b/pkg/bindings/system/types_version_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:07.950759332 -0600 CST m=+0.000140376
*/
// Changed
@@ -39,6 +38,7 @@ func (o *VersionOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/volumes/types_create_options.go b/pkg/bindings/volumes/types_create_options.go
index 80bdac2d2..171090afe 100644
--- a/pkg/bindings/volumes/types_create_options.go
+++ b/pkg/bindings/volumes/types_create_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:14.043860791 -0600 CST m=+0.000188944
*/
// Changed
@@ -39,6 +38,7 @@ func (o *CreateOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/volumes/types_inspect_options.go b/pkg/bindings/volumes/types_inspect_options.go
index ba8c70b63..3a1d396a7 100644
--- a/pkg/bindings/volumes/types_inspect_options.go
+++ b/pkg/bindings/volumes/types_inspect_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:14.189902005 -0600 CST m=+0.000151439
*/
// Changed
@@ -39,6 +38,7 @@ func (o *InspectOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/volumes/types_list_options.go b/pkg/bindings/volumes/types_list_options.go
index 99dec132c..56033a575 100644
--- a/pkg/bindings/volumes/types_list_options.go
+++ b/pkg/bindings/volumes/types_list_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:14.326721724 -0600 CST m=+0.000172471
*/
// Changed
@@ -39,6 +38,7 @@ func (o *ListOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/volumes/types_prune_options.go b/pkg/bindings/volumes/types_prune_options.go
index cdbc03fc9..c043d69d0 100644
--- a/pkg/bindings/volumes/types_prune_options.go
+++ b/pkg/bindings/volumes/types_prune_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:14.463307398 -0600 CST m=+0.000180868
*/
// Changed
@@ -39,6 +38,7 @@ func (o *PruneOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/bindings/volumes/types_remove_options.go b/pkg/bindings/volumes/types_remove_options.go
index 923d1353c..1f8ba4e22 100644
--- a/pkg/bindings/volumes/types_remove_options.go
+++ b/pkg/bindings/volumes/types_remove_options.go
@@ -4,6 +4,7 @@ import (
"net/url"
"reflect"
"strconv"
+ "strings"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@@ -11,8 +12,6 @@ import (
/*
This file is generated automatically by go generate. Do not edit.
-
-Created 2020-12-18 15:58:14.60278922 -0600 CST m=+0.000134408
*/
// Changed
@@ -39,6 +38,7 @@ func (o *RemoveOptions) ToParams() (url.Values, error) {
if !o.Changed(fieldName) {
continue
}
+ fieldName = strings.ToLower(fieldName)
f := s.Field(i)
if reflect.Ptr == f.Kind() {
f = f.Elem()
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index 96687b1de..d8576c101 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -434,3 +434,9 @@ type ContainerStatsReport struct {
// Results, set when there is no error.
Stats []define.ContainerStats
}
+
+// ContainerRenameOptions describes input options for renaming a container.
+type ContainerRenameOptions struct {
+ // NewName is the new name that will be given to the container.
+ NewName string
+}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 7d38a97f2..d2552770c 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -37,6 +37,7 @@ type ContainerEngine interface {
ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
ContainerPort(ctx context.Context, nameOrID string, options ContainerPortOptions) ([]*ContainerPortReport, error)
ContainerPrune(ctx context.Context, options ContainerPruneOptions) ([]*reports.PruneReport, error)
+ ContainerRename(ctr context.Context, nameOrID string, options ContainerRenameOptions) 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)
diff --git a/pkg/domain/entities/volumes.go b/pkg/domain/entities/volumes.go
index 06438f5e9..c826ee389 100644
--- a/pkg/domain/entities/volumes.go
+++ b/pkg/domain/entities/volumes.go
@@ -2,8 +2,8 @@ package entities
import (
"net/url"
- "time"
+ "github.com/containers/podman/v2/libpod/define"
docker_api_types "github.com/docker/docker/api/types"
docker_api_types_volume "github.com/docker/docker/api/types/volume"
)
@@ -26,38 +26,7 @@ type IDOrNameResponse struct {
}
type VolumeConfigResponse struct {
- // Name is the name of the volume.
- Name string `json:"Name"`
- // Driver is the driver used to create the volume.
- // This will be properly implemented in a future version.
- Driver string `json:"Driver"`
- // Mountpoint is the path on the host where the volume is mounted.
- Mountpoint string `json:"Mountpoint"`
- // CreatedAt is the date and time the volume was created at. This is not
- // stored for older Libpod volumes; if so, it will be omitted.
- CreatedAt time.Time `json:"CreatedAt,omitempty"`
- // Status is presently unused and provided only for Docker compatibility.
- // In the future it will be used to return information on the volume's
- // current state.
- Status map[string]string `json:"Status,omitempty"`
- // Labels includes the volume's configured labels, key:value pairs that
- // can be passed during volume creation to provide information for third
- // party tools.
- Labels map[string]string `json:"Labels"`
- // Scope is unused and provided solely for Docker compatibility. It is
- // unconditionally set to "local".
- Scope string `json:"Scope"`
- // Options is a set of options that were used when creating the volume.
- // It is presently not used.
- Options map[string]string `json:"Options"`
- // UID is the UID that the volume was created with.
- UID int `json:"UID"`
- // GID is the GID that the volume was created with.
- GID int `json:"GID"`
- // Anonymous indicates that the volume was created as an anonymous
- // volume for a specific container, and will be be removed when any
- // container using it is removed.
- Anonymous bool `json:"Anonymous"`
+ define.InspectVolumeData
}
// VolumeInfo Volume list response
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index b5f5a0e91..a8f4d44a8 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -902,7 +902,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
if err := ic.Libpod.RemoveContainer(ctx, ctr, false, true); err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr ||
errors.Cause(err) == define.ErrCtrRemoved {
- logrus.Warnf("Container %s does not exist: %v", ctr.ID(), err)
+ logrus.Infof("Container %s was already removed, skipping --rm", ctr.ID())
} else {
logrus.Errorf("Error removing container %s: %v", ctr.ID(), err)
}
@@ -1312,3 +1312,17 @@ func (ic *ContainerEngine) ShouldRestart(ctx context.Context, nameOrID string) (
return &entities.BoolReport{Value: ctr.ShouldRestart(ctx)}, nil
}
+
+// ContainerRename renames the given container.
+func (ic *ContainerEngine) ContainerRename(ctx context.Context, nameOrID string, opts entities.ContainerRenameOptions) error {
+ ctr, err := ic.Libpod.LookupContainer(nameOrID)
+ if err != nil {
+ return err
+ }
+
+ if _, err := ic.Libpod.RenameContainer(ctx, ctr, opts.NewName); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/pkg/domain/infra/abi/containers_stat.go b/pkg/domain/infra/abi/containers_stat.go
index 5b43ee2f4..931e77026 100644
--- a/pkg/domain/infra/abi/containers_stat.go
+++ b/pkg/domain/infra/abi/containers_stat.go
@@ -144,16 +144,29 @@ func resolveContainerPaths(container *libpod.Container, mountPoint string, conta
}
if volume != nil {
logrus.Debugf("Container path %q resolved to volume %q on path %q", containerPath, volume.Name(), searchPath)
+
+ // TODO: We really need to force the volume to mount
+ // before doing this, but that API is not exposed
+ // externally right now and doing so is beyond the scope
+ // of this commit.
+ mountPoint, err := volume.MountPoint()
+ if err != nil {
+ return "", "", err
+ }
+ if mountPoint == "" {
+ return "", "", errors.Errorf("volume %s is not mounted, cannot copy into it", volume.Name())
+ }
+
// We found a matching volume for searchPath. We now
// need to first find the relative path of our input
// path to the searchPath, and then join it with the
// volume's mount point.
pathRelativeToVolume := strings.TrimPrefix(pathRelativeToContainerMountPoint, searchPath)
- absolutePathOnTheVolumeMount, err := securejoin.SecureJoin(volume.MountPoint(), pathRelativeToVolume)
+ absolutePathOnTheVolumeMount, err := securejoin.SecureJoin(mountPoint, pathRelativeToVolume)
if err != nil {
return "", "", err
}
- return volume.MountPoint(), absolutePathOnTheVolumeMount, nil
+ return mountPoint, absolutePathOnTheVolumeMount, nil
}
if mount := findBindMount(container, searchPath); mount != nil {
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 97fa9d374..f29b98696 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -312,7 +312,17 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
var reclaimableSize int64
for _, v := range vols {
var consInUse int
- volSize, err := sizeOfPath(v.MountPoint())
+ mountPoint, err := v.MountPoint()
+ if err != nil {
+ return nil, err
+ }
+ if mountPoint == "" {
+ // We can't get any info on this volume, as it's not
+ // mounted.
+ // TODO: fix this.
+ continue
+ }
+ volSize, err := sizeOfPath(mountPoint)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/abi/volumes.go b/pkg/domain/infra/abi/volumes.go
index 3c9dd9fc0..823605052 100644
--- a/pkg/domain/infra/abi/volumes.go
+++ b/pkg/domain/infra/abi/volumes.go
@@ -103,25 +103,12 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
}
reports := make([]*entities.VolumeInspectReport, 0, len(vols))
for _, v := range vols {
- var uid, gid int
- uid, err = v.UID()
- if err != nil {
- return nil, nil, err
- }
- gid, err = v.GID()
+ inspectOut, err := v.Inspect()
if err != nil {
return nil, nil, err
}
config := entities.VolumeConfigResponse{
- Name: v.Name(),
- Driver: v.Driver(),
- Mountpoint: v.MountPoint(),
- CreatedAt: v.CreatedTime(),
- Labels: v.Labels(),
- Scope: v.Scope(),
- Options: v.Options(),
- UID: uid,
- GID: gid,
+ InspectVolumeData: *inspectOut,
}
reports = append(reports, &entities.VolumeInspectReport{VolumeConfigResponse: &config})
}
@@ -155,25 +142,12 @@ func (ic *ContainerEngine) VolumeList(ctx context.Context, opts entities.VolumeL
}
reports := make([]*entities.VolumeListReport, 0, len(vols))
for _, v := range vols {
- var uid, gid int
- uid, err = v.UID()
- if err != nil {
- return nil, err
- }
- gid, err = v.GID()
+ inspectOut, err := v.Inspect()
if err != nil {
return nil, err
}
config := entities.VolumeConfigResponse{
- Name: v.Name(),
- Driver: v.Driver(),
- Mountpoint: v.MountPoint(),
- CreatedAt: v.CreatedTime(),
- Labels: v.Labels(),
- Scope: v.Scope(),
- Options: v.Options(),
- UID: uid,
- GID: gid,
+ InspectVolumeData: *inspectOut,
}
reports = append(reports, &entities.VolumeListReport{VolumeConfigResponse: config})
}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 49bcdec98..8aab4a9cd 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -820,3 +820,8 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
func (ic *ContainerEngine) ShouldRestart(_ context.Context, id string) (bool, error) {
return containers.ShouldRestart(ic.ClientCtx, id, nil)
}
+
+// ContainerRename renames the given container.
+func (ic *ContainerEngine) ContainerRename(ctx context.Context, nameOrID string, opts entities.ContainerRenameOptions) error {
+ return errors.Errorf("NOT YET IMPLEMENTED")
+}
diff --git a/test/apiv2/30-volumes.at b/test/apiv2/30-volumes.at
index 33f4ea37f..b38810039 100644
--- a/test/apiv2/30-volumes.at
+++ b/test/apiv2/30-volumes.at
@@ -12,7 +12,7 @@ t POST libpod/volumes/create name=foo1 201 \
.Mountpoint=$volumepath/foo1/_data \
.CreatedAt~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.* \
.Labels={} \
- .Options=null
+ .Options={}
t POST libpod/volumes/create '' 201
t POST libpod/volumes/create \
'"Name":"foo2","Label":{"testlabel":"testonly"},"Options":{"type":"tmpfs","o":"nodev,noexec"}}' 201 \
diff --git a/test/apiv2/45-system.at b/test/apiv2/45-system.at
index 44cd05a13..985d86e56 100644
--- a/test/apiv2/45-system.at
+++ b/test/apiv2/45-system.at
@@ -19,7 +19,7 @@ t POST libpod/volumes/create name=foo1 201 \
.Mountpoint=$volumepath/foo1/_data \
.CreatedAt~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.* \
.Labels={} \
- .Options=null
+ .Options={}
t GET system/df 200 '.Volumes[0].Name=foo1'
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index abc37792a..3270ce685 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -623,7 +623,7 @@ var _ = Describe("Podman checkpoint", func() {
result := podmanTest.Podman([]string{"container", "checkpoint", "-l"})
result.WaitWithDefaultTimeout()
Expect(result).To(ExitWithError())
- Expect(result.ErrorToString()).To(ContainSubstring("Cannot checkpoint containers that have been started with '--rm'"))
+ Expect(result.ErrorToString()).To(ContainSubstring("cannot checkpoint containers that have been started with '--rm'"))
// Checkpointing with --export should still work
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 18679dd53..2668b1e7b 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -122,7 +122,7 @@ var _ = SynchronizedBeforeSuite(func() []byte {
}
// Pull cirros but don't put it into the cache
- pullImages := []string{cirros, fedoraToolbox}
+ pullImages := []string{cirros, fedoraToolbox, volumeTest}
pullImages = append(pullImages, CACHE_IMAGES...)
for _, image := range pullImages {
podman.createArtifact(image)
@@ -483,13 +483,7 @@ func (p *PodmanTestIntegration) CleanupVolume() {
session := p.Podman([]string{"volume", "rm", "-fa"})
session.Wait(90)
- // Stop remove service on volume cleanup
- p.StopRemoteService()
-
- // Nuke tempdir
- if err := os.RemoveAll(p.TempDir); err != nil {
- fmt.Printf("%q\n", err)
- }
+ p.Cleanup()
}
// InspectContainerToJSON takes the session output of an inspect
diff --git a/test/e2e/config.go b/test/e2e/config.go
index e66cd6846..2552595ad 100644
--- a/test/e2e/config.go
+++ b/test/e2e/config.go
@@ -15,6 +15,7 @@ var (
healthcheck = "quay.io/libpod/alpine_healthcheck:latest"
ImageCacheDir = "/tmp/podman/imagecachedir"
fedoraToolbox = "registry.fedoraproject.org/f32/fedora-toolbox:latest"
+ volumeTest = "quay.io/libpod/volume-plugin-test-img:latest"
// This image has seccomp profiles that blocks all syscalls.
// The intention behind blocking all syscalls is to prevent
diff --git a/test/e2e/config/containers.conf b/test/e2e/config/containers.conf
index 35153ba05..5a5e4b7a5 100644
--- a/test/e2e/config/containers.conf
+++ b/test/e2e/config/containers.conf
@@ -56,3 +56,17 @@ umask = "0002"
[engine]
network_cmd_options=["allow_host_loopback=true"]
+
+# We need to ensure each test runs on a separate plugin instance...
+# For now, let's just make a bunch of plugin paths and have each test use one.
+[engine.volume_plugins]
+testvol0 = "/run/docker/plugins/testvol0.sock"
+testvol1 = "/run/docker/plugins/testvol1.sock"
+testvol2 = "/run/docker/plugins/testvol2.sock"
+testvol3 = "/run/docker/plugins/testvol3.sock"
+testvol4 = "/run/docker/plugins/testvol4.sock"
+testvol5 = "/run/docker/plugins/testvol5.sock"
+testvol6 = "/run/docker/plugins/testvol6.sock"
+testvol7 = "/run/docker/plugins/testvol7.sock"
+testvol8 = "/run/docker/plugins/testvol8.sock"
+testvol9 = "/run/docker/plugins/testvol9.sock"
diff --git a/test/e2e/rename_test.go b/test/e2e/rename_test.go
new file mode 100644
index 000000000..324e6a54a
--- /dev/null
+++ b/test/e2e/rename_test.go
@@ -0,0 +1,93 @@
+package integration
+
+import (
+ "fmt"
+ "os"
+
+ . "github.com/containers/podman/v2/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("podman rename", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ SkipIfRemote("Rename not yet implemented by podman-remote")
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ podmanTest.SeedImages()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+
+ })
+
+ It("podman rename on non-existent container", func() {
+ session := podmanTest.Podman([]string{"rename", "doesNotExist", "aNewName"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ })
+
+ It("Podman rename on existing container with bad name", func() {
+ ctrName := "testCtr"
+ ctr := podmanTest.Podman([]string{"create", "--name", ctrName, ALPINE, "top"})
+ ctr.WaitWithDefaultTimeout()
+ Expect(ctr.ExitCode()).To(Equal(0))
+
+ newName := "invalid<>:char"
+ rename := podmanTest.Podman([]string{"rename", ctrName, newName})
+ rename.WaitWithDefaultTimeout()
+ Expect(rename.ExitCode()).To(Not(Equal(0)))
+
+ ps := podmanTest.Podman([]string{"ps", "-aq", "--filter", fmt.Sprintf("name=%s", ctrName), "--format", "{{ .Names }}"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps.ExitCode()).To(Equal(0))
+ Expect(ps.OutputToString()).To(ContainSubstring(ctrName))
+ })
+
+ It("Successfully rename a created container", func() {
+ ctrName := "testCtr"
+ ctr := podmanTest.Podman([]string{"create", "--name", ctrName, ALPINE, "top"})
+ ctr.WaitWithDefaultTimeout()
+ Expect(ctr.ExitCode()).To(Equal(0))
+
+ newName := "aNewName"
+ rename := podmanTest.Podman([]string{"rename", ctrName, newName})
+ rename.WaitWithDefaultTimeout()
+ Expect(rename.ExitCode()).To(Equal(0))
+
+ ps := podmanTest.Podman([]string{"ps", "-aq", "--filter", fmt.Sprintf("name=%s", newName), "--format", "{{ .Names }}"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps.ExitCode()).To(Equal(0))
+ Expect(ps.OutputToString()).To(ContainSubstring(newName))
+ })
+
+ It("Successfully rename a running container", func() {
+ ctrName := "testCtr"
+ ctr := podmanTest.Podman([]string{"run", "-d", "--name", ctrName, ALPINE, "top"})
+ ctr.WaitWithDefaultTimeout()
+ Expect(ctr.ExitCode()).To(Equal(0))
+
+ newName := "aNewName"
+ rename := podmanTest.Podman([]string{"rename", ctrName, newName})
+ rename.WaitWithDefaultTimeout()
+ Expect(rename.ExitCode()).To(Equal(0))
+
+ ps := podmanTest.Podman([]string{"ps", "-aq", "--filter", fmt.Sprintf("name=%s", newName), "--format", "{{ .Names }}"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps.ExitCode()).To(Equal(0))
+ Expect(ps.OutputToString()).To(ContainSubstring(newName))
+ })
+})
diff --git a/test/e2e/volume_plugin_test.go b/test/e2e/volume_plugin_test.go
new file mode 100644
index 000000000..16edab27c
--- /dev/null
+++ b/test/e2e/volume_plugin_test.go
@@ -0,0 +1,184 @@
+package integration
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+
+ . "github.com/containers/podman/v2/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("Podman volume plugins", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ podmanTest.SeedImages()
+ os.Setenv("CONTAINERS_CONF", "config/containers.conf")
+ SkipIfRemote("Volume plugins only supported as local")
+ SkipIfRootless("Root is required for volume plugin testing")
+ os.MkdirAll("/run/docker/plugins", 0755)
+ })
+
+ AfterEach(func() {
+ podmanTest.CleanupVolume()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+ os.Unsetenv("CONTAINERS_CONF")
+ })
+
+ It("volume create with nonexistent plugin errors", func() {
+ session := podmanTest.Podman([]string{"volume", "create", "--driver", "notexist", "test_volume_name"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ })
+
+ It("volume create with not-running plugin does not error", func() {
+ session := podmanTest.Podman([]string{"volume", "create", "--driver", "testvol0", "test_volume_name"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ })
+
+ It("volume create and remove with running plugin succeeds", func() {
+ podmanTest.AddImageToRWStore(volumeTest)
+
+ pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes")
+ os.Mkdir(pluginStatePath, 0755)
+
+ // Keep this distinct within tests to avoid multiple tests using the same plugin.
+ pluginName := "testvol1"
+ plugin := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins", "-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath})
+ plugin.WaitWithDefaultTimeout()
+ Expect(plugin.ExitCode()).To(Equal(0))
+
+ volName := "testVolume1"
+ create := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, volName})
+ create.WaitWithDefaultTimeout()
+ Expect(create.ExitCode()).To(Equal(0))
+
+ ls1 := podmanTest.Podman([]string{"volume", "ls", "-q"})
+ ls1.WaitWithDefaultTimeout()
+ Expect(ls1.ExitCode()).To(Equal(0))
+ arrOutput := ls1.OutputToStringArray()
+ Expect(len(arrOutput)).To(Equal(1))
+ Expect(arrOutput[0]).To(ContainSubstring(volName))
+
+ remove := podmanTest.Podman([]string{"volume", "rm", volName})
+ remove.WaitWithDefaultTimeout()
+ Expect(remove.ExitCode()).To(Equal(0))
+
+ ls2 := podmanTest.Podman([]string{"volume", "ls", "-q"})
+ ls2.WaitWithDefaultTimeout()
+ Expect(ls2.ExitCode()).To(Equal(0))
+ Expect(len(ls2.OutputToStringArray())).To(Equal(0))
+ })
+
+ It("volume inspect with running plugin succeeds", func() {
+ podmanTest.AddImageToRWStore(volumeTest)
+
+ pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes")
+ os.Mkdir(pluginStatePath, 0755)
+
+ // Keep this distinct within tests to avoid multiple tests using the same plugin.
+ pluginName := "testvol2"
+ plugin := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins", "-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath})
+ plugin.WaitWithDefaultTimeout()
+ Expect(plugin.ExitCode()).To(Equal(0))
+
+ volName := "testVolume1"
+ create := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, volName})
+ create.WaitWithDefaultTimeout()
+ Expect(create.ExitCode()).To(Equal(0))
+
+ volInspect := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .Driver }}", volName})
+ volInspect.WaitWithDefaultTimeout()
+ Expect(volInspect.ExitCode()).To(Equal(0))
+ Expect(volInspect.OutputToString()).To(ContainSubstring(pluginName))
+ })
+
+ It("remove plugin with stopped plugin succeeds", func() {
+ podmanTest.AddImageToRWStore(volumeTest)
+
+ pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes")
+ os.Mkdir(pluginStatePath, 0755)
+
+ // Keep this distinct within tests to avoid multiple tests using the same plugin.
+ pluginName := "testvol3"
+ ctrName := "pluginCtr"
+ plugin := podmanTest.Podman([]string{"run", "--name", ctrName, "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins", "-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath})
+ plugin.WaitWithDefaultTimeout()
+ Expect(plugin.ExitCode()).To(Equal(0))
+
+ volName := "testVolume1"
+ create := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, volName})
+ create.WaitWithDefaultTimeout()
+ Expect(create.ExitCode()).To(Equal(0))
+
+ ls1 := podmanTest.Podman([]string{"volume", "ls", "-q"})
+ ls1.WaitWithDefaultTimeout()
+ Expect(ls1.ExitCode()).To(Equal(0))
+ arrOutput := ls1.OutputToStringArray()
+ Expect(len(arrOutput)).To(Equal(1))
+ Expect(arrOutput[0]).To(ContainSubstring(volName))
+
+ stop := podmanTest.Podman([]string{"stop", "--timeout", "0", ctrName})
+ stop.WaitWithDefaultTimeout()
+ Expect(stop.ExitCode()).To(Equal(0))
+
+ // Remove should exit non-zero because missing plugin
+ remove := podmanTest.Podman([]string{"volume", "rm", volName})
+ remove.WaitWithDefaultTimeout()
+ Expect(remove.ExitCode()).To(Not(Equal(0)))
+
+ // But the volume should still be gone
+ ls2 := podmanTest.Podman([]string{"volume", "ls", "-q"})
+ ls2.WaitWithDefaultTimeout()
+ Expect(ls2.ExitCode()).To(Equal(0))
+ Expect(len(ls2.OutputToStringArray())).To(Equal(0))
+ })
+
+ It("use plugin in containers", func() {
+ podmanTest.AddImageToRWStore(volumeTest)
+
+ pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes")
+ os.Mkdir(pluginStatePath, 0755)
+
+ // Keep this distinct within tests to avoid multiple tests using the same plugin.
+ pluginName := "testvol4"
+ plugin := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins", "-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath})
+ plugin.WaitWithDefaultTimeout()
+ Expect(plugin.ExitCode()).To(Equal(0))
+
+ volName := "testVolume1"
+ create := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, volName})
+ create.WaitWithDefaultTimeout()
+ Expect(create.ExitCode()).To(Equal(0))
+
+ ctr1 := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "-v", fmt.Sprintf("%v:/test", volName), ALPINE, "sh", "-c", "touch /test/testfile && echo helloworld > /test/testfile"})
+ ctr1.WaitWithDefaultTimeout()
+ Expect(ctr1.ExitCode()).To(Equal(0))
+
+ ctr2 := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "-v", fmt.Sprintf("%v:/test", volName), ALPINE, "cat", "/test/testfile"})
+ ctr2.WaitWithDefaultTimeout()
+ Expect(ctr2.ExitCode()).To(Equal(0))
+ Expect(ctr2.OutputToString()).To(ContainSubstring("helloworld"))
+
+ // HACK: `volume rm -f` is timing out trying to remove containers using the volume.
+ // Solution: remove them manually...
+ // TODO: fix this when I get back
+ rmAll := podmanTest.Podman([]string{"rm", "-af"})
+ rmAll.WaitWithDefaultTimeout()
+ Expect(rmAll.ExitCode()).To(Equal(0))
+ })
+})
diff --git a/test/python/docker/test_containers.py b/test/python/docker/test_containers.py
index 5a9f761a6..01e049ed4 100644
--- a/test/python/docker/test_containers.py
+++ b/test/python/docker/test_containers.py
@@ -179,11 +179,3 @@ class TestContainers(unittest.TestCase):
filters = {"name": "top"}
ctnrs = self.client.containers.list(all=True, filters=filters)
self.assertEqual(len(ctnrs), 1)
-
- def test_rename_container(self):
- top = self.client.containers.get(TestContainers.topContainerId)
-
- # rename bogus container
- with self.assertRaises(errors.APIError) as error:
- top.rename(name="newname")
- self.assertEqual(error.exception.response.status_code, 404)
diff --git a/test/system/050-stop.bats b/test/system/050-stop.bats
index f604ea2e2..548fd56ee 100644
--- a/test/system/050-stop.bats
+++ b/test/system/050-stop.bats
@@ -67,4 +67,32 @@ load helpers
done
}
+# Regression test for #8501
+@test "podman stop - unlock while waiting for timeout" {
+ # Test that the container state transitions to "stopping" and that other
+ # commands can get the container's lock. To do that, run a container that
+ # ingores SIGTERM such that the Podman would wait 20 seconds for the stop
+ # to finish. This gives us enough time to try some commands and inspect
+ # the container's status.
+
+ run_podman run --name stopme -d $IMAGE sh -c \
+ "trap 'echo Received SIGTERM, ignoring' SIGTERM; echo READY; while :; do sleep 1; done"
+
+ # Stop the container in the background
+ $PODMAN stop -t 20 stopme &
+
+ # Other commands can acquire the lock
+ run_podman ps -a
+
+ # The container state transitioned to "stopping"
+ run_podman inspect --format '{{.State.Status}}' stopme
+ is "$output" "stopping" "Status of container should be 'stopping'"
+
+ run_podman kill stopme
+
+ # Exit code should be 137 as it was killed
+ run_podman inspect --format '{{.State.ExitCode}}' stopme
+ is "$output" "137" "Exit code of killed container"
+}
+
# vim: filetype=sh
diff --git a/test/testvol/main.go b/test/testvol/main.go
new file mode 100644
index 000000000..14f253aa7
--- /dev/null
+++ b/test/testvol/main.go
@@ -0,0 +1,309 @@
+package main
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sync"
+ "time"
+
+ "github.com/docker/go-plugins-helpers/volume"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
+)
+
+var rootCmd = &cobra.Command{
+ Use: "testvol",
+ Short: "testvol - volume plugin for Podman",
+ Long: `Creates simple directory volumes using the Volume Plugin API for testing volume plugin functionality`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ return startServer(config.sockName)
+ },
+ PersistentPreRunE: before,
+}
+
+// Configuration for the volume plugin
+type cliConfig struct {
+ logLevel string
+ sockName string
+ path string
+}
+
+// Default configuration is stored here. Will be overwritten by flags.
+var config cliConfig = cliConfig{
+ logLevel: "error",
+ sockName: "test-volume-plugin",
+}
+
+func init() {
+ rootCmd.Flags().StringVar(&config.sockName, "sock-name", config.sockName, "Name of unix socket for plugin")
+ rootCmd.Flags().StringVar(&config.path, "path", "", "Path to initialize state and mount points")
+ rootCmd.PersistentFlags().StringVar(&config.logLevel, "log-level", config.logLevel, "Log messages including and over the specified level: debug, info, warn, error, fatal, panic")
+}
+
+func before(cmd *cobra.Command, args []string) error {
+ if config.logLevel == "" {
+ config.logLevel = "error"
+ }
+
+ level, err := logrus.ParseLevel(config.logLevel)
+ if err != nil {
+ return err
+ }
+
+ logrus.SetLevel(level)
+
+ return nil
+}
+
+func main() {
+ if err := rootCmd.Execute(); err != nil {
+ logrus.Errorf("Error running volume plugin: %v", err)
+ os.Exit(1)
+ }
+
+ os.Exit(0)
+}
+
+// startServer runs the HTTP server and responds to requests
+func startServer(socketPath string) error {
+ logrus.Debugf("Starting server...")
+
+ if config.path == "" {
+ path, err := ioutil.TempDir("", "test_volume_plugin")
+ if err != nil {
+ return errors.Wrapf(err, "error getting directory for plugin")
+ }
+ config.path = path
+ } else {
+ pathStat, err := os.Stat(config.path)
+ if err != nil {
+ return errors.Wrapf(err, "unable to access requested plugin state directory")
+ }
+ if !pathStat.IsDir() {
+ return errors.Errorf("cannot use %v as plugin state dir as it is not a directory", config.path)
+ }
+ }
+
+ handle, err := makeDirDriver(config.path)
+ if err != nil {
+ return errors.Wrapf(err, "error making volume driver")
+ }
+ logrus.Infof("Using %s for volume path", config.path)
+
+ server := volume.NewHandler(handle)
+ if err := server.ServeUnix(socketPath, 0); err != nil {
+ return errors.Wrapf(err, "error starting server")
+ }
+ return nil
+}
+
+// DirDriver is a trivial volume driver implementation.
+// the volumes field maps name to volume
+type DirDriver struct {
+ lock sync.Mutex
+ volumesPath string
+ volumes map[string]*dirVol
+}
+
+type dirVol struct {
+ name string
+ path string
+ options map[string]string
+ mounts map[string]bool
+ createTime time.Time
+}
+
+// Make a new DirDriver.
+func makeDirDriver(path string) (volume.Driver, error) {
+ drv := new(DirDriver)
+ drv.volumesPath = path
+ drv.volumes = make(map[string]*dirVol)
+
+ return drv, nil
+}
+
+// Capabilities returns the capabilities of the driver.
+func (d *DirDriver) Capabilities() *volume.CapabilitiesResponse {
+ logrus.Infof("Hit Capabilities() endpoint")
+
+ return &volume.CapabilitiesResponse{
+ volume.Capability{
+ "local",
+ },
+ }
+}
+
+// Create creates a volume.
+func (d *DirDriver) Create(opts *volume.CreateRequest) error {
+ d.lock.Lock()
+ defer d.lock.Unlock()
+
+ logrus.Infof("Hit Create() endpoint")
+
+ if _, exists := d.volumes[opts.Name]; exists {
+ return errors.Errorf("volume with name %s already exists", opts.Name)
+ }
+
+ newVol := new(dirVol)
+ newVol.name = opts.Name
+ newVol.mounts = make(map[string]bool)
+ newVol.options = make(map[string]string)
+ newVol.createTime = time.Now()
+ for k, v := range opts.Options {
+ newVol.options[k] = v
+ }
+
+ volPath := filepath.Join(d.volumesPath, opts.Name)
+ if err := os.Mkdir(volPath, 0755); err != nil {
+ return errors.Wrapf(err, "error making volume directory")
+ }
+ newVol.path = volPath
+
+ d.volumes[opts.Name] = newVol
+
+ logrus.Debugf("Made volume with name %s and path %s", newVol.name, newVol.path)
+
+ return nil
+}
+
+// List lists all volumes available.
+func (d *DirDriver) List() (*volume.ListResponse, error) {
+ d.lock.Lock()
+ defer d.lock.Unlock()
+
+ logrus.Infof("Hit List() endpoint")
+
+ vols := new(volume.ListResponse)
+ vols.Volumes = []*volume.Volume{}
+
+ for _, vol := range d.volumes {
+ newVol := new(volume.Volume)
+ newVol.Name = vol.name
+ newVol.Mountpoint = vol.path
+ newVol.CreatedAt = vol.createTime.String()
+ vols.Volumes = append(vols.Volumes, newVol)
+ logrus.Debugf("Adding volume %s to list response", newVol.Name)
+ }
+
+ return vols, nil
+}
+
+// Get retrieves a single volume.
+func (d *DirDriver) Get(req *volume.GetRequest) (*volume.GetResponse, error) {
+ d.lock.Lock()
+ defer d.lock.Unlock()
+
+ logrus.Infof("Hit Get() endpoint")
+
+ vol, exists := d.volumes[req.Name]
+ if !exists {
+ logrus.Debugf("Did not find volume %s", req.Name)
+ return nil, errors.Errorf("no volume with name %s found", req.Name)
+ }
+
+ logrus.Debugf("Found volume %s", req.Name)
+
+ resp := new(volume.GetResponse)
+ resp.Volume = new(volume.Volume)
+ resp.Volume.Name = vol.name
+ resp.Volume.Mountpoint = vol.path
+ resp.Volume.CreatedAt = vol.createTime.String()
+
+ return resp, nil
+}
+
+// Remove removes a single volume.
+func (d *DirDriver) Remove(req *volume.RemoveRequest) error {
+ d.lock.Lock()
+ defer d.lock.Unlock()
+
+ logrus.Infof("Hit Remove() endpoint")
+
+ vol, exists := d.volumes[req.Name]
+ if !exists {
+ logrus.Debugf("Did not find volume %s", req.Name)
+ return errors.Errorf("no volume with name %s found")
+ }
+ logrus.Debugf("Found volume %s", req.Name)
+
+ if len(vol.mounts) > 0 {
+ logrus.Debugf("Cannot remove %s, is mounted", req.Name)
+ return errors.Errorf("volume %s is mounted and cannot be removed")
+ }
+
+ delete(d.volumes, req.Name)
+
+ if err := os.RemoveAll(vol.path); err != nil {
+ return errors.Wrapf(err, "error removing mountpoint of volume %s", req.Name)
+ }
+
+ logrus.Debugf("Removed volume %s", req.Name)
+
+ return nil
+}
+
+// Path returns the path a single volume is mounted at.
+func (d *DirDriver) Path(req *volume.PathRequest) (*volume.PathResponse, error) {
+ d.lock.Lock()
+ defer d.lock.Unlock()
+
+ logrus.Infof("Hit Path() endpoint")
+
+ // TODO: Should we return error if not mounted?
+
+ vol, exists := d.volumes[req.Name]
+ if !exists {
+ logrus.Debugf("Cannot locate volume %s", req.Name)
+ return nil, errors.Errorf("no volume with name %s found", req.Name)
+ }
+
+ return &volume.PathResponse{
+ vol.path,
+ }, nil
+}
+
+// Mount mounts the volume.
+func (d *DirDriver) Mount(req *volume.MountRequest) (*volume.MountResponse, error) {
+ d.lock.Lock()
+ defer d.lock.Unlock()
+
+ logrus.Infof("Hit Mount() endpoint")
+
+ vol, exists := d.volumes[req.Name]
+ if !exists {
+ logrus.Debugf("Cannot locate volume %s", req.Name)
+ return nil, errors.Errorf("no volume with name %s found", req.Name)
+ }
+
+ vol.mounts[req.ID] = true
+
+ return &volume.MountResponse{
+ vol.path,
+ }, nil
+}
+
+// Unmount unmounts the volume.
+func (d *DirDriver) Unmount(req *volume.UnmountRequest) error {
+ d.lock.Lock()
+ defer d.lock.Unlock()
+
+ logrus.Infof("Hit Unmount() endpoint")
+
+ vol, exists := d.volumes[req.Name]
+ if !exists {
+ logrus.Debugf("Cannot locate volume %s", req.Name)
+ return errors.Errorf("no volume with name %s found", req.Name)
+ }
+
+ mount := vol.mounts[req.ID]
+ if !mount {
+ logrus.Debugf("Volume %s is not mounted by %s", req.Name, req.ID)
+ return errors.Errorf("volume %s is not mounted by %s", req.Name, req.ID)
+ }
+
+ delete(vol.mounts, req.ID)
+
+ return nil
+}
diff --git a/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go b/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go
index 7a9f97d1c..d9c1d37db 100644
--- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go
+++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go
@@ -102,7 +102,7 @@ func (plugin *cniNetworkPlugin) podUnlock(podNetwork PodNetwork) {
fullPodName := buildFullPodName(podNetwork)
lock, ok := plugin.pods[fullPodName]
if !ok {
- logrus.Warningf("Unbalanced pod lock unref for %s", fullPodName)
+ logrus.Errorf("Cannot find reference in refcount map for %s. Refcount cannot be determined.", fullPodName)
return
} else if lock.refcount == 0 {
// This should never ever happen, but handle it anyway
@@ -121,12 +121,12 @@ func newWatcher(confDir string) (*fsnotify.Watcher, error) {
// Ensure plugin directory exists, because the following monitoring logic
// relies on that.
if err := os.MkdirAll(confDir, 0755); err != nil {
- return nil, fmt.Errorf("failed to create %q: %v", confDir, err)
+ return nil, fmt.Errorf("failed to create directory %q: %v", confDir, err)
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
- return nil, fmt.Errorf("could not create new watcher %v", err)
+ return nil, fmt.Errorf("failed to create new watcher %v", err)
}
defer func() {
// Close watcher on error
@@ -275,13 +275,13 @@ func loadNetworks(confDir string, cni *libcni.CNIConfig) (map[string]*cniNetwork
if strings.HasSuffix(confFile, ".conflist") {
confList, err = libcni.ConfListFromFile(confFile)
if err != nil {
- logrus.Warningf("Error loading CNI config list file %s: %v", confFile, err)
+ logrus.Errorf("Error loading CNI config list file %s: %v", confFile, err)
continue
}
} else {
conf, err := libcni.ConfFromFile(confFile)
if err != nil {
- logrus.Warningf("Error loading CNI config file %s: %v", confFile, err)
+ logrus.Errorf("Error loading CNI config file %s: %v", confFile, err)
continue
}
if conf.Network.Type == "" {
@@ -290,7 +290,7 @@ func loadNetworks(confDir string, cni *libcni.CNIConfig) (map[string]*cniNetwork
}
confList, err = libcni.ConfListFromConf(conf)
if err != nil {
- logrus.Warningf("Error converting CNI config file %s to list: %v", confFile, err)
+ logrus.Errorf("Error converting CNI config file %s to list: %v", confFile, err)
continue
}
}
@@ -321,7 +321,7 @@ func loadNetworks(confDir string, cni *libcni.CNIConfig) (map[string]*cniNetwork
if _, ok := networks[confList.Name]; !ok {
networks[confList.Name] = cniNet
} else {
- logrus.Infof("Ignore CNI network %s (type=%v) at %s because already exists", confList.Name, confList.Plugins[0].Network.Type, confFile)
+ logrus.Infof("Ignored CNI network %s (type=%v) at %s because already exists", confList.Name, confList.Plugins[0].Network.Type, confFile)
}
if defaultNetName == "" {
@@ -348,7 +348,7 @@ func (plugin *cniNetworkPlugin) syncNetworkConfig() error {
// Update defaultNetName if it is changeable
if plugin.defaultNetName.changeable {
plugin.defaultNetName.name = defaultNetName
- logrus.Infof("Update default CNI network name to %s", defaultNetName)
+ logrus.Infof("Updated default CNI network name to %s", defaultNetName)
} else {
logrus.Debugf("Default CNI network name %s is unchangeable", plugin.defaultNetName.name)
}
@@ -479,8 +479,8 @@ func (plugin *cniNetworkPlugin) forEachNetwork(podNetwork *PodNetwork, fromCache
var newRt *libcni.RuntimeConf
cniNet, newRt, err = plugin.loadNetworkFromCache(network.Name, rt)
if err != nil {
- logrus.Debugf("error loading cached network config: %v", err)
- logrus.Debugf("falling back to loading from existing plugins on disk")
+ logrus.Errorf("error loading cached network config: %v", err)
+ logrus.Warningf("falling back to loading from existing plugins on disk")
} else {
// Use the updated RuntimeConf
rt = newRt
@@ -570,7 +570,7 @@ func (plugin *cniNetworkPlugin) getCachedNetworkInfo(containerID string) ([]NetA
cacheFile := filepath.Join(dirPath, fname)
bytes, err := ioutil.ReadFile(cacheFile)
if err != nil {
- logrus.Warningf("failed to read CNI cache file %s: %v", cacheFile, err)
+ logrus.Errorf("failed to read CNI cache file %s: %v", cacheFile, err)
continue
}
@@ -582,7 +582,7 @@ func (plugin *cniNetworkPlugin) getCachedNetworkInfo(containerID string) ([]NetA
}{}
if err := json.Unmarshal(bytes, &cachedInfo); err != nil {
- logrus.Warningf("failed to unmarshal CNI cache file %s: %v", cacheFile, err)
+ logrus.Errorf("failed to unmarshal CNI cache file %s: %v", cacheFile, err)
continue
}
if cachedInfo.Kind != libcni.CNICacheV1 {
@@ -632,13 +632,12 @@ func (plugin *cniNetworkPlugin) TearDownPodWithContext(ctx context.Context, podN
if err := tearDownLoopback(podNetwork.NetNS); err != nil {
// ignore error
- logrus.Errorf("Ignoring error tearing down loopback interface: %v", err)
+ logrus.Warningf("Ignoring error tearing down loopback interface: %v", err)
}
return plugin.forEachNetwork(&podNetwork, true, func(network *cniNetwork, podNetwork *PodNetwork, rt *libcni.RuntimeConf) error {
if err := network.deleteFromNetwork(ctx, rt, plugin.cniConfig); err != nil {
- logrus.Errorf("Error while removing pod from CNI network %q: %s", network.name, err)
- return err
+ return fmt.Errorf("Error while removing pod from CNI network %q: %s", network.name, err)
}
return nil
})
@@ -718,7 +717,7 @@ func (network *cniNetwork) checkNetwork(ctx context.Context, rt *libcni.RuntimeC
result, err = cni.GetNetworkListCachedResult(network.config, rt)
if err != nil {
- logrus.Errorf("Error GetNetworkListCachedResult: %v", err)
+ logrus.Errorf("Error getting network list cached result: %v", err)
return nil, err
} else if result != nil {
return result, nil
@@ -771,7 +770,6 @@ func (network *cniNetwork) checkNetwork(ctx context.Context, rt *libcni.RuntimeC
func (network *cniNetwork) deleteFromNetwork(ctx context.Context, rt *libcni.RuntimeConf, cni *libcni.CNIConfig) error {
logrus.Infof("About to del CNI network %s (type=%v)", network.name, network.config.Plugins[0].Network.Type)
if err := cni.DelNetworkList(ctx, network.config, rt); err != nil {
- logrus.Errorf("Error deleting network: %v", err)
return err
}
return nil
diff --git a/vendor/modules.txt b/vendor/modules.txt
index b7b8795dd..88ee67917 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -224,7 +224,7 @@ github.com/coreos/go-systemd/v22/dbus
github.com/coreos/go-systemd/v22/internal/dlopen
github.com/coreos/go-systemd/v22/journal
github.com/coreos/go-systemd/v22/sdjournal
-# github.com/cri-o/ocicni v0.2.1-0.20201125151022-df072ea5421c
+# github.com/cri-o/ocicni v0.2.1-0.20201204103948-b6cbe99b9756
github.com/cri-o/ocicni/pkg/ocicni
# github.com/cyphar/filepath-securejoin v0.2.2
github.com/cyphar/filepath-securejoin
@@ -628,7 +628,7 @@ golang.org/x/net/proxy
# golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/oauth2
golang.org/x/oauth2/internal
-# golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
+# golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
golang.org/x/sync/errgroup
golang.org/x/sync/semaphore
# golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3