summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml10
-rw-r--r--.gitignore1
-rw-r--r--Makefile125
-rw-r--r--RELEASE_PROCESS.md18
-rw-r--r--cmd/podman/common/create.go27
-rw-r--r--cmd/podman/common/create_test.go53
-rw-r--r--cmd/podman/containers/ps.go8
-rw-r--r--cmd/podman/images/inspect.go6
-rw-r--r--cmd/podman/images/save.go2
-rw-r--r--cmd/podman/machine/init.go21
-rw-r--r--cmd/podman/networks/inspect.go2
-rw-r--r--cmd/podman/pods/create.go32
-rw-r--r--cmd/podman/system/service.go3
-rwxr-xr-xcontrib/cirrus/runner.sh22
-rw-r--r--docs/source/markdown/links/podman-container-inspect.11
-rw-r--r--docs/source/markdown/links/podman-image-inspect.11
-rw-r--r--docs/source/markdown/podman-container-inspect.1.md318
-rw-r--r--docs/source/markdown/podman-container.1.md2
-rw-r--r--docs/source/markdown/podman-create.1.md2
-rw-r--r--docs/source/markdown/podman-generate-kube.1.md8
-rw-r--r--docs/source/markdown/podman-image-inspect.1.md105
-rw-r--r--docs/source/markdown/podman-image.1.md48
-rw-r--r--docs/source/markdown/podman-inspect.1.md4
-rw-r--r--docs/source/markdown/podman-machine-init.1.md4
-rw-r--r--docs/source/markdown/podman-network-connect.1.md2
-rw-r--r--docs/source/markdown/podman-pod-create.1.md18
-rw-r--r--docs/source/markdown/podman-pod-inspect.1.md2
-rw-r--r--docs/source/markdown/podman-rmi.1.md4
-rw-r--r--docs/source/markdown/podman-run.1.md2
-rw-r--r--docs/source/markdown/podman-save.1.md4
-rw-r--r--docs/source/markdown/podman-system-service.1.md5
-rw-r--r--docs/source/markdown/podman-volume-inspect.1.md2
-rw-r--r--go.mod12
-rw-r--r--go.sum37
-rwxr-xr-xhack/get_release_info.sh70
-rw-r--r--libpod/container.go9
-rw-r--r--libpod/container_config.go2
-rw-r--r--libpod/container_inspect.go51
-rw-r--r--libpod/container_internal_linux.go97
-rw-r--r--libpod/define/pod_inspect.go2
-rw-r--r--libpod/kube.go5
-rw-r--r--libpod/network/cni/cni_conversion.go6
-rw-r--r--libpod/network/cni/network.go2
-rw-r--r--libpod/network/cni/run.go17
-rw-r--r--libpod/network/types/network.go28
-rw-r--r--libpod/options.go12
-rw-r--r--libpod/pod_api.go8
-rw-r--r--pkg/api/handlers/libpod/images.go18
-rw-r--r--pkg/api/handlers/libpod/pods.go4
-rw-r--r--pkg/api/handlers/types.go3
-rw-r--r--pkg/api/server/register_images.go4
-rw-r--r--pkg/autoupdate/autoupdate.go3
-rw-r--r--pkg/bindings/images/types.go2
-rw-r--r--pkg/bindings/images/types_export_options.go15
-rw-r--r--pkg/domain/entities/images.go2
-rw-r--r--pkg/domain/entities/pods.go67
-rw-r--r--pkg/domain/infra/abi/containers.go55
-rw-r--r--pkg/domain/infra/abi/generate.go4
-rw-r--r--pkg/domain/infra/abi/images.go1
-rw-r--r--pkg/domain/infra/tunnel/images.go4
-rw-r--r--pkg/env/env.go5
-rw-r--r--pkg/specgen/generate/config_linux.go1
-rw-r--r--pkg/specgen/generate/container_create.go28
-rw-r--r--pkg/specgen/generate/oci.go7
-rw-r--r--pkg/specgen/podspecgen.go2
-rw-r--r--pkg/specgen/specgen.go4
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_image.py5
-rw-r--r--test/e2e/config/containers.conf1
-rw-r--r--test/e2e/containers_conf_test.go8
-rw-r--r--test/e2e/play_kube_test.go24
-rw-r--r--test/e2e/pod_create_test.go19
-rw-r--r--test/e2e/ps_test.go57
-rw-r--r--test/e2e/run_volume_test.go33
-rw-r--r--test/e2e/top_test.go6
-rw-r--r--test/system/001-basic.bats3
-rw-r--r--test/system/120-load.bats12
-rw-r--r--test/utils/utils.go15
-rw-r--r--test/version/main.go11
-rw-r--r--utils/utils.go7
-rw-r--r--utils/utils_supported.go6
-rw-r--r--vendor/github.com/checkpoint-restore/checkpointctl/lib/metadata.go108
-rw-r--r--vendor/github.com/containernetworking/cni/libcni/api.go74
-rw-r--r--vendor/github.com/containernetworking/cni/libcni/conf.go14
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/invoke/exec.go10
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/020/types.go85
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/040/types.go306
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/100/types.go307
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/args.go18
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/create/create.go56
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/current/types.go276
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/internal/convert.go92
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/internal/create.go66
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/types.go31
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/version/conf.go15
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/version/plugin.go8
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/version/version.go52
-rw-r--r--vendor/github.com/containers/common/libimage/copier.go18
-rw-r--r--vendor/github.com/containers/common/libimage/image.go18
-rw-r--r--vendor/github.com/containers/common/libimage/pull.go2
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go6
-rw-r--r--vendor/github.com/containers/common/pkg/config/containers.conf7
-rw-r--r--vendor/github.com/containers/common/pkg/config/default.go6
-rw-r--r--vendor/github.com/containers/common/pkg/secrets/secrets.go6
-rw-r--r--vendor/github.com/containers/common/pkg/secrets/secretsdb.go12
-rw-r--r--vendor/github.com/containers/psgo/.codespellrc2
-rw-r--r--vendor/github.com/containers/psgo/.golangci.yml6
-rw-r--r--vendor/github.com/containers/psgo/.travis.yml19
-rw-r--r--vendor/github.com/containers/psgo/Makefile40
-rw-r--r--vendor/github.com/containers/psgo/README.md4
-rw-r--r--vendor/github.com/containers/psgo/go.mod3
-rw-r--r--vendor/github.com/containers/psgo/go.sum1
-rw-r--r--vendor/github.com/containers/psgo/internal/host/host.go2
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/ns.go2
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/pids.go31
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/status.go2
-rw-r--r--vendor/github.com/containers/psgo/internal/process/process.go2
-rw-r--r--vendor/github.com/containers/psgo/psgo.go54
-rw-r--r--vendor/github.com/mitchellh/mapstructure/CHANGELOG.md10
-rw-r--r--vendor/github.com/mitchellh/mapstructure/decode_hooks.go3
-rw-r--r--vendor/github.com/mitchellh/mapstructure/mapstructure.go13
-rw-r--r--vendor/github.com/vishvananda/netlink/class_linux.go10
-rw-r--r--vendor/github.com/vishvananda/netlink/devlink_linux.go121
-rw-r--r--vendor/github.com/vishvananda/netlink/filter_linux.go6
-rw-r--r--vendor/github.com/vishvananda/netlink/handle_linux.go16
-rw-r--r--vendor/github.com/vishvananda/netlink/handle_unspecified.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/inet_diag.go1
-rw-r--r--vendor/github.com/vishvananda/netlink/ipset_linux.go60
-rw-r--r--vendor/github.com/vishvananda/netlink/link.go195
-rw-r--r--vendor/github.com/vishvananda/netlink/link_linux.go131
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/devlink_linux.go23
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/link_linux.go36
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/nl_linux.go11
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go (renamed from vendor/github.com/vishvananda/netlink/nl/parse_attr.go)14
-rw-r--r--vendor/github.com/vishvananda/netlink/qdisc.go16
-rw-r--r--vendor/github.com/vishvananda/netlink/qdisc_linux.go16
-rw-r--r--vendor/github.com/vishvananda/netlink/route.go14
-rw-r--r--vendor/github.com/vishvananda/netlink/route_linux.go218
-rw-r--r--vendor/github.com/vishvananda/netlink/route_unspecified.go10
-rw-r--r--vendor/github.com/vishvananda/netlink/socket_linux.go47
-rw-r--r--vendor/github.com/vishvananda/netlink/tcp.go66
-rw-r--r--vendor/github.com/vishvananda/netlink/tcp_linux.go76
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_policy.go13
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go2
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_state.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_state_linux.go23
-rw-r--r--vendor/github.com/vishvananda/netns/README.md11
-rw-r--r--vendor/github.com/vishvananda/netns/netns_linux.go18
-rw-r--r--vendor/modules.txt21
148 files changed, 3529 insertions, 1097 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 581aaaa7b..968854771 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -359,11 +359,15 @@ osx_alt_build_task:
TEST_FLAVOR: "altbuild"
ALT_NAME: 'OSX Cross'
osx_instance:
- image: 'catalina-base'
- script:
+ image: 'big-sur-base'
+ setup_script:
- brew install go
- brew install go-md2man
- - make podman-remote-release-darwin.zip
+ - go version
+ build_amd64_script:
+ - make podman-remote-release-darwin_amd64.zip
+ build_arm64_script:
+ - make podman-remote-release-darwin_arm64.zip GOARCH=arm64
always: *binary_artifacts
diff --git a/.gitignore b/.gitignore
index 08e5309ee..d54013bfd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,7 @@ release.txt
/test/checkseccomp/checkseccomp
/test/copyimg/copyimg
/test/goecho/goecho
+/test/version/version
/test/testvol/testvol
.vscode*
tags
diff --git a/Makefile b/Makefile
index cf796ed3c..37396a4a6 100644
--- a/Makefile
+++ b/Makefile
@@ -23,6 +23,7 @@
export GOPROXY=https://proxy.golang.org
GO ?= go
+GOCMD = CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO)
COVERAGE_PATH ?= .coverage
DESTDIR ?=
EPOCH_TEST_COMMIT ?= $(shell git merge-base $${DEST_BRANCH:-main} HEAD)
@@ -107,12 +108,9 @@ LIBSECCOMP_COMMIT := v2.3.3
# caller may override in special circumstances if needed.
GINKGOTIMEOUT ?= -timeout=90m
-RELEASE_VERSION ?= $(shell hack/get_release_info.sh VERSION)
-RELEASE_NUMBER ?= $(shell hack/get_release_info.sh NUMBER|sed -e 's/^v\(.*\)/\1/')
-RELEASE_DIST ?= $(shell hack/get_release_info.sh DIST)
-RELEASE_DIST_VER ?= $(shell hack/get_release_info.sh DIST_VER)
-RELEASE_ARCH ?= $(shell hack/get_release_info.sh ARCH)
-RELEASE_BASENAME := $(shell hack/get_release_info.sh BASENAME)
+# Conditional required to produce empty-output if binary not built yet.
+RELEASE_VERSION = $(shell if test -x test/version/version; then test/version/version; fi)
+RELEASE_NUMBER = $(shell echo "$(RELEASE_VERSION)" | sed -e 's/^v\(.*\)/\1/')
# If non-empty, logs all output from server during remote system testing
PODMAN_SERVER_LOG ?=
@@ -153,7 +151,11 @@ err_if_empty = $(if $(strip $($(1))),$(strip $($(1))),$(error Required variable
# Podman does not work w/o CGO_ENABLED, except in some very specific cases
CGO_ENABLED ?= 1
# Default to the native OS type and architecture unless otherwise specified
-GOOS ?= $(shell $(GO) env GOOS)
+NATIVE_GOOS := $(shell env -u GOOS $(GO) env GOOS)
+GOOS ?= $(NATIVE_GOOS)
+# Default to the native architecture type
+NATIVE_GOARCH := $(shell env -u GOARCH $(GO) env GOARCH)
+GOARCH ?= $(NATIVE_GOARCH)
ifeq ($(call err_if_empty,GOOS),windows)
BINSFX := .exe
SRCBINDIR := bin/windows
@@ -165,7 +167,7 @@ BINSFX := -remote
SRCBINDIR := bin
endif
# Necessary for nested-$(MAKE) calls and docs/remote-docs.sh
-export GOOS CGO_ENABLED BINSFX SRCBINDIR
+export GOOS GOARCH CGO_ENABLED BINSFX SRCBINDIR
define go-get
env GO111MODULE=off \
@@ -242,11 +244,11 @@ gofmt: ## Verify the source code gofmt
.PHONY: test/checkseccomp/checkseccomp
test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go)
- $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp
+ $(GOCMD) 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
+ $(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol
.PHONY: volume-plugin-test-image
volume-plugin-test-img:
@@ -254,7 +256,10 @@ volume-plugin-test-img:
.PHONY: test/goecho/goecho
test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go)
- $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho
+ $(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho
+
+test/version/version: .gopathok version/version.go
+ $(GO) build -o $@ ./test/version/
.PHONY: codespell
codespell:
@@ -292,8 +297,7 @@ ifeq (,$(findstring systemd,$(BUILDTAGS)))
Install libsystemd on Ubuntu or systemd-devel on rpm based \
distro for journald support."
endif
- CGO_ENABLED=$(CGO_ENABLED) \
- $(GO) build \
+ $(GOCMD) build \
$(BUILDFLAGS) \
-ldflags '$(LDFLAGS_PODMAN)' \
-tags "$(BUILDTAGS)" \
@@ -304,18 +308,14 @@ $(SRCBINDIR):
mkdir -p $(SRCBINDIR)
$(SRCBINDIR)/podman$(BINSFX): $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum
- CGO_ENABLED=$(CGO_ENABLED) \
- GOOS=$(GOOS) \
- $(GO) build \
+ $(GOCMD) build \
$(BUILDFLAGS) \
-ldflags '$(LDFLAGS_PODMAN)' \
-tags "${REMOTETAGS}" \
-o $@ ./cmd/podman
$(SRCBINDIR)/podman-remote-static: $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum
- CGO_ENABLED=0 \
- GOOS=$(GOOS) \
- $(GO) build \
+ $(GOCMD) build \
$(BUILDFLAGS) \
-ldflags '$(LDFLAGS_PODMAN_STATIC)' \
-tags "${REMOTETAGS}" \
@@ -333,6 +333,7 @@ podman-remote-linux: ## Build podman-remote for Linux
$(MAKE) \
CGO_ENABLED=0 \
GOOS=linux \
+ GOARCH=$(GOARCH) \
bin/podman-remote
PHONY: podman-remote-static
@@ -350,6 +351,7 @@ podman-remote-darwin: ## Build podman-remote for macOS
$(MAKE) \
CGO_ENABLED=0 \
GOOS=darwin \
+ GOARCH=$(GOARCH) \
bin/darwin/podman
###
@@ -359,7 +361,7 @@ podman-remote-darwin: ## Build podman-remote for macOS
.PHONY: generate-bindings
generate-bindings:
ifneq ($(GOOS),darwin)
- GO111MODULE=off $(GO) generate ./pkg/bindings/... ;
+ GO111MODULE=off $(GOCMD) generate ./pkg/bindings/... ;
endif
# DO NOT USE: use local-cross instead
@@ -444,12 +446,14 @@ docs: $(MANPAGES) ## Generate documentation
# docs/remote-docs.sh requires a locally executable 'podman-remote' binary
# in addition to the target-archetecture binary (if any).
-install-podman-remote-%-docs: podman-remote-$(shell env -i HOME=$$HOME PATH=$$PATH go env GOOS) docs $(MANPAGES)
+podman-remote-%-docs: podman-remote-$(NATIVE_GOOS)
+ $(eval GOOS := $*)
+ $(MAKE) docs $(MANPAGES)
rm -rf docs/build/remote
mkdir -p docs/build/remote
ln -sf $(CURDIR)/docs/source/markdown/links docs/build/man/
docs/remote-docs.sh \
- $* \
+ $(GOOS) \
docs/build/remote/$* \
$(if $(findstring windows,$*),docs/source/markdown,docs/build/man)
@@ -491,7 +495,7 @@ run-docker-py-tests:
-rm test/__init__.py
.PHONY: localunit
-localunit: test/goecho/goecho
+localunit: test/goecho/goecho test/version/version
rm -rf ${COVERAGE_PATH} && mkdir -p ${COVERAGE_PATH}
$(GOBIN)/ginkgo \
-r \
@@ -581,7 +585,8 @@ system.test-binary: .install.ginkgo
$(GO) test -c ./test/system
.PHONY: test-binaries
-test-binaries: test/checkseccomp/checkseccomp test/goecho/goecho install.catatonit
+test-binaries: test/checkseccomp/checkseccomp test/goecho/goecho install.catatonit test/version/version
+ @echo "Canonical source version: $(call err_if_empty,RELEASE_VERSION)"
.PHONY: tests-included
tests-included:
@@ -601,40 +606,71 @@ tests-expect-exit:
### Release/Packaging targets
###
-podman-release.tar.gz: binaries docs ## Build all binaries, docs., and installation tree, into a tarball.
+.PHONY: podman-release
+podman-release: podman-release-$(GOARCH).tar.gz # Build all Linux binaries for $GOARCH, docs., and installation tree, into a tarball.
+
+# The following two targets are nuanced and complex:
+# Cross-building the podman-remote documentation requires a functional
+# native architecture executable. However `make` only deals with
+# files/timestamps, it doesn't understand if an existing binary will
+# function on the system or not. This makes building cross-platform
+# releases incredibly accident-prone and fragile. The only practical
+# way to deal with this, is via multiple conditional (nested) `make`
+# calls along with careful manipulation of `$GOOS` and `$GOARCH`.
+
+podman-release-%.tar.gz: test/version/version
$(eval TMPDIR := $(shell mktemp -d podman_tmp_XXXX))
- $(eval SUBDIR := podman-v$(RELEASE_NUMBER))
+ $(eval SUBDIR := podman-v$(call err_if_empty,RELEASE_NUMBER))
+ $(eval _DSTARGS := "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr")
+ $(eval GOARCH := $*)
mkdir -p "$(TMPDIR)/$(SUBDIR)"
- $(MAKE) install.bin install.man \
- install.systemd "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr"
+ $(MAKE) GOOS=$(GOOS) GOARCH=$(NATIVE_GOARCH) \
+ clean-binaries docs podman-remote-$(GOOS)-docs
+ if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then \
+ $(MAKE) CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) \
+ BUILDTAGS="$(BUILDTAGS_CROSS)" clean-binaries binaries; \
+ else \
+ $(MAKE) GOOS=$(GOOS) GOARCH=$(GOARCH) binaries; \
+ fi
+ $(MAKE) $(_DSTARGS) install.bin-nobuild install.remote-nobuild install.man install.systemd
tar -czvf $@ --xattrs -C "$(TMPDIR)" "./$(SUBDIR)"
+ if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then $(MAKE) clean-binaries; fi
-rm -rf "$(TMPDIR)"
-podman-remote-release-%.zip: podman-remote-% install-podman-remote-%-docs ## Build podman-remote for GOOS=%, docs., and installation zip.
+podman-remote-release-%.zip: test/version/version ## Build podman-remote for %=$GOOS_$GOARCH, and docs. into an installation zip.
$(eval TMPDIR := $(shell mktemp -d podman_tmp_XXXX))
- $(eval SUBDIR := podman-$(RELEASE_NUMBER))
+ $(eval SUBDIR := podman-$(call err_if_empty,RELEASE_NUMBER))
+ $(eval _DSTARGS := "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr")
+ $(eval GOOS := $(firstword $(subst _, ,$*)))
+ $(eval GOARCH := $(lastword $(subst _, ,$*)))
+ $(eval _GOPLAT := GOOS=$(call err_if_empty,GOOS) GOARCH=$(call err_if_empty,GOARCH))
mkdir -p "$(TMPDIR)/$(SUBDIR)"
- $(MAKE) \
- GOOS=$* \
- DESTDIR=$(TMPDIR)/ \
- BINDIR=$(SUBDIR) \
- SELINUXOPT="" \
- install.remote-nobuild
- cp -r ./docs/build/remote/$* "$(TMPDIR)/$(SUBDIR)/docs/"
+ $(MAKE) GOOS=$(GOOS) GOARCH=$(NATIVE_GOARCH) \
+ clean-binaries podman-remote-$(GOOS)-docs
+ if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then \
+ $(MAKE) CGO_ENABLED=0 $(GOPLAT) BUILDTAGS="$(BUILDTAGS_CROSS)" \
+ clean-binaries podman-remote-$(GOOS); \
+ else \
+ $(MAKE) $(GOPLAT) podman-remote-$(GOOS); \
+ fi
+ cp -r ./docs/build/remote/$(GOOS) "$(TMPDIR)/$(SUBDIR)/docs/"
cp ./contrib/remote/containers.conf "$(TMPDIR)/$(SUBDIR)/"
+ $(MAKE) $(GOPLAT) $(_DSTARGS) SELINUXOPT="" install.remote-nobuild
cd "$(TMPDIR)" && \
zip --recurse-paths "$(CURDIR)/$@" "./"
+ if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then $(MAKE) clean-binaries; fi
-rm -rf "$(TMPDIR)"
.PHONY: podman.msi
-podman.msi: podman-v$(RELEASE_NUMBER).msi ## Build podman-remote, package for installation on Windows
-podman-v$(RELEASE_NUMBER).msi: podman-remote-windows install-podman-remote-windows-docs
+podman.msi: test/version/version ## Build podman-remote, package for installation on Windows
+ $(MAKE) podman-v$(RELEASE_NUMBER).msi
+podman-v$(RELEASE_NUMBER).msi: podman-remote-windows podman-remote-windows-docs
$(eval DOCFILE := docs/build/remote/windows)
find $(DOCFILE) -print | \
wixl-heat --var var.ManSourceDir --component-group ManFiles \
--directory-ref INSTALLDIR --prefix $(DOCFILE)/ > \
$(DOCFILE)/pages.wsx
- wixl -D VERSION=$(RELEASE_VERSION) -D ManSourceDir=$(DOCFILE) \
+ wixl -D VERSION=$(call err_if_empty,RELEASE_VERSION) -D ManSourceDir=$(DOCFILE) \
-o $@ contrib/msi/podman.wxs $(DOCFILE)/pages.wsx
.PHONY: package
@@ -819,8 +855,13 @@ uninstall:
rm -f ${DESTDIR}${USERSYSTEMDDIR}/podman.socket
rm -f ${DESTDIR}${USERSYSTEMDDIR}/podman.service
+.PHONY: clean-binaries
+clean-binaries: ## Remove platform/architecture specific binary files
+ rm -rf \
+ bin \
+
.PHONY: clean
-clean: ## Clean all make artifacts
+clean: clean-binaries ## Clean all make artifacts
rm -rf \
.gopathok \
_output \
@@ -828,10 +869,10 @@ clean: ## Clean all make artifacts
$(wildcard podman-remote*.zip) \
$(wildcard podman_tmp_*) \
$(wildcard podman*.tar.gz) \
- bin \
build \
test/checkseccomp/checkseccomp \
test/goecho/goecho \
+ test/version/version \
test/__init__.py \
test/testdata/redis-image \
libpod/container_ffjson.go \
diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md
index bdf8aca88..32d4c039e 100644
--- a/RELEASE_PROCESS.md
+++ b/RELEASE_PROCESS.md
@@ -234,16 +234,24 @@ spelled with complete minutiae.
1. Return to the Cirrus-CI Build page for the new release tag, confirm
(or wait for) it to complete, re-running any failed tasks as appropriate.
- 1. For anything other than an RC, download the new release artifacts
- (the binaries which were actually tested). Visit each of the
- "Build for ...", "Static Build", and "... Cross" tasks.
- 1. Under the "Artifacts" section of each task, click the "gosrc" item,
+ 1. For anything other than an RC, download the new release artifacts from CI
+ (the binaries which were actually tested). The items are
+ located under the *checks* tab in github for:
+
+ * `Cirrus CI / Alt Arch. Cross` - tarball for each architecture
+ * `Cirrus CI / OSX Cross` - two zip files (amd64 and arm64)
+ * `Cirrus CI / Windows Cross` - an `msi` file
+ * `Cirrus CI / Static Build` - the `bin/podman-remote` file
+
+ Under the "Artifacts" section of each task, click the "gosrc" link,
find and download the release archive (`zip`, `tar.gz` or `.msi`).
Save the the archive with a meaningful name, for example
`podman-v3.0.0.msi`.
1. For the "Static Build" task, find the compiled `podman` and `podman-remote`
- binaries under the "binary", "bin" links. Tar these files as
+ binaries under the "binary", then "bin" links. Tar these files as
`podman-static.tar.gz`.
+ 1. The `podman-vX.Y.Z.dmg` file is produced manually by someone in
+ posession of a developer signing key.
1. In the directory where you downloaded the archives, run
`sha256sum *.tar.gz *.zip *.msi > shasums` to generate SHA sums.
1. Go to `https://github.com/containers/podman/releases/tag/vX.Y.Z` and
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index 6200592b4..a969e17e9 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -15,6 +15,18 @@ const sizeWithUnitFormat = "(format: `<number>[<unit>]`, where unit = b (bytes),
var containerConfig = registry.PodmanConfig()
+// ContainerToPodOptions takes the Container and Pod Create options, assigning the matching values back to podCreate for the purpose of the libpod API
+// For this function to succeed, the JSON tags in PodCreateOptions and ContainerCreateOptions need to match due to the Marshaling and Unmarshaling done.
+// The types of the options also need to match or else the unmarshaling will fail even if the tags match
+func ContainerToPodOptions(containerCreate *entities.ContainerCreateOptions, podCreate *entities.PodCreateOptions) error {
+ contMarshal, err := json.Marshal(containerCreate)
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(contMarshal, podCreate)
+}
+
+// DefineCreateFlags declares and instantiates the container create flags
func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, isInfra bool) {
createFlags := cmd.Flags()
@@ -144,14 +156,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
_ = cmd.RegisterFlagCompletionFunc(cpusetMemsFlagName, completion.AutocompleteNone)
- deviceFlagName := "device"
- createFlags.StringSliceVar(
- &cf.Devices,
- deviceFlagName, devices(),
- "Add a host device to the container",
- )
- _ = cmd.RegisterFlagCompletionFunc(deviceFlagName, completion.AutocompleteDefault)
-
deviceCgroupRuleFlagName := "device-cgroup-rule"
createFlags.StringSliceVar(
&cf.DeviceCGroupRule,
@@ -865,4 +869,11 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
volumeDesciption,
)
_ = cmd.RegisterFlagCompletionFunc(volumeFlagName, AutocompleteVolumeFlag)
+ deviceFlagName := "device"
+ createFlags.StringSliceVar(
+ &cf.Devices,
+ deviceFlagName, devices(),
+ "Add a host device to the container",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(deviceFlagName, completion.AutocompleteDefault)
}
diff --git a/cmd/podman/common/create_test.go b/cmd/podman/common/create_test.go
new file mode 100644
index 000000000..17b47dd16
--- /dev/null
+++ b/cmd/podman/common/create_test.go
@@ -0,0 +1,53 @@
+package common_test
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+
+ "github.com/containers/podman/v3/cmd/podman/common"
+ "github.com/containers/podman/v3/pkg/domain/entities"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestPodOptions(t *testing.T) {
+ entry := "/test1"
+ exampleOptions := entities.ContainerCreateOptions{CPUS: 5.5, CPUSetCPUs: "0-4", Entrypoint: &entry, Hostname: "foo", Name: "testing123", Volume: []string{"/fakeVol1", "/fakeVol2"}, Net: &entities.NetOptions{CNINetworks: []string{"FakeNetwork"}}, PID: "ns:/proc/self/ns"}
+
+ podOptions := entities.PodCreateOptions{}
+ err := common.ContainerToPodOptions(&exampleOptions, &podOptions)
+ assert.Nil(t, err)
+
+ cc := reflect.ValueOf(&exampleOptions).Elem()
+ pc := reflect.ValueOf(&podOptions).Elem()
+
+ pcType := reflect.TypeOf(podOptions)
+ for i := 0; i < pc.NumField(); i++ {
+ podField := pc.FieldByIndex([]int{i})
+ podType := pcType.Field(i)
+ for j := 0; j < cc.NumField(); j++ {
+ containerField := cc.FieldByIndex([]int{j})
+ containerType := reflect.TypeOf(exampleOptions).Field(j)
+ tagPod := strings.Split(string(podType.Tag.Get("json")), ",")[0]
+ tagContainer := strings.Split(string(containerType.Tag.Get("json")), ",")[0]
+ if tagPod == tagContainer && (tagPod != "" && tagContainer != "") {
+ areEqual := true
+ if containerField.Kind() == podField.Kind() {
+ switch containerField.Kind() {
+ case reflect.Slice:
+ for i, w := range containerField.Interface().([]string) {
+ areEqual = podField.Interface().([]string)[i] == w
+ }
+ case reflect.String:
+ areEqual = (podField.String() == containerField.String())
+ case reflect.Bool:
+ areEqual = (podField.Bool() == containerField.Bool())
+ case reflect.Ptr:
+ areEqual = (reflect.DeepEqual(podField.Elem().Interface(), containerField.Elem().Interface()))
+ }
+ }
+ assert.True(t, areEqual)
+ }
+ }
+ }
+}
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go
index ff792b78b..afb8edd91 100644
--- a/cmd/podman/containers/ps.go
+++ b/cmd/podman/containers/ps.go
@@ -221,7 +221,10 @@ func ps(cmd *cobra.Command, _ []string) error {
}
hdrs, format := createPsOut()
+
+ noHeading, _ := cmd.Flags().GetBool("noheading")
if cmd.Flags().Changed("format") {
+ noHeading = noHeading || !report.HasTable(listOpts.Format)
format = report.NormalizeFormat(listOpts.Format)
format = report.EnforceRange(format)
}
@@ -240,8 +243,7 @@ func ps(cmd *cobra.Command, _ []string) error {
defer w.Flush()
headers := func() error { return nil }
- noHeading, _ := cmd.Flags().GetBool("noheading")
- if !(noHeading || listOpts.Quiet || cmd.Flags().Changed("format")) {
+ if !noHeading {
headers = func() error {
return tmpl.Execute(w, hdrs)
}
@@ -298,9 +300,11 @@ func createPsOut() ([]map[string]string, string) {
"IPC": "ipc",
"MNT": "mnt",
"NET": "net",
+ "Networks": "networks",
"PIDNS": "pidns",
"Pod": "pod id",
"PodName": "podname", // undo camelcase space break
+ "RunningFor": "running for",
"UTS": "uts",
"User": "userns",
})
diff --git a/cmd/podman/images/inspect.go b/cmd/podman/images/inspect.go
index 35c173a60..dd8cf8056 100644
--- a/cmd/podman/images/inspect.go
+++ b/cmd/podman/images/inspect.go
@@ -17,9 +17,9 @@ var (
Long: `Displays the low-level information of an image identified by name or ID.`,
RunE: inspectExec,
ValidArgsFunction: common.AutocompleteImages,
- Example: `podman inspect alpine
- podman inspect --format "imageId: {{.Id}} size: {{.Size}}" alpine
- podman inspect --format "image: {{.ImageName}} driver: {{.Driver}}" myctr`,
+ Example: `podman image inspect alpine
+ podman image inspect --format "imageId: {{.Id}} size: {{.Size}}" alpine
+ podman image inspect --format "image: {{.ImageName}} driver: {{.Driver}}" myctr`,
}
inspectOpts *entities.InspectOptions
)
diff --git a/cmd/podman/images/save.go b/cmd/podman/images/save.go
index 19dadb2ad..4f45cb912 100644
--- a/cmd/podman/images/save.go
+++ b/cmd/podman/images/save.go
@@ -84,6 +84,8 @@ func saveFlags(cmd *cobra.Command) {
flags.BoolVar(&saveOpts.Compress, "compress", false, "Compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)")
+ flags.BoolVar(&saveOpts.OciAcceptUncompressedLayers, "uncompressed", false, "Accept uncompressed layers when copying OCI images")
+
formatFlagName := "format"
flags.StringVar(&saveOpts.Format, formatFlagName, define.V2s2Archive, "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-archive, docker-dir (directory with v2s2 manifest type)")
_ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteImageSaveFormat)
diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go
index ec44a707d..19f31d1a6 100644
--- a/cmd/podman/machine/init.go
+++ b/cmd/podman/machine/init.go
@@ -3,6 +3,8 @@
package machine
import (
+ "fmt"
+
"github.com/containers/common/pkg/completion"
"github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/pkg/machine"
@@ -26,6 +28,7 @@ var (
var (
initOpts = machine.InitOptions{}
defaultMachineName = "podman-machine-default"
+ now bool
)
func init() {
@@ -61,6 +64,12 @@ func init() {
)
_ = initCmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone)
+ flags.BoolVar(
+ &now,
+ "now", false,
+ "Start machine now",
+ )
+
ImagePathFlagName := "image-path"
flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Engine.MachineImage, "Path to qcow image")
_ = initCmd.RegisterFlagCompletionFunc(ImagePathFlagName, completion.AutocompleteDefault)
@@ -91,5 +100,15 @@ func initMachine(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
- return vm.Init(initOpts)
+ err = vm.Init(initOpts)
+ if err != nil {
+ return err
+ }
+ if now {
+ err = vm.Start(initOpts.Name, machine.StartOptions{})
+ if err == nil {
+ fmt.Printf("Machine %q started successfully\n", initOpts.Name)
+ }
+ }
+ return err
}
diff --git a/cmd/podman/networks/inspect.go b/cmd/podman/networks/inspect.go
index c0e5b9720..4f3e86fc9 100644
--- a/cmd/podman/networks/inspect.go
+++ b/cmd/podman/networks/inspect.go
@@ -12,7 +12,7 @@ var (
networkinspectDescription = `Inspect network`
networkinspectCommand = &cobra.Command{
Use: "inspect [options] NETWORK [NETWORK...]",
- Short: "network inspect",
+ Short: "Displays the raw CNI network configuration for one or more networks.",
Long: networkinspectDescription,
RunE: networkInspect,
Example: `podman network inspect podman`,
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
index 7000c92c8..ca73a8356 100644
--- a/cmd/podman/pods/create.go
+++ b/cmd/podman/pods/create.go
@@ -132,7 +132,6 @@ func create(cmd *cobra.Command, args []string) error {
createOptions.Share = nil
} else {
// reassign certain optios for lbpod api, these need to be populated in spec
- MapOptions()
flags := cmd.Flags()
infraOptions.Net, err = common.NetFlagsToNetOptions(nil, *flags, false)
if err != nil {
@@ -142,13 +141,11 @@ func create(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
- createOptions.Net = infraOptions.Net
createOptions.Share = strings.Split(share, ",")
if cmd.Flag("infra-command").Changed {
// Only send content to server side if user changed defaults
cmdIn, err := cmd.Flags().GetString("infra-command")
infraOptions.Entrypoint = &cmdIn
- createOptions.InfraCommand = cmdIn
if err != nil {
return err
}
@@ -161,6 +158,10 @@ func create(cmd *cobra.Command, args []string) error {
return err
}
}
+ err = common.ContainerToPodOptions(&infraOptions, &createOptions)
+ if err != nil {
+ return err
+ }
}
if cmd.Flag("pod-id-file").Changed {
@@ -196,8 +197,8 @@ func create(cmd *cobra.Command, args []string) error {
if createOptions.Cpus > float64(numCPU) {
createOptions.Cpus = float64(numCPU)
}
- copy := createOptions.CpusetCpus
- cpuSet := createOptions.Cpus
+ copy := infraOptions.CPUSetCPUs
+ cpuSet := infraOptions.CPUS
if cpuSet == 0 {
cpuSet = float64(sysinfo.NumCPU())
}
@@ -217,10 +218,10 @@ func create(cmd *cobra.Command, args []string) error {
if core > int(cpuSet) {
if copy == "" {
copy = "0-" + strconv.Itoa(int(cpuSet))
- createOptions.CpusetCpus = copy
+ infraOptions.CPUSetCPUs = copy
break
} else {
- createOptions.CpusetCpus = copy
+ infraOptions.CPUSetCPUs = copy
break
}
} else if ind != 0 {
@@ -229,6 +230,8 @@ func create(cmd *cobra.Command, args []string) error {
copy = "" + strconv.Itoa(core)
}
}
+ createOptions.Cpus = infraOptions.CPUS
+ createOptions.CpusetCpus = infraOptions.CPUSetCPUs
podSpec := specgen.NewPodSpecGenerator()
podSpec, err = entities.ToPodSpecGen(*podSpec, &createOptions)
if err != nil {
@@ -248,11 +251,8 @@ func create(cmd *cobra.Command, args []string) error {
}
podSpec.InfraImage = imageName
if infraOptions.Entrypoint != nil {
- createOptions.InfraCommand = *infraOptions.Entrypoint
+ createOptions.InfraCommand = infraOptions.Entrypoint
}
- infraOptions.CPUS = createOptions.Cpus
- infraOptions.CPUSetCPUs = createOptions.CpusetCpus
- infraOptions.PID = createOptions.Pid
podSpec.InfraContainerSpec = specgen.NewSpecGenerator(imageName, false)
podSpec.InfraContainerSpec.RawImageName = rawImageName
podSpec.InfraContainerSpec.NetworkOptions = podSpec.NetworkOptions
@@ -290,13 +290,3 @@ func replacePod(name string) error {
}
return removePods([]string{name}, rmOptions, false)
}
-
-func MapOptions() {
- createOptions.Cpus = infraOptions.CPUS
- createOptions.CpusetCpus = infraOptions.CPUSetCPUs
- createOptions.Hostname = infraOptions.Hostname
- createOptions.InfraConmonPidFile = infraOptions.ConmonPIDFile
- createOptions.InfraName = infraOptions.Name
- createOptions.Pid = infraOptions.PID
- createOptions.Volume = infraOptions.Volume
-}
diff --git a/cmd/podman/system/service.go b/cmd/podman/system/service.go
index a30f43839..d6fe8837b 100644
--- a/cmd/podman/system/service.go
+++ b/cmd/podman/system/service.go
@@ -52,8 +52,9 @@ func init() {
flags := srvCmd.Flags()
+ cfg := registry.PodmanConfig()
timeFlagName := "time"
- flags.Int64VarP(&srvArgs.Timeout, timeFlagName, "t", 5, "Time until the service session expires in seconds. Use 0 to disable the timeout")
+ flags.Int64VarP(&srvArgs.Timeout, timeFlagName, "t", int64(cfg.Engine.ServiceTimeout), "Time until the service session expires in seconds. Use 0 to disable the timeout")
_ = srvCmd.RegisterFlagCompletionFunc(timeFlagName, completion.AutocompleteNone)
flags.StringVarP(&srvArgs.CorsHeaders, "cors", "", "", "Set CORS Headers")
_ = srvCmd.RegisterFlagCompletionFunc("cors", completion.AutocompleteNone)
diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh
index c1972b90f..128398c38 100755
--- a/contrib/cirrus/runner.sh
+++ b/contrib/cirrus/runner.sh
@@ -205,10 +205,12 @@ function _run_build() {
# Ensure always start from clean-slate with all vendor modules downloaded
make clean
make vendor
- make podman-release.tar.gz # includes podman, podman-remote, and docs
+ make podman-release # includes podman, podman-remote, and docs
}
function _run_altbuild() {
+ local -a arches
+ local arch
req_env_vars ALT_NAME
# Defined in .cirrus.yml
# shellcheck disable=SC2154
@@ -221,7 +223,7 @@ function _run_altbuild() {
make build-all-new-commits GIT_BASE_BRANCH=origin/$DEST_BRANCH
;;
*Windows*)
- make podman-remote-release-windows.zip
+ make podman-remote-release-windows_amd64.zip
make podman.msi
;;
*Without*)
@@ -232,7 +234,21 @@ function _run_altbuild() {
rpmbuild --rebuild ./podman-*.src.rpm
;;
Alt*Cross)
- make local-cross
+ arches=(\
+ amd64
+ ppc64le
+ arm
+ arm64
+ 386
+ s390x
+ mips
+ mipsle
+ mips64
+ mips64le)
+ for arch in "${arches[@]}"; do
+ msg "Building release archive for $arch"
+ make podman-release-${arch}.tar.gz GOARCH=$arch
+ done
;;
*Static*)
req_env_vars CTR_FQIN
diff --git a/docs/source/markdown/links/podman-container-inspect.1 b/docs/source/markdown/links/podman-container-inspect.1
deleted file mode 100644
index 261043845..000000000
--- a/docs/source/markdown/links/podman-container-inspect.1
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/podman-inspect.1
diff --git a/docs/source/markdown/links/podman-image-inspect.1 b/docs/source/markdown/links/podman-image-inspect.1
deleted file mode 100644
index 261043845..000000000
--- a/docs/source/markdown/links/podman-image-inspect.1
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/podman-inspect.1
diff --git a/docs/source/markdown/podman-container-inspect.1.md b/docs/source/markdown/podman-container-inspect.1.md
new file mode 100644
index 000000000..72b7cef3b
--- /dev/null
+++ b/docs/source/markdown/podman-container-inspect.1.md
@@ -0,0 +1,318 @@
+% podman-container-inspect(1)
+
+## NAME
+podman\-container\-inspect - Display a container's configuration
+
+## SYNOPSIS
+**podman container inspect** [*options*] *container* [*container* ...]
+
+## DESCRIPTION
+
+This displays the low-level information on containers identified by name or ID. By default, this will render
+all results in a JSON array. If a format is specified, the given template will be executed for each result.
+
+## OPTIONS
+
+#### **--format**, **-f**=*format*
+
+Format the output using the given Go template.
+The keys of the returned JSON can be used as the values for the --format flag (see examples below).
+
+#### **--latest**, **-l**
+
+Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
+to run containers such as CRI-O, the last started container could be from either of those methods.
+
+(This option is not available with the remote Podman client.)
+
+#### **--size**, **-s**
+
+In addition to normal output, display the total file size if the type is a container.
+
+
+## EXAMPLE
+
+```
+$ podman container inspect foobar
+[
+ {
+ "Id": "99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6",
+ "Created": "2021-09-16T06:09:08.936623325-04:00",
+ "Path": "echo",
+ "Args": [
+ "hi"
+ ],
+ "State": {
+ "OciVersion": "1.0.2-dev",
+ "Status": "exited",
+ "Running": false,
+ "Paused": false,
+ "Restarting": false,
+ "OOMKilled": false,
+ "Dead": false,
+ "Pid": 0,
+ "ExitCode": 0,
+ "Error": "",
+ "StartedAt": "2021-09-16T06:09:09.033564436-04:00",
+ "FinishedAt": "2021-09-16T06:09:09.036184314-04:00",
+ "Healthcheck": {
+ "Status": "",
+ "FailingStreak": 0,
+ "Log": null
+ }
+ },
+ "Image": "14119a10abf4669e8cdbdff324a9f9605d99697215a0d21c360fe8dfa8471bab",
+ "ImageName": "docker.io/library/alpine:latest",
+ "Rootfs": "",
+ "Pod": "",
+ "ResolvConfPath": "/run/user/3267/containers/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/resolv.conf",
+ "HostnamePath": "/run/user/3267/containers/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/hostname",
+ "HostsPath": "/run/user/3267/containers/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/hosts",
+ "StaticDir": "/home/dwalsh/.local/share/containers/storage/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata",
+ "OCIConfigPath": "/home/dwalsh/.local/share/containers/storage/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/config.json",
+ "OCIRuntime": "crun",
+ "ConmonPidFile": "/run/user/3267/containers/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/conmon.pid",
+ "PidFile": "/run/user/3267/containers/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/pidfile",
+ "Name": "foobar",
+ "RestartCount": 0,
+ "Driver": "overlay",
+ "MountLabel": "system_u:object_r:container_file_t:s0:c25,c695",
+ "ProcessLabel": "system_u:system_r:container_t:s0:c25,c695",
+ "AppArmorProfile": "",
+ "EffectiveCaps": [
+ "CAP_CHOWN",
+ "CAP_DAC_OVERRIDE",
+ "CAP_FOWNER",
+ "CAP_FSETID",
+ "CAP_KILL",
+ "CAP_NET_BIND_SERVICE",
+ "CAP_SETFCAP",
+ "CAP_SETGID",
+ "CAP_SETPCAP",
+ "CAP_SETUID",
+ "CAP_SYS_CHROOT"
+ ],
+ "BoundingCaps": [
+ "CAP_CHOWN",
+ "CAP_DAC_OVERRIDE",
+ "CAP_FOWNER",
+ "CAP_FSETID",
+ "CAP_KILL",
+ "CAP_NET_BIND_SERVICE",
+ "CAP_SETFCAP",
+ "CAP_SETGID",
+ "CAP_SETPCAP",
+ "CAP_SETUID",
+ "CAP_SYS_CHROOT"
+ ],
+ "ExecIDs": [],
+ "GraphDriver": {
+ "Name": "overlay",
+ "Data": {
+ "LowerDir": "/home/dwalsh/.local/share/containers/storage/overlay/e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68/diff",
+ "UpperDir": "/home/dwalsh/.local/share/containers/storage/overlay/8f3d70434a3db17410ec4710caf4f251f3e4ed0a96a08124e4b3d4af0a0ea300/diff",
+ "WorkDir": "/home/dwalsh/.local/share/containers/storage/overlay/8f3d70434a3db17410ec4710caf4f251f3e4ed0a96a08124e4b3d4af0a0ea300/work"
+ }
+ },
+ "Mounts": [],
+ "Dependencies": [],
+ "NetworkSettings": {
+ "EndpointID": "",
+ "Gateway": "",
+ "IPAddress": "",
+ "IPPrefixLen": 0,
+ "IPv6Gateway": "",
+ "GlobalIPv6Address": "",
+ "GlobalIPv6PrefixLen": 0,
+ "MacAddress": "",
+ "Bridge": "",
+ "SandboxID": "",
+ "HairpinMode": false,
+ "LinkLocalIPv6Address": "",
+ "LinkLocalIPv6PrefixLen": 0,
+ "Ports": {},
+ "SandboxKey": ""
+ },
+ "ExitCommand": [
+ "/usr/bin/podman",
+ "--root",
+ "/home/dwalsh/.local/share/containers/storage",
+ "--runroot",
+ "/run/user/3267/containers",
+ "--log-level",
+ "warning",
+ "--cgroup-manager",
+ "systemd",
+ "--tmpdir",
+ "/run/user/3267/libpod/tmp",
+ "--runtime",
+ "crun",
+ "--storage-driver",
+ "overlay",
+ "--events-backend",
+ "journald",
+ "container",
+ "cleanup",
+ "99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6"
+ ],
+ "Namespace": "",
+ "IsInfra": false,
+ "Config": {
+ "Hostname": "99f66530fe9c",
+ "Domainname": "",
+ "User": "",
+ "AttachStdin": false,
+ "AttachStdout": false,
+ "AttachStderr": false,
+ "Tty": false,
+ "OpenStdin": false,
+ "StdinOnce": false,
+ "Env": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=xterm",
+ "container=podman",
+ "HOME=/root",
+ "HOSTNAME=99f66530fe9c"
+ ],
+ "Cmd": [
+ "echo",
+ "hi"
+ ],
+ "Image": "docker.io/library/alpine:latest",
+ "Volumes": null,
+ "WorkingDir": "/",
+ "Entrypoint": "",
+ "OnBuild": null,
+ "Labels": null,
+ "Annotations": {
+ "io.container.manager": "libpod",
+ "io.kubernetes.cri-o.Created": "2021-09-16T06:09:08.936623325-04:00",
+ "io.kubernetes.cri-o.TTY": "false",
+ "io.podman.annotations.autoremove": "FALSE",
+ "io.podman.annotations.init": "FALSE",
+ "io.podman.annotations.privileged": "FALSE",
+ "io.podman.annotations.publish-all": "FALSE",
+ "org.opencontainers.image.stopSignal": "15"
+ },
+ "StopSignal": 15,
+ "CreateCommand": [
+ "podman",
+ "run",
+ "--name",
+ "foobar",
+ "alpine",
+ "echo",
+ "hi"
+ ],
+ "Timezone": "local",
+ "Umask": "0022",
+ "Timeout": 0,
+ "StopTimeout": 10
+ },
+ "HostConfig": {
+ "Binds": [],
+ "CgroupManager": "systemd",
+ "CgroupMode": "private",
+ "ContainerIDFile": "",
+ "LogConfig": {
+ "Type": "journald",
+ "Config": null,
+ "Path": "",
+ "Tag": "",
+ "Size": "0B"
+ },
+ "NetworkMode": "slirp4netns",
+ "PortBindings": {},
+ "RestartPolicy": {
+ "Name": "",
+ "MaximumRetryCount": 0
+ },
+ "AutoRemove": false,
+ "VolumeDriver": "",
+ "VolumesFrom": null,
+ "CapAdd": [],
+ "CapDrop": [
+ "CAP_AUDIT_WRITE",
+ "CAP_MKNOD",
+ "CAP_NET_RAW"
+ ],
+ "Dns": [],
+ "DnsOptions": [],
+ "DnsSearch": [],
+ "ExtraHosts": [],
+ "GroupAdd": [],
+ "IpcMode": "private",
+ "Cgroup": "",
+ "Cgroups": "default",
+ "Links": null,
+ "OomScoreAdj": 0,
+ "PidMode": "private",
+ "Privileged": false,
+ "PublishAllPorts": false,
+ "ReadonlyRootfs": false,
+ "SecurityOpt": [],
+ "Tmpfs": {},
+ "UTSMode": "private",
+ "UsernsMode": "",
+ "ShmSize": 65536000,
+ "Runtime": "oci",
+ "ConsoleSize": [
+ 0,
+ 0
+ ],
+ "Isolation": "",
+ "CpuShares": 0,
+ "Memory": 0,
+ "NanoCpus": 0,
+ "CgroupParent": "user.slice",
+ "BlkioWeight": 0,
+ "BlkioWeightDevice": null,
+ "BlkioDeviceReadBps": null,
+ "BlkioDeviceWriteBps": null,
+ "BlkioDeviceReadIOps": null,
+ "BlkioDeviceWriteIOps": null,
+ "CpuPeriod": 0,
+ "CpuQuota": 0,
+ "CpuRealtimePeriod": 0,
+ "CpuRealtimeRuntime": 0,
+ "CpusetCpus": "",
+ "CpusetMems": "",
+ "Devices": [],
+ "DiskQuota": 0,
+ "KernelMemory": 0,
+ "MemoryReservation": 0,
+ "MemorySwap": 0,
+ "MemorySwappiness": 0,
+ "OomKillDisable": false,
+ "PidsLimit": 2048,
+ "Ulimits": [],
+ "CpuCount": 0,
+ "CpuPercent": 0,
+ "IOMaximumIOps": 0,
+ "IOMaximumBandwidth": 0,
+ "CgroupConf": null
+ }
+ }
+]
+```
+
+```
+$ podman container inspect nervous_fermi --format "{{.ImageName}}"
+registry.access.redhat.com/ubi8:latest
+```
+
+```
+$ podman container inspect foobar --format "{{.GraphDriver.Name}}"
+overlay
+```
+
+```
+$ podman container inspect --latest --format {{.EffectiveCaps}}
+[CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_FSETID CAP_KILL CAP_NET_BIND_SERVICE CAP_SETFCAP CAP_SETGID CAP_SETPCAP CAP_SETUID CAP_SYS_CHROOT]
+```
+
+## SEE ALSO
+**[podman(1)](podman.1.md)**,**[podman-container(1)](podman-container.1.md)**, **[podman-inspect(1)](podman-inspect.1.md)**
+
+## HISTORY
+Sep 2021, Originally compiled by Dan Walsh <dwalsh@redhat.com>
diff --git a/docs/source/markdown/podman-container.1.md b/docs/source/markdown/podman-container.1.md
index 3cc90d9ec..c950347a9 100644
--- a/docs/source/markdown/podman-container.1.md
+++ b/docs/source/markdown/podman-container.1.md
@@ -24,7 +24,7 @@ The container command allows you to manage containers
| exists | [podman-container-exists(1)](podman-container-exists.1.md) | Check if a container exists in local storage |
| export | [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. |
| init | [podman-init(1)](podman-init.1.md) | Initialize a container |
-| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. |
+| inspect | [podman-container-inspect(1)](podman-container-inspect.1.md)| Display a container's configuration. |
| kill | [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. |
| list | [podman-ps(1)](podman-ps.1.md) | List the containers on the system.(alias ls) |
| logs | [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. |
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 0c48f105e..c3e2bbfca 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -682,7 +682,7 @@ Valid _mode_ values are:
#### **--network-alias**=*alias*
-Add network-scoped alias for the container
+Add network-scoped alias for the container. NOTE: A container will only have access to aliases on the first network that it joins. This is a limitation that will be removed in a later release.
#### **--no-healthcheck**
diff --git a/docs/source/markdown/podman-generate-kube.1.md b/docs/source/markdown/podman-generate-kube.1.md
index 2e9f68bf3..9ae3941ec 100644
--- a/docs/source/markdown/podman-generate-kube.1.md
+++ b/docs/source/markdown/podman-generate-kube.1.md
@@ -37,8 +37,6 @@ random port is assigned by Podman in the specification.
Create Kubernetes Pod YAML for a container called `some-mariadb`.
```
$ sudo podman generate kube some-mariadb
-# Generation of Kubernetes YAML is still under development!
-#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
@@ -93,8 +91,6 @@ status: {}
Create Kubernetes Pod YAML for a container with the directory `/home/user/my-data` on the host bind-mounted in the container to `/volume`.
```
$ podman generate kube my-container-with-bind-mounted-data
-# Generation of Kubernetes YAML is still under development!
-#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
@@ -147,8 +143,6 @@ status: {}
Create Kubernetes Pod YAML for a container with the named volume `priceless-data` mounted in the container at `/volume`.
```
$ podman generate kube my-container-using-priceless-data
-# Generation of Kubernetes YAML is still under development!
-#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
@@ -200,8 +194,6 @@ status: {}
Create Kubernetes Pod YAML for a pod called `demoweb` and include a service.
```
$ sudo podman generate kube -s demoweb
-# Generation of Kubernetes YAML is still under development!
-#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
diff --git a/docs/source/markdown/podman-image-inspect.1.md b/docs/source/markdown/podman-image-inspect.1.md
new file mode 100644
index 000000000..a4f81dfc0
--- /dev/null
+++ b/docs/source/markdown/podman-image-inspect.1.md
@@ -0,0 +1,105 @@
+% podman-image-inspect(1)
+
+## NAME
+podman\-image\-inspect - Display an image's configuration
+
+## SYNOPSIS
+**podman image inspect** [*options*] *image* [*image* ...]
+
+## DESCRIPTION
+
+This displays the low-level information on images identified by name or ID. By default, this will render
+all results in a JSON array. If a format is specified, the given template will be executed for each result.
+
+## OPTIONS
+
+#### **--format**, **-f**=*format*
+
+Format the output using the given Go template.
+The keys of the returned JSON can be used as the values for the --format flag (see examples below).
+
+## EXAMPLE
+
+```
+$ podman image inspect fedora
+[
+ {
+ "Id": "37e5619f4a8ca9dbc4d6c0ae7890625674a10dbcfb76201399e2aaddb40da17d",
+ "Digest": "sha256:1b0d4ddd99b1a8c8a80e885aafe6034c95f266da44ead992aab388e6aa91611a",
+ "RepoTags": [
+ "registry.fedoraproject.org/fedora:latest"
+ ],
+ "RepoDigests": [
+ "registry.fedoraproject.org/fedora@sha256:1b0d4ddd99b1a8c8a80e885aafe6034c95f266da44ead992aab388e6aa91611a",
+ "registry.fedoraproject.org/fedora@sha256:b5290db40008aae9272ad3a6bd8070ef7ecd547c3bef014b894c327960acc582"
+ ],
+ "Parent": "",
+ "Comment": "Created by Image Factory",
+ "Created": "2021-08-09T05:48:47Z",
+ "Config": {
+ "Env": [
+ "DISTTAG=f34container",
+ "FGC=f34",
+ "container=oci"
+ ],
+ "Cmd": [
+ "/bin/bash"
+ ],
+ "Labels": {
+ "license": "MIT",
+ "name": "fedora",
+ "vendor": "Fedora Project",
+ "version": "34"
+ }
+ },
+ "Version": "1.10.1",
+ "Author": "",
+ "Architecture": "amd64",
+ "Os": "linux",
+ "Size": 183852302,
+ "VirtualSize": 183852302,
+ "GraphDriver": {
+ "Name": "overlay",
+ "Data": {
+ "UpperDir": "/home/dwalsh/.local/share/containers/storage/overlay/0203e243f1ca4b6bb49371ecd21363212467ec6d7d3fa9f324cd4e78cc6b5fa2/diff",
+ "WorkDir": "/home/dwalsh/.local/share/containers/storage/overlay/0203e243f1ca4b6bb49371ecd21363212467ec6d7d3fa9f324cd4e78cc6b5fa2/work"
+ }
+ },
+ "RootFS": {
+ "Type": "layers",
+ "Layers": [
+ "sha256:0203e243f1ca4b6bb49371ecd21363212467ec6d7d3fa9f324cd4e78cc6b5fa2"
+ ]
+ },
+ "Labels": {
+ "license": "MIT",
+ "name": "fedora",
+ "vendor": "Fedora Project",
+ "version": "34"
+ },
+ "Annotations": {},
+ "ManifestType": "application/vnd.docker.distribution.manifest.v2+json",
+ "User": "",
+ "History": [
+ {
+ "created": "2021-08-09T05:48:47Z",
+ "comment": "Created by Image Factory"
+ }
+ ],
+ "NamesHistory": [
+ "registry.fedoraproject.org/fedora:latest"
+ ]
+ }
+]
+```
+
+```
+$ podman image inspect --format '{{ .Id }}' fedora
+37e5619f4a8ca9dbc4d6c0ae7890625674a10dbcfb76201399e2aaddb40da17d
+```
+
+## SEE ALSO
+**[podman(1)](podman.1.md)**,**[podman-image(1)](podman-image.1.md)**, **[podman-inspect(1)](podman-inspect.1.md)**
+
+## HISTORY
+Sep 2021, Originally compiled by Dan Walsh <dwalsh@redhat.com>
diff --git a/docs/source/markdown/podman-image.1.md b/docs/source/markdown/podman-image.1.md
index 3e6050d99..01024519f 100644
--- a/docs/source/markdown/podman-image.1.md
+++ b/docs/source/markdown/podman-image.1.md
@@ -11,30 +11,30 @@ The image command allows you to manage images
## COMMANDS
-| Command | Man Page | Description |
-| -------- | ----------------------------------------------- | --------------------------------------------------------------------------- |
-| build | [podman-build(1)](podman-build.1.md) | Build a container using a Dockerfile. |
-| diff | [podman-image-diff(1)](podman-image-diff.1.md) | Inspect changes on an image's filesystem. |
-| exists | [podman-image-exists(1)](podman-image-exists.1.md) | Check if an image exists in local storage. |
-| history | [podman-history(1)](podman-history.1.md) | Show the history of an image. |
-| import | [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. |
-| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display an image or image's configuration. |
-| list | [podman-images(1)](podman-images.1.md) | List the container images on the system.(alias ls) |
-| load | [podman-load(1)](podman-load.1.md) | Load an image from the docker archive. |
-| mount | [podman-image-mount(1)](podman-image-mount.1.md) | Mount an image's root filesystem. |
-| prune | [podman-image-prune(1)](podman-image-prune.1.md) | Remove all unused images from the local store. |
-| pull | [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. |
-| push | [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. |
-| rm | [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. |
-| save | [podman-save(1)](podman-save.1.md) | Save an image to docker-archive or oci. |
-| scp | [podman-image-scp(1)](podman-image-scp.1.md) | Securely copy an image from one host to another. |
-| search | [podman-search(1)](podman-search.1.md) | Search a registry for an image. |
-| sign | [podman-image-sign(1)](podman-image-sign.1.md) | Create a signature for an image. |
-| tag | [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. |
-| tree | [podman-image-tree(1)](podman-image-tree.1.md) | Prints layer hierarchy of an image in a tree format. |
-| trust | [podman-image-trust(1)](podman-image-trust.1.md) | Manage container registry image trust policy. |
-| unmount | [podman-image-unmount(1)](podman-image-unmount.1.md) | Unmount an image's root filesystem. |
-| untag | [podman-untag(1)](podman-untag.1.md) | Removes one or more names from a locally-stored image. |
+| Command | Man Page | Description |
+| -------- | --------------------------------------------------- | ----------------------------------------------------------------------- |
+| build | [podman-build(1)](podman-build.1.md) | Build a container using a Dockerfile. |
+| diff | [podman-image-diff(1)](podman-image-diff.1.md) | Inspect changes on an image's filesystem. |
+| exists | [podman-image-exists(1)](podman-image-exists.1.md) | Check if an image exists in local storage. |
+| history | [podman-history(1)](podman-history.1.md) | Show the history of an image. |
+| import | [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. |
+| inspect | [podman-image-inspect(1)](podman-image-inspect.1.md)| Display an image's configuration. |
+| list | [podman-images(1)](podman-images.1.md) | List the container images on the system.(alias ls) |
+| load | [podman-load(1)](podman-load.1.md) | Load an image from the docker archive. |
+| mount | [podman-image-mount(1)](podman-image-mount.1.md) | Mount an image's root filesystem. |
+| prune | [podman-image-prune(1)](podman-image-prune.1.md) | Remove all unused images from the local store. |
+| pull | [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. |
+| push | [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. |
+| rm | [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. |
+| save | [podman-save(1)](podman-save.1.md) | Save an image to docker-archive or oci. |
+| scp | [podman-image-scp(1)](podman-image-scp.1.md) | Securely copy an image from one host to another. |
+| search | [podman-search(1)](podman-search.1.md) | Search a registry for an image. |
+| sign | [podman-image-sign(1)](podman-image-sign.1.md) | Create a signature for an image. |
+| tag | [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. |
+| tree | [podman-image-tree(1)](podman-image-tree.1.md) | Prints layer hierarchy of an image in a tree format. |
+| trust | [podman-image-trust(1)](podman-image-trust.1.md) | Manage container registry image trust policy. |
+| unmount | [podman-image-unmount(1)](podman-image-unmount.1.md) | Unmount an image's root filesystem. |
+| untag | [podman-untag(1)](podman-untag.1.md) | Removes one or more names from a locally-stored image. |
## SEE ALSO
podman
diff --git a/docs/source/markdown/podman-inspect.1.md b/docs/source/markdown/podman-inspect.1.md
index ae26c1bbb..83dc5cbbe 100644
--- a/docs/source/markdown/podman-inspect.1.md
+++ b/docs/source/markdown/podman-inspect.1.md
@@ -14,6 +14,8 @@ all results in a JSON array. If the inspect type is all, the order of inspection
If a format is specified, the given template will be executed for each result.
For more inspection options, see also
+[podman-container-inspect(1)](podman-container-inspect.1.md),
+[podman-image-inspect(1)](podman-image-inspect.1.md),
[podman-network-inspect(1)](podman-network-inspect.1.md),
[podman-pod-inspect(1)](podman-pod-inspect.1.md), and
[podman-volume-inspect(1)](podman-volume-inspect.1.md).
@@ -160,7 +162,7 @@ myNetwork
```
## SEE ALSO
-podman(1)
+**[podman(1)](podman.1.md)**,**[podman-container-inspect(1)](podman-container-inspect.1.md)**,**[podman-image-inspect(1)](podman-image-inspect.1.md)**,**[podman-network-inspect(1)](podman-network-inspect.1.md)**,**[podman-pod-inspect(1)](podman-pod-inspect.1.md)**,**[podman-volume-inspect(1)](podman-volume-inspect.1.md)**.
## HISTORY
July 2017, Originally compiled by Dan Walsh <dwalsh@redhat.com>
diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md
index c864a87ef..1236db602 100644
--- a/docs/source/markdown/podman-machine-init.1.md
+++ b/docs/source/markdown/podman-machine-init.1.md
@@ -47,6 +47,10 @@ Defaults to `testing`.
Memory (in MB).
+#### **--now**
+
+Start the virtual machine immediately after it has been initialized.
+
#### **--help**
Print usage statement.
diff --git a/docs/source/markdown/podman-network-connect.1.md b/docs/source/markdown/podman-network-connect.1.md
index 47a54bd33..39893c676 100644
--- a/docs/source/markdown/podman-network-connect.1.md
+++ b/docs/source/markdown/podman-network-connect.1.md
@@ -14,6 +14,8 @@ Once connected, the container can communicate with other containers in the same
#### **--alias**
Add network-scoped alias for the container. If the network is using the `dnsname` CNI plugin, these aliases
can be used for name resolution on the given network. Multiple *--alias* options may be specified as input.
+NOTE: A container will only have access to aliases on the first network that it joins. This is a limitation
+that will be removed in a later release.
## EXAMPLE
diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md
index b4c3fc2eb..fcb8ddeb9 100644
--- a/docs/source/markdown/podman-pod-create.1.md
+++ b/docs/source/markdown/podman-pod-create.1.md
@@ -38,6 +38,22 @@ Examples of the List Format:
0-4,9 # bits 0, 1, 2, 3, 4, and 9 set
0-2,7,12-14 # bits 0, 1, 2, 7, 12, 13, and 14 set
+#### **--device**=_host-device_[**:**_container-device_][**:**_permissions_]
+
+Add a host device to the pod. Optional *permissions* parameter
+can be used to specify device permissions It is a combination of
+**r** for read, **w** for write, and **m** for **mknod**(2).
+
+Example: **--device=/dev/sdc:/dev/xvdc:rwm**.
+
+Note: if _host_device_ is a symbolic link then it will be resolved first.
+The pod will only store the major and minor numbers of the host device.
+
+Note: the pod implements devices by storing the initial configuration passed by the user and recreating the device on each container added to the pod.
+
+Podman may load kernel modules required for using the specified
+device. The devices that Podman will load modules for when necessary are:
+/dev/fuse.
#### **--dns**=*ipaddr*
@@ -141,7 +157,7 @@ Set network mode for the pod. Supported values are:
#### **--network-alias**=strings
-Add a DNS alias for the container. When the container is joined to a CNI network with support for the dnsname plugin, the container will be accessible through this name from other containers in the network.
+Add a DNS alias for the pod. When the pod is joined to a CNI network with support for the dnsname plugin, the containers inside the pod will be accessible through this name from other containers in the network.
#### **--no-hosts**
diff --git a/docs/source/markdown/podman-pod-inspect.1.md b/docs/source/markdown/podman-pod-inspect.1.md
index 1f4e6cb06..0c58b099e 100644
--- a/docs/source/markdown/podman-pod-inspect.1.md
+++ b/docs/source/markdown/podman-pod-inspect.1.md
@@ -70,7 +70,7 @@ Valid placeholders for the Go template are listed below:
```
## SEE ALSO
-podman-pod(1), podman-pod-ps(1)
+**[podman(1)](podman.1.md)**,**[podman-pod(1)](podman-pod.1.md)**, **[podman-inspect(1)](podman-inspect.1.md)**
## HISTORY
August 2018, Originally compiled by Brent Baude <bbaude@redhat.com>
diff --git a/docs/source/markdown/podman-rmi.1.md b/docs/source/markdown/podman-rmi.1.md
index e34b1964b..4f3ec5541 100644
--- a/docs/source/markdown/podman-rmi.1.md
+++ b/docs/source/markdown/podman-rmi.1.md
@@ -12,6 +12,8 @@ podman\-rmi - Removes one or more locally stored images
Removes one or more locally stored images.
Passing an argument _image_ deletes it, along with any of its dangling parent images. A dangling image is an image without a tag and without being referenced by another image.
+Note: To delete an image from a remote registry, use the [**skopeo delete**](https://github.com/containers/skopeo/blob/main/docs/skopeo-delete.1.md) command. Some registries do not allow users to delete an image via a CLI remotely.
+
## OPTIONS
#### **--all**, **-a**
@@ -51,7 +53,7 @@ $ podman rmi -a -f
**125** The command fails for any other reason
## SEE ALSO
-podman(1)
+podman(1), skopeo-delete(1)
## HISTORY
March 2017, Originally compiled by Dan Walsh <dwalsh@redhat.com>
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 7b6a56fc6..a369ce5ea 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -702,7 +702,7 @@ Valid _mode_ values are:
#### **--network-alias**=*alias*
-Add network-scoped alias for the container
+Add network-scoped alias for the container. NOTE: A container will only have access to aliases on the first network that it joins. This is a limitation that will be removed in a later release.
#### **--no-healthcheck**
diff --git a/docs/source/markdown/podman-save.1.md b/docs/source/markdown/podman-save.1.md
index 1f1f60b22..842bc8b41 100644
--- a/docs/source/markdown/podman-save.1.md
+++ b/docs/source/markdown/podman-save.1.md
@@ -29,6 +29,10 @@ Note: `:` is a restricted character and cannot be part of the file name.
Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type, compressed or uncompressed, as source)
Note: This flag can only be set when using the **dir** transport i.e --format=oci-dir or --format=docker-dir
+#### **--uncompressed**
+
+Accept uncompressed layers when copying OCI images.
+
#### **--output**, **-o**=*file*
Write to a file, default is STDOUT
diff --git a/docs/source/markdown/podman-system-service.1.md b/docs/source/markdown/podman-system-service.1.md
index dfb026de1..3bc4fc7f1 100644
--- a/docs/source/markdown/podman-system-service.1.md
+++ b/docs/source/markdown/podman-system-service.1.md
@@ -30,6 +30,9 @@ Note: The default systemd unit files (system and user) change the log-level opti
The time until the session expires in _seconds_. The default is 5
seconds. A value of `0` means no timeout, therefore the session will not expire.
+The default timeout can be changed via the `service_timeout=VALUE` field in containers.conf.
+See **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information.
+
#### **--cors**
CORS headers to inject to the HTTP response. The default value is empty string which disables CORS headers.
@@ -46,7 +49,7 @@ podman system service --time 5
```
## SEE ALSO
-podman(1), podman-system-service(1), podman-system-connection(1)
+**[podman(1)](podman.1.md)**, **[podman-system-connection(1)](podman-system-connection.1.md)**, **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)**
## HISTORY
January 2020, Originally compiled by Brent Baude `<bbaude@redhat.com>`
diff --git a/docs/source/markdown/podman-volume-inspect.1.md b/docs/source/markdown/podman-volume-inspect.1.md
index ea0ee91b4..4595ccda6 100644
--- a/docs/source/markdown/podman-volume-inspect.1.md
+++ b/docs/source/markdown/podman-volume-inspect.1.md
@@ -40,7 +40,7 @@ $ podman volume inspect --format "{{.Driver}} {{.Scope}}" myvol
```
## SEE ALSO
-podman-volume(1)
+**[podman(1)](podman.1.md)**,**[podman-volume(1)](podman-volume.1.md)**, **[podman-inspect(1)](podman-inspect.1.md)**
## HISTORY
November 2018, Originally compiled by Urvashi Mohnani <umohnani@redhat.com>
diff --git a/go.mod b/go.mod
index 8930cf29e..3aa7c684a 100644
--- a/go.mod
+++ b/go.mod
@@ -6,17 +6,17 @@ require (
github.com/BurntSushi/toml v0.4.1
github.com/blang/semver v3.5.1+incompatible
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37
- github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7
+ github.com/checkpoint-restore/checkpointctl v0.0.0-20210922093614-c31748bec9f2
github.com/checkpoint-restore/go-criu/v5 v5.1.0
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9
- github.com/containernetworking/cni v0.8.1
- github.com/containernetworking/plugins v0.9.1
+ github.com/containernetworking/cni v1.0.1
+ github.com/containernetworking/plugins v1.0.1
github.com/containers/buildah v1.23.0
- github.com/containers/common v0.44.1-0.20210914173811-fcaa2e0de285
+ github.com/containers/common v0.44.1-0.20210921143342-f2f10e650c73
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.16.0
github.com/containers/ocicrypt v1.1.2
- github.com/containers/psgo v1.6.0
+ github.com/containers/psgo v1.7.1
github.com/containers/storage v1.36.0
github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
@@ -62,7 +62,7 @@ require (
github.com/uber/jaeger-client-go v2.29.1+incompatible
github.com/vbauerster/mpb/v6 v6.0.4
github.com/vbauerster/mpb/v7 v7.1.4 // indirect
- github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852
+ github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
go.etcd.io/bbolt v1.3.6
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
diff --git a/go.sum b/go.sum
index e1a707daa..aa3c0f0d6 100644
--- a/go.sum
+++ b/go.sum
@@ -95,6 +95,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
+github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@@ -121,6 +122,7 @@ github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37 h1:uxxtrnACqI9zK4ENDMf0WpXfUsHP5V8liuq5QdgDISU=
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U=
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
+github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
@@ -129,8 +131,8 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7 h1:ZmSAEFFtv3mepC4/Ze6E/hi6vGZlhRvywqp1l+w+qqw=
-github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7/go.mod h1:Kp3ezoDVdhfYxZUtgs4OL8sVvgOLz3txk0sbQD0opvw=
+github.com/checkpoint-restore/checkpointctl v0.0.0-20210922093614-c31748bec9f2 h1:z7G4H5f1Z/n3di9qnGtKDm6jmP434HD7dIEh3YyLn9I=
+github.com/checkpoint-restore/checkpointctl v0.0.0-20210922093614-c31748bec9f2/go.mod h1:yvaQuauIKzvfX/PIqINxWxoOYd35Dk/U2MS8onfkRHU=
github.com/checkpoint-restore/go-criu/v4 v4.0.2/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
@@ -238,16 +240,18 @@ github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1Dv
github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
-github.com/containernetworking/cni v0.8.1 h1:7zpDnQ3T3s4ucOuJ/ZCLrYBxzkg0AELFfII3Epo9TmI=
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
+github.com/containernetworking/cni v1.0.1 h1:9OIL/sZmMYDBe+G8svzILAlulUpaDTUjeAbtH/JNLBo=
+github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y=
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
-github.com/containernetworking/plugins v0.9.1 h1:FD1tADPls2EEi3flPc2OegIY1M9pUa9r2Quag7HMLV8=
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
+github.com/containernetworking/plugins v1.0.1 h1:wwCfYbTCj5FC0EJgyzyjTXmqysOiJE9r712Z+2KVZAk=
+github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE=
github.com/containers/buildah v1.23.0 h1:qGIeSNOczUHzvnaaOS29HSMiYAjw6JgIXYksAyvqnLs=
github.com/containers/buildah v1.23.0/go.mod h1:K0iMKgy/MffkkgELBXhSXwTy2HTT6hM0X8qruDR1FwU=
github.com/containers/common v0.44.0/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo=
-github.com/containers/common v0.44.1-0.20210914173811-fcaa2e0de285 h1:sXBzh8CcqR5cGGY9cM/AUIk58CJKHbyljVtFh8HYyLY=
-github.com/containers/common v0.44.1-0.20210914173811-fcaa2e0de285/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo=
+github.com/containers/common v0.44.1-0.20210921143342-f2f10e650c73 h1:+qKOyTHbuFo3GPsrUksphfHxYMIJQmPgwpDdQnARGAI=
+github.com/containers/common v0.44.1-0.20210921143342-f2f10e650c73/go.mod h1:zxv7KjdYddSGoWuLUVp6eSb++Ow1zmSMB2jwxuNB4cU=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.16.0 h1:WQcNSzb7+ngS2cfynx0vUwhk+scpgiKlldVcsF8GPbI=
@@ -259,8 +263,8 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU
github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0=
github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
-github.com/containers/psgo v1.6.0 h1:jkl/5kndKmJ/bnSFq8in6xRDAzgW26GnNuTxoycNFvk=
-github.com/containers/psgo v1.6.0/go.mod h1:ggVhB2KQi9qGZdqSlczqN0BwcJdotmpRru87S1anRO8=
+github.com/containers/psgo v1.7.1 h1:2N6KADeFvBm1aI2iXxu6+/Xh7CCkdh8p8F3F/cpIU5I=
+github.com/containers/psgo v1.7.1/go.mod h1:mWGpFzW73qWFA+blhF6l7GuKzbrACkYgr/ajiNQR+RM=
github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM=
github.com/containers/storage v1.35.0/go.mod h1:qzYhasQP2/V9D9XdO+vRwkHBhsBO0oznMLzzRDQ8s20=
github.com/containers/storage v1.36.0 h1:OelxllCW19tnNngYuZw2ty/zLabVMG5rSs3KSwO1Lzc=
@@ -270,6 +274,7 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
+github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -555,6 +560,7 @@ github.com/insomniacslk/dhcp v0.0.0-20210120172423-cc9239ac6294/go.mod h1:TKl4jN
github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee h1:PAXLXk1heNZ5yokbMBpVLZQxo43wCZxRwl00mX+dd44=
github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
+github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw=
github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -652,8 +658,9 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
+github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
@@ -703,8 +710,8 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
-github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
@@ -713,7 +720,7 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
-github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
+github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -818,7 +825,9 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
+github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf h1:b0+ZBD3rohnkQ4q5duD1+RyTXTg9yk+qTOPMSQtapO0=
@@ -909,12 +918,14 @@ github.com/vbauerster/mpb/v7 v7.1.4 h1:XGWpWEB8aWnvqSlAMA7F7kdeUGqcTujuVFvYj9+59
github.com/vbauerster/mpb/v7 v7.1.4/go.mod h1:4zulrZfvshMOnd2APiHgWS9Yrw08AzZVRr9G11tkpcQ=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
-github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 h1:cPXZWzzG0NllBLdjWoD1nDfaqu98YMv+OneaKc8sPOA=
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
+github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA852UkGH42H+Oee69djmxS3ANzl2b/JtT1YiA=
+github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
-github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
+github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
+github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
diff --git a/hack/get_release_info.sh b/hack/get_release_info.sh
deleted file mode 100755
index e1020e677..000000000
--- a/hack/get_release_info.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env bash
-
-# This script produces various bits of metadata needed by Makefile. Using
-# a script allows uniform behavior across multiple environments and
-# distributions. The script expects a single argument, as reflected below.
-
-set -euo pipefail
-
-cd "${GOSRC:-$(dirname $0)/../}"
-
-valid_args() {
- REGEX='^\s+[[:upper:]]+\*[)]'
- egrep --text --no-filename --group-separator=' ' --only-matching "$REGEX" "$0" | \
- cut -d '*' -f 1
-}
-
-# `git describe` will never produce a useful version number under all
-# branches. This is because the podman release process (see `RELEASE_PROCESS.md`)
-# tags release versions only on release-branches (i.e. never on main).
-# Scraping the version number directly from the source, is the only way
-# to reliably obtain the number from all the various contexts supported by
-# the `Makefile`.
-scrape_version() {
- local v
- # extract the value of 'var Version'
- v=$(sed -ne 's/^var\s\+Version\s\+=\s.*("\(.*\)").*/\1/p' <version/version.go)
- # If it's empty, something has changed in version.go, that would be bad!
- test -n "$v"
- # Value consumed literally, must not have any embedded newlines
- echo -n "$v"
-}
-
-unset OUTPUT
-case "$1" in
- # Wild-card suffix needed by valid_args() e.g. possible bad grep of "$(echo $FOO)"
- VERSION*)
- OUTPUT="${CIRRUS_TAG:-$(scrape_version)}"
- ;;
- NUMBER*)
- OUTPUT="$($0 VERSION | sed 's/-.*//')"
- ;;
- DIST_VER*)
- OUTPUT="$(source /etc/os-release; echo $VERSION_ID | cut -d '.' -f 1)"
- ;;
- DIST*)
- OUTPUT="$(source /etc/os-release; echo $ID)"
- ;;
- ARCH*)
- OUTPUT="${GOARCH:-$(go env GOARCH 2> /dev/null)}"
- ;;
- BASENAME*)
- OUTPUT="podman"
- ;;
- REMOTENAME*)
- OUTPUT="$($0 BASENAME)-remote"
- ;;
- *)
- echo "Error, unknown/unsupported argument '$1', valid arguments:"
- valid_args
- exit 1
- ;;
-esac
-
-if [[ -n "$OUTPUT" ]]
-then
- echo -n "$OUTPUT"
-else
- echo "Error, empty output for info: '$1'" > /dev/stderr
- exit 2
-fi
diff --git a/libpod/container.go b/libpod/container.go
index cf727926c..5c56ff036 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -8,7 +8,7 @@ import (
"os"
"time"
- cnitypes "github.com/containernetworking/cni/pkg/types/current"
+ types040 "github.com/containernetworking/cni/pkg/types/040"
"github.com/containers/common/pkg/secrets"
"github.com/containers/image/v5/manifest"
"github.com/containers/podman/v3/libpod/define"
@@ -176,7 +176,7 @@ type ContainerState struct {
// active.
// These are DEPRECATED and will be removed in a future release.
// This field is only used for backwarts compatibility.
- NetworkStatusOld []*cnitypes.Result `json:"networkResults,omitempty"`
+ NetworkStatusOld []*types040.Result `json:"networkResults,omitempty"`
// NetworkStatus contains the network Status for all networks
// the container is attached to. Only populated if we created a network
// namespace for the container, and the network namespace is currently
@@ -278,6 +278,11 @@ func (c *Container) Config() *ContainerConfig {
return returnConfig
}
+// DeviceHostSrc returns the user supplied device to be passed down in the pod
+func (c *Container) DeviceHostSrc() []spec.LinuxDevice {
+ return c.config.DeviceHostSrc
+}
+
// Runtime returns the container's Runtime.
func (c *Container) Runtime() *Runtime {
return c.runtime
diff --git a/libpod/container_config.go b/libpod/container_config.go
index 0374c25fe..54d102a71 100644
--- a/libpod/container_config.go
+++ b/libpod/container_config.go
@@ -381,6 +381,8 @@ type ContainerMiscConfig struct {
PidFile string `json:"pid_file,omitempty"`
// CDIDevices contains devices that use the CDI
CDIDevices []string `json:"cdiDevices,omitempty"`
+ // DeviceHostSrc contains the original source on the host
+ DeviceHostSrc []spec.LinuxDevice `json:"device_host_src,omitempty"`
// EnvSecrets are secrets that are set as environment variables
EnvSecrets map[string]*secrets.Secret `json:"secret_env,omitempty"`
// InitContainerType specifies if the container is an initcontainer
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 530160b2d..e65c86cef 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -819,27 +819,10 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
// Devices
// Do not include if privileged - assumed that all devices will be
// included.
- hostConfig.Devices = []define.InspectDevice{}
- if ctrSpec.Linux != nil && !hostConfig.Privileged {
- for _, dev := range ctrSpec.Linux.Devices {
- key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor)
- if deviceNodes == nil {
- nodes, err := util.FindDeviceNodes()
- if err != nil {
- return nil, err
- }
- deviceNodes = nodes
- }
- path, ok := deviceNodes[key]
- if !ok {
- logrus.Warnf("Could not locate device %s on host", key)
- continue
- }
- newDev := define.InspectDevice{}
- newDev.PathOnHost = path
- newDev.PathInContainer = dev.Path
- hostConfig.Devices = append(hostConfig.Devices, newDev)
- }
+ var err error
+ hostConfig.Devices, err = c.GetDevices(*&hostConfig.Privileged, *ctrSpec, deviceNodes)
+ if err != nil {
+ return nil, err
}
// Ulimits
@@ -885,3 +868,29 @@ func (c *Container) inHostPidNS() (bool, error) {
}
return true, nil
}
+
+func (c *Container) GetDevices(priv bool, ctrSpec spec.Spec, deviceNodes map[string]string) ([]define.InspectDevice, error) {
+ devices := []define.InspectDevice{}
+ if ctrSpec.Linux != nil && !priv {
+ for _, dev := range ctrSpec.Linux.Devices {
+ key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor)
+ if deviceNodes == nil {
+ nodes, err := util.FindDeviceNodes()
+ if err != nil {
+ return nil, err
+ }
+ deviceNodes = nodes
+ }
+ path, ok := deviceNodes[key]
+ if !ok {
+ logrus.Warnf("Could not locate device %s on host", key)
+ continue
+ }
+ newDev := define.InspectDevice{}
+ newDev.PathOnHost = path
+ newDev.PathInContainer = dev.Path
+ devices = append(devices, newDev)
+ }
+ }
+ return devices, nil
+}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 6ebbfd1f3..0a663200a 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -369,13 +369,46 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
if err != nil {
return nil, err
}
- volMount := spec.Mount{
- Type: "bind",
- Source: mountPoint,
- Destination: namedVol.Dest,
- Options: namedVol.Options,
+
+ overlayFlag := false
+ for _, o := range namedVol.Options {
+ if o == "O" {
+ overlayFlag = true
+ }
+ }
+
+ if overlayFlag {
+ contentDir, err := overlay.TempDir(c.config.StaticDir, c.RootUID(), c.RootGID())
+ if err != nil {
+ return nil, err
+ }
+ overlayMount, err := overlay.Mount(contentDir, mountPoint, namedVol.Dest, c.RootUID(), c.RootGID(), c.runtime.store.GraphOptions())
+ if err != nil {
+ return nil, errors.Wrapf(err, "mounting overlay failed %q", mountPoint)
+ }
+
+ for _, o := range namedVol.Options {
+ switch o {
+ case "U":
+ if err := chown.ChangeHostPathOwnership(mountPoint, true, int(hostUID), int(hostGID)); err != nil {
+ return nil, err
+ }
+
+ if err := chown.ChangeHostPathOwnership(contentDir, true, int(hostUID), int(hostGID)); err != nil {
+ return nil, err
+ }
+ }
+ }
+ g.AddMount(overlayMount)
+ } else {
+ volMount := spec.Mount{
+ Type: "bind",
+ Source: mountPoint,
+ Destination: namedVol.Dest,
+ Options: namedVol.Options,
+ }
+ g.AddMount(volMount)
}
- g.AddMount(volMount)
}
// Check if the spec file mounts contain the options z, Z or U.
@@ -2050,35 +2083,39 @@ func (c *Container) getHosts() string {
}
}
- // Add gateway entry
- var depCtr *Container
- netStatus := c.getNetworkStatus()
- if c.config.NetNsCtr != "" {
- // ignoring the error because there isn't anything to do
- depCtr, _ = c.getRootNetNsDepCtr()
- } else if len(netStatus) != 0 {
- depCtr = c
- }
-
- if depCtr != nil {
- for _, status := range depCtr.getNetworkStatus() {
- for _, netInt := range status.Interfaces {
- for _, netAddress := range netInt.Networks {
- if netAddress.Gateway != nil {
- hosts += fmt.Sprintf("%s host.containers.internal\n", netAddress.Gateway.String())
+ // Add gateway entry if we are not in a machine. If we use podman machine
+ // the gvproxy dns server will take care of host.containers.internal.
+ // https://github.com/containers/gvisor-tap-vsock/commit/1108ea45162281046d239047a6db9bc187e64b08
+ if !c.runtime.config.Engine.MachineEnabled {
+ var depCtr *Container
+ netStatus := c.getNetworkStatus()
+ if c.config.NetNsCtr != "" {
+ // ignoring the error because there isn't anything to do
+ depCtr, _ = c.getRootNetNsDepCtr()
+ } else if len(netStatus) != 0 {
+ depCtr = c
+ }
+
+ if depCtr != nil {
+ for _, status := range depCtr.getNetworkStatus() {
+ for _, netInt := range status.Interfaces {
+ for _, netAddress := range netInt.Networks {
+ if netAddress.Gateway != nil {
+ hosts += fmt.Sprintf("%s host.containers.internal\n", netAddress.Gateway.String())
+ }
}
}
}
- }
- } else if c.config.NetMode.IsSlirp4netns() {
- gatewayIP, err := GetSlirp4netnsGateway(c.slirp4netnsSubnet)
- if err != nil {
- logrus.Warn("failed to determine gatewayIP: ", err.Error())
+ } else if c.config.NetMode.IsSlirp4netns() {
+ gatewayIP, err := GetSlirp4netnsGateway(c.slirp4netnsSubnet)
+ if err != nil {
+ logrus.Warn("failed to determine gatewayIP: ", err.Error())
+ } else {
+ hosts += fmt.Sprintf("%s host.containers.internal\n", gatewayIP.String())
+ }
} else {
- hosts += fmt.Sprintf("%s host.containers.internal\n", gatewayIP.String())
+ logrus.Debug("network configuration does not support host.containers.internal address")
}
- } else {
- logrus.Debug("network configuration does not support host.containers.internal address")
}
return hosts
diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go
index b7a6e76b5..e78d97850 100644
--- a/libpod/define/pod_inspect.go
+++ b/libpod/define/pod_inspect.go
@@ -59,6 +59,8 @@ type InspectPodData struct {
CPUSetCPUs string `json:"cpuset_cpus,omitempty"`
// Mounts contains volume related information for the pod
Mounts []InspectMount `json:"mounts,omitempty"`
+ // Devices contains the specified host devices
+ Devices []InspectDevice `json:"devices,omitempty"`
}
// InspectPodInfraConfig contains the configuration of the pod's infra
diff --git a/libpod/kube.go b/libpod/kube.go
index 54e8a7c50..9b96dd99d 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/network/types"
+ "github.com/containers/podman/v3/pkg/env"
"github.com/containers/podman/v3/pkg/lookup"
"github.com/containers/podman/v3/pkg/namespaces"
"github.com/containers/podman/v3/pkg/specgen"
@@ -570,12 +571,16 @@ func ocicniPortMappingToContainerPort(portMappings []types.OCICNIPortMapping) ([
// libpodEnvVarsToKubeEnvVars converts a key=value string slice to []v1.EnvVar
func libpodEnvVarsToKubeEnvVars(envs []string) ([]v1.EnvVar, error) {
+ defaultEnv := env.DefaultEnvVariables()
envVars := make([]v1.EnvVar, 0, len(envs))
for _, e := range envs {
split := strings.SplitN(e, "=", 2)
if len(split) != 2 {
return envVars, errors.Errorf("environment variable %s is malformed; should be key=value", e)
}
+ if defaultEnv[split[0]] == split[1] {
+ continue
+ }
ev := v1.EnvVar{
Name: split[0],
Value: split[1],
diff --git a/libpod/network/cni/cni_conversion.go b/libpod/network/cni/cni_conversion.go
index d69dd7eb3..7a73b874a 100644
--- a/libpod/network/cni/cni_conversion.go
+++ b/libpod/network/cni/cni_conversion.go
@@ -14,7 +14,6 @@ import (
"time"
"github.com/containernetworking/cni/libcni"
- "github.com/containernetworking/cni/pkg/version"
"github.com/containers/podman/v3/libpod/network/types"
"github.com/containers/podman/v3/libpod/network/util"
pkgutil "github.com/containers/podman/v3/pkg/util"
@@ -283,7 +282,10 @@ func (n *cniNetwork) createCNIConfigListFromNetwork(network *types.Network, writ
ipMasq = false
}
// create CNI plugin configuration
- ncList := newNcList(network.Name, version.Current(), network.Labels, network.Options)
+ // explicitly use CNI version 0.4.0 here, to use v1.0.0 at least containernetwork-plugins-1.0.1 has to be installed
+ // the dnsname plugin also needs to be updated for 1.0.0
+ // TODO change to 1.0.0 when most distros support it
+ ncList := newNcList(network.Name, "0.4.0", network.Labels, network.Options)
var plugins []interface{}
switch network.Driver {
diff --git a/libpod/network/cni/network.go b/libpod/network/cni/network.go
index d77e63a5d..02801641e 100644
--- a/libpod/network/cni/network.go
+++ b/libpod/network/cni/network.go
@@ -127,7 +127,7 @@ func (n *cniNetwork) loadNetworks() error {
conf, err := libcni.ConfListFromFile(file)
if err != nil {
// do not log ENOENT errors
- if !os.IsNotExist(err) {
+ if !errors.Is(err, os.ErrNotExist) {
logrus.Warnf("Error loading CNI config file %s: %v", file, err)
}
continue
diff --git a/libpod/network/cni/run.go b/libpod/network/cni/run.go
index b69953c4b..834e7c867 100644
--- a/libpod/network/cni/run.go
+++ b/libpod/network/cni/run.go
@@ -10,7 +10,7 @@ import (
"github.com/containernetworking/cni/libcni"
cnitypes "github.com/containernetworking/cni/pkg/types"
- "github.com/containernetworking/cni/pkg/types/current"
+ types040 "github.com/containernetworking/cni/pkg/types/040"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/network/types"
@@ -107,14 +107,9 @@ func (n *cniNetwork) Setup(namespacePath string, options types.SetupOptions) (ma
return nil, retErr
}
- var cnires *current.Result
- cnires, retErr = current.GetResult(res)
- if retErr != nil {
- return nil, retErr
- }
- logrus.Debugf("cni result for container %s network %s: %v", options.ContainerID, name, cnires)
+ logrus.Debugf("cni result for container %s network %s: %v", options.ContainerID, name, res)
var status types.StatusBlock
- status, retErr = CNIResultToStatus(cnires)
+ status, retErr = CNIResultToStatus(res)
if retErr != nil {
return nil, retErr
}
@@ -125,8 +120,12 @@ func (n *cniNetwork) Setup(namespacePath string, options types.SetupOptions) (ma
// CNIResultToStatus convert the cni result to status block
// nolint:golint
-func CNIResultToStatus(cniResult *current.Result) (types.StatusBlock, error) {
+func CNIResultToStatus(res cnitypes.Result) (types.StatusBlock, error) {
result := types.StatusBlock{}
+ cniResult, err := types040.GetResult(res)
+ if err != nil {
+ return result, err
+ }
nameservers := make([]net.IP, 0, len(cniResult.DNS.Nameservers))
for _, nameserver := range cniResult.DNS.Nameservers {
ip := net.ParseIP(nameserver)
diff --git a/libpod/network/types/network.go b/libpod/network/types/network.go
index 6053ceb29..68a32d499 100644
--- a/libpod/network/types/network.go
+++ b/libpod/network/types/network.go
@@ -32,11 +32,11 @@ type ContainerNetwork interface {
// Network describes the Network attributes.
type Network struct {
// Name of the Network.
- Name string `json:"name,omitempty"`
+ Name string `json:"name"`
// ID of the Network.
- ID string `json:"id,omitempty"`
+ ID string `json:"id"`
// Driver for this Network, e.g. bridge, macvlan...
- Driver string `json:"driver,omitempty"`
+ Driver string `json:"driver"`
// InterfaceName is the network interface name on the host.
NetworkInterface string `json:"network_interface,omitempty"`
// Created contains the timestamp when this network was created.
@@ -97,7 +97,7 @@ func (n *IPNet) UnmarshalText(text []byte) error {
type Subnet struct {
// Subnet for this Network in CIDR form.
// swagger:strfmt string
- Subnet IPNet `json:"subnet,omitempty"`
+ Subnet IPNet `json:"subnet"`
// Gateway IP for this Network.
// swagger:strfmt string
Gateway net.IP `json:"gateway,omitempty"`
@@ -134,14 +134,14 @@ type NetInterface struct {
// Networks list of assigned subnets with their gateway.
Networks []NetAddress `json:"networks,omitempty"`
// MacAddress for this Interface.
- MacAddress net.HardwareAddr `json:"mac_address,omitempty"`
+ MacAddress net.HardwareAddr `json:"mac_address"`
}
// NetAddress contains the subnet and gatway.
type NetAddress struct {
// Subnet of this NetAddress. Note that the subnet contains the
// actual ip of the net interface and not the network address.
- Subnet IPNet `json:"subnet,omitempty"`
+ Subnet IPNet `json:"subnet"`
// Gateway for the Subnet. This can be nil if there is no gateway, e.g. internal network.
Gateway net.IP `json:"gateway,omitempty"`
}
@@ -157,27 +157,27 @@ type PerNetworkOptions struct {
// StaticMac for this container. Optional.
StaticMAC net.HardwareAddr `json:"static_mac,omitempty"`
// InterfaceName for this container. Required.
- InterfaceName string `json:"interface_name,omitempty"`
+ InterfaceName string `json:"interface_name"`
}
// NetworkOptions for a given container.
type NetworkOptions struct {
// ContainerID is the container id, used for iptables comments and ipam allocation.
- ContainerID string `json:"container_id,omitempty"`
+ ContainerID string `json:"container_id"`
// ContainerName is the container name, used as dns name.
- ContainerName string `json:"container_name,omitempty"`
+ ContainerName string `json:"container_name"`
// PortMappings contains the port mappings for this container
PortMappings []PortMapping `json:"port_mappings,omitempty"`
// Networks contains all networks with the PerNetworkOptions.
// The map should contain at least one element.
- Networks map[string]PerNetworkOptions `json:"networks,omitempty"`
+ Networks map[string]PerNetworkOptions `json:"networks"`
}
// PortMapping is one or more ports that will be mapped into the container.
type PortMapping struct {
// HostIP is the IP that we will bind to on the host.
// If unset, assumed to be 0.0.0.0 (all interfaces).
- HostIP string `json:"host_ip,omitempty"`
+ HostIP string `json:"host_ip"`
// ContainerPort is the port number that will be exposed from the
// container.
// Mandatory.
@@ -186,7 +186,7 @@ type PortMapping struct {
// the container.
// If omitted, a random port on the host (guaranteed to be over 1024)
// will be assigned.
- HostPort uint16 `json:"host_port,omitempty"`
+ HostPort uint16 `json:"host_port"`
// Range is the number of ports that will be forwarded, starting at
// HostPort and ContainerPort and counting up.
// This is 1-indexed, so 1 is assumed to be a single port (only the
@@ -195,12 +195,12 @@ type PortMapping struct {
// If unset, assumed to be 1 (a single port).
// Both hostport + range and containerport + range must be less than
// 65536.
- Range uint16 `json:"range,omitempty"`
+ Range uint16 `json:"range"`
// Protocol is the protocol forward.
// Must be either "tcp", "udp", and "sctp", or some combination of these
// separated by commas.
// If unset, assumed to be TCP.
- Protocol string `json:"protocol,omitempty"`
+ Protocol string `json:"protocol"`
}
// OCICNIPortMapping maps to the standard CNI portmapping Capability.
diff --git a/libpod/options.go b/libpod/options.go
index 3f6ccf1cb..a80f51c6a 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -21,6 +21,7 @@ import (
"github.com/containers/podman/v3/pkg/util"
"github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
+ "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -1809,6 +1810,17 @@ func WithInitCtrType(containerType string) CtrCreateOption {
}
}
+// WithHostDevice adds the original host src to the config
+func WithHostDevice(dev []specs.LinuxDevice) CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return define.ErrCtrFinalized
+ }
+ ctr.config.DeviceHostSrc = dev
+ return nil
+ }
+}
+
// Pod Creation Options
// WithPodCreateCommand adds the full command plus arguments of the current
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 4e0acf950..ff818edc2 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -583,6 +583,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
// container.
var infraConfig *define.InspectPodInfraConfig
var inspectMounts []define.InspectMount
+ var devices []define.InspectDevice
if p.state.InfraContainerID != "" {
infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
if err != nil {
@@ -604,6 +605,12 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
return nil, err
}
+ var nodes map[string]string
+ devices, err = infra.GetDevices(false, *infra.config.Spec, nodes)
+ if err != nil {
+ return nil, err
+ }
+
if len(infra.Config().ContainerNetworkConfig.DNSServer) > 0 {
infraConfig.DNSServer = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSServer))
for _, entry := range infra.Config().ContainerNetworkConfig.DNSServer {
@@ -652,6 +659,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
CPUPeriod: p.CPUPeriod(),
CPUQuota: p.CPUQuota(),
Mounts: inspectMounts,
+ Devices: devices,
}
return &inspectData, nil
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index b4f08a746..51157d204 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -289,9 +289,10 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- Compress bool `schema:"compress"`
- Format string `schema:"format"`
- References []string `schema:"references"`
+ Compress bool `schema:"compress"`
+ Format string `schema:"format"`
+ OciAcceptUncompressedLayers bool `schema:"ociAcceptUncompressedLayers"`
+ References []string `schema:"references"`
}{
Format: define.OCIArchive,
}
@@ -353,11 +354,12 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
// Use the ABI image engine to share as much code as possible.
opts := entities.ImageSaveOptions{
- Compress: query.Compress,
- Format: query.Format,
- MultiImageArchive: len(query.References) > 1,
- Output: output,
- RemoveSignatures: true,
+ Compress: query.Compress,
+ Format: query.Format,
+ MultiImageArchive: len(query.References) > 1,
+ OciAcceptUncompressedLayers: query.OciAcceptUncompressedLayers,
+ Output: output,
+ RemoveSignatures: true,
}
imageEngine := abi.ImageEngine{Libpod: runtime}
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 1f03e121e..9f46ecc52 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -41,8 +41,8 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
return
}
if !psg.NoInfra {
- infraOptions := &entities.ContainerCreateOptions{ImageVolume: "bind", IsInfra: true, Net: &entities.NetOptions{}} // options for pulling the image and FillOutSpec
- err = specgenutil.FillOutSpecGen(psg.InfraContainerSpec, infraOptions, []string{}) // necessary for default values in many cases (userns, idmappings)
+ infraOptions := &entities.ContainerCreateOptions{ImageVolume: "bind", IsInfra: true, Net: &entities.NetOptions{}, Devices: psg.Devices} // options for pulling the image and FillOutSpec
+ err = specgenutil.FillOutSpecGen(psg.InfraContainerSpec, infraOptions, []string{}) // necessary for default values in many cases (userns, idmappings)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error filling out specgen"))
return
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index b82c586ea..fedab3bb3 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -183,7 +183,8 @@ func ImageToImageSummary(l *libimage.Image) (*entities.ImageSummary, error) {
}
is := entities.ImageSummary{
- ID: l.ID(),
+ // docker adds sha256: in front of the ID
+ ID: "sha256:" + l.ID(),
ParentId: imageData.Parent,
RepoTags: imageData.RepoTags,
RepoDigests: imageData.RepoDigests,
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 95981226c..dce609a4e 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -1150,6 +1150,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// name: compress
// type: boolean
// description: use compression on image
+ // - in: query
+ // name: ociAcceptUncompressedLayers
+ // type: boolean
+ // description: accept uncompressed layers when copying OCI images
// produces:
// - application/json
// responses:
diff --git a/pkg/autoupdate/autoupdate.go b/pkg/autoupdate/autoupdate.go
index 894178bb9..29c234ce9 100644
--- a/pkg/autoupdate/autoupdate.go
+++ b/pkg/autoupdate/autoupdate.go
@@ -404,7 +404,8 @@ func newerRemoteImageAvailable(ctx context.Context, runtime *libpod.Runtime, img
if err != nil {
return false, err
}
- return img.HasDifferentDigest(ctx, remoteRef)
+ options := &libimage.HasDifferentDigestOptions{AuthFilePath: authfile}
+ return img.HasDifferentDigest(ctx, remoteRef, options)
}
// newerLocalImageAvailable returns true if the container and local image have different digests
diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go
index 801f5ed96..6ff9f18ec 100644
--- a/pkg/bindings/images/types.go
+++ b/pkg/bindings/images/types.go
@@ -65,6 +65,8 @@ type ExportOptions struct {
Compress *bool
// Format of the output
Format *string
+ // Accept uncompressed layers when copying OCI images.
+ OciAcceptUncompressedLayers *bool
}
//go:generate go run ../generator/generator.go PruneOptions
diff --git a/pkg/bindings/images/types_export_options.go b/pkg/bindings/images/types_export_options.go
index 6229e435c..649b6814e 100644
--- a/pkg/bindings/images/types_export_options.go
+++ b/pkg/bindings/images/types_export_options.go
@@ -46,3 +46,18 @@ func (o *ExportOptions) GetFormat() string {
}
return *o.Format
}
+
+// WithOciAcceptUncompressedLayers set field OciAcceptUncompressedLayers to given value
+func (o *ExportOptions) WithOciAcceptUncompressedLayers(value bool) *ExportOptions {
+ o.OciAcceptUncompressedLayers = &value
+ return o
+}
+
+// GetOciAcceptUncompressedLayers returns value of field OciAcceptUncompressedLayers
+func (o *ExportOptions) GetOciAcceptUncompressedLayers() bool {
+ if o.OciAcceptUncompressedLayers == nil {
+ var z bool
+ return z
+ }
+ return *o.OciAcceptUncompressedLayers
+}
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index c575212b1..edd23e662 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -301,6 +301,8 @@ type ImageSaveOptions struct {
// than one image. Additional tags will be interpreted as references
// to images which are added to the archive.
MultiImageArchive bool
+ // Accept uncompressed layers when copying OCI images.
+ OciAcceptUncompressedLayers bool
// Output - write image to the specified path.
Output string
// Do not save the signature from the source image
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index a74725c63..f0c88d77e 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -112,26 +112,28 @@ type PodSpec struct {
PodSpecGen specgen.PodSpecGenerator
}
-// PodCreateOptions provides all possible options for creating a pod and its infra container
+// PodCreateOptions provides all possible options for creating a pod and its infra container.
+// The JSON tags below are made to match the respective field in ContainerCreateOptions for the purpose of mapping.
// swagger:model PodCreateOptions
type PodCreateOptions struct {
- CGroupParent string
- CreateCommand []string
- Hostname string
- Infra bool
- InfraImage string
- InfraName string
- InfraCommand string
- InfraConmonPidFile string
- Labels map[string]string
- Name string
- Net *NetOptions
- Share []string
- Pid string
- Cpus float64
- CpusetCpus string
- Userns specgen.Namespace
- Volume []string
+ CGroupParent string `json:"cgroup_parent,omitempty"`
+ CreateCommand []string `json:"create_command,omitempty"`
+ Devices []string `json:"devices,omitempty"`
+ Hostname string `json:"hostname,omitempty"`
+ Infra bool `json:"infra,omitempty"`
+ InfraImage string `json:"infra_image,omitempty"`
+ InfraName string `json:"container_name,omitempty"`
+ InfraCommand *string `json:"container_command,omitempty"`
+ InfraConmonPidFile string `json:"container_conmon_pidfile,omitempty"`
+ Labels map[string]string `json:"labels,omitempty"`
+ Name string `json:"name,omitempty"`
+ Net *NetOptions `json:"net,omitempty"`
+ Share []string `json:"share,omitempty"`
+ Pid string `json:"pid,omitempty"`
+ Cpus float64 `json:"cpus,omitempty"`
+ CpusetCpus string `json:"cpuset_cpus,omitempty"`
+ Userns specgen.Namespace `json:"-"`
+ Volume []string `json:"volume,omitempty"`
}
// PodLogsOptions describes the options to extract pod logs.
@@ -152,24 +154,24 @@ type ContainerCreateOptions struct {
CapDrop []string
CgroupNS string
CGroupsMode string
- CGroupParent string
+ CGroupParent string `json:"cgroup_parent,omitempty"`
CIDFile string
- ConmonPIDFile string
+ ConmonPIDFile string `json:"container_conmon_pidfile,omitempty"`
CPUPeriod uint64
CPUQuota int64
CPURTPeriod uint64
CPURTRuntime int64
CPUShares uint64
- CPUS float64
- CPUSetCPUs string
+ CPUS float64 `json:"cpus,omitempty"`
+ CPUSetCPUs string `json:"cpuset_cpus,omitempty"`
CPUSetMems string
- Devices []string
+ Devices []string `json:"devices,omitempty"`
DeviceCGroupRule []string
DeviceReadBPs []string
DeviceReadIOPs []string
DeviceWriteBPs []string
DeviceWriteIOPs []string
- Entrypoint *string
+ Entrypoint *string `json:"container_command,omitempty"`
Env []string
EnvHost bool
EnvFile []string
@@ -181,7 +183,7 @@ type ContainerCreateOptions struct {
HealthRetries uint
HealthStartPeriod string
HealthTimeout string
- Hostname string
+ Hostname string `json:"hostname,omitempty"`
HTTPProxy bool
ImageVolume string
Init bool
@@ -198,14 +200,14 @@ type ContainerCreateOptions struct {
MemoryReservation string
MemorySwap string
MemorySwappiness int64
- Name string
+ Name string `json:"container_name,omitempty"`
NoHealthCheck bool
OOMKillDisable bool
OOMScoreAdj int
Arch string
OS string
Variant string
- PID string
+ PID string `json:"pid,omitempty"`
PIDsLimit *int64
Platform string
Pod string
@@ -244,17 +246,17 @@ type ContainerCreateOptions struct {
UIDMap []string
Ulimit []string
User string
- UserNS string
+ UserNS string `json:"-"`
UTS string
Mount []string
- Volume []string
+ Volume []string `json:"volume,omitempty"`
VolumesFrom []string
Workdir string
SeccompPolicy string
PidFile string
IsInfra bool
- Net *NetOptions
+ Net *NetOptions `json:"net,omitempty"`
CgroupConf []string
}
@@ -294,9 +296,10 @@ func ToPodSpecGen(s specgen.PodSpecGenerator, p *PodCreateOptions) (*specgen.Pod
s.Pid = out
s.Hostname = p.Hostname
s.Labels = p.Labels
+ s.Devices = p.Devices
s.NoInfra = !p.Infra
- if len(p.InfraCommand) > 0 {
- s.InfraCommand = strings.Split(p.InfraCommand, " ")
+ if p.InfraCommand != nil && len(*p.InfraCommand) > 0 {
+ s.InfraCommand = strings.Split(*p.InfraCommand, " ")
}
if len(p.InfraConmonPidFile) > 0 {
s.InfraConmonPidFile = p.InfraConmonPidFile
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index dc5f7a0df..affed64d1 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -830,21 +830,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri
}
return reports, errors.Wrapf(err, "unable to start container %s", ctr.ID())
}
-
- if ecode, err := ctr.Wait(ctx); err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
- // Check events
- event, err := ic.Libpod.GetLastContainerEvent(ctx, ctr.ID(), events.Exited)
- if err != nil {
- logrus.Errorf("Cannot get exit code: %v", err)
- exitCode = define.ExecErrorCodeNotFound
- } else {
- exitCode = event.ContainerExitCode
- }
- }
- } else {
- exitCode = int(ecode)
- }
+ exitCode = ic.GetContainerExitCode(ctx, ctr)
reports = append(reports, &entities.ContainerStartReport{
Id: ctr.ID(),
RawInput: rawInput,
@@ -985,21 +971,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
report.ExitCode = define.ExitCode(err)
return &report, err
}
-
- if ecode, err := ctr.Wait(ctx); err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
- // Check events
- event, err := ic.Libpod.GetLastContainerEvent(ctx, ctr.ID(), events.Exited)
- if err != nil {
- logrus.Errorf("Cannot get exit code: %v", err)
- report.ExitCode = define.ExecErrorCodeNotFound
- } else {
- report.ExitCode = event.ContainerExitCode
- }
- }
- } else {
- report.ExitCode = int(ecode)
- }
+ report.ExitCode = ic.GetContainerExitCode(ctx, ctr)
if opts.Rm && !ctr.ShouldRestart(ctx) {
if err := ic.Libpod.RemoveContainer(ctx, ctr, false, true); err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr ||
@@ -1013,6 +985,29 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
return &report, nil
}
+func (ic *ContainerEngine) GetContainerExitCode(ctx context.Context, ctr *libpod.Container) int {
+ exitCode, err := ctr.Wait(ctx)
+ if err == nil {
+ return int(exitCode)
+ }
+ if errors.Cause(err) != define.ErrNoSuchCtr {
+ logrus.Errorf("Could not retrieve exit code: %v", err)
+ return define.ExecErrorCodeNotFound
+ }
+ // Make 4 attempt with 0.25s backoff between each for 1 second total
+ var event *events.Event
+ for i := 0; i < 4; i++ {
+ event, err = ic.Libpod.GetLastContainerEvent(ctx, ctr.ID(), events.Exited)
+ if err != nil {
+ time.Sleep(250 * time.Millisecond)
+ continue
+ }
+ return int(event.ContainerExitCode)
+ }
+ logrus.Errorf("Could not retrieve exit code from event: %v", err)
+ return define.ExecErrorCodeNotFound
+}
+
func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []string, options entities.ContainerLogsOptions) error {
if options.StdoutWriter == nil && options.StderrWriter == nil {
return errors.New("no io.Writer set for container logs")
diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go
index 2d7bc15f5..1e614ce58 100644
--- a/pkg/domain/infra/abi/generate.go
+++ b/pkg/domain/infra/abi/generate.go
@@ -210,9 +210,7 @@ func generateKubeYAML(kubeKind interface{}) ([]byte, error) {
func generateKubeOutput(content [][]byte) ([]byte, error) {
output := make([]byte, 0)
- header := `# Generation of Kubernetes YAML is still under development!
-#
-# Save the output of this file and use kubectl create -f to import
+ header := `# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-%s
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index a88d38a10..f8ee0304d 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -367,6 +367,7 @@ func (ir *ImageEngine) Load(ctx context.Context, options entities.ImageLoadOptio
func (ir *ImageEngine) Save(ctx context.Context, nameOrID string, tags []string, options entities.ImageSaveOptions) error {
saveOptions := &libimage.SaveOptions{}
saveOptions.DirForceCompress = options.Compress
+ saveOptions.OciAcceptUncompressedLayers = options.OciAcceptUncompressedLayers
saveOptions.RemoveSignatures = options.RemoveSignatures
if !options.Quiet {
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index db4e14aba..282770613 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -165,6 +165,9 @@ func (ir *ImageEngine) Untag(ctx context.Context, nameOrID string, tags []string
if t, ok := ref.(reference.Tagged); ok {
tag = t.Tag()
}
+ if t, ok := ref.(reference.Digested); ok {
+ tag += "@" + t.Digest().String()
+ }
if r, ok := ref.(reference.Named); ok {
repo = r.Name()
}
@@ -253,6 +256,7 @@ func (ir *ImageEngine) Save(ctx context.Context, nameOrID string, tags []string,
err error
)
options := new(images.ExportOptions).WithFormat(opts.Format).WithCompress(opts.Compress)
+ options = options.WithOciAcceptUncompressedLayers(opts.OciAcceptUncompressedLayers)
switch opts.Format {
case "oci-dir", "docker-dir":
diff --git a/pkg/env/env.go b/pkg/env/env.go
index 0d55e5560..ecd2d62a5 100644
--- a/pkg/env/env.go
+++ b/pkg/env/env.go
@@ -17,8 +17,9 @@ const whiteSpaces = " \t"
// DefaultEnvVariables returns a default environment, with $PATH and $TERM set.
func DefaultEnvVariables() map[string]string {
return map[string]string{
- "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
- "TERM": "xterm",
+ "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM": "xterm",
+ "container": "podman",
}
}
diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go
index 6b9e9c4bf..2d1e2b288 100644
--- a/pkg/specgen/generate/config_linux.go
+++ b/pkg/specgen/generate/config_linux.go
@@ -132,7 +132,6 @@ func DevicesFromPath(g *generate.Generator, devicePath string) error {
}
return nil
}
-
return addDevice(g, strings.Join(append([]string{resolvedDevicePath}, devs[1:]...), ":"))
}
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 91230338e..fefa9b4a9 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -30,24 +30,27 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
// If joining a pod, retrieve the pod for use, and its infra container
var pod *libpod.Pod
- var cont *libpod.Container
- var config *libpod.ContainerConfig
+ var infraConfig *libpod.ContainerConfig
if s.Pod != "" {
pod, err = rt.LookupPod(s.Pod)
if err != nil {
return nil, nil, nil, errors.Wrapf(err, "error retrieving pod %s", s.Pod)
}
if pod.HasInfraContainer() {
- cont, err = pod.InfraContainer()
+ infra, err := pod.InfraContainer()
if err != nil {
return nil, nil, nil, err
}
- config = cont.Config()
+ infraConfig = infra.Config()
}
}
- if config != nil && (len(config.NamedVolumes) > 0 || len(config.UserVolumes) > 0 || len(config.ImageVolumes) > 0 || len(config.OverlayVolumes) > 0) {
- s.VolumesFrom = append(s.VolumesFrom, config.ID)
+ if infraConfig != nil && (len(infraConfig.NamedVolumes) > 0 || len(infraConfig.UserVolumes) > 0 || len(infraConfig.ImageVolumes) > 0 || len(infraConfig.OverlayVolumes) > 0) {
+ s.VolumesFrom = append(s.VolumesFrom, infraConfig.ID)
+ }
+
+ if infraConfig != nil && len(infraConfig.Spec.Linux.Devices) > 0 {
+ s.DevicesFrom = append(s.DevicesFrom, infraConfig.ID)
}
// Set defaults for unset namespaces
if s.PidNS.IsDefault() {
@@ -166,6 +169,16 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
logrus.Debugf("setting container name %s", s.Name)
options = append(options, libpod.WithName(s.Name))
}
+ if len(s.DevicesFrom) > 0 {
+ for _, dev := range s.DevicesFrom {
+ ctr, err := rt.GetContainer(dev)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ devices := ctr.DeviceHostSrc()
+ s.Devices = append(s.Devices, devices...)
+ }
+ }
if len(s.Devices) > 0 {
opts = extractCDIDevices(s)
options = append(options, opts...)
@@ -174,6 +187,9 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
if err != nil {
return nil, nil, nil, err
}
+ if len(s.HostDeviceList) > 0 {
+ options = append(options, libpod.WithHostDevice(s.HostDeviceList))
+ }
return runtimeSpec, s, options, err
}
func ExecuteCreate(ctx context.Context, rt *libpod.Runtime, runtimeSpec *spec.Spec, s *specgen.SpecGenerator, infra bool, options ...libpod.CtrCreateOption) (*libpod.Container, error) {
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index 80c7f112f..55010f716 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -301,8 +301,8 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
g.AddProcessEnv("container", "podman")
g.Config.Linux.Resources = s.ResourceLimits
-
// Devices
+
if s.Privileged {
// If privileged, we need to add all the host devices to the
// spec. We do not add the user provided ones because we are
@@ -313,17 +313,18 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
} else {
// add default devices from containers.conf
for _, device := range rtc.Containers.Devices {
- if err := DevicesFromPath(&g, device); err != nil {
+ if err = DevicesFromPath(&g, device); err != nil {
return nil, err
}
}
// add default devices specified by caller
for _, device := range s.Devices {
- if err := DevicesFromPath(&g, device.Path); err != nil {
+ if err = DevicesFromPath(&g, device.Path); err != nil {
return nil, err
}
}
}
+ s.HostDeviceList = s.Devices
for _, dev := range s.DeviceCGroupRule {
g.AddLinuxResourcesDevice(true, dev.Type, dev.Major, dev.Minor, dev.Access)
diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go
index 5f72fc47d..83fa9426c 100644
--- a/pkg/specgen/podspecgen.go
+++ b/pkg/specgen/podspecgen.go
@@ -88,6 +88,8 @@ type PodBasicConfig struct {
// Image volumes bind-mount a container-image mount into the pod's infra container.
// Optional.
ImageVolumes []*ImageVolume `json:"image_volumes,omitempty"`
+ // Devices contains user specified Devices to be added to the Pod
+ Devices []string `json:"pod_devices,omitempty"`
}
// PodNetworkConfig contains networking configuration for a pod.
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index e0609c5bc..7aa27487a 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -254,6 +254,10 @@ type ContainerStorageConfig struct {
// DeviceCGroupRule are device cgroup rules that allow containers
// to use additional types of devices.
DeviceCGroupRule []spec.LinuxDeviceCgroup `json:"device_cgroup_rule,omitempty"`
+ // DevicesFrom is a way to ensure your container inherits device specific information from another container
+ DevicesFrom []string `json:"devices_from,omitempty"`
+ // HostDeviceList is used to recreate the mounted device on inherited containers
+ HostDeviceList []spec.LinuxDevice `json:"host_device_list,omitempty"`
// IpcNS is the container's IPC namespace.
// Default is private.
// Conflicts with ShmSize if not set to private.
diff --git a/test/apiv2/python/rest_api/test_v2_0_0_image.py b/test/apiv2/python/rest_api/test_v2_0_0_image.py
index bcacaa935..58d03b149 100644
--- a/test/apiv2/python/rest_api/test_v2_0_0_image.py
+++ b/test/apiv2/python/rest_api/test_v2_0_0_image.py
@@ -32,6 +32,9 @@ class ImageTestCase(APITestCase):
for k in required_keys:
self.assertIn(k, item)
+ # Id should be prefixed with sha256: (#11645)
+ self.assertIn("sha256:",item['Id'])
+
def test_inspect(self):
r = requests.get(self.podman_url + "/v1.40/images/alpine/json")
self.assertEqual(r.status_code, 200, r.text)
@@ -59,6 +62,8 @@ class ImageTestCase(APITestCase):
for item in required_keys:
self.assertIn(item, image)
_ = parse(image["Created"])
+ # Id should be prefixed with sha256: (#11645)
+ self.assertIn("sha256:",image['Id'])
def test_delete(self):
r = requests.delete(self.podman_url + "/v1.40/images/alpine?force=true")
diff --git a/test/e2e/config/containers.conf b/test/e2e/config/containers.conf
index bbd712254..c33f32ab4 100644
--- a/test/e2e/config/containers.conf
+++ b/test/e2e/config/containers.conf
@@ -59,6 +59,7 @@ no_hosts=true
[engine]
network_cmd_options=["allow_host_loopback=true"]
+service_timeout=1234
# 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.
diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go
index f5e85e723..fac200c3c 100644
--- a/test/e2e/containers_conf_test.go
+++ b/test/e2e/containers_conf_test.go
@@ -444,4 +444,12 @@ var _ = Describe("Podman run", func() {
Expect(session).Should(Exit(0))
Expect(session.ErrorToString()).To(ContainSubstring("invalid image_copy_tmp_dir"))
})
+
+ It("podman system sevice --help shows (default 20)", func() {
+ SkipIfRemote("this test is only for local")
+ result := podmanTest.Podman([]string{"system", "service", "--help"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring("(default 1234)"))
+ })
})
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index fcda89fbc..0d5b9d52c 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -63,12 +63,6 @@ spec:
- -d
- "1.5"
env:
- - name: PATH
- value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- - name: TERM
- value: xterm
- - name: container
- value: podman
- name: HOSTNAME
value: label-pod
image: quay.io/libpod/alpine:latest
@@ -171,12 +165,6 @@ spec:
- -d
- "1.5"
env:
- - name: PATH
- value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- - name: TERM
- value: xterm
- - name: container
- value: podman
- name: HOSTNAME
value: label-pod
image: quay.io/libpod/alpine:latest
@@ -287,13 +275,7 @@ spec:
- {{.}}
{{ end }}
env:
- - name: PATH
- value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- - name: TERM
- value: xterm
- name: HOSTNAME
- - name: container
- value: podman
{{ range .Env }}
- name: {{ .Name }}
{{ if (eq .ValueFrom "configmap") }}
@@ -453,13 +435,7 @@ spec:
- {{.}}
{{ end }}
env:
- - name: PATH
- value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- - name: TERM
- value: xterm
- name: HOSTNAME
- - name: container
- value: podman
image: {{ .Image }}
name: {{ .Name }}
imagePullPolicy: {{ .PullPolicy }}
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index 7d40d36dd..76a05fa0f 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -881,6 +881,25 @@ ENTRYPOINT ["sleep","99999"]
ctr3 := podmanTest.Podman([]string{"run", "--pod", podName, ALPINE, "cat", "/tmp1/test"})
ctr3.WaitWithDefaultTimeout()
Expect(ctr3.OutputToString()).To(ContainSubstring("hello"))
+ })
+
+ It("podman pod create --device", func() {
+ SkipIfRootless("Cannot create devices in /dev in rootless mode")
+ Expect(os.MkdirAll("/dev/foodevdir", os.ModePerm)).To(BeNil())
+ defer os.RemoveAll("/dev/foodevdir")
+
+ mknod := SystemExec("mknod", []string{"/dev/foodevdir/null", "c", "1", "3"})
+ mknod.WaitWithDefaultTimeout()
+ Expect(mknod).Should(Exit(0))
+
+ podName := "testPod"
+ session := podmanTest.Podman([]string{"pod", "create", "--device", "/dev/foodevdir:/dev/bar", "--name", podName})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ session = podmanTest.Podman([]string{"run", "-q", "--pod", podName, ALPINE, "stat", "-c%t:%T", "/dev/bar/null"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal("1:3"))
})
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index aeb88e481..010885dd5 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -6,7 +6,6 @@ import (
"regexp"
"sort"
"strconv"
- "strings"
. "github.com/containers/podman/v3/test/utils"
"github.com/containers/storage/pkg/stringid"
@@ -187,7 +186,10 @@ var _ = Describe("Podman ps", func() {
result.WaitWithDefaultTimeout()
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(ContainSubstring("bravo"))
+
+ actual := result.OutputToString()
+ Expect(actual).To(ContainSubstring("bravo"))
+ Expect(actual).To(ContainSubstring("NAMES"))
})
It("podman ps --filter network=container:<id>", func() {
@@ -206,7 +208,9 @@ var _ = Describe("Podman ps", func() {
result.WaitWithDefaultTimeout()
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(ContainSubstring("second"))
+ actual := result.OutputToString()
+ Expect(actual).To(ContainSubstring("second"))
+ Expect(actual).ToNot(ContainSubstring("table"))
})
It("podman ps namespace flag", func() {
@@ -228,7 +232,7 @@ var _ = Describe("Podman ps", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
// it must contains `::` when some ns is null. If it works normally, it should be "$num1:$num2:$num3"
- Expect(result.OutputToString()).To(Not(ContainSubstring(`::`)))
+ Expect(result.OutputToString()).ToNot(ContainSubstring(`::`))
})
It("podman ps with no containers is valid json format", func() {
@@ -285,11 +289,14 @@ var _ = Describe("Podman ps", func() {
result := podmanTest.Podman([]string{"ps", "-a", "--format", "table {{.ID}} {{.Image}} {{.ImageID}} {{.Labels}}"})
result.WaitWithDefaultTimeout()
-
- Expect(result.OutputToStringArray()[0]).ToNot(ContainSubstring("table"))
- Expect(result.OutputToStringArray()[0]).ToNot(ContainSubstring("ImageID"))
- Expect(result.OutputToStringArray()[0]).To(ContainSubstring("alpine:latest"))
Expect(result).Should(Exit(0))
+
+ Expect(result.OutputToString()).ToNot(ContainSubstring("table"))
+
+ actual := result.OutputToStringArray()
+ Expect(actual[0]).To(ContainSubstring("CONTAINER ID"))
+ Expect(actual[0]).ToNot(ContainSubstring("ImageID"))
+ Expect(actual[1]).To(ContainSubstring("alpine:latest"))
})
It("podman ps ancestor filter flag", func() {
@@ -380,7 +387,9 @@ var _ = Describe("Podman ps", func() {
psFilter.WaitWithDefaultTimeout()
Expect(psFilter).Should(Exit(0))
- Expect(strings.Contains(psFilter.OutputToString(), ctrName)).To(BeFalse())
+ actual := psFilter.OutputToString()
+ Expect(actual).ToNot(ContainSubstring(ctrName))
+ Expect(actual).ToNot(ContainSubstring("NAMES"))
})
It("podman ps mutually exclusive flags", func() {
@@ -453,14 +462,13 @@ var _ = Describe("Podman ps", func() {
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"ps", "-a", "--sort=command", "--format", "{{.Command}}"})
-
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- sortedArr := session.OutputToStringArray()
+ Expect(session.OutputToString()).ToNot(ContainSubstring("COMMAND"))
+ sortedArr := session.OutputToStringArray()
Expect(sort.SliceIsSorted(sortedArr, func(i, j int) bool { return sortedArr[i] < sortedArr[j] })).To(BeTrue())
-
})
It("podman --pod", func() {
@@ -474,7 +482,7 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--no-trunc"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(Not(ContainSubstring(podid)))
+ Expect(session.OutputToString()).ToNot(ContainSubstring(podid))
session = podmanTest.Podman([]string{"ps", "--pod", "--no-trunc"})
session.WaitWithDefaultTimeout()
@@ -510,7 +518,11 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--format", "{{.Ports}}"})
session.WaitWithDefaultTimeout()
- Expect(session.OutputToString()).To(ContainSubstring("0.0.0.0:2000-2006"))
+ Expect(session).To(Exit(0))
+
+ actual := session.OutputToString()
+ Expect(actual).To(ContainSubstring("0.0.0.0:2000-2006"))
+ Expect(actual).ToNot(ContainSubstring("PORT"))
})
It("podman ps test with invalid port range", func() {
@@ -628,7 +640,10 @@ var _ = Describe("Podman ps", func() {
result := podmanTest.Podman([]string{"ps", "-a", "--format", "{{.RunningFor}}"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(ContainSubstring("ago"))
+
+ actual := result.OutputToString()
+ Expect(actual).To(ContainSubstring("ago"))
+ Expect(actual).ToNot(ContainSubstring("RUNNING FOR"))
})
It("podman ps filter test", func() {
@@ -823,8 +838,9 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--all", "--no-trunc", "--filter", "network=" + net})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(ContainSubstring(ctrWithNet))
- Expect(session.OutputToString()).To(Not(ContainSubstring(ctrWithoutNet)))
+ actual := session.OutputToString()
+ Expect(actual).To(ContainSubstring(ctrWithNet))
+ Expect(actual).ToNot(ContainSubstring(ctrWithoutNet))
})
It("podman ps --format networks", func() {
@@ -835,12 +851,15 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--all", "--format", "{{ .Networks }}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+
+ actual := session.OutputToString()
+ Expect(actual).ToNot(ContainSubstring("NETWORKS"))
if isRootless() {
// rootless container don't have a network by default
- Expect(session.OutputToString()).To(Equal(""))
+ Expect(actual).To(BeEmpty())
} else {
// default network name is podman
- Expect(session.OutputToString()).To(Equal("podman"))
+ Expect(actual).To(Equal("podman"))
}
net1 := stringid.GenerateNonCryptoID()
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 59937b6c0..4264e1efe 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -242,6 +242,39 @@ var _ = Describe("Podman run with volumes", func() {
Expect(session).Should(Exit(0))
})
+ It("podman support overlay on named volume", func() {
+ SkipIfRemote("Overlay volumes only work locally")
+ if os.Getenv("container") != "" {
+ Skip("Overlay mounts not supported when running in a container")
+ }
+ if rootless.IsRootless() {
+ if _, err := exec.LookPath("fuse-overlayfs"); err != nil {
+ Skip("Fuse-Overlayfs required for rootless overlay mount test")
+ }
+ }
+ session := podmanTest.Podman([]string{"volume", "create", "myvolume"})
+ session.WaitWithDefaultTimeout()
+ volName := session.OutputToString()
+ Expect(session).Should(Exit(0))
+
+ // create file on actual volume
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data", ALPINE, "sh", "-c", "echo hello >> " + "/data/test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // create file on overlayed volume
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O", ALPINE, "sh", "-c", "echo hello >> " + "/data/overlayed"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // volume should contain only `test` not `overlayed`
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data", ALPINE, "sh", "-c", "ls /data"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.OutputToString()).To(Not(ContainSubstring("overlayed")))
+ Expect(session.OutputToString()).To(ContainSubstring("test"))
+
+ })
+
It("podman run with noexec can't exec", func() {
session := podmanTest.Podman([]string{"run", "--rm", "-v", "/bin:/hostbin:noexec", ALPINE, "/hostbin/ls", "/"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/top_test.go b/test/e2e/top_test.go
index 3cf6244b6..93c4f3f12 100644
--- a/test/e2e/top_test.go
+++ b/test/e2e/top_test.go
@@ -73,6 +73,12 @@ var _ = Describe("Podman top", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
+
+ // Just a smoke test since groups may change over time.
+ result = podmanTest.Podman([]string{"container", "top", "test", "groups", "hgroups"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
})
It("podman top with options", func() {
diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats
index 963c89281..888c075b8 100644
--- a/test/system/001-basic.bats
+++ b/test/system/001-basic.bats
@@ -57,6 +57,9 @@ function setup() {
# Now untag the digest reference again.
run_podman untag $IMAGE $IMAGE@$digest
+
+ # Make sure the original image is still present (#11557).
+ run_podman image exists $IMAGE
}
# PR #7212: allow --remote anywhere before subcommand, not just as 1st flag
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index 97ea0f528..f2f9bf4d4 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -183,4 +183,16 @@ verify_iid_and_name() {
run_podman rmi -f $img1 $img2
}
+@test "podman save --oci-accept-uncompressed-layers" {
+ archive=$PODMAN_TMPDIR/myimage-$(random_string 8).tar
+ untar=$PODMAN_TMPDIR/myuntar-$(random_string 8)
+ mkdir -p $untar
+
+ # Create a tarball, unpack it and make sure the layers are uncompressed.
+ run_podman save -o $archive --format oci-archive --uncompressed $IMAGE
+ run tar -C $untar -xvf $archive
+ run file $untar/blobs/sha256/*
+ is "$output" ".*POSIX tar archive" "layers are uncompressed"
+}
+
# vim: filetype=sh
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 80af7fb7c..bfefc58ec 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -19,7 +19,7 @@ import (
)
var (
- defaultWaitTimeout = 90
+ DefaultWaitTimeout = 90
OSReleasePath = "/etc/os-release"
ProcessOneCgroupPath = "/proc/1/cgroup"
)
@@ -317,15 +317,20 @@ func (s *PodmanSession) IsJSONOutputValid() bool {
return true
}
-// WaitWithDefaultTimeout waits for process finished with defaultWaitTimeout
+// WaitWithDefaultTimeout waits for process finished with DefaultWaitTimeout
func (s *PodmanSession) WaitWithDefaultTimeout() {
- Eventually(s, defaultWaitTimeout).Should(Exit())
+ s.WaitWithTimeout(DefaultWaitTimeout)
+}
+
+// WaitWithTimeout waits for process finished with DefaultWaitTimeout
+func (s *PodmanSession) WaitWithTimeout(timeout int) {
+ Eventually(s, timeout).Should(Exit())
os.Stdout.Sync()
os.Stderr.Sync()
fmt.Println("output:", s.OutputToString())
}
-// CreateTempDirinTempDir create a temp dir with prefix podman_test
+// CreateTempDirInTempDir create a temp dir with prefix podman_test
func CreateTempDirInTempDir() (string, error) {
return ioutil.TempDir("", "podman_test")
}
@@ -337,7 +342,7 @@ func SystemExec(command string, args []string) *PodmanSession {
if err != nil {
Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " ")))
}
- session.Wait(defaultWaitTimeout)
+ session.Wait(DefaultWaitTimeout)
return &PodmanSession{session}
}
diff --git a/test/version/main.go b/test/version/main.go
new file mode 100644
index 000000000..2a751de78
--- /dev/null
+++ b/test/version/main.go
@@ -0,0 +1,11 @@
+package main
+
+import (
+ "fmt"
+
+ "github.com/containers/podman/v3/version"
+)
+
+func main() {
+ fmt.Printf(version.Version.String())
+}
diff --git a/utils/utils.go b/utils/utils.go
index 185ac4865..b08630d2f 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -12,6 +12,7 @@ import (
"sync"
"github.com/containers/podman/v3/libpod/define"
+ "github.com/containers/podman/v3/pkg/cgroups"
"github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -190,7 +191,11 @@ func moveProcessToScope(pidPath, slice, scope string) error {
func MovePauseProcessToScope(pausePidPath string) {
err := moveProcessToScope(pausePidPath, "user.slice", "podman-pause.scope")
if err != nil {
- if RunsOnSystemd() {
+ unified, err := cgroups.IsCgroup2UnifiedMode()
+ if err != nil {
+ logrus.Warnf("Failed to detect if running with cgroup unified: %v", err)
+ }
+ if RunsOnSystemd() && unified {
logrus.Warnf("Failed to add pause process to systemd sandbox cgroup: %v", err)
} else {
logrus.Debugf("Failed to add pause process to systemd sandbox cgroup: %v", err)
diff --git a/utils/utils_supported.go b/utils/utils_supported.go
index ebc870d26..1404e3194 100644
--- a/utils/utils_supported.go
+++ b/utils/utils_supported.go
@@ -47,10 +47,10 @@ func RunUnderSystemdScope(pid int, slice string, unitName string) error {
// On errors check if the cgroup already exists, if it does move the process there
if props, err := conn.GetUnitTypeProperties(unitName, "Scope"); err == nil {
if cgroup, ok := props["ControlGroup"].(string); ok && cgroup != "" {
- if err := moveUnderCgroup(cgroup, "", []uint32{uint32(pid)}); err != nil {
- return err
+ if err := moveUnderCgroup(cgroup, "", []uint32{uint32(pid)}); err == nil {
+ return nil
}
- return nil
+ // On errors return the original error message we got from StartTransientUnit.
}
}
return err
diff --git a/vendor/github.com/checkpoint-restore/checkpointctl/lib/metadata.go b/vendor/github.com/checkpoint-restore/checkpointctl/lib/metadata.go
index 1c74903ad..7c59ed23f 100644
--- a/vendor/github.com/checkpoint-restore/checkpointctl/lib/metadata.go
+++ b/vendor/github.com/checkpoint-restore/checkpointctl/lib/metadata.go
@@ -6,12 +6,10 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
- "net"
"os"
"path/filepath"
"time"
- cnitypes "github.com/containernetworking/cni/pkg/types/current"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@@ -91,16 +89,73 @@ type CheckpointedPodOptions struct {
ProcessLabel string `json:"processLabel"`
}
-func DetectCheckpointArchiveType(checkpointDirectory string) (CheckpointType, error) {
- _, err := os.Stat(filepath.Join(checkpointDirectory, CheckpointedPodsFile))
+// This is metadata stored inside of Pod checkpoint archive
+type PodSandboxConfig struct {
+ Metadata SandboxMetadta `json:"metadata"`
+ Hostname string `json:"hostname"`
+}
+
+type SandboxMetadta struct {
+ Name string `json:"name"`
+ UID string `json:"uid"`
+ Namespace string `json:"namespace"`
+}
+
+func checkForFile(checkpointDirectory, file string) (bool, error) {
+ _, err := os.Stat(filepath.Join(checkpointDirectory, file))
if err != nil && !os.IsNotExist(err) {
- return Unknown, errors.Wrapf(err, "Failed to access %q\n", CheckpointedPodsFile)
+ return false, errors.Wrapf(err, "Failed to access %q\n", file)
+ }
+ if os.IsNotExist(err) {
+ return false, nil
+ }
+
+ return true, nil
+}
+
+func DetectCheckpointArchiveType(checkpointDirectory string) (CheckpointType, error) {
+ kubelet, err := checkForFile(checkpointDirectory, CheckpointedPodsFile)
+ if os.IsNotExist(err) {
+ return Unknown, err
+ }
+
+ container, err := checkForFile(checkpointDirectory, ConfigDumpFile)
+ if os.IsNotExist(err) {
+ return Unknown, err
}
+
+ pod, err := checkForFile(checkpointDirectory, PodDumpFile)
if os.IsNotExist(err) {
+ return Unknown, err
+ }
+
+ if pod && !container && !kubelet {
+ return Pod, nil
+ }
+
+ if !pod && container && !kubelet {
return Container, nil
}
- return Kubelet, nil
+ if !pod && !container && kubelet {
+ return Kubelet, nil
+ }
+
+ return Unknown, nil
+}
+
+func ReadPodCheckpointDumpFile(checkpointDirectory string) (*PodSandboxConfig, string, error) {
+ var podSandboxConfig PodSandboxConfig
+ podDumpFile, err := ReadJSONFile(&podSandboxConfig, checkpointDirectory, PodDumpFile)
+
+ return &podSandboxConfig, podDumpFile, err
+}
+
+func ReadPodCheckpointOptionsFile(checkpointDirectory string) (*CheckpointedPodOptions, string, error) {
+ var checkpointedPodOptions CheckpointedPodOptions
+ podOptionsFile, err := ReadJSONFile(&checkpointedPodOptions, checkpointDirectory, PodOptionsFile)
+
+ return &checkpointedPodOptions, podOptionsFile, err
}
func ReadContainerCheckpointSpecDump(checkpointDirectory string) (*spec.Spec, string, error) {
@@ -124,13 +179,6 @@ func ReadContainerCheckpointDeletedFiles(checkpointDirectory string) ([]string,
return deletedFiles, deletedFilesFile, err
}
-func ReadContainerCheckpointNetworkStatus(checkpointDirectory string) ([]*cnitypes.Result, string, error) {
- var networkStatus []*cnitypes.Result
- networkStatusFile, err := ReadJSONFile(&networkStatus, checkpointDirectory, NetworkStatusFile)
-
- return networkStatus, networkStatusFile, err
-}
-
func ReadKubeletCheckpoints(checkpointsDirectory string) (*CheckpointMetadata, string, error) {
var checkpointMetadata CheckpointMetadata
checkpointMetadataPath, err := ReadJSONFile(&checkpointMetadata, checkpointsDirectory, CheckpointedPodsFile)
@@ -138,40 +186,6 @@ func ReadKubeletCheckpoints(checkpointsDirectory string) (*CheckpointMetadata, s
return &checkpointMetadata, checkpointMetadataPath, err
}
-func GetIPFromNetworkStatus(networkStatus []*cnitypes.Result) net.IP {
- if len(networkStatus) == 0 {
- return nil
- }
- // Take the first IP address
- if len(networkStatus[0].IPs) == 0 {
- return nil
- }
- IP := networkStatus[0].IPs[0].Address.IP
-
- return IP
-}
-
-func GetMACFromNetworkStatus(networkStatus []*cnitypes.Result) net.HardwareAddr {
- if len(networkStatus) == 0 {
- return nil
- }
- // Take the first device with a defined sandbox
- if len(networkStatus[0].Interfaces) == 0 {
- return nil
- }
- var MAC net.HardwareAddr
- MAC = nil
- for _, n := range networkStatus[0].Interfaces {
- if n.Sandbox != "" {
- MAC, _ = net.ParseMAC(n.Mac)
-
- break
- }
- }
-
- return MAC
-}
-
// WriteJSONFile marshalls and writes the given data to a JSON file
func WriteJSONFile(v interface{}, dir, file string) (string, error) {
fileJSON, err := json.MarshalIndent(v, "", " ")
diff --git a/vendor/github.com/containernetworking/cni/libcni/api.go b/vendor/github.com/containernetworking/cni/libcni/api.go
index 7e52bd838..0d82a2dd3 100644
--- a/vendor/github.com/containernetworking/cni/libcni/api.go
+++ b/vendor/github.com/containernetworking/cni/libcni/api.go
@@ -14,6 +14,12 @@
package libcni
+// Note this is the actual implementation of the CNI specification, which
+// is reflected in the https://github.com/containernetworking/cni/blob/master/SPEC.md file
+// it is typically bundled into runtime providers (i.e. containerd or cri-o would use this
+// before calling runc or hcsshim). It is also bundled into CNI providers as well, for example,
+// to add an IP to a container, to parse the configuration of the CNI and so on.
+
import (
"context"
"encoding/json"
@@ -25,6 +31,7 @@ import (
"github.com/containernetworking/cni/pkg/invoke"
"github.com/containernetworking/cni/pkg/types"
+ "github.com/containernetworking/cni/pkg/types/create"
"github.com/containernetworking/cni/pkg/utils"
"github.com/containernetworking/cni/pkg/version"
)
@@ -278,7 +285,7 @@ func (c *CNIConfig) getCachedConfig(netName string, rt *RuntimeConf) ([]byte, *R
unmarshaled := cachedInfo{}
if err := json.Unmarshal(bytes, &unmarshaled); err != nil {
- return nil, nil, fmt.Errorf("failed to unmarshal cached network %q config: %v", netName, err)
+ return nil, nil, fmt.Errorf("failed to unmarshal cached network %q config: %w", netName, err)
}
if unmarshaled.Kind != CNICacheV1 {
return nil, nil, fmt.Errorf("read cached network %q config has wrong kind: %v", netName, unmarshaled.Kind)
@@ -304,15 +311,8 @@ func (c *CNIConfig) getLegacyCachedResult(netName, cniVersion string, rt *Runtim
return nil, nil
}
- // Read the version of the cached result
- decoder := version.ConfigDecoder{}
- resultCniVersion, err := decoder.Decode(data)
- if err != nil {
- return nil, err
- }
-
- // Ensure we can understand the result
- result, err := version.NewResult(resultCniVersion, data)
+ // Load the cached result
+ result, err := create.CreateFromBytes(data)
if err != nil {
return nil, err
}
@@ -322,10 +322,10 @@ func (c *CNIConfig) getLegacyCachedResult(netName, cniVersion string, rt *Runtim
// should match the config version unless the config was changed
// while the container was running.
result, err = result.GetAsVersion(cniVersion)
- if err != nil && resultCniVersion != cniVersion {
- return nil, fmt.Errorf("failed to convert cached result version %q to config version %q: %v", resultCniVersion, cniVersion, err)
+ if err != nil {
+ return nil, fmt.Errorf("failed to convert cached result to config version %q: %w", cniVersion, err)
}
- return result, err
+ return result, nil
}
func (c *CNIConfig) getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) {
@@ -346,18 +346,11 @@ func (c *CNIConfig) getCachedResult(netName, cniVersion string, rt *RuntimeConf)
newBytes, err := json.Marshal(&cachedInfo.RawResult)
if err != nil {
- return nil, fmt.Errorf("failed to marshal cached network %q config: %v", netName, err)
+ return nil, fmt.Errorf("failed to marshal cached network %q config: %w", netName, err)
}
- // Read the version of the cached result
- decoder := version.ConfigDecoder{}
- resultCniVersion, err := decoder.Decode(newBytes)
- if err != nil {
- return nil, err
- }
-
- // Ensure we can understand the result
- result, err := version.NewResult(resultCniVersion, newBytes)
+ // Load the cached result
+ result, err := create.CreateFromBytes(newBytes)
if err != nil {
return nil, err
}
@@ -367,10 +360,10 @@ func (c *CNIConfig) getCachedResult(netName, cniVersion string, rt *RuntimeConf)
// should match the config version unless the config was changed
// while the container was running.
result, err = result.GetAsVersion(cniVersion)
- if err != nil && resultCniVersion != cniVersion {
- return nil, fmt.Errorf("failed to convert cached result version %q to config version %q: %v", resultCniVersion, cniVersion, err)
+ if err != nil {
+ return nil, fmt.Errorf("failed to convert cached result to config version %q: %w", cniVersion, err)
}
- return result, err
+ return result, nil
}
// GetNetworkListCachedResult returns the cached Result of the previous
@@ -428,12 +421,12 @@ func (c *CNIConfig) AddNetworkList(ctx context.Context, list *NetworkConfigList,
for _, net := range list.Plugins {
result, err = c.addNetwork(ctx, list.Name, list.CNIVersion, net, result, rt)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("plugin %s failed (add): %w", pluginDescription(net.Network), err)
}
}
if err = c.cacheAdd(result, list.Bytes, list.Name, rt); err != nil {
- return nil, fmt.Errorf("failed to set network %q cached result: %v", list.Name, err)
+ return nil, fmt.Errorf("failed to set network %q cached result: %w", list.Name, err)
}
return result, nil
@@ -469,7 +462,7 @@ func (c *CNIConfig) CheckNetworkList(ctx context.Context, list *NetworkConfigLis
cachedResult, err := c.getCachedResult(list.Name, list.CNIVersion, rt)
if err != nil {
- return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
+ return fmt.Errorf("failed to get network %q cached result: %w", list.Name, err)
}
for _, net := range list.Plugins {
@@ -506,14 +499,14 @@ func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList,
} else if gtet {
cachedResult, err = c.getCachedResult(list.Name, list.CNIVersion, rt)
if err != nil {
- return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
+ return fmt.Errorf("failed to get network %q cached result: %w", list.Name, err)
}
}
for i := len(list.Plugins) - 1; i >= 0; i-- {
net := list.Plugins[i]
if err := c.delNetwork(ctx, list.Name, list.CNIVersion, net, cachedResult, rt); err != nil {
- return err
+ return fmt.Errorf("plugin %s failed (delete): %w", pluginDescription(net.Network), err)
}
}
_ = c.cacheDel(list.Name, rt)
@@ -521,6 +514,19 @@ func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList,
return nil
}
+func pluginDescription(net *types.NetConf) string {
+ if net == nil {
+ return "<missing>"
+ }
+ pluginType := net.Type
+ out := fmt.Sprintf("type=%q", pluginType)
+ name := net.Name
+ if name != "" {
+ out += fmt.Sprintf(" name=%q", name)
+ }
+ return out
+}
+
// AddNetwork executes the plugin with the ADD command
func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
result, err := c.addNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, nil, rt)
@@ -529,7 +535,7 @@ func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *Runt
}
if err = c.cacheAdd(result, net.Bytes, net.Network.Name, rt); err != nil {
- return nil, fmt.Errorf("failed to set network %q cached result: %v", net.Network.Name, err)
+ return nil, fmt.Errorf("failed to set network %q cached result: %w", net.Network.Name, err)
}
return result, nil
@@ -546,7 +552,7 @@ func (c *CNIConfig) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *Ru
cachedResult, err := c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
if err != nil {
- return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err)
+ return fmt.Errorf("failed to get network %q cached result: %w", net.Network.Name, err)
}
return c.checkNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt)
}
@@ -561,7 +567,7 @@ func (c *CNIConfig) DelNetwork(ctx context.Context, net *NetworkConfig, rt *Runt
} else if gtet {
cachedResult, err = c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
if err != nil {
- return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err)
+ return fmt.Errorf("failed to get network %q cached result: %w", net.Network.Name, err)
}
}
diff --git a/vendor/github.com/containernetworking/cni/libcni/conf.go b/vendor/github.com/containernetworking/cni/libcni/conf.go
index d8920cf8c..d28135ff3 100644
--- a/vendor/github.com/containernetworking/cni/libcni/conf.go
+++ b/vendor/github.com/containernetworking/cni/libcni/conf.go
@@ -43,7 +43,7 @@ func (e NoConfigsFoundError) Error() string {
func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
conf := &NetworkConfig{Bytes: bytes}
if err := json.Unmarshal(bytes, &conf.Network); err != nil {
- return nil, fmt.Errorf("error parsing configuration: %s", err)
+ return nil, fmt.Errorf("error parsing configuration: %w", err)
}
if conf.Network.Type == "" {
return nil, fmt.Errorf("error parsing configuration: missing 'type'")
@@ -54,7 +54,7 @@ func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
func ConfFromFile(filename string) (*NetworkConfig, error) {
bytes, err := ioutil.ReadFile(filename)
if err != nil {
- return nil, fmt.Errorf("error reading %s: %s", filename, err)
+ return nil, fmt.Errorf("error reading %s: %w", filename, err)
}
return ConfFromBytes(bytes)
}
@@ -62,7 +62,7 @@ func ConfFromFile(filename string) (*NetworkConfig, error) {
func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
rawList := make(map[string]interface{})
if err := json.Unmarshal(bytes, &rawList); err != nil {
- return nil, fmt.Errorf("error parsing configuration list: %s", err)
+ return nil, fmt.Errorf("error parsing configuration list: %w", err)
}
rawName, ok := rawList["name"]
@@ -114,11 +114,11 @@ func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
for i, conf := range plugins {
newBytes, err := json.Marshal(conf)
if err != nil {
- return nil, fmt.Errorf("failed to marshal plugin config %d: %v", i, err)
+ return nil, fmt.Errorf("failed to marshal plugin config %d: %w", i, err)
}
netConf, err := ConfFromBytes(newBytes)
if err != nil {
- return nil, fmt.Errorf("failed to parse plugin config %d: %v", i, err)
+ return nil, fmt.Errorf("failed to parse plugin config %d: %w", i, err)
}
list.Plugins = append(list.Plugins, netConf)
}
@@ -129,7 +129,7 @@ func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
func ConfListFromFile(filename string) (*NetworkConfigList, error) {
bytes, err := ioutil.ReadFile(filename)
if err != nil {
- return nil, fmt.Errorf("error reading %s: %s", filename, err)
+ return nil, fmt.Errorf("error reading %s: %w", filename, err)
}
return ConfListFromBytes(bytes)
}
@@ -218,7 +218,7 @@ func InjectConf(original *NetworkConfig, newValues map[string]interface{}) (*Net
config := make(map[string]interface{})
err := json.Unmarshal(original.Bytes, &config)
if err != nil {
- return nil, fmt.Errorf("unmarshal existing network bytes: %s", err)
+ return nil, fmt.Errorf("unmarshal existing network bytes: %w", err)
}
for key, value := range newValues {
diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
index 8e6d30b82..e79bffe63 100644
--- a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
+++ b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
@@ -20,6 +20,7 @@ import (
"os"
"github.com/containernetworking/cni/pkg/types"
+ "github.com/containernetworking/cni/pkg/types/create"
"github.com/containernetworking/cni/pkg/version"
)
@@ -83,14 +84,7 @@ func ExecPluginWithResult(ctx context.Context, pluginPath string, netconf []byte
return nil, err
}
- // Plugin must return result in same version as specified in netconf
- versionDecoder := &version.ConfigDecoder{}
- confVersion, err := versionDecoder.Decode(netconf)
- if err != nil {
- return nil, err
- }
-
- return version.NewResult(confVersion, stdoutBytes)
+ return create.CreateFromBytes(stdoutBytes)
}
func ExecPluginWithoutResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) error {
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go
index 36f31678a..99b151ff2 100644
--- a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go
+++ b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go
@@ -22,25 +22,47 @@ import (
"os"
"github.com/containernetworking/cni/pkg/types"
+ convert "github.com/containernetworking/cni/pkg/types/internal"
)
const ImplementedSpecVersion string = "0.2.0"
-var SupportedVersions = []string{"", "0.1.0", ImplementedSpecVersion}
+var supportedVersions = []string{"", "0.1.0", ImplementedSpecVersion}
+
+// Register converters for all versions less than the implemented spec version
+func init() {
+ convert.RegisterConverter("0.1.0", []string{ImplementedSpecVersion}, convertFrom010)
+ convert.RegisterConverter(ImplementedSpecVersion, []string{"0.1.0"}, convertTo010)
+
+ // Creator
+ convert.RegisterCreator(supportedVersions, NewResult)
+}
// Compatibility types for CNI version 0.1.0 and 0.2.0
+// NewResult creates a new Result object from JSON data. The JSON data
+// must be compatible with the CNI versions implemented by this type.
func NewResult(data []byte) (types.Result, error) {
result := &Result{}
if err := json.Unmarshal(data, result); err != nil {
return nil, err
}
- return result, nil
+ for _, v := range supportedVersions {
+ if result.CNIVersion == v {
+ if result.CNIVersion == "" {
+ result.CNIVersion = "0.1.0"
+ }
+ return result, nil
+ }
+ }
+ return nil, fmt.Errorf("result type supports %v but unmarshalled CNIVersion is %q",
+ supportedVersions, result.CNIVersion)
}
+// GetResult converts the given Result object to the ImplementedSpecVersion
+// and returns the concrete type or an error
func GetResult(r types.Result) (*Result, error) {
- // We expect version 0.1.0/0.2.0 results
- result020, err := r.GetAsVersion(ImplementedSpecVersion)
+ result020, err := convert.Convert(r, ImplementedSpecVersion)
if err != nil {
return nil, err
}
@@ -51,6 +73,32 @@ func GetResult(r types.Result) (*Result, error) {
return result, nil
}
+func convertFrom010(from types.Result, toVersion string) (types.Result, error) {
+ if toVersion != "0.2.0" {
+ panic("only converts to version 0.2.0")
+ }
+ fromResult := from.(*Result)
+ return &Result{
+ CNIVersion: ImplementedSpecVersion,
+ IP4: fromResult.IP4.Copy(),
+ IP6: fromResult.IP6.Copy(),
+ DNS: *fromResult.DNS.Copy(),
+ }, nil
+}
+
+func convertTo010(from types.Result, toVersion string) (types.Result, error) {
+ if toVersion != "0.1.0" {
+ panic("only converts to version 0.1.0")
+ }
+ fromResult := from.(*Result)
+ return &Result{
+ CNIVersion: "0.1.0",
+ IP4: fromResult.IP4.Copy(),
+ IP6: fromResult.IP6.Copy(),
+ DNS: *fromResult.DNS.Copy(),
+ }, nil
+}
+
// Result is what gets returned from the plugin (via stdout) to the caller
type Result struct {
CNIVersion string `json:"cniVersion,omitempty"`
@@ -60,17 +108,16 @@ type Result struct {
}
func (r *Result) Version() string {
- return ImplementedSpecVersion
+ return r.CNIVersion
}
func (r *Result) GetAsVersion(version string) (types.Result, error) {
- for _, supportedVersion := range SupportedVersions {
- if version == supportedVersion {
- r.CNIVersion = version
- return r, nil
- }
+ // If the creator of the result did not set the CNIVersion, assume it
+ // should be the highest spec version implemented by this Result
+ if r.CNIVersion == "" {
+ r.CNIVersion = ImplementedSpecVersion
}
- return nil, fmt.Errorf("cannot convert version %q to %s", SupportedVersions, version)
+ return convert.Convert(r, version)
}
func (r *Result) Print() error {
@@ -93,6 +140,22 @@ type IPConfig struct {
Routes []types.Route
}
+func (i *IPConfig) Copy() *IPConfig {
+ if i == nil {
+ return nil
+ }
+
+ var routes []types.Route
+ for _, fromRoute := range i.Routes {
+ routes = append(routes, *fromRoute.Copy())
+ }
+ return &IPConfig{
+ IP: i.IP,
+ Gateway: i.Gateway,
+ Routes: routes,
+ }
+}
+
// net.IPNet is not JSON (un)marshallable so this duality is needed
// for our custom IPNet type
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/040/types.go b/vendor/github.com/containernetworking/cni/pkg/types/040/types.go
new file mode 100644
index 000000000..3633b0eaa
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/040/types.go
@@ -0,0 +1,306 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types040
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net"
+ "os"
+
+ "github.com/containernetworking/cni/pkg/types"
+ types020 "github.com/containernetworking/cni/pkg/types/020"
+ convert "github.com/containernetworking/cni/pkg/types/internal"
+)
+
+const ImplementedSpecVersion string = "0.4.0"
+
+var supportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion}
+
+// Register converters for all versions less than the implemented spec version
+func init() {
+ // Up-converters
+ convert.RegisterConverter("0.1.0", supportedVersions, convertFrom02x)
+ convert.RegisterConverter("0.2.0", supportedVersions, convertFrom02x)
+ convert.RegisterConverter("0.3.0", supportedVersions, convertInternal)
+ convert.RegisterConverter("0.3.1", supportedVersions, convertInternal)
+
+ // Down-converters
+ convert.RegisterConverter("0.4.0", []string{"0.3.0", "0.3.1"}, convertInternal)
+ convert.RegisterConverter("0.4.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
+ convert.RegisterConverter("0.3.1", []string{"0.1.0", "0.2.0"}, convertTo02x)
+ convert.RegisterConverter("0.3.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
+
+ // Creator
+ convert.RegisterCreator(supportedVersions, NewResult)
+}
+
+func NewResult(data []byte) (types.Result, error) {
+ result := &Result{}
+ if err := json.Unmarshal(data, result); err != nil {
+ return nil, err
+ }
+ for _, v := range supportedVersions {
+ if result.CNIVersion == v {
+ return result, nil
+ }
+ }
+ return nil, fmt.Errorf("result type supports %v but unmarshalled CNIVersion is %q",
+ supportedVersions, result.CNIVersion)
+}
+
+func GetResult(r types.Result) (*Result, error) {
+ resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ result, ok := resultCurrent.(*Result)
+ if !ok {
+ return nil, fmt.Errorf("failed to convert result")
+ }
+ return result, nil
+}
+
+func NewResultFromResult(result types.Result) (*Result, error) {
+ newResult, err := convert.Convert(result, ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ return newResult.(*Result), nil
+}
+
+// Result is what gets returned from the plugin (via stdout) to the caller
+type Result struct {
+ CNIVersion string `json:"cniVersion,omitempty"`
+ Interfaces []*Interface `json:"interfaces,omitempty"`
+ IPs []*IPConfig `json:"ips,omitempty"`
+ Routes []*types.Route `json:"routes,omitempty"`
+ DNS types.DNS `json:"dns,omitempty"`
+}
+
+func convert020IPConfig(from *types020.IPConfig, ipVersion string) *IPConfig {
+ return &IPConfig{
+ Version: ipVersion,
+ Address: from.IP,
+ Gateway: from.Gateway,
+ }
+}
+
+func convertFrom02x(from types.Result, toVersion string) (types.Result, error) {
+ fromResult := from.(*types020.Result)
+ toResult := &Result{
+ CNIVersion: toVersion,
+ DNS: *fromResult.DNS.Copy(),
+ Routes: []*types.Route{},
+ }
+ if fromResult.IP4 != nil {
+ toResult.IPs = append(toResult.IPs, convert020IPConfig(fromResult.IP4, "4"))
+ for _, fromRoute := range fromResult.IP4.Routes {
+ toResult.Routes = append(toResult.Routes, fromRoute.Copy())
+ }
+ }
+
+ if fromResult.IP6 != nil {
+ toResult.IPs = append(toResult.IPs, convert020IPConfig(fromResult.IP6, "6"))
+ for _, fromRoute := range fromResult.IP6.Routes {
+ toResult.Routes = append(toResult.Routes, fromRoute.Copy())
+ }
+ }
+
+ return toResult, nil
+}
+
+func convertInternal(from types.Result, toVersion string) (types.Result, error) {
+ fromResult := from.(*Result)
+ toResult := &Result{
+ CNIVersion: toVersion,
+ DNS: *fromResult.DNS.Copy(),
+ Routes: []*types.Route{},
+ }
+ for _, fromIntf := range fromResult.Interfaces {
+ toResult.Interfaces = append(toResult.Interfaces, fromIntf.Copy())
+ }
+ for _, fromIPC := range fromResult.IPs {
+ toResult.IPs = append(toResult.IPs, fromIPC.Copy())
+ }
+ for _, fromRoute := range fromResult.Routes {
+ toResult.Routes = append(toResult.Routes, fromRoute.Copy())
+ }
+ return toResult, nil
+}
+
+func convertTo02x(from types.Result, toVersion string) (types.Result, error) {
+ fromResult := from.(*Result)
+ toResult := &types020.Result{
+ CNIVersion: toVersion,
+ DNS: *fromResult.DNS.Copy(),
+ }
+
+ for _, fromIP := range fromResult.IPs {
+ // Only convert the first IP address of each version as 0.2.0
+ // and earlier cannot handle multiple IP addresses
+ if fromIP.Version == "4" && toResult.IP4 == nil {
+ toResult.IP4 = &types020.IPConfig{
+ IP: fromIP.Address,
+ Gateway: fromIP.Gateway,
+ }
+ } else if fromIP.Version == "6" && toResult.IP6 == nil {
+ toResult.IP6 = &types020.IPConfig{
+ IP: fromIP.Address,
+ Gateway: fromIP.Gateway,
+ }
+ }
+ if toResult.IP4 != nil && toResult.IP6 != nil {
+ break
+ }
+ }
+
+ for _, fromRoute := range fromResult.Routes {
+ is4 := fromRoute.Dst.IP.To4() != nil
+ if is4 && toResult.IP4 != nil {
+ toResult.IP4.Routes = append(toResult.IP4.Routes, types.Route{
+ Dst: fromRoute.Dst,
+ GW: fromRoute.GW,
+ })
+ } else if !is4 && toResult.IP6 != nil {
+ toResult.IP6.Routes = append(toResult.IP6.Routes, types.Route{
+ Dst: fromRoute.Dst,
+ GW: fromRoute.GW,
+ })
+ }
+ }
+
+ // 0.2.0 and earlier require at least one IP address in the Result
+ if toResult.IP4 == nil && toResult.IP6 == nil {
+ return nil, fmt.Errorf("cannot convert: no valid IP addresses")
+ }
+
+ return toResult, nil
+}
+
+func (r *Result) Version() string {
+ return r.CNIVersion
+}
+
+func (r *Result) GetAsVersion(version string) (types.Result, error) {
+ // If the creator of the result did not set the CNIVersion, assume it
+ // should be the highest spec version implemented by this Result
+ if r.CNIVersion == "" {
+ r.CNIVersion = ImplementedSpecVersion
+ }
+ return convert.Convert(r, version)
+}
+
+func (r *Result) Print() error {
+ return r.PrintTo(os.Stdout)
+}
+
+func (r *Result) PrintTo(writer io.Writer) error {
+ data, err := json.MarshalIndent(r, "", " ")
+ if err != nil {
+ return err
+ }
+ _, err = writer.Write(data)
+ return err
+}
+
+// Interface contains values about the created interfaces
+type Interface struct {
+ Name string `json:"name"`
+ Mac string `json:"mac,omitempty"`
+ Sandbox string `json:"sandbox,omitempty"`
+}
+
+func (i *Interface) String() string {
+ return fmt.Sprintf("%+v", *i)
+}
+
+func (i *Interface) Copy() *Interface {
+ if i == nil {
+ return nil
+ }
+ newIntf := *i
+ return &newIntf
+}
+
+// Int returns a pointer to the int value passed in. Used to
+// set the IPConfig.Interface field.
+func Int(v int) *int {
+ return &v
+}
+
+// IPConfig contains values necessary to configure an IP address on an interface
+type IPConfig struct {
+ // IP version, either "4" or "6"
+ Version string
+ // Index into Result structs Interfaces list
+ Interface *int
+ Address net.IPNet
+ Gateway net.IP
+}
+
+func (i *IPConfig) String() string {
+ return fmt.Sprintf("%+v", *i)
+}
+
+func (i *IPConfig) Copy() *IPConfig {
+ if i == nil {
+ return nil
+ }
+
+ ipc := &IPConfig{
+ Version: i.Version,
+ Address: i.Address,
+ Gateway: i.Gateway,
+ }
+ if i.Interface != nil {
+ intf := *i.Interface
+ ipc.Interface = &intf
+ }
+ return ipc
+}
+
+// JSON (un)marshallable types
+type ipConfig struct {
+ Version string `json:"version"`
+ Interface *int `json:"interface,omitempty"`
+ Address types.IPNet `json:"address"`
+ Gateway net.IP `json:"gateway,omitempty"`
+}
+
+func (c *IPConfig) MarshalJSON() ([]byte, error) {
+ ipc := ipConfig{
+ Version: c.Version,
+ Interface: c.Interface,
+ Address: types.IPNet(c.Address),
+ Gateway: c.Gateway,
+ }
+
+ return json.Marshal(ipc)
+}
+
+func (c *IPConfig) UnmarshalJSON(data []byte) error {
+ ipc := ipConfig{}
+ if err := json.Unmarshal(data, &ipc); err != nil {
+ return err
+ }
+
+ c.Version = ipc.Version
+ c.Interface = ipc.Interface
+ c.Address = net.IPNet(ipc.Address)
+ c.Gateway = ipc.Gateway
+ return nil
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/100/types.go b/vendor/github.com/containernetworking/cni/pkg/types/100/types.go
new file mode 100644
index 000000000..0e1e8b857
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/100/types.go
@@ -0,0 +1,307 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types100
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net"
+ "os"
+
+ "github.com/containernetworking/cni/pkg/types"
+ types040 "github.com/containernetworking/cni/pkg/types/040"
+ convert "github.com/containernetworking/cni/pkg/types/internal"
+)
+
+const ImplementedSpecVersion string = "1.0.0"
+
+var supportedVersions = []string{ImplementedSpecVersion}
+
+// Register converters for all versions less than the implemented spec version
+func init() {
+ // Up-converters
+ convert.RegisterConverter("0.1.0", supportedVersions, convertFrom02x)
+ convert.RegisterConverter("0.2.0", supportedVersions, convertFrom02x)
+ convert.RegisterConverter("0.3.0", supportedVersions, convertFrom04x)
+ convert.RegisterConverter("0.3.1", supportedVersions, convertFrom04x)
+ convert.RegisterConverter("0.4.0", supportedVersions, convertFrom04x)
+
+ // Down-converters
+ convert.RegisterConverter("1.0.0", []string{"0.3.0", "0.3.1", "0.4.0"}, convertTo04x)
+ convert.RegisterConverter("1.0.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
+
+ // Creator
+ convert.RegisterCreator(supportedVersions, NewResult)
+}
+
+func NewResult(data []byte) (types.Result, error) {
+ result := &Result{}
+ if err := json.Unmarshal(data, result); err != nil {
+ return nil, err
+ }
+ for _, v := range supportedVersions {
+ if result.CNIVersion == v {
+ return result, nil
+ }
+ }
+ return nil, fmt.Errorf("result type supports %v but unmarshalled CNIVersion is %q",
+ supportedVersions, result.CNIVersion)
+}
+
+func GetResult(r types.Result) (*Result, error) {
+ resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ result, ok := resultCurrent.(*Result)
+ if !ok {
+ return nil, fmt.Errorf("failed to convert result")
+ }
+ return result, nil
+}
+
+func NewResultFromResult(result types.Result) (*Result, error) {
+ newResult, err := convert.Convert(result, ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ return newResult.(*Result), nil
+}
+
+// Result is what gets returned from the plugin (via stdout) to the caller
+type Result struct {
+ CNIVersion string `json:"cniVersion,omitempty"`
+ Interfaces []*Interface `json:"interfaces,omitempty"`
+ IPs []*IPConfig `json:"ips,omitempty"`
+ Routes []*types.Route `json:"routes,omitempty"`
+ DNS types.DNS `json:"dns,omitempty"`
+}
+
+func convertFrom02x(from types.Result, toVersion string) (types.Result, error) {
+ result040, err := convert.Convert(from, "0.4.0")
+ if err != nil {
+ return nil, err
+ }
+ result100, err := convertFrom04x(result040, ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ return result100, nil
+}
+
+func convertIPConfigFrom040(from *types040.IPConfig) *IPConfig {
+ to := &IPConfig{
+ Address: from.Address,
+ Gateway: from.Gateway,
+ }
+ if from.Interface != nil {
+ intf := *from.Interface
+ to.Interface = &intf
+ }
+ return to
+}
+
+func convertInterfaceFrom040(from *types040.Interface) *Interface {
+ return &Interface{
+ Name: from.Name,
+ Mac: from.Mac,
+ Sandbox: from.Sandbox,
+ }
+}
+
+func convertFrom04x(from types.Result, toVersion string) (types.Result, error) {
+ fromResult := from.(*types040.Result)
+ toResult := &Result{
+ CNIVersion: toVersion,
+ DNS: *fromResult.DNS.Copy(),
+ Routes: []*types.Route{},
+ }
+ for _, fromIntf := range fromResult.Interfaces {
+ toResult.Interfaces = append(toResult.Interfaces, convertInterfaceFrom040(fromIntf))
+ }
+ for _, fromIPC := range fromResult.IPs {
+ toResult.IPs = append(toResult.IPs, convertIPConfigFrom040(fromIPC))
+ }
+ for _, fromRoute := range fromResult.Routes {
+ toResult.Routes = append(toResult.Routes, fromRoute.Copy())
+ }
+ return toResult, nil
+}
+
+func convertIPConfigTo040(from *IPConfig) *types040.IPConfig {
+ version := "6"
+ if from.Address.IP.To4() != nil {
+ version = "4"
+ }
+ to := &types040.IPConfig{
+ Version: version,
+ Address: from.Address,
+ Gateway: from.Gateway,
+ }
+ if from.Interface != nil {
+ intf := *from.Interface
+ to.Interface = &intf
+ }
+ return to
+}
+
+func convertInterfaceTo040(from *Interface) *types040.Interface {
+ return &types040.Interface{
+ Name: from.Name,
+ Mac: from.Mac,
+ Sandbox: from.Sandbox,
+ }
+}
+
+func convertTo04x(from types.Result, toVersion string) (types.Result, error) {
+ fromResult := from.(*Result)
+ toResult := &types040.Result{
+ CNIVersion: toVersion,
+ DNS: *fromResult.DNS.Copy(),
+ Routes: []*types.Route{},
+ }
+ for _, fromIntf := range fromResult.Interfaces {
+ toResult.Interfaces = append(toResult.Interfaces, convertInterfaceTo040(fromIntf))
+ }
+ for _, fromIPC := range fromResult.IPs {
+ toResult.IPs = append(toResult.IPs, convertIPConfigTo040(fromIPC))
+ }
+ for _, fromRoute := range fromResult.Routes {
+ toResult.Routes = append(toResult.Routes, fromRoute.Copy())
+ }
+ return toResult, nil
+}
+
+func convertTo02x(from types.Result, toVersion string) (types.Result, error) {
+ // First convert to 0.4.0
+ result040, err := convertTo04x(from, "0.4.0")
+ if err != nil {
+ return nil, err
+ }
+ result02x, err := convert.Convert(result040, toVersion)
+ if err != nil {
+ return nil, err
+ }
+ return result02x, nil
+}
+
+func (r *Result) Version() string {
+ return r.CNIVersion
+}
+
+func (r *Result) GetAsVersion(version string) (types.Result, error) {
+ // If the creator of the result did not set the CNIVersion, assume it
+ // should be the highest spec version implemented by this Result
+ if r.CNIVersion == "" {
+ r.CNIVersion = ImplementedSpecVersion
+ }
+ return convert.Convert(r, version)
+}
+
+func (r *Result) Print() error {
+ return r.PrintTo(os.Stdout)
+}
+
+func (r *Result) PrintTo(writer io.Writer) error {
+ data, err := json.MarshalIndent(r, "", " ")
+ if err != nil {
+ return err
+ }
+ _, err = writer.Write(data)
+ return err
+}
+
+// Interface contains values about the created interfaces
+type Interface struct {
+ Name string `json:"name"`
+ Mac string `json:"mac,omitempty"`
+ Sandbox string `json:"sandbox,omitempty"`
+}
+
+func (i *Interface) String() string {
+ return fmt.Sprintf("%+v", *i)
+}
+
+func (i *Interface) Copy() *Interface {
+ if i == nil {
+ return nil
+ }
+ newIntf := *i
+ return &newIntf
+}
+
+// Int returns a pointer to the int value passed in. Used to
+// set the IPConfig.Interface field.
+func Int(v int) *int {
+ return &v
+}
+
+// IPConfig contains values necessary to configure an IP address on an interface
+type IPConfig struct {
+ // Index into Result structs Interfaces list
+ Interface *int
+ Address net.IPNet
+ Gateway net.IP
+}
+
+func (i *IPConfig) String() string {
+ return fmt.Sprintf("%+v", *i)
+}
+
+func (i *IPConfig) Copy() *IPConfig {
+ if i == nil {
+ return nil
+ }
+
+ ipc := &IPConfig{
+ Address: i.Address,
+ Gateway: i.Gateway,
+ }
+ if i.Interface != nil {
+ intf := *i.Interface
+ ipc.Interface = &intf
+ }
+ return ipc
+}
+
+// JSON (un)marshallable types
+type ipConfig struct {
+ Interface *int `json:"interface,omitempty"`
+ Address types.IPNet `json:"address"`
+ Gateway net.IP `json:"gateway,omitempty"`
+}
+
+func (c *IPConfig) MarshalJSON() ([]byte, error) {
+ ipc := ipConfig{
+ Interface: c.Interface,
+ Address: types.IPNet(c.Address),
+ Gateway: c.Gateway,
+ }
+
+ return json.Marshal(ipc)
+}
+
+func (c *IPConfig) UnmarshalJSON(data []byte) error {
+ ipc := ipConfig{}
+ if err := json.Unmarshal(data, &ipc); err != nil {
+ return err
+ }
+
+ c.Interface = ipc.Interface
+ c.Address = net.IPNet(ipc.Address)
+ c.Gateway = ipc.Gateway
+ return nil
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/args.go b/vendor/github.com/containernetworking/cni/pkg/types/args.go
index 4eac64899..7516f03ef 100644
--- a/vendor/github.com/containernetworking/cni/pkg/types/args.go
+++ b/vendor/github.com/containernetworking/cni/pkg/types/args.go
@@ -91,16 +91,26 @@ func LoadArgs(args string, container interface{}) error {
unknownArgs = append(unknownArgs, pair)
continue
}
- keyFieldIface := keyField.Addr().Interface()
- u, ok := keyFieldIface.(encoding.TextUnmarshaler)
+
+ var keyFieldInterface interface{}
+ switch {
+ case keyField.Kind() == reflect.Ptr:
+ keyField.Set(reflect.New(keyField.Type().Elem()))
+ keyFieldInterface = keyField.Interface()
+ case keyField.CanAddr() && keyField.Addr().CanInterface():
+ keyFieldInterface = keyField.Addr().Interface()
+ default:
+ return UnmarshalableArgsError{fmt.Errorf("field '%s' has no valid interface", keyString)}
+ }
+ u, ok := keyFieldInterface.(encoding.TextUnmarshaler)
if !ok {
return UnmarshalableArgsError{fmt.Errorf(
"ARGS: cannot unmarshal into field '%s' - type '%s' does not implement encoding.TextUnmarshaler",
- keyString, reflect.TypeOf(keyFieldIface))}
+ keyString, reflect.TypeOf(keyFieldInterface))}
}
err := u.UnmarshalText([]byte(valueString))
if err != nil {
- return fmt.Errorf("ARGS: error parsing value of pair %q: %v)", pair, err)
+ return fmt.Errorf("ARGS: error parsing value of pair %q: %w", pair, err)
}
}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/create/create.go b/vendor/github.com/containernetworking/cni/pkg/types/create/create.go
new file mode 100644
index 000000000..ed28b33e8
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/create/create.go
@@ -0,0 +1,56 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package create
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/containernetworking/cni/pkg/types"
+ convert "github.com/containernetworking/cni/pkg/types/internal"
+)
+
+// DecodeVersion returns the CNI version from CNI configuration or result JSON,
+// or an error if the operation could not be performed.
+func DecodeVersion(jsonBytes []byte) (string, error) {
+ var conf struct {
+ CNIVersion string `json:"cniVersion"`
+ }
+ err := json.Unmarshal(jsonBytes, &conf)
+ if err != nil {
+ return "", fmt.Errorf("decoding version from network config: %w", err)
+ }
+ if conf.CNIVersion == "" {
+ return "0.1.0", nil
+ }
+ return conf.CNIVersion, nil
+}
+
+// Create creates a CNI Result using the given JSON with the expected
+// version, or an error if the creation could not be performed
+func Create(version string, bytes []byte) (types.Result, error) {
+ return convert.Create(version, bytes)
+}
+
+// CreateFromBytes creates a CNI Result from the given JSON, automatically
+// detecting the CNI spec version of the result. An error is returned if the
+// operation could not be performed.
+func CreateFromBytes(bytes []byte) (types.Result, error) {
+ version, err := DecodeVersion(bytes)
+ if err != nil {
+ return nil, err
+ }
+ return convert.Create(version, bytes)
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go
deleted file mode 100644
index 754cc6e72..000000000
--- a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2016 CNI authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package current
-
-import (
- "encoding/json"
- "fmt"
- "io"
- "net"
- "os"
-
- "github.com/containernetworking/cni/pkg/types"
- "github.com/containernetworking/cni/pkg/types/020"
-)
-
-const ImplementedSpecVersion string = "0.4.0"
-
-var SupportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion}
-
-func NewResult(data []byte) (types.Result, error) {
- result := &Result{}
- if err := json.Unmarshal(data, result); err != nil {
- return nil, err
- }
- return result, nil
-}
-
-func GetResult(r types.Result) (*Result, error) {
- resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
- if err != nil {
- return nil, err
- }
- result, ok := resultCurrent.(*Result)
- if !ok {
- return nil, fmt.Errorf("failed to convert result")
- }
- return result, nil
-}
-
-var resultConverters = []struct {
- versions []string
- convert func(types.Result) (*Result, error)
-}{
- {types020.SupportedVersions, convertFrom020},
- {SupportedVersions, convertFrom030},
-}
-
-func convertFrom020(result types.Result) (*Result, error) {
- oldResult, err := types020.GetResult(result)
- if err != nil {
- return nil, err
- }
-
- newResult := &Result{
- CNIVersion: ImplementedSpecVersion,
- DNS: oldResult.DNS,
- Routes: []*types.Route{},
- }
-
- if oldResult.IP4 != nil {
- newResult.IPs = append(newResult.IPs, &IPConfig{
- Version: "4",
- Address: oldResult.IP4.IP,
- Gateway: oldResult.IP4.Gateway,
- })
- for _, route := range oldResult.IP4.Routes {
- newResult.Routes = append(newResult.Routes, &types.Route{
- Dst: route.Dst,
- GW: route.GW,
- })
- }
- }
-
- if oldResult.IP6 != nil {
- newResult.IPs = append(newResult.IPs, &IPConfig{
- Version: "6",
- Address: oldResult.IP6.IP,
- Gateway: oldResult.IP6.Gateway,
- })
- for _, route := range oldResult.IP6.Routes {
- newResult.Routes = append(newResult.Routes, &types.Route{
- Dst: route.Dst,
- GW: route.GW,
- })
- }
- }
-
- return newResult, nil
-}
-
-func convertFrom030(result types.Result) (*Result, error) {
- newResult, ok := result.(*Result)
- if !ok {
- return nil, fmt.Errorf("failed to convert result")
- }
- newResult.CNIVersion = ImplementedSpecVersion
- return newResult, nil
-}
-
-func NewResultFromResult(result types.Result) (*Result, error) {
- version := result.Version()
- for _, converter := range resultConverters {
- for _, supportedVersion := range converter.versions {
- if version == supportedVersion {
- return converter.convert(result)
- }
- }
- }
- return nil, fmt.Errorf("unsupported CNI result22 version %q", version)
-}
-
-// Result is what gets returned from the plugin (via stdout) to the caller
-type Result struct {
- CNIVersion string `json:"cniVersion,omitempty"`
- Interfaces []*Interface `json:"interfaces,omitempty"`
- IPs []*IPConfig `json:"ips,omitempty"`
- Routes []*types.Route `json:"routes,omitempty"`
- DNS types.DNS `json:"dns,omitempty"`
-}
-
-// Convert to the older 0.2.0 CNI spec Result type
-func (r *Result) convertTo020() (*types020.Result, error) {
- oldResult := &types020.Result{
- CNIVersion: types020.ImplementedSpecVersion,
- DNS: r.DNS,
- }
-
- for _, ip := range r.IPs {
- // Only convert the first IP address of each version as 0.2.0
- // and earlier cannot handle multiple IP addresses
- if ip.Version == "4" && oldResult.IP4 == nil {
- oldResult.IP4 = &types020.IPConfig{
- IP: ip.Address,
- Gateway: ip.Gateway,
- }
- } else if ip.Version == "6" && oldResult.IP6 == nil {
- oldResult.IP6 = &types020.IPConfig{
- IP: ip.Address,
- Gateway: ip.Gateway,
- }
- }
-
- if oldResult.IP4 != nil && oldResult.IP6 != nil {
- break
- }
- }
-
- for _, route := range r.Routes {
- is4 := route.Dst.IP.To4() != nil
- if is4 && oldResult.IP4 != nil {
- oldResult.IP4.Routes = append(oldResult.IP4.Routes, types.Route{
- Dst: route.Dst,
- GW: route.GW,
- })
- } else if !is4 && oldResult.IP6 != nil {
- oldResult.IP6.Routes = append(oldResult.IP6.Routes, types.Route{
- Dst: route.Dst,
- GW: route.GW,
- })
- }
- }
-
- if oldResult.IP4 == nil && oldResult.IP6 == nil {
- return nil, fmt.Errorf("cannot convert: no valid IP addresses")
- }
-
- return oldResult, nil
-}
-
-func (r *Result) Version() string {
- return ImplementedSpecVersion
-}
-
-func (r *Result) GetAsVersion(version string) (types.Result, error) {
- switch version {
- case "0.3.0", "0.3.1", ImplementedSpecVersion:
- r.CNIVersion = version
- return r, nil
- case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]:
- return r.convertTo020()
- }
- return nil, fmt.Errorf("cannot convert version 0.3.x to %q", version)
-}
-
-func (r *Result) Print() error {
- return r.PrintTo(os.Stdout)
-}
-
-func (r *Result) PrintTo(writer io.Writer) error {
- data, err := json.MarshalIndent(r, "", " ")
- if err != nil {
- return err
- }
- _, err = writer.Write(data)
- return err
-}
-
-// Convert this old version result to the current CNI version result
-func (r *Result) Convert() (*Result, error) {
- return r, nil
-}
-
-// Interface contains values about the created interfaces
-type Interface struct {
- Name string `json:"name"`
- Mac string `json:"mac,omitempty"`
- Sandbox string `json:"sandbox,omitempty"`
-}
-
-func (i *Interface) String() string {
- return fmt.Sprintf("%+v", *i)
-}
-
-// Int returns a pointer to the int value passed in. Used to
-// set the IPConfig.Interface field.
-func Int(v int) *int {
- return &v
-}
-
-// IPConfig contains values necessary to configure an IP address on an interface
-type IPConfig struct {
- // IP version, either "4" or "6"
- Version string
- // Index into Result structs Interfaces list
- Interface *int
- Address net.IPNet
- Gateway net.IP
-}
-
-func (i *IPConfig) String() string {
- return fmt.Sprintf("%+v", *i)
-}
-
-// JSON (un)marshallable types
-type ipConfig struct {
- Version string `json:"version"`
- Interface *int `json:"interface,omitempty"`
- Address types.IPNet `json:"address"`
- Gateway net.IP `json:"gateway,omitempty"`
-}
-
-func (c *IPConfig) MarshalJSON() ([]byte, error) {
- ipc := ipConfig{
- Version: c.Version,
- Interface: c.Interface,
- Address: types.IPNet(c.Address),
- Gateway: c.Gateway,
- }
-
- return json.Marshal(ipc)
-}
-
-func (c *IPConfig) UnmarshalJSON(data []byte) error {
- ipc := ipConfig{}
- if err := json.Unmarshal(data, &ipc); err != nil {
- return err
- }
-
- c.Version = ipc.Version
- c.Interface = ipc.Interface
- c.Address = net.IPNet(ipc.Address)
- c.Gateway = ipc.Gateway
- return nil
-}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/internal/convert.go b/vendor/github.com/containernetworking/cni/pkg/types/internal/convert.go
new file mode 100644
index 000000000..bdbe4b0a5
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/internal/convert.go
@@ -0,0 +1,92 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package convert
+
+import (
+ "fmt"
+
+ "github.com/containernetworking/cni/pkg/types"
+)
+
+// ConvertFn should convert from the given arbitrary Result type into a
+// Result implementing CNI specification version passed in toVersion.
+// The function is guaranteed to be passed a Result type matching the
+// fromVersion it was registered with, and is guaranteed to be
+// passed a toVersion matching one of the toVersions it was registered with.
+type ConvertFn func(from types.Result, toVersion string) (types.Result, error)
+
+type converter struct {
+ // fromVersion is the CNI Result spec version that convertFn accepts
+ fromVersion string
+ // toVersions is a list of versions that convertFn can convert to
+ toVersions []string
+ convertFn ConvertFn
+}
+
+var converters []*converter
+
+func findConverter(fromVersion, toVersion string) *converter {
+ for _, c := range converters {
+ if c.fromVersion == fromVersion {
+ for _, v := range c.toVersions {
+ if v == toVersion {
+ return c
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// Convert converts a CNI Result to the requested CNI specification version,
+// or returns an error if the conversion could not be performed or failed
+func Convert(from types.Result, toVersion string) (types.Result, error) {
+ if toVersion == "" {
+ toVersion = "0.1.0"
+ }
+
+ fromVersion := from.Version()
+
+ // Shortcut for same version
+ if fromVersion == toVersion {
+ return from, nil
+ }
+
+ // Otherwise find the right converter
+ c := findConverter(fromVersion, toVersion)
+ if c == nil {
+ return nil, fmt.Errorf("no converter for CNI result version %s to %s",
+ fromVersion, toVersion)
+ }
+ return c.convertFn(from, toVersion)
+}
+
+// RegisterConverter registers a CNI Result converter. SHOULD NOT BE CALLED
+// EXCEPT FROM CNI ITSELF.
+func RegisterConverter(fromVersion string, toVersions []string, convertFn ConvertFn) {
+ // Make sure there is no converter already registered for these
+ // from and to versions
+ for _, v := range toVersions {
+ if findConverter(fromVersion, v) != nil {
+ panic(fmt.Sprintf("converter already registered for %s to %s",
+ fromVersion, v))
+ }
+ }
+ converters = append(converters, &converter{
+ fromVersion: fromVersion,
+ toVersions: toVersions,
+ convertFn: convertFn,
+ })
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/internal/create.go b/vendor/github.com/containernetworking/cni/pkg/types/internal/create.go
new file mode 100644
index 000000000..963630912
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/internal/create.go
@@ -0,0 +1,66 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package convert
+
+import (
+ "fmt"
+
+ "github.com/containernetworking/cni/pkg/types"
+)
+
+type ResultFactoryFunc func([]byte) (types.Result, error)
+
+type creator struct {
+ // CNI Result spec versions that createFn can create a Result for
+ versions []string
+ createFn ResultFactoryFunc
+}
+
+var creators []*creator
+
+func findCreator(version string) *creator {
+ for _, c := range creators {
+ for _, v := range c.versions {
+ if v == version {
+ return c
+ }
+ }
+ }
+ return nil
+}
+
+// Create creates a CNI Result using the given JSON, or an error if the creation
+// could not be performed
+func Create(version string, bytes []byte) (types.Result, error) {
+ if c := findCreator(version); c != nil {
+ return c.createFn(bytes)
+ }
+ return nil, fmt.Errorf("unsupported CNI result version %q", version)
+}
+
+// RegisterCreator registers a CNI Result creator. SHOULD NOT BE CALLED
+// EXCEPT FROM CNI ITSELF.
+func RegisterCreator(versions []string, createFn ResultFactoryFunc) {
+ // Make sure there is no creator already registered for these versions
+ for _, v := range versions {
+ if findCreator(v) != nil {
+ panic(fmt.Sprintf("creator already registered for %s", v))
+ }
+ }
+ creators = append(creators, &creator{
+ versions: versions,
+ createFn: createFn,
+ })
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/types.go b/vendor/github.com/containernetworking/cni/pkg/types/types.go
index 3fa757a5d..fba17dfc0 100644
--- a/vendor/github.com/containernetworking/cni/pkg/types/types.go
+++ b/vendor/github.com/containernetworking/cni/pkg/types/types.go
@@ -83,8 +83,6 @@ type NetConfList struct {
Plugins []*NetConf `json:"plugins,omitempty"`
}
-type ResultFactoryFunc func([]byte) (Result, error)
-
// Result is an interface that provides the result of plugin execution
type Result interface {
// The highest CNI specification result version the result supports
@@ -118,6 +116,24 @@ type DNS struct {
Options []string `json:"options,omitempty"`
}
+func (d *DNS) Copy() *DNS {
+ if d == nil {
+ return nil
+ }
+
+ to := &DNS{Domain: d.Domain}
+ for _, ns := range d.Nameservers {
+ to.Nameservers = append(to.Nameservers, ns)
+ }
+ for _, s := range d.Search {
+ to.Search = append(to.Search, s)
+ }
+ for _, o := range d.Options {
+ to.Options = append(to.Options, o)
+ }
+ return to
+}
+
type Route struct {
Dst net.IPNet
GW net.IP
@@ -127,6 +143,17 @@ func (r *Route) String() string {
return fmt.Sprintf("%+v", *r)
}
+func (r *Route) Copy() *Route {
+ if r == nil {
+ return nil
+ }
+
+ return &Route{
+ Dst: r.Dst,
+ GW: r.GW,
+ }
+}
+
// Well known error codes
// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
const (
diff --git a/vendor/github.com/containernetworking/cni/pkg/version/conf.go b/vendor/github.com/containernetworking/cni/pkg/version/conf.go
index 3cca58bbe..808c33b83 100644
--- a/vendor/github.com/containernetworking/cni/pkg/version/conf.go
+++ b/vendor/github.com/containernetworking/cni/pkg/version/conf.go
@@ -15,23 +15,12 @@
package version
import (
- "encoding/json"
- "fmt"
+ "github.com/containernetworking/cni/pkg/types/create"
)
// ConfigDecoder can decode the CNI version available in network config data
type ConfigDecoder struct{}
func (*ConfigDecoder) Decode(jsonBytes []byte) (string, error) {
- var conf struct {
- CNIVersion string `json:"cniVersion"`
- }
- err := json.Unmarshal(jsonBytes, &conf)
- if err != nil {
- return "", fmt.Errorf("decoding version from network config: %s", err)
- }
- if conf.CNIVersion == "" {
- return "0.1.0", nil
- }
- return conf.CNIVersion, nil
+ return create.DecodeVersion(jsonBytes)
}
diff --git a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go
index 1df427243..d4bc9d169 100644
--- a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go
+++ b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go
@@ -68,7 +68,7 @@ func (*PluginDecoder) Decode(jsonBytes []byte) (PluginInfo, error) {
var info pluginInfo
err := json.Unmarshal(jsonBytes, &info)
if err != nil {
- return nil, fmt.Errorf("decoding version info: %s", err)
+ return nil, fmt.Errorf("decoding version info: %w", err)
}
if info.CNIVersion_ == "" {
return nil, fmt.Errorf("decoding version info: missing field cniVersion")
@@ -97,20 +97,20 @@ func ParseVersion(version string) (int, int, int, error) {
major, err := strconv.Atoi(parts[0])
if err != nil {
- return -1, -1, -1, fmt.Errorf("failed to convert major version part %q: %v", parts[0], err)
+ return -1, -1, -1, fmt.Errorf("failed to convert major version part %q: %w", parts[0], err)
}
if len(parts) >= 2 {
minor, err = strconv.Atoi(parts[1])
if err != nil {
- return -1, -1, -1, fmt.Errorf("failed to convert minor version part %q: %v", parts[1], err)
+ return -1, -1, -1, fmt.Errorf("failed to convert minor version part %q: %w", parts[1], err)
}
}
if len(parts) >= 3 {
micro, err = strconv.Atoi(parts[2])
if err != nil {
- return -1, -1, -1, fmt.Errorf("failed to convert micro version part %q: %v", parts[2], err)
+ return -1, -1, -1, fmt.Errorf("failed to convert micro version part %q: %w", parts[2], err)
}
}
diff --git a/vendor/github.com/containernetworking/cni/pkg/version/version.go b/vendor/github.com/containernetworking/cni/pkg/version/version.go
index 8f3508e61..1326f8038 100644
--- a/vendor/github.com/containernetworking/cni/pkg/version/version.go
+++ b/vendor/github.com/containernetworking/cni/pkg/version/version.go
@@ -19,13 +19,13 @@ import (
"fmt"
"github.com/containernetworking/cni/pkg/types"
- "github.com/containernetworking/cni/pkg/types/020"
- "github.com/containernetworking/cni/pkg/types/current"
+ types100 "github.com/containernetworking/cni/pkg/types/100"
+ "github.com/containernetworking/cni/pkg/types/create"
)
// Current reports the version of the CNI spec implemented by this library
func Current() string {
- return "0.4.0"
+ return types100.ImplementedSpecVersion
}
// Legacy PluginInfo describes a plugin that is backwards compatible with the
@@ -36,29 +36,28 @@ func Current() string {
// Any future CNI spec versions which meet this definition should be added to
// this list.
var Legacy = PluginSupports("0.1.0", "0.2.0")
-var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0")
+var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0")
-var resultFactories = []struct {
- supportedVersions []string
- newResult types.ResultFactoryFunc
-}{
- {current.SupportedVersions, current.NewResult},
- {types020.SupportedVersions, types020.NewResult},
+// VersionsFrom returns a list of versions starting from min, inclusive
+func VersionsStartingFrom(min string) PluginInfo {
+ out := []string{}
+ // cheat, just assume ordered
+ ok := false
+ for _, v := range All.SupportedVersions() {
+ if !ok && v == min {
+ ok = true
+ }
+ if ok {
+ out = append(out, v)
+ }
+ }
+ return PluginSupports(out...)
}
// Finds a Result object matching the requested version (if any) and asks
// that object to parse the plugin result, returning an error if parsing failed.
func NewResult(version string, resultBytes []byte) (types.Result, error) {
- reconciler := &Reconciler{}
- for _, resultFactory := range resultFactories {
- err := reconciler.CheckRaw(version, resultFactory.supportedVersions)
- if err == nil {
- // Result supports this version
- return resultFactory.newResult(resultBytes)
- }
- }
-
- return nil, fmt.Errorf("unsupported CNI result version %q", version)
+ return create.Create(version, resultBytes)
}
// ParsePrevResult parses a prevResult in a NetConf structure and sets
@@ -68,15 +67,22 @@ func ParsePrevResult(conf *types.NetConf) error {
return nil
}
+ // Prior to 1.0.0, Result types may not marshal a CNIVersion. Since the
+ // result version must match the config version, if the Result's version
+ // is empty, inject the config version.
+ if ver, ok := conf.RawPrevResult["CNIVersion"]; !ok || ver == "" {
+ conf.RawPrevResult["CNIVersion"] = conf.CNIVersion
+ }
+
resultBytes, err := json.Marshal(conf.RawPrevResult)
if err != nil {
- return fmt.Errorf("could not serialize prevResult: %v", err)
+ return fmt.Errorf("could not serialize prevResult: %w", err)
}
conf.RawPrevResult = nil
- conf.PrevResult, err = NewResult(conf.CNIVersion, resultBytes)
+ conf.PrevResult, err = create.Create(conf.CNIVersion, resultBytes)
if err != nil {
- return fmt.Errorf("could not parse prevResult: %v", err)
+ return fmt.Errorf("could not parse prevResult: %w", err)
}
return nil
diff --git a/vendor/github.com/containers/common/libimage/copier.go b/vendor/github.com/containers/common/libimage/copier.go
index a44f098ad..42d3690b9 100644
--- a/vendor/github.com/containers/common/libimage/copier.go
+++ b/vendor/github.com/containers/common/libimage/copier.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/copy"
"github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/pkg/compression"
"github.com/containers/image/v5/signature"
storageTransport "github.com/containers/image/v5/storage"
"github.com/containers/image/v5/types"
@@ -40,6 +41,10 @@ type CopyOptions struct {
// Allows for customizing the destination reference lookup. This can
// be used to use custom blob caches.
DestinationLookupReferenceFunc LookupReferenceFunc
+ // CompressionFormat is the format to use for the compression of the blobs
+ CompressionFormat *compression.Algorithm
+ // CompressionLevel specifies what compression level is used
+ CompressionLevel *int
// containers-auth.json(5) file to use when authenticating against
// container registries.
@@ -65,6 +70,8 @@ type CopyOptions struct {
// types. Short forms (e.g., oci, v2s2) used by some tools are not
// supported.
ManifestMIMEType string
+ // Accept uncompressed layers when copying OCI images.
+ OciAcceptUncompressedLayers bool
// If OciEncryptConfig is non-nil, it indicates that an image should be
// encrypted. The encryption options is derived from the construction
// of EncryptConfig object. Note: During initial encryption process of
@@ -242,6 +249,17 @@ func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) {
c.systemContext.DockerCertPath = options.CertDirPath
}
+ if options.CompressionFormat != nil {
+ c.systemContext.CompressionFormat = options.CompressionFormat
+ }
+
+ if options.CompressionLevel != nil {
+ c.systemContext.CompressionLevel = options.CompressionLevel
+ }
+
+ // NOTE: for the sake of consistency it's called Oci* in the CopyOptions.
+ c.systemContext.OCIAcceptUncompressedLayers = options.OciAcceptUncompressedLayers
+
policy, err := signature.DefaultPolicy(c.systemContext)
if err != nil {
return nil, err
diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go
index ff7d546e9..8456d5280 100644
--- a/vendor/github.com/containers/common/libimage/image.go
+++ b/vendor/github.com/containers/common/libimage/image.go
@@ -715,10 +715,18 @@ func (i *Image) Size() (int64, error) {
return i.runtime.store.ImageSize(i.ID())
}
+// HasDifferentDigestOptions allows for customizing the check if another
+// (remote) image has a different digest.
+type HasDifferentDigestOptions struct {
+ // containers-auth.json(5) file to use when authenticating against
+ // container registries.
+ AuthFilePath string
+}
+
// HasDifferentDigest returns true if the image specified by `remoteRef` has a
// different digest than the local one. This check can be useful to check for
// updates on remote registries.
-func (i *Image) HasDifferentDigest(ctx context.Context, remoteRef types.ImageReference) (bool, error) {
+func (i *Image) HasDifferentDigest(ctx context.Context, remoteRef types.ImageReference, options *HasDifferentDigestOptions) (bool, error) {
// We need to account for the arch that the image uses. It seems
// common on ARM to tweak this option to pull the correct image. See
// github.com/containers/podman/issues/6613.
@@ -738,6 +746,14 @@ func (i *Image) HasDifferentDigest(ctx context.Context, remoteRef types.ImageRef
sys.VariantChoice = inspectInfo.Variant
}
+ if options != nil && options.AuthFilePath != "" {
+ sys.AuthFilePath = options.AuthFilePath
+ }
+
+ return i.hasDifferentDigestWithSystemContext(ctx, remoteRef, sys)
+}
+
+func (i *Image) hasDifferentDigestWithSystemContext(ctx context.Context, remoteRef types.ImageReference, sys *types.SystemContext) (bool, error) {
remoteImg, err := remoteRef.NewImage(ctx, sys)
if err != nil {
return false, err
diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go
index 8712a13fd..1c322c37e 100644
--- a/vendor/github.com/containers/common/libimage/pull.go
+++ b/vendor/github.com/containers/common/libimage/pull.go
@@ -561,7 +561,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
}
if pullPolicy == config.PullPolicyNewer && localImage != nil {
- isNewer, err := localImage.HasDifferentDigest(ctx, srcRef)
+ isNewer, err := localImage.hasDifferentDigestWithSystemContext(ctx, srcRef, c.systemContext)
if err != nil {
pullErrors = append(pullErrors, err)
continue
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index b982aa552..c1f63577a 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -335,7 +335,7 @@ type EngineConfig struct {
// ActiveService index to Destinations added v2.0.3
ActiveService string `toml:"active_service,omitempty"`
- // Destinations mapped by service Names
+ // ServiceDestinations mapped by service Names
ServiceDestinations map[string]Destination `toml:"service_destinations,omitempty"`
// RuntimePath is the path to OCI runtime binary for launching containers.
@@ -379,6 +379,10 @@ type EngineConfig struct {
// containers/storage. As such this is not exposed via the config file.
StateType RuntimeStateStore `toml:"-"`
+ // ServiceTimeout is the number of seconds to wait without a connection
+ // before the `podman system service` times out and exits
+ ServiceTimeout uint `toml:"service_timeout,omitempty"`
+
// StaticDir is the path to a persistent directory to store container
// files.
StaticDir string `toml:"static_dir,omitempty"`
diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf
index dc38f8ec6..7c72ec79f 100644
--- a/vendor/github.com/containers/common/pkg/config/containers.conf
+++ b/vendor/github.com/containers/common/pkg/config/containers.conf
@@ -422,7 +422,7 @@ default_sysctls = [
# Default options to pass to the slirp4netns binary.
# For example "allow_host_loopback=true"
#
-#network_cmd_options = []
+#network_cmd_options = ["enable_ipv6=true",]
# Whether to use chroot instead of pivot_root in the runtime
#
@@ -466,6 +466,11 @@ default_sysctls = [
# container/storage tmp directory will be used.
# image_copy_tmp_dir="/var/tmp"
+# Number of seconds to wait without a connection
+# before the `podman system service` times out and exits
+#
+#service_timeout = 5
+
# Directory for persistent engine files (database, etc)
# By default, this will be configured relative to where the containers/storage
# stores containers
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
index 5ce73bd2a..34d17d72c 100644
--- a/vendor/github.com/containers/common/pkg/config/default.go
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -198,7 +198,6 @@ func DefaultConfig() (*Config, error) {
TZ: "",
Umask: "0022",
UTSNS: "private",
- UserNS: "host",
UserNSSize: DefaultUserNSSize,
},
Network: NetworkConfig{
@@ -257,8 +256,11 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
c.ImageBuildFormat = "oci"
c.CgroupManager = defaultCgroupManager()
+ c.ServiceTimeout = uint(5)
c.StopTimeout = uint(10)
-
+ c.NetworkCmdOptions = []string{
+ "enable_ipv6=true",
+ }
c.Remote = isRemote()
c.OCIRuntimes = map[string][]string{
"crun": {
diff --git a/vendor/github.com/containers/common/pkg/secrets/secrets.go b/vendor/github.com/containers/common/pkg/secrets/secrets.go
index 2e7802369..aea983cb1 100644
--- a/vendor/github.com/containers/common/pkg/secrets/secrets.go
+++ b/vendor/github.com/containers/common/pkg/secrets/secrets.go
@@ -24,8 +24,8 @@ const secretIDLength = 25
// errInvalidPath indicates that the secrets path is invalid
var errInvalidPath = errors.New("invalid secrets path")
-// errNoSuchSecret indicates that the secret does not exist
-var errNoSuchSecret = errors.New("no such secret")
+// ErrNoSuchSecret indicates that the secret does not exist
+var ErrNoSuchSecret = errors.New("no such secret")
// errSecretNameInUse indicates that the secret name is already in use
var errSecretNameInUse = errors.New("secret name in use")
@@ -152,7 +152,7 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, driv
newID = newID[0:secretIDLength]
_, err := s.lookupSecret(newID)
if err != nil {
- if errors.Cause(err) == errNoSuchSecret {
+ if errors.Cause(err) == ErrNoSuchSecret {
secr.ID = newID
break
} else {
diff --git a/vendor/github.com/containers/common/pkg/secrets/secretsdb.go b/vendor/github.com/containers/common/pkg/secrets/secretsdb.go
index 1395d103c..0c4929995 100644
--- a/vendor/github.com/containers/common/pkg/secrets/secretsdb.go
+++ b/vendor/github.com/containers/common/pkg/secrets/secretsdb.go
@@ -71,14 +71,14 @@ func (s *SecretsManager) getNameAndID(nameOrID string) (name, id string, err err
name, id, err = s.getExactNameAndID(nameOrID)
if err == nil {
return name, id, nil
- } else if errors.Cause(err) != errNoSuchSecret {
+ } else if errors.Cause(err) != ErrNoSuchSecret {
return "", "", err
}
// ID prefix may have been given, iterate through all IDs.
// ID and partial ID has a max length of 25, so we return if its greater than that.
if len(nameOrID) > secretIDLength {
- return "", "", errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
+ return "", "", errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
}
exists := false
var foundID, foundName string
@@ -96,7 +96,7 @@ func (s *SecretsManager) getNameAndID(nameOrID string) (name, id string, err err
if exists {
return foundName, foundID, nil
}
- return "", "", errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
+ return "", "", errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
}
// getExactNameAndID takes a secret's name or ID and returns both its name and full ID.
@@ -115,7 +115,7 @@ func (s *SecretsManager) getExactNameAndID(nameOrID string) (name, id string, er
return name, id, nil
}
- return "", "", errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
+ return "", "", errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
}
// exactSecretExists checks if the secret exists, given a name or ID
@@ -123,7 +123,7 @@ func (s *SecretsManager) getExactNameAndID(nameOrID string) (name, id string, er
func (s *SecretsManager) exactSecretExists(nameOrID string) (bool, error) {
_, _, err := s.getExactNameAndID(nameOrID)
if err != nil {
- if errors.Cause(err) == errNoSuchSecret {
+ if errors.Cause(err) == ErrNoSuchSecret {
return false, nil
}
return false, err
@@ -158,7 +158,7 @@ func (s *SecretsManager) lookupSecret(nameOrID string) (*Secret, error) {
return &secret, nil
}
- return nil, errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
+ return nil, errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
}
// Store creates a new secret in the secrets database.
diff --git a/vendor/github.com/containers/psgo/.codespellrc b/vendor/github.com/containers/psgo/.codespellrc
new file mode 100644
index 000000000..604bc21da
--- /dev/null
+++ b/vendor/github.com/containers/psgo/.codespellrc
@@ -0,0 +1,2 @@
+[codespell]
+skip = ./vendor,./.git
diff --git a/vendor/github.com/containers/psgo/.golangci.yml b/vendor/github.com/containers/psgo/.golangci.yml
new file mode 100644
index 000000000..a098068fe
--- /dev/null
+++ b/vendor/github.com/containers/psgo/.golangci.yml
@@ -0,0 +1,6 @@
+# For documentation, see https://golangci-lint.run/usage/configuration/
+
+linters:
+ enable:
+ - errorlint
+ - gofumpt
diff --git a/vendor/github.com/containers/psgo/.travis.yml b/vendor/github.com/containers/psgo/.travis.yml
deleted file mode 100644
index c07bb140b..000000000
--- a/vendor/github.com/containers/psgo/.travis.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-language: go
-
-sudo: required
-
-servics:
- - docker
-
-go:
- - tip
-
-before_install:
- - sudo add-apt-repository ppa:duggan/bats --yes
- - sudo apt-get update -qq
- - sudo apt-get install -qq bats
-
-script:
- - make validate
- - make build
- - make test
diff --git a/vendor/github.com/containers/psgo/Makefile b/vendor/github.com/containers/psgo/Makefile
index 831dfa31f..fb6126e7c 100644
--- a/vendor/github.com/containers/psgo/Makefile
+++ b/vendor/github.com/containers/psgo/Makefile
@@ -1,28 +1,25 @@
-export GO111MODULE=off
-export GOPROXY=https://proxy.golang.org
-
SHELL= /bin/bash
GO ?= go
BUILD_DIR := ./bin
BIN_DIR := /usr/local/bin
NAME := psgo
-PROJECT := github.com/containers/psgo
BATS_TESTS := *.bats
-GO_SRC=$(shell find . -name \*.go)
-GO_BUILD=$(GO) build
-# Go module support: set `-mod=vendor` to use the vendored sources
-ifeq ($(shell go help mod >/dev/null 2>&1 && echo true), true)
- GO_BUILD=GO111MODULE=on $(GO) build -mod=vendor
+# Not all platforms support -buildmode=pie, plus it's incompatible with -race.
+ifeq ($(shell $(GO) env GOOS),linux)
+ ifeq (,$(filter $(shell $(GO) env GOARCH),mips mipsle mips64 mips64le ppc64 riscv64))
+ ifeq (,$(findstring -race,$(EXTRA_BUILD_FLAGS)))
+ GO_BUILDMODE := "-buildmode=pie"
+ endif
+ endif
endif
-
-GOBIN ?= $(GO)/bin
+GO_BUILD := $(GO) build $(GO_BUILDMODE)
all: validate build
.PHONY: build
-build: $(GO_SRC)
- $(GO_BUILD) -buildmode=pie -o $(BUILD_DIR)/$(NAME) $(PROJECT)/sample
+build:
+ $(GO_BUILD) $(EXTRA_BUILD_FLAGS) -o $(BUILD_DIR)/$(NAME) ./sample
.PHONY: clean
clean:
@@ -30,13 +27,13 @@ clean:
.PHONY: vendor
vendor:
- GO111MODULE=on go mod tidy
- GO111MODULE=on go mod vendor
- GO111MODULE=on go mod verify
+ go mod tidy
+ go mod vendor
+ go mod verify
.PHONY: validate
-validate: .install.lint
- $(GOBIN)/golangci-lint run
+validate:
+ golangci-lint run
.PHONY: test
test: test-unit test-integration
@@ -47,17 +44,12 @@ test-integration:
.PHONY: test-unit
test-unit:
- go test -v $(PROJECT)
- go test -v $(PROJECT)/internal/...
+ $(GO) test -v $(EXTRA_TEST_FLAGS) ./...
.PHONY: install
install:
sudo install -D -m755 $(BUILD_DIR)/$(NAME) $(BIN_DIR)
-.PHONY: .install.lint
-.install.lint:
- VERSION=1.24.0 GOBIN=$(GOBIN) sh ./hack/install_golangci.sh
-
.PHONY: uninstall
uninstall:
sudo rm $(BIN_DIR)/$(NAME)
diff --git a/vendor/github.com/containers/psgo/README.md b/vendor/github.com/containers/psgo/README.md
index fed42c683..684c80a0c 100644
--- a/vendor/github.com/containers/psgo/README.md
+++ b/vendor/github.com/containers/psgo/README.md
@@ -73,8 +73,12 @@ The ps library is compatible with all AIX format descriptors of the ps command-l
- Set of inheritable capabilities. See capabilities(7) for more information.
- **capprm**
- Set of permitted capabilities. See capabilities(7) for more information.
+- **groups**
+ - Supplmentary groups inside the container.
- **hgroup**
- The corresponding effective group of a container process on the host.
+- **hgroups**
+ - Supplmentary groups on the host.
- **hpid**
- The corresponding host PID of a container process.
- **huser**
diff --git a/vendor/github.com/containers/psgo/go.mod b/vendor/github.com/containers/psgo/go.mod
index 699874cf7..fd19d9b48 100644
--- a/vendor/github.com/containers/psgo/go.mod
+++ b/vendor/github.com/containers/psgo/go.mod
@@ -1,10 +1,9 @@
module github.com/containers/psgo
-go 1.13
+go 1.14
require (
github.com/opencontainers/runc v1.0.2
- github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2
)
diff --git a/vendor/github.com/containers/psgo/go.sum b/vendor/github.com/containers/psgo/go.sum
index 0ba04956f..85b0f4ff7 100644
--- a/vendor/github.com/containers/psgo/go.sum
+++ b/vendor/github.com/containers/psgo/go.sum
@@ -39,7 +39,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
diff --git a/vendor/github.com/containers/psgo/internal/host/host.go b/vendor/github.com/containers/psgo/internal/host/host.go
index 33ad67a11..3c708a2b8 100644
--- a/vendor/github.com/containers/psgo/internal/host/host.go
+++ b/vendor/github.com/containers/psgo/internal/host/host.go
@@ -54,7 +54,7 @@ func BootTime() (int64, error) {
btimeSec, err := strconv.ParseInt(btimeStr, 10, 64)
if err != nil {
- return 0, fmt.Errorf("error parsing boot time from /proc/stat: %s", err)
+ return 0, fmt.Errorf("error parsing boot time from /proc/stat: %w", err)
}
bootTime = &btimeSec
return btimeSec, nil
diff --git a/vendor/github.com/containers/psgo/internal/proc/ns.go b/vendor/github.com/containers/psgo/internal/proc/ns.go
index 4778048f2..28ee6a2c9 100644
--- a/vendor/github.com/containers/psgo/internal/proc/ns.go
+++ b/vendor/github.com/containers/psgo/internal/proc/ns.go
@@ -59,7 +59,7 @@ func ReadMappings(path string) ([]IDMap, error) {
for {
line, _, err := buf.ReadLine()
if err != nil {
- if err == io.EOF {
+ if err == io.EOF { //nolint:errorlint // False positive, see https://github.com/polyfloyd/go-errorlint/pull/12
return mappings, nil
}
return nil, fmt.Errorf("cannot read line from %s: %w", path, err)
diff --git a/vendor/github.com/containers/psgo/internal/proc/pids.go b/vendor/github.com/containers/psgo/internal/proc/pids.go
index 69e8befc1..2687396e1 100644
--- a/vendor/github.com/containers/psgo/internal/proc/pids.go
+++ b/vendor/github.com/containers/psgo/internal/proc/pids.go
@@ -52,7 +52,7 @@ func GetPIDs() ([]string, error) {
return pids, nil
}
-// GetPIDsFromCgroup returns a strings slice of all pids listesd in pid's pids
+// GetPIDsFromCgroup returns a strings slice of all pids listed in pid's pids
// cgroup. It automatically detects if we're running in unified mode or not.
func GetPIDsFromCgroup(pid string) ([]string, error) {
unified, err := cgroups.IsCgroup2UnifiedMode()
@@ -65,11 +65,12 @@ func GetPIDsFromCgroup(pid string) ([]string, error) {
return getPIDsFromCgroupV1(pid)
}
-// getPIDsFromCgroupV1 returns a strings slice of all pids listesd in pid's pids
+// getPIDsFromCgroupV1 returns a strings slice of all pids listed in pid's pids
// cgroup.
func getPIDsFromCgroupV1(pid string) ([]string, error) {
// First, find the corresponding path to the PID cgroup.
- f, err := os.Open(fmt.Sprintf("/proc/%s/cgroup", pid))
+ pidPath := fmt.Sprintf("/proc/%s/cgroup", pid)
+ f, err := os.Open(pidPath)
if err != nil {
return nil, err
}
@@ -83,7 +84,8 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
continue
}
if fields[1] == "pids" {
- cgroupPath = fmt.Sprintf("/sys/fs/cgroup/pids/%s/cgroup.procs", fields[2])
+ cgroupPath = filepath.Join(cgroups.CgroupRoot, "pids", fields[2], "cgroup.procs")
+ break
}
}
@@ -94,7 +96,18 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
// Second, extract the PIDs inside the cgroup.
f, err = os.Open(cgroupPath)
if err != nil {
- return nil, err
+ if os.IsNotExist(err) {
+ // OCI runtimes might mount the container cgroup at the root, breaking what it showed
+ // in /proc/$PID/cgroup and the path.
+ // Check if the PID still exists to make sure the process is still alive.
+ if _, errStat := os.Stat(pidPath); errStat == nil {
+ cgroupPath = filepath.Join(cgroups.CgroupRoot, "pids", "cgroup.procs")
+ f, err = os.Open(cgroupPath)
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
}
defer f.Close()
@@ -107,7 +120,7 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
return pids, nil
}
-// getPIDsFromCgroupV2 returns a strings slice of all pids listesd in pid's pids
+// getPIDsFromCgroupV2 returns a strings slice of all pids listed in pid's pids
// cgroup.
func getPIDsFromCgroupV2(pid string) ([]string, error) {
// First, find the corresponding path to the PID cgroup.
@@ -124,8 +137,10 @@ func getPIDsFromCgroupV2(pid string) ([]string, error) {
if len(fields) != 3 {
continue
}
- cgroupSlice = fields[2]
- break
+ if fields[1] == "" {
+ cgroupSlice = fields[2]
+ break
+ }
}
if cgroupSlice == "" {
diff --git a/vendor/github.com/containers/psgo/internal/proc/status.go b/vendor/github.com/containers/psgo/internal/proc/status.go
index 2753915fd..1896b5c07 100644
--- a/vendor/github.com/containers/psgo/internal/proc/status.go
+++ b/vendor/github.com/containers/psgo/internal/proc/status.go
@@ -182,7 +182,7 @@ func readStatusUserNS(pid string) ([]string, error) {
c := exec.Command(args[0], args[1:]...)
output, err := c.CombinedOutput()
if err != nil {
- return nil, fmt.Errorf("error executing %q: %v", strings.Join(args, " "), err)
+ return nil, fmt.Errorf("error executing %q: %w", strings.Join(args, " "), err)
}
return strings.Split(string(output), "\n"), nil
diff --git a/vendor/github.com/containers/psgo/internal/process/process.go b/vendor/github.com/containers/psgo/internal/process/process.go
index 8fd49e416..715039610 100644
--- a/vendor/github.com/containers/psgo/internal/process/process.go
+++ b/vendor/github.com/containers/psgo/internal/process/process.go
@@ -215,7 +215,7 @@ func (p *Process) StartTime() (time.Time, error) {
return time.Unix(sinceBoot+bootTime, 0), nil
}
-// CPUTime returns the cumlative CPU time of process p as a time.Duration.
+// CPUTime returns the cumulative CPU time of process p as a time.Duration.
func (p *Process) CPUTime() (time.Duration, error) {
user, err := strconv.ParseInt(p.Stat.Utime, 10, 64)
if err != nil {
diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go
index b0569fa1c..ea893e7ca 100644
--- a/vendor/github.com/containers/psgo/psgo.go
+++ b/vendor/github.com/containers/psgo/psgo.go
@@ -175,6 +175,11 @@ var (
procFn: processGROUP,
},
{
+ normal: "groups",
+ header: "GROUPS",
+ procFn: processGROUPS,
+ },
+ {
code: "%P",
normal: "ppid",
header: "PPID",
@@ -306,6 +311,12 @@ var (
procFn: processHGROUP,
},
{
+ normal: "hgroups",
+ header: "HGROUPS",
+ onHost: true,
+ procFn: processHGROUPS,
+ },
+ {
normal: "rss",
header: "RSS",
procFn: processRSS,
@@ -620,14 +631,29 @@ func findHostProcess(p *process.Process, ctx *psContext) *process.Process {
}
// processGROUP returns the effective group ID of the process. This will be
-// the textual group ID, if it can be optained, or a decimal representation
+// the textual group ID, if it can be obtained, or a decimal representation
// otherwise.
func processGROUP(p *process.Process, ctx *psContext) (string, error) {
return process.LookupGID(p.Status.Gids[1])
}
+// processGROUPS returns the supplementary groups of the process separated by
+// comma. This will be the textual group ID, if it can be obtained, or a
+// decimal representation otherwise.
+func processGROUPS(p *process.Process, ctx *psContext) (string, error) {
+ var err error
+ groups := make([]string, len(p.Status.Groups))
+ for i, g := range p.Status.Groups {
+ groups[i], err = process.LookupGID(g)
+ if err != nil {
+ return "", err
+ }
+ }
+ return strings.Join(groups, ","), nil
+}
+
// processRGROUP returns the real group ID of the process. This will be
-// the textual group ID, if it can be optained, or a decimal representation
+// the textual group ID, if it can be obtained, or a decimal representation
// otherwise.
func processRGROUP(p *process.Process, ctx *psContext) (string, error) {
return process.LookupGID(p.Status.Gids[0])
@@ -639,14 +665,14 @@ func processPPID(p *process.Process, ctx *psContext) (string, error) {
}
// processUSER returns the effective user name of the process. This will be
-// the textual user ID, if it can be optained, or a decimal representation
+// the textual user ID, if it can be obtained, or a decimal representation
// otherwise.
func processUSER(p *process.Process, ctx *psContext) (string, error) {
return process.LookupUID(p.Status.Uids[1])
}
// processRUSER returns the effective user name of the process. This will be
-// the textual user ID, if it can be optained, or a decimal representation
+// the textual user ID, if it can be obtained, or a decimal representation
// otherwise.
func processRUSER(p *process.Process, ctx *psContext) (string, error) {
return process.LookupUID(p.Status.Uids[0])
@@ -867,6 +893,26 @@ func processHGROUP(p *process.Process, ctx *psContext) (string, error) {
return "?", nil
}
+// processHGROUPS returns the supplementary groups of the corresponding host
+// process of the (container) or "?" if no corresponding process could be
+// found.
+func processHGROUPS(p *process.Process, ctx *psContext) (string, error) {
+ if hp := findHostProcess(p, ctx); hp != nil {
+ groups := hp.Status.Groups
+ if ctx.opts != nil && len(ctx.opts.GIDMap) > 0 {
+ var err error
+ for i, g := range groups {
+ groups[i], err = findID(g, ctx.opts.GIDMap, process.LookupGID, "/proc/sys/fs/overflowgid")
+ if err != nil {
+ return "", err
+ }
+ }
+ }
+ return strings.Join(groups, ","), nil
+ }
+ return "?", nil
+}
+
// processRSS returns the resident set size of process p in KiB (1024-byte
// units).
func processRSS(p *process.Process, ctx *psContext) (string, error) {
diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
index 1955f2878..9fe803a5e 100644
--- a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
+++ b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
@@ -1,6 +1,12 @@
-## unreleased
+## 1.4.2
-* Fix regression where `*time.Time` value would be set to empty and not be sent
+* Custom name matchers to support any sort of casing, formatting, etc. for
+ field names. [GH-250]
+* Fix possible panic in ComposeDecodeHookFunc [GH-251]
+
+## 1.4.1
+
+* Fix regression where `*time.Time` value would be set to empty and not be sent
to decode hooks properly [GH-232]
## 1.4.0
diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
index 92e6f76ff..4d4bbc733 100644
--- a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
+++ b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
@@ -62,7 +62,8 @@ func DecodeHookExec(
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
var err error
- var data interface{}
+ data := f.Interface()
+
newFrom := f
for _, f1 := range fs {
data, err = DecodeHookExec(f1, newFrom, t)
diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go
index 3643901f5..dcee0f2d6 100644
--- a/vendor/github.com/mitchellh/mapstructure/mapstructure.go
+++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go
@@ -192,7 +192,7 @@ type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface
// source and target types.
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
-// DecodeHookFuncRaw is a DecodeHookFunc which has complete access to both the source and target
+// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
// values.
type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
@@ -258,6 +258,11 @@ type DecoderConfig struct {
// The tag name that mapstructure reads for field names. This
// defaults to "mapstructure"
TagName string
+
+ // MatchName is the function used to match the map key to the struct
+ // field name or tag. Defaults to `strings.EqualFold`. This can be used
+ // to implement case-sensitive tag values, support snake casing, etc.
+ MatchName func(mapKey, fieldName string) bool
}
// A Decoder takes a raw interface value and turns it into structured
@@ -376,6 +381,10 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
config.TagName = "mapstructure"
}
+ if config.MatchName == nil {
+ config.MatchName = strings.EqualFold
+ }
+
result := &Decoder{
config: config,
}
@@ -1340,7 +1349,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
continue
}
- if strings.EqualFold(mK, fieldName) {
+ if d.config.MatchName(mK, fieldName) {
rawMapKey = dataValKey
rawMapVal = dataVal.MapIndex(dataValKey)
break
diff --git a/vendor/github.com/vishvananda/netlink/class_linux.go b/vendor/github.com/vishvananda/netlink/class_linux.go
index e664ade7f..029568a3f 100644
--- a/vendor/github.com/vishvananda/netlink/class_linux.go
+++ b/vendor/github.com/vishvananda/netlink/class_linux.go
@@ -176,6 +176,12 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
options.AddRtAttr(nl.TCA_HTB_PARMS, opt.Serialize())
options.AddRtAttr(nl.TCA_HTB_RTAB, SerializeRtab(rtab))
options.AddRtAttr(nl.TCA_HTB_CTAB, SerializeRtab(ctab))
+ if htb.Rate >= uint64(1<<32) {
+ options.AddRtAttr(nl.TCA_HTB_RATE64, nl.Uint64Attr(htb.Rate))
+ }
+ if htb.Ceil >= uint64(1<<32) {
+ options.AddRtAttr(nl.TCA_HTB_CEIL64, nl.Uint64Attr(htb.Ceil))
+ }
case "hfsc":
hfsc := class.(*HfscClass)
opt := nl.HfscCopt{}
@@ -306,6 +312,10 @@ func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, erro
htb.Quantum = opt.Quantum
htb.Level = opt.Level
htb.Prio = opt.Prio
+ case nl.TCA_HTB_RATE64:
+ htb.Rate = native.Uint64(datum.Value[0:8])
+ case nl.TCA_HTB_CEIL64:
+ htb.Ceil = native.Uint64(datum.Value[0:8])
}
}
return detailed, nil
diff --git a/vendor/github.com/vishvananda/netlink/devlink_linux.go b/vendor/github.com/vishvananda/netlink/devlink_linux.go
index 29b3f8ec1..7d57080e8 100644
--- a/vendor/github.com/vishvananda/netlink/devlink_linux.go
+++ b/vendor/github.com/vishvananda/netlink/devlink_linux.go
@@ -27,6 +27,18 @@ type DevlinkDevice struct {
Attrs DevlinkDevAttrs
}
+// DevlinkPort represents port and its attributes
+type DevlinkPort struct {
+ BusName string
+ DeviceName string
+ PortIndex uint32
+ PortType uint16
+ NetdeviceName string
+ NetdevIfIndex uint32
+ RdmaDeviceName string
+ PortFlavour uint16
+}
+
func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
devices := make([]*DevlinkDevice, 0, len(msgs))
for _, m := range msgs {
@@ -270,3 +282,112 @@ func (h *Handle) DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error
func DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error {
return pkgHandle.DevLinkSetEswitchMode(Dev, NewMode)
}
+
+func (port *DevlinkPort) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
+ for _, a := range attrs {
+ switch a.Attr.Type {
+ case nl.DEVLINK_ATTR_BUS_NAME:
+ port.BusName = string(a.Value)
+ case nl.DEVLINK_ATTR_DEV_NAME:
+ port.DeviceName = string(a.Value)
+ case nl.DEVLINK_ATTR_PORT_INDEX:
+ port.PortIndex = native.Uint32(a.Value)
+ case nl.DEVLINK_ATTR_PORT_TYPE:
+ port.PortType = native.Uint16(a.Value)
+ case nl.DEVLINK_ATTR_PORT_NETDEV_NAME:
+ port.NetdeviceName = string(a.Value)
+ case nl.DEVLINK_ATTR_PORT_NETDEV_IFINDEX:
+ port.NetdevIfIndex = native.Uint32(a.Value)
+ case nl.DEVLINK_ATTR_PORT_IBDEV_NAME:
+ port.RdmaDeviceName = string(a.Value)
+ case nl.DEVLINK_ATTR_PORT_FLAVOUR:
+ port.PortFlavour = native.Uint16(a.Value)
+ }
+ }
+ return nil
+}
+
+func parseDevLinkAllPortList(msgs [][]byte) ([]*DevlinkPort, error) {
+ ports := make([]*DevlinkPort, 0, len(msgs))
+ for _, m := range msgs {
+ attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
+ if err != nil {
+ return nil, err
+ }
+ port := &DevlinkPort{}
+ if err = port.parseAttributes(attrs); err != nil {
+ return nil, err
+ }
+ ports = append(ports, port)
+ }
+ return ports, nil
+}
+
+// DevLinkGetPortList provides a pointer to devlink ports and nil error,
+// otherwise returns an error code.
+func (h *Handle) DevLinkGetAllPortList() ([]*DevlinkPort, error) {
+ f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME)
+ if err != nil {
+ return nil, err
+ }
+ msg := &nl.Genlmsg{
+ Command: nl.DEVLINK_CMD_PORT_GET,
+ Version: nl.GENL_DEVLINK_VERSION,
+ }
+ req := h.newNetlinkRequest(int(f.ID),
+ unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP)
+ req.AddData(msg)
+ msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return nil, err
+ }
+ ports, err := parseDevLinkAllPortList(msgs)
+ if err != nil {
+ return nil, err
+ }
+ return ports, nil
+}
+
+// DevLinkGetPortList provides a pointer to devlink ports and nil error,
+// otherwise returns an error code.
+func DevLinkGetAllPortList() ([]*DevlinkPort, error) {
+ return pkgHandle.DevLinkGetAllPortList()
+}
+
+func parseDevlinkPortMsg(msgs [][]byte) (*DevlinkPort, error) {
+ m := msgs[0]
+ attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
+ if err != nil {
+ return nil, err
+ }
+ port := &DevlinkPort{}
+ if err = port.parseAttributes(attrs); err != nil {
+ return nil, err
+ }
+ return port, nil
+}
+
+// DevLinkGetPortByIndexprovides a pointer to devlink device and nil error,
+// otherwise returns an error code.
+func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
+
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_GET, Bus, Device)
+ if err != nil {
+ return nil, err
+ }
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex)))
+
+ respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return nil, err
+ }
+ port, err := parseDevlinkPortMsg(respmsg)
+ return port, err
+}
+
+// DevLinkGetPortByIndex provides a pointer to devlink portand nil error,
+// otherwise returns an error code.
+func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
+ return pkgHandle.DevLinkGetPortByIndex(Bus, Device, PortIndex)
+}
diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go
index ef6fabe81..2cd46266c 100644
--- a/vendor/github.com/vishvananda/netlink/filter_linux.go
+++ b/vendor/github.com/vishvananda/netlink/filter_linux.go
@@ -36,6 +36,7 @@ type U32 struct {
ClassId uint32
Divisor uint32 // Divisor MUST be power of 2.
Hash uint32
+ Link uint32
RedirIndex int
Sel *TcU32Sel
Actions []Action
@@ -225,6 +226,9 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
if filter.Hash != 0 {
options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash))
}
+ if filter.Link != 0 {
+ options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link))
+ }
actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
// backwards compatibility
if filter.RedirIndex != 0 {
@@ -666,6 +670,8 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
u32.Divisor = native.Uint32(datum.Value)
case nl.TCA_U32_HASH:
u32.Hash = native.Uint32(datum.Value)
+ case nl.TCA_U32_LINK:
+ u32.Link = native.Uint32(datum.Value)
}
}
return detailed, nil
diff --git a/vendor/github.com/vishvananda/netlink/handle_linux.go b/vendor/github.com/vishvananda/netlink/handle_linux.go
index 26887b759..65356679d 100644
--- a/vendor/github.com/vishvananda/netlink/handle_linux.go
+++ b/vendor/github.com/vishvananda/netlink/handle_linux.go
@@ -21,6 +21,22 @@ type Handle struct {
lookupByDump bool
}
+// SetSocketTimeout configures timeout for default netlink sockets
+func SetSocketTimeout(to time.Duration) error {
+ if to < time.Microsecond {
+ return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
+ }
+
+ nl.SocketTimeoutTv = unix.NsecToTimeval(to.Nanoseconds())
+ return nil
+}
+
+// GetSocketTimeout returns the timeout value used by default netlink sockets
+func GetSocketTimeout() time.Duration {
+ nsec := unix.TimevalToNsec(nl.SocketTimeoutTv)
+ return time.Duration(nsec) * time.Nanosecond
+}
+
// SupportsNetlinkFamily reports whether the passed netlink family is supported by this Handle
func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
_, ok := h.sockets[nlFamily]
diff --git a/vendor/github.com/vishvananda/netlink/handle_unspecified.go b/vendor/github.com/vishvananda/netlink/handle_unspecified.go
index df341f706..3a6db8137 100644
--- a/vendor/github.com/vishvananda/netlink/handle_unspecified.go
+++ b/vendor/github.com/vishvananda/netlink/handle_unspecified.go
@@ -237,6 +237,10 @@ func (h *Handle) RouteAdd(route *Route) error {
return ErrNotImplemented
}
+func (h *Handle) RouteAppend(route *Route) error {
+ return ErrNotImplemented
+}
+
func (h *Handle) RouteDel(route *Route) error {
return ErrNotImplemented
}
diff --git a/vendor/github.com/vishvananda/netlink/inet_diag.go b/vendor/github.com/vishvananda/netlink/inet_diag.go
index 72c1fcb59..bee391a80 100644
--- a/vendor/github.com/vishvananda/netlink/inet_diag.go
+++ b/vendor/github.com/vishvananda/netlink/inet_diag.go
@@ -27,4 +27,5 @@ const (
type InetDiagTCPInfoResp struct {
InetDiagMsg *Socket
TCPInfo *TCPInfo
+ TCPBBRInfo *TCPBBRInfo
}
diff --git a/vendor/github.com/vishvananda/netlink/ipset_linux.go b/vendor/github.com/vishvananda/netlink/ipset_linux.go
index 5487fc1cc..2adc2440a 100644
--- a/vendor/github.com/vishvananda/netlink/ipset_linux.go
+++ b/vendor/github.com/vishvananda/netlink/ipset_linux.go
@@ -23,13 +23,15 @@ type IPSetEntry struct {
// IPSetResult is the result of a dump request for a set
type IPSetResult struct {
- Nfgenmsg *nl.Nfgenmsg
- Protocol uint8
- Revision uint8
- Family uint8
- Flags uint8
- SetName string
- TypeName string
+ Nfgenmsg *nl.Nfgenmsg
+ Protocol uint8
+ ProtocolMinVersion uint8
+ Revision uint8
+ Family uint8
+ Flags uint8
+ SetName string
+ TypeName string
+ Comment string
HashSize uint32
NumEntries uint32
@@ -38,6 +40,7 @@ type IPSetResult struct {
SizeInMemory uint32
CadtFlags uint32
Timeout *uint32
+ LineNo uint32
Entries []IPSetEntry
}
@@ -52,7 +55,7 @@ type IpsetCreateOptions struct {
}
// IpsetProtocol returns the ipset protocol version from the kernel
-func IpsetProtocol() (uint8, error) {
+func IpsetProtocol() (uint8, uint8, error) {
return pkgHandle.IpsetProtocol()
}
@@ -86,20 +89,20 @@ func IpsetAdd(setname string, entry *IPSetEntry) error {
return pkgHandle.ipsetAddDel(nl.IPSET_CMD_ADD, setname, entry)
}
-// IpsetDele deletes an entry from an existing ipset.
+// IpsetDel deletes an entry from an existing ipset.
func IpsetDel(setname string, entry *IPSetEntry) error {
return pkgHandle.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry)
}
-func (h *Handle) IpsetProtocol() (uint8, error) {
+func (h *Handle) IpsetProtocol() (protocol uint8, minVersion uint8, err error) {
req := h.newIpsetRequest(nl.IPSET_CMD_PROTOCOL)
msgs, err := req.Execute(unix.NETLINK_NETFILTER, 0)
if err != nil {
- return 0, err
+ return 0, 0, err
}
-
- return ipsetUnserialize(msgs).Protocol, nil
+ response := ipsetUnserialize(msgs)
+ return response.Protocol, response.ProtocolMinVersion, nil
}
func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOptions) error {
@@ -112,7 +115,7 @@ func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOption
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_TYPENAME, nl.ZeroTerminated(typename)))
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_REVISION, nl.Uint8Attr(0)))
- req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(0)))
+ req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(2))) // 2 == inet
data := nl.NewRtAttr(nl.IPSET_ATTR_DATA|int(nl.NLA_F_NESTED), nil)
@@ -187,6 +190,11 @@ func (h *Handle) IpsetListAll() ([]IPSetResult, error) {
func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error {
req := h.newIpsetRequest(nlCmd)
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
+
+ if entry.Comment != "" {
+ req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_COMMENT, nl.ZeroTerminated(entry.Comment)))
+ }
+
data := nl.NewRtAttr(nl.IPSET_ATTR_DATA|int(nl.NLA_F_NESTED), nil)
if !entry.Replace {
@@ -197,7 +205,12 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *entry.Timeout})
}
if entry.MAC != nil {
- data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_ETHER, entry.MAC))
+ nestedData := nl.NewRtAttr(nl.IPSET_ATTR_ETHER|int(nl.NLA_F_NET_BYTEORDER), entry.MAC)
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_ETHER|int(nl.NLA_F_NESTED), nestedData.Serialize()))
+ }
+ if entry.IP != nil {
+ nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP)
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NESTED), nestedData.Serialize()))
}
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_LINENO | nl.NLA_F_NET_BYTEORDER, Value: 0})
@@ -249,6 +262,8 @@ func (result *IPSetResult) unserialize(msg []byte) {
result.Protocol = attr.Value[0]
case nl.IPSET_ATTR_SETNAME:
result.SetName = nl.BytesToString(attr.Value)
+ case nl.IPSET_ATTR_COMMENT:
+ result.Comment = nl.BytesToString(attr.Value)
case nl.IPSET_ATTR_TYPENAME:
result.TypeName = nl.BytesToString(attr.Value)
case nl.IPSET_ATTR_REVISION:
@@ -261,6 +276,8 @@ func (result *IPSetResult) unserialize(msg []byte) {
result.parseAttrData(attr.Value)
case nl.IPSET_ATTR_ADT | nl.NLA_F_NESTED:
result.parseAttrADT(attr.Value)
+ case nl.IPSET_ATTR_PROTOCOL_MIN:
+ result.ProtocolMinVersion = attr.Value[0]
default:
log.Printf("unknown ipset attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
}
@@ -285,6 +302,17 @@ func (result *IPSetResult) parseAttrData(data []byte) {
result.SizeInMemory = attr.Uint32()
case nl.IPSET_ATTR_CADT_FLAGS | nl.NLA_F_NET_BYTEORDER:
result.CadtFlags = attr.Uint32()
+ case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED:
+ for nested := range nl.ParseAttributes(attr.Value) {
+ switch nested.Type {
+ case nl.IPSET_ATTR_IP | nl.NLA_F_NET_BYTEORDER:
+ result.Entries = append(result.Entries, IPSetEntry{IP: nested.Value})
+ }
+ }
+ case nl.IPSET_ATTR_CADT_LINENO | nl.NLA_F_NET_BYTEORDER:
+ result.LineNo = attr.Uint32()
+ case nl.IPSET_ATTR_COMMENT:
+ result.Comment = nl.BytesToString(attr.Value)
default:
log.Printf("unknown ipset data attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
}
@@ -316,6 +344,8 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) {
entry.Packets = &val
case nl.IPSET_ATTR_ETHER:
entry.MAC = net.HardwareAddr(attr.Value)
+ case nl.IPSET_ATTR_IP:
+ entry.IP = net.IP(attr.Value)
case nl.IPSET_ATTR_COMMENT:
entry.Comment = nl.BytesToString(attr.Value)
case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED:
diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go
index e2441bd71..32ca7cd64 100644
--- a/vendor/github.com/vishvananda/netlink/link.go
+++ b/vendor/github.com/vishvananda/netlink/link.go
@@ -555,6 +555,27 @@ const (
BOND_ARP_VALIDATE_ALL
)
+var bondArpValidateToString = map[BondArpValidate]string{
+ BOND_ARP_VALIDATE_NONE: "none",
+ BOND_ARP_VALIDATE_ACTIVE: "active",
+ BOND_ARP_VALIDATE_BACKUP: "backup",
+ BOND_ARP_VALIDATE_ALL: "none",
+}
+var StringToBondArpValidateMap = map[string]BondArpValidate{
+ "none": BOND_ARP_VALIDATE_NONE,
+ "active": BOND_ARP_VALIDATE_ACTIVE,
+ "backup": BOND_ARP_VALIDATE_BACKUP,
+ "all": BOND_ARP_VALIDATE_ALL,
+}
+
+func (b BondArpValidate) String() string {
+ s, ok := bondArpValidateToString[b]
+ if !ok {
+ return fmt.Sprintf("BondArpValidate(%d)", b)
+ }
+ return s
+}
+
// BondPrimaryReselect type
type BondPrimaryReselect int
@@ -565,6 +586,25 @@ const (
BOND_PRIMARY_RESELECT_FAILURE
)
+var bondPrimaryReselectToString = map[BondPrimaryReselect]string{
+ BOND_PRIMARY_RESELECT_ALWAYS: "always",
+ BOND_PRIMARY_RESELECT_BETTER: "better",
+ BOND_PRIMARY_RESELECT_FAILURE: "failure",
+}
+var StringToBondPrimaryReselectMap = map[string]BondPrimaryReselect{
+ "always": BOND_PRIMARY_RESELECT_ALWAYS,
+ "better": BOND_PRIMARY_RESELECT_BETTER,
+ "failure": BOND_PRIMARY_RESELECT_FAILURE,
+}
+
+func (b BondPrimaryReselect) String() string {
+ s, ok := bondPrimaryReselectToString[b]
+ if !ok {
+ return fmt.Sprintf("BondPrimaryReselect(%d)", b)
+ }
+ return s
+}
+
// BondArpAllTargets type
type BondArpAllTargets int
@@ -574,6 +614,23 @@ const (
BOND_ARP_ALL_TARGETS_ALL
)
+var bondArpAllTargetsToString = map[BondArpAllTargets]string{
+ BOND_ARP_ALL_TARGETS_ANY: "any",
+ BOND_ARP_ALL_TARGETS_ALL: "all",
+}
+var StringToBondArpAllTargetsMap = map[string]BondArpAllTargets{
+ "any": BOND_ARP_ALL_TARGETS_ANY,
+ "all": BOND_ARP_ALL_TARGETS_ALL,
+}
+
+func (b BondArpAllTargets) String() string {
+ s, ok := bondArpAllTargetsToString[b]
+ if !ok {
+ return fmt.Sprintf("BondArpAllTargets(%d)", b)
+ }
+ return s
+}
+
// BondFailOverMac type
type BondFailOverMac int
@@ -584,6 +641,25 @@ const (
BOND_FAIL_OVER_MAC_FOLLOW
)
+var bondFailOverMacToString = map[BondFailOverMac]string{
+ BOND_FAIL_OVER_MAC_NONE: "none",
+ BOND_FAIL_OVER_MAC_ACTIVE: "active",
+ BOND_FAIL_OVER_MAC_FOLLOW: "follow",
+}
+var StringToBondFailOverMacMap = map[string]BondFailOverMac{
+ "none": BOND_FAIL_OVER_MAC_NONE,
+ "active": BOND_FAIL_OVER_MAC_ACTIVE,
+ "follow": BOND_FAIL_OVER_MAC_FOLLOW,
+}
+
+func (b BondFailOverMac) String() string {
+ s, ok := bondFailOverMacToString[b]
+ if !ok {
+ return fmt.Sprintf("BondFailOverMac(%d)", b)
+ }
+ return s
+}
+
// BondXmitHashPolicy type
type BondXmitHashPolicy int
@@ -675,6 +751,25 @@ const (
BOND_AD_SELECT_COUNT
)
+var bondAdSelectToString = map[BondAdSelect]string{
+ BOND_AD_SELECT_STABLE: "stable",
+ BOND_AD_SELECT_BANDWIDTH: "bandwidth",
+ BOND_AD_SELECT_COUNT: "count",
+}
+var StringToBondAdSelectMap = map[string]BondAdSelect{
+ "stable": BOND_AD_SELECT_STABLE,
+ "bandwidth": BOND_AD_SELECT_BANDWIDTH,
+ "count": BOND_AD_SELECT_COUNT,
+}
+
+func (b BondAdSelect) String() string {
+ s, ok := bondAdSelectToString[b]
+ if !ok {
+ return fmt.Sprintf("BondAdSelect(%d)", b)
+ }
+ return s
+}
+
// BondAdInfo represents ad info for bond
type BondAdInfo struct {
AggregatorId int
@@ -706,7 +801,7 @@ type Bond struct {
AllSlavesActive int
MinLinks int
LpInterval int
- PackersPerSlave int
+ PacketsPerSlave int
LacpRate BondLacpRate
AdSelect BondAdSelect
// looking at iproute tool AdInfo can only be retrived. It can't be set.
@@ -739,7 +834,7 @@ func NewLinkBond(atr LinkAttrs) *Bond {
AllSlavesActive: -1,
MinLinks: -1,
LpInterval: -1,
- PackersPerSlave: -1,
+ PacketsPerSlave: -1,
LacpRate: -1,
AdSelect: -1,
AdActorSysPrio: -1,
@@ -789,8 +884,10 @@ func (bond *Bond) Type() string {
type BondSlaveState uint8
const (
- BondStateActive = iota // Link is active.
- BondStateBackup // Link is backup.
+ //BondStateActive Link is active.
+ BondStateActive BondSlaveState = iota
+ //BondStateBackup Link is backup.
+ BondStateBackup
)
func (s BondSlaveState) String() string {
@@ -804,15 +901,19 @@ func (s BondSlaveState) String() string {
}
}
-// BondSlaveState represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave
+// BondSlaveMiiStatus represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave
// attribute, which contains the status of MII link monitoring
type BondSlaveMiiStatus uint8
const (
- BondLinkUp = iota // link is up and running.
- BondLinkFail // link has just gone down.
- BondLinkDown // link has been down for too long time.
- BondLinkBack // link is going back.
+ //BondLinkUp link is up and running.
+ BondLinkUp BondSlaveMiiStatus = iota
+ //BondLinkFail link has just gone down.
+ BondLinkFail
+ //BondLinkDown link has been down for too long time.
+ BondLinkDown
+ //BondLinkBack link is going back.
+ BondLinkBack
)
func (s BondSlaveMiiStatus) String() string {
@@ -845,6 +946,30 @@ func (b *BondSlave) SlaveType() string {
return "bond"
}
+// Geneve devices must specify RemoteIP and ID (VNI) on create
+// https://github.com/torvalds/linux/blob/47ec5303d73ea344e84f46660fff693c57641386/drivers/net/geneve.c#L1209-L1223
+type Geneve struct {
+ LinkAttrs
+ ID uint32 // vni
+ Remote net.IP
+ Ttl uint8
+ Tos uint8
+ Dport uint16
+ UdpCsum uint8
+ UdpZeroCsum6Tx uint8
+ UdpZeroCsum6Rx uint8
+ Link uint32
+ FlowBased bool
+}
+
+func (geneve *Geneve) Attrs() *LinkAttrs {
+ return &geneve.LinkAttrs
+}
+
+func (geneve *Geneve) Type() string {
+ return "geneve"
+}
+
// Gretap devices must specify LocalIP and RemoteIP on create
type Gretap struct {
LinkAttrs
@@ -1068,6 +1193,58 @@ var StringToIPoIBMode = map[string]IPoIBMode{
"connected": IPOIB_MODE_CONNECTED,
}
+const (
+ CAN_STATE_ERROR_ACTIVE = iota
+ CAN_STATE_ERROR_WARNING
+ CAN_STATE_ERROR_PASSIVE
+ CAN_STATE_BUS_OFF
+ CAN_STATE_STOPPED
+ CAN_STATE_SLEEPING
+)
+
+type Can struct {
+ LinkAttrs
+
+ BitRate uint32
+ SamplePoint uint32
+ TimeQuanta uint32
+ PropagationSegment uint32
+ PhaseSegment1 uint32
+ PhaseSegment2 uint32
+ SyncJumpWidth uint32
+ BitRatePreScaler uint32
+
+ Name string
+ TimeSegment1Min uint32
+ TimeSegment1Max uint32
+ TimeSegment2Min uint32
+ TimeSegment2Max uint32
+ SyncJumpWidthMax uint32
+ BitRatePreScalerMin uint32
+ BitRatePreScalerMax uint32
+ BitRatePreScalerInc uint32
+
+ ClockFrequency uint32
+
+ State uint32
+
+ Mask uint32
+ Flags uint32
+
+ TxError uint16
+ RxError uint16
+
+ RestartMs uint32
+}
+
+func (can *Can) Attrs() *LinkAttrs {
+ return &can.LinkAttrs
+}
+
+func (can *Can) Type() string {
+ return "can"
+}
+
type IPoIB struct {
LinkAttrs
Pkey uint16
diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go
index c02fa63b8..3b959299c 100644
--- a/vendor/github.com/vishvananda/netlink/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/link_linux.go
@@ -34,6 +34,21 @@ const (
TUNTAP_MULTI_QUEUE_DEFAULTS TuntapFlag = TUNTAP_MULTI_QUEUE | TUNTAP_NO_PI
)
+var StringToTuntapModeMap = map[string]TuntapMode{
+ "tun": TUNTAP_MODE_TUN,
+ "tap": TUNTAP_MODE_TAP,
+}
+
+func (ttm TuntapMode) String() string {
+ switch ttm {
+ case TUNTAP_MODE_TUN:
+ return "tun"
+ case TUNTAP_MODE_TAP:
+ return "tap"
+ }
+ return "unknown"
+}
+
const (
VF_LINK_STATE_AUTO uint32 = 0
VF_LINK_STATE_ENABLE uint32 = 1
@@ -1046,8 +1061,8 @@ func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) {
if bond.LpInterval >= 0 {
data.AddRtAttr(nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval)))
}
- if bond.PackersPerSlave >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PackersPerSlave)))
+ if bond.PacketsPerSlave >= 0 {
+ data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PacketsPerSlave)))
}
if bond.LacpRate >= 0 {
data.AddRtAttr(nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate)))
@@ -1404,6 +1419,8 @@ func (h *Handle) linkModify(link Link, flags int) error {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
}
+ case *Geneve:
+ addGeneveAttrs(link, linkInfo)
case *Gretap:
addGretapAttrs(link, linkInfo)
case *Iptun:
@@ -1667,6 +1684,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Macvlan{}
case "macvtap":
link = &Macvtap{}
+ case "geneve":
+ link = &Geneve{}
case "gretap":
link = &Gretap{}
case "ip6gretap":
@@ -1693,6 +1712,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Tuntap{}
case "ipoib":
link = &IPoIB{}
+ case "can":
+ link = &Can{}
default:
link = &GenericLink{LinkType: linkType}
}
@@ -1714,6 +1735,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseMacvlanData(link, data)
case "macvtap":
parseMacvtapData(link, data)
+ case "geneve":
+ parseGeneveData(link, data)
case "gretap":
parseGretapData(link, data)
case "ip6gretap":
@@ -1742,6 +1765,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseTuntapData(link, data)
case "ipoib":
parseIPoIBData(link, data)
+ case "can":
+ parseCanData(link, data)
}
case nl.IFLA_INFO_SLAVE_KIND:
slaveType = string(info.Value[:len(info.Value)-1])
@@ -2299,7 +2324,7 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
case nl.IFLA_BOND_LP_INTERVAL:
bond.LpInterval = int(native.Uint32(data[i].Value[0:4]))
case nl.IFLA_BOND_PACKETS_PER_SLAVE:
- bond.PackersPerSlave = int(native.Uint32(data[i].Value[0:4]))
+ bond.PacketsPerSlave = int(native.Uint32(data[i].Value[0:4]))
case nl.IFLA_BOND_AD_LACP_RATE:
bond.LacpRate = BondLacpRate(data[i].Value[0])
case nl.IFLA_BOND_AD_SELECT:
@@ -2448,6 +2473,58 @@ func linkFlags(rawFlags uint32) net.Flags {
return f
}
+func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+
+ if geneve.FlowBased {
+ // In flow based mode, no other attributes need to be configured
+ linkInfo.AddRtAttr(nl.IFLA_GENEVE_COLLECT_METADATA, boolAttr(geneve.FlowBased))
+ return
+ }
+
+ if ip := geneve.Remote; ip != nil {
+ if ip4 := ip.To4(); ip4 != nil {
+ data.AddRtAttr(nl.IFLA_GENEVE_REMOTE, ip.To4())
+ } else {
+ data.AddRtAttr(nl.IFLA_GENEVE_REMOTE6, []byte(ip))
+ }
+ }
+
+ if geneve.ID != 0 {
+ data.AddRtAttr(nl.IFLA_GENEVE_ID, nl.Uint32Attr(geneve.ID))
+ }
+
+ if geneve.Dport != 0 {
+ data.AddRtAttr(nl.IFLA_GENEVE_PORT, htons(geneve.Dport))
+ }
+
+ if geneve.Ttl != 0 {
+ data.AddRtAttr(nl.IFLA_GENEVE_TTL, nl.Uint8Attr(geneve.Ttl))
+ }
+
+ if geneve.Tos != 0 {
+ data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos))
+ }
+}
+
+func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) {
+ geneve := link.(*Geneve)
+ for _, datum := range data {
+ switch datum.Attr.Type {
+ case nl.IFLA_GENEVE_ID:
+ geneve.ID = native.Uint32(datum.Value[0:4])
+ case nl.IFLA_GENEVE_REMOTE, nl.IFLA_GENEVE_REMOTE6:
+ geneve.Remote = datum.Value
+ case nl.IFLA_GENEVE_PORT:
+ geneve.Dport = ntohs(datum.Value[0:2])
+ case nl.IFLA_GENEVE_TTL:
+ geneve.Ttl = uint8(datum.Value[0])
+ case nl.IFLA_GENEVE_TOS:
+ geneve.Tos = uint8(datum.Value[0])
+ }
+ }
+}
+
func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
@@ -3172,6 +3249,54 @@ func parseIPoIBData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
+func parseCanData(link Link, data []syscall.NetlinkRouteAttr) {
+ can := link.(*Can)
+ for _, datum := range data {
+
+ switch datum.Attr.Type {
+ case nl.IFLA_CAN_BITTIMING:
+ can.BitRate = native.Uint32(datum.Value)
+ can.SamplePoint = native.Uint32(datum.Value[4:])
+ can.TimeQuanta = native.Uint32(datum.Value[8:])
+ can.PropagationSegment = native.Uint32(datum.Value[12:])
+ can.PhaseSegment1 = native.Uint32(datum.Value[16:])
+ can.PhaseSegment2 = native.Uint32(datum.Value[20:])
+ can.SyncJumpWidth = native.Uint32(datum.Value[24:])
+ can.BitRatePreScaler = native.Uint32(datum.Value[28:])
+ case nl.IFLA_CAN_BITTIMING_CONST:
+ can.Name = string(datum.Value[:16])
+ can.TimeSegment1Min = native.Uint32(datum.Value[16:])
+ can.TimeSegment1Max = native.Uint32(datum.Value[20:])
+ can.TimeSegment2Min = native.Uint32(datum.Value[24:])
+ can.TimeSegment2Max = native.Uint32(datum.Value[28:])
+ can.SyncJumpWidthMax = native.Uint32(datum.Value[32:])
+ can.BitRatePreScalerMin = native.Uint32(datum.Value[36:])
+ can.BitRatePreScalerMax = native.Uint32(datum.Value[40:])
+ can.BitRatePreScalerInc = native.Uint32(datum.Value[44:])
+ case nl.IFLA_CAN_CLOCK:
+ can.ClockFrequency = native.Uint32(datum.Value)
+ case nl.IFLA_CAN_STATE:
+ can.State = native.Uint32(datum.Value)
+ case nl.IFLA_CAN_CTRLMODE:
+ can.Mask = native.Uint32(datum.Value)
+ can.Flags = native.Uint32(datum.Value[4:])
+ case nl.IFLA_CAN_BERR_COUNTER:
+ can.TxError = native.Uint16(datum.Value)
+ can.RxError = native.Uint16(datum.Value[2:])
+ case nl.IFLA_CAN_RESTART_MS:
+ can.RestartMs = native.Uint32(datum.Value)
+ case nl.IFLA_CAN_DATA_BITTIMING_CONST:
+ case nl.IFLA_CAN_RESTART:
+ case nl.IFLA_CAN_DATA_BITTIMING:
+ case nl.IFLA_CAN_TERMINATION:
+ case nl.IFLA_CAN_TERMINATION_CONST:
+ case nl.IFLA_CAN_BITRATE_CONST:
+ case nl.IFLA_CAN_DATA_BITRATE_CONST:
+ case nl.IFLA_CAN_BITRATE_MAX:
+ }
+ }
+}
+
func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
data.AddRtAttr(nl.IFLA_IPOIB_PKEY, nl.Uint16Attr(uint16(ipoib.Pkey)))
diff --git a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
index db66faaad..aa6155e21 100644
--- a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
@@ -10,6 +10,7 @@ const (
const (
DEVLINK_CMD_GET = 1
+ DEVLINK_CMD_PORT_GET = 5
DEVLINK_CMD_ESWITCH_GET = 29
DEVLINK_CMD_ESWITCH_SET = 30
)
@@ -17,9 +18,15 @@ const (
const (
DEVLINK_ATTR_BUS_NAME = 1
DEVLINK_ATTR_DEV_NAME = 2
+ DEVLINK_ATTR_PORT_INDEX = 3
+ DEVLINK_ATTR_PORT_TYPE = 4
+ DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
+ DEVLINK_ATTR_PORT_NETDEV_NAME = 7
+ DEVLINK_ATTR_PORT_IBDEV_NAME = 8
DEVLINK_ATTR_ESWITCH_MODE = 25
DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
+ DEVLINK_ATTR_PORT_FLAVOUR = 77
)
const (
@@ -38,3 +45,19 @@ const (
DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0
DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 1
)
+
+const (
+ DEVLINK_PORT_FLAVOUR_PHYSICAL = 0
+ DEVLINK_PORT_FLAVOUR_CPU = 1
+ DEVLINK_PORT_FLAVOUR_DSA = 2
+ DEVLINK_PORT_FLAVOUR_PCI_PF = 3
+ DEVLINK_PORT_FLAVOUR_PCI_VF = 4
+ DEVLINK_PORT_FLAVOUR_VIRTUAL = 5
+)
+
+const (
+ DEVLINK_PORT_TYPE_NOTSET = 0
+ DEVLINK_PORT_TYPE_AUTO = 1
+ DEVLINK_PORT_TYPE_ETH = 2
+ DEVLINK_PORT_TYPE_IB = 3
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
index faee2fa03..c72cc436e 100644
--- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
@@ -174,6 +174,22 @@ const (
)
const (
+ IFLA_GENEVE_UNSPEC = iota
+ IFLA_GENEVE_ID // vni
+ IFLA_GENEVE_REMOTE
+ IFLA_GENEVE_TTL
+ IFLA_GENEVE_TOS
+ IFLA_GENEVE_PORT // destination port
+ IFLA_GENEVE_COLLECT_METADATA
+ IFLA_GENEVE_REMOTE6
+ IFLA_GENEVE_UDP_CSUM
+ IFLA_GENEVE_UDP_ZERO_CSUM6_TX
+ IFLA_GENEVE_UDP_ZERO_CSUM6_RX
+ IFLA_GENEVE_LABEL
+ IFLA_GENEVE_MAX = IFLA_GENEVE_LABEL
+)
+
+const (
IFLA_GRE_UNSPEC = iota
IFLA_GRE_LINK
IFLA_GRE_IFLAGS
@@ -673,3 +689,23 @@ const (
IFLA_IPOIB_UMCAST
IFLA_IPOIB_MAX = IFLA_IPOIB_UMCAST
)
+
+const (
+ IFLA_CAN_UNSPEC = iota
+ IFLA_CAN_BITTIMING
+ IFLA_CAN_BITTIMING_CONST
+ IFLA_CAN_CLOCK
+ IFLA_CAN_STATE
+ IFLA_CAN_CTRLMODE
+ IFLA_CAN_RESTART_MS
+ IFLA_CAN_RESTART
+ IFLA_CAN_BERR_COUNTER
+ IFLA_CAN_DATA_BITTIMING
+ IFLA_CAN_DATA_BITTIMING_CONST
+ IFLA_CAN_TERMINATION
+ IFLA_CAN_TERMINATION_CONST
+ IFLA_CAN_BITRATE_CONST
+ IFLA_CAN_DATA_BITRATE_CONST
+ IFLA_CAN_BITRATE_MAX
+ IFLA_CAN_MAX = IFLA_CAN_BITRATE_MAX
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
index cef64b82e..dcd4b9469 100644
--- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
@@ -35,6 +35,9 @@ var SupportedNlFamilies = []int{unix.NETLINK_ROUTE, unix.NETLINK_XFRM, unix.NETL
var nextSeqNr uint32
+// Default netlink socket timeout, 60s
+var SocketTimeoutTv = unix.Timeval{Sec: 60, Usec: 0}
+
// GetIPFamily returns the family type of a net.IP.
func GetIPFamily(ip net.IP) int {
if len(ip) <= net.IPv4len {
@@ -426,6 +429,14 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
if err != nil {
return nil, err
}
+
+ if err := s.SetSendTimeout(&SocketTimeoutTv); err != nil {
+ return nil, err
+ }
+ if err := s.SetReceiveTimeout(&SocketTimeoutTv); err != nil {
+ return nil, err
+ }
+
defer s.Close()
} else {
s.Lock()
diff --git a/vendor/github.com/vishvananda/netlink/nl/parse_attr.go b/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go
index 19eb8f28e..7f49125cf 100644
--- a/vendor/github.com/vishvananda/netlink/nl/parse_attr.go
+++ b/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go
@@ -3,6 +3,7 @@ package nl
import (
"encoding/binary"
"fmt"
+ "log"
)
type Attribute struct {
@@ -18,9 +19,20 @@ func ParseAttributes(data []byte) <-chan Attribute {
i := 0
for i+4 < len(data) {
length := int(native.Uint16(data[i : i+2]))
+ attrType := native.Uint16(data[i+2 : i+4])
+
+ if length < 4 {
+ log.Printf("attribute 0x%02x has invalid length of %d bytes", attrType, length)
+ break
+ }
+
+ if len(data) < i+length {
+ log.Printf("attribute 0x%02x of length %d is truncated, only %d bytes remaining", attrType, length, len(data)-i)
+ break
+ }
result <- Attribute{
- Type: native.Uint16(data[i+2 : i+4]),
+ Type: attrType,
Value: data[i+4 : i+length],
}
i += rtaAlignOf(length)
diff --git a/vendor/github.com/vishvananda/netlink/qdisc.go b/vendor/github.com/vishvananda/netlink/qdisc.go
index 8418569ee..f594c9c21 100644
--- a/vendor/github.com/vishvananda/netlink/qdisc.go
+++ b/vendor/github.com/vishvananda/netlink/qdisc.go
@@ -308,13 +308,15 @@ func (qdisc *Fq) Type() string {
// FQ_Codel (Fair Queuing Controlled Delay) is queuing discipline that combines Fair Queuing with the CoDel AQM scheme.
type FqCodel struct {
QdiscAttrs
- Target uint32
- Limit uint32
- Interval uint32
- ECN uint32
- Flows uint32
- Quantum uint32
- // There are some more attributes here, but support for them seems not ubiquitous
+ Target uint32
+ Limit uint32
+ Interval uint32
+ ECN uint32
+ Flows uint32
+ Quantum uint32
+ CEThreshold uint32
+ DropBatchSize uint32
+ MemoryLimit uint32
}
func (fqcodel *FqCodel) String() string {
diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
index d0e1ca194..edc4b726a 100644
--- a/vendor/github.com/vishvananda/netlink/qdisc_linux.go
+++ b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
@@ -250,7 +250,15 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
if qdisc.Quantum > 0 {
options.AddRtAttr(nl.TCA_FQ_CODEL_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum))))
}
-
+ if qdisc.CEThreshold > 0 {
+ options.AddRtAttr(nl.TCA_FQ_CODEL_CE_THRESHOLD, nl.Uint32Attr(qdisc.CEThreshold))
+ }
+ if qdisc.DropBatchSize > 0 {
+ options.AddRtAttr(nl.TCA_FQ_CODEL_DROP_BATCH_SIZE, nl.Uint32Attr(qdisc.DropBatchSize))
+ }
+ if qdisc.MemoryLimit > 0 {
+ options.AddRtAttr(nl.TCA_FQ_CODEL_MEMORY_LIMIT, nl.Uint32Attr(qdisc.MemoryLimit))
+ }
case *Fq:
options.AddRtAttr(nl.TCA_FQ_RATE_ENABLE, nl.Uint32Attr((uint32(qdisc.Pacing))))
@@ -497,6 +505,12 @@ func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
fqCodel.Flows = native.Uint32(datum.Value)
case nl.TCA_FQ_CODEL_QUANTUM:
fqCodel.Quantum = native.Uint32(datum.Value)
+ case nl.TCA_FQ_CODEL_CE_THRESHOLD:
+ fqCodel.CEThreshold = native.Uint32(datum.Value)
+ case nl.TCA_FQ_CODEL_DROP_BATCH_SIZE:
+ fqCodel.DropBatchSize = native.Uint32(datum.Value)
+ case nl.TCA_FQ_CODEL_MEMORY_LIMIT:
+ fqCodel.MemoryLimit = native.Uint32(datum.Value)
}
}
return nil
diff --git a/vendor/github.com/vishvananda/netlink/route.go b/vendor/github.com/vishvananda/netlink/route.go
index b16254174..845f41808 100644
--- a/vendor/github.com/vishvananda/netlink/route.go
+++ b/vendor/github.com/vishvananda/netlink/route.go
@@ -27,6 +27,9 @@ type Encap interface {
Equal(Encap) bool
}
+//Protocol describe what was the originator of the route
+type RouteProtocol int
+
// Route represents a netlink route.
type Route struct {
LinkIndex int
@@ -36,7 +39,7 @@ type Route struct {
Src net.IP
Gw net.IP
MultiPath []*NexthopInfo
- Protocol int
+ Protocol RouteProtocol
Priority int
Table int
Type int
@@ -45,6 +48,7 @@ type Route struct {
MPLSDst *int
NewDst Destination
Encap Encap
+ Via Destination
MTU int
Window int
Rtt int
@@ -79,6 +83,9 @@ func (r Route) String() string {
if r.Encap != nil {
elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap))
}
+ if r.Via != nil {
+ elems = append(elems, fmt.Sprintf("Via: %s", r.Via))
+ }
elems = append(elems, fmt.Sprintf("Src: %s", r.Src))
if len(r.MultiPath) > 0 {
elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath))
@@ -107,6 +114,7 @@ func (r Route) Equal(x Route) bool {
r.Flags == x.Flags &&
(r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) &&
(r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) &&
+ (r.Via == x.Via || (r.Via != nil && r.Via.Equal(x.Via))) &&
(r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap)))
}
@@ -136,6 +144,7 @@ type NexthopInfo struct {
Flags int
NewDst Destination
Encap Encap
+ Via Destination
}
func (n *NexthopInfo) String() string {
@@ -147,6 +156,9 @@ func (n *NexthopInfo) String() string {
if n.Encap != nil {
elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap))
}
+ if n.Via != nil {
+ elems = append(elems, fmt.Sprintf("Via: %s", n.Via))
+ }
elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1))
elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw))
elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags()))
diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go
index 4e778a417..32641cb0d 100644
--- a/vendor/github.com/vishvananda/netlink/route_linux.go
+++ b/vendor/github.com/vishvananda/netlink/route_linux.go
@@ -1,8 +1,11 @@
package netlink
import (
+ "bytes"
+ "encoding/binary"
"fmt"
"net"
+ "strconv"
"strings"
"syscall"
@@ -21,6 +24,23 @@ const (
SCOPE_NOWHERE Scope = unix.RT_SCOPE_NOWHERE
)
+func (s Scope) String() string {
+ switch s {
+ case SCOPE_UNIVERSE:
+ return "universe"
+ case SCOPE_SITE:
+ return "site"
+ case SCOPE_LINK:
+ return "link"
+ case SCOPE_HOST:
+ return "host"
+ case SCOPE_NOWHERE:
+ return "nowhere"
+ default:
+ return "unknown"
+ }
+}
+
const (
RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota)
RT_FILTER_SCOPE
@@ -446,6 +466,62 @@ func (e *SEG6LocalEncap) Equal(x Encap) bool {
return true
}
+type Via struct {
+ AddrFamily int
+ Addr net.IP
+}
+
+func (v *Via) Equal(x Destination) bool {
+ o, ok := x.(*Via)
+ if !ok {
+ return false
+ }
+ if v.AddrFamily == x.Family() && v.Addr.Equal(o.Addr) {
+ return true
+ }
+ return false
+}
+
+func (v *Via) String() string {
+ return fmt.Sprintf("Family: %d, Address: %s", v.AddrFamily, v.Addr.String())
+}
+
+func (v *Via) Family() int {
+ return v.AddrFamily
+}
+
+func (v *Via) Encode() ([]byte, error) {
+ buf := &bytes.Buffer{}
+ err := binary.Write(buf, native, uint16(v.AddrFamily))
+ if err != nil {
+ return nil, err
+ }
+ err = binary.Write(buf, native, v.Addr)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+func (v *Via) Decode(b []byte) error {
+ native := nl.NativeEndian()
+ if len(b) < 6 {
+ return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b))
+ }
+ v.AddrFamily = int(native.Uint16(b[0:2]))
+ if v.AddrFamily == nl.FAMILY_V4 {
+ v.Addr = net.IP(b[2:6])
+ return nil
+ } else if v.AddrFamily == nl.FAMILY_V6 {
+ if len(b) < 18 {
+ return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b))
+ }
+ v.Addr = net.IP(b[2:])
+ return nil
+ }
+ return fmt.Errorf("decoding failed: address family %d unknown", v.AddrFamily)
+}
+
// RouteAdd will add a route to the system.
// Equivalent to: `ip route add $route`
func RouteAdd(route *Route) error {
@@ -460,6 +536,32 @@ func (h *Handle) RouteAdd(route *Route) error {
return h.routeHandle(route, req, nl.NewRtMsg())
}
+// RouteAppend will append a route to the system.
+// Equivalent to: `ip route append $route`
+func RouteAppend(route *Route) error {
+ return pkgHandle.RouteAppend(route)
+}
+
+// RouteAppend will append a route to the system.
+// Equivalent to: `ip route append $route`
+func (h *Handle) RouteAppend(route *Route) error {
+ flags := unix.NLM_F_CREATE | unix.NLM_F_APPEND | unix.NLM_F_ACK
+ req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
+ return h.routeHandle(route, req, nl.NewRtMsg())
+}
+
+// RouteAddEcmp will add a route to the system.
+func RouteAddEcmp(route *Route) error {
+ return pkgHandle.RouteAddEcmp(route)
+}
+
+// RouteAddEcmp will add a route to the system.
+func (h *Handle) RouteAddEcmp(route *Route) error {
+ flags := unix.NLM_F_CREATE | unix.NLM_F_ACK
+ req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
+ return h.routeHandle(route, req, nl.NewRtMsg())
+}
+
// RouteReplace will add a route to the system.
// Equivalent to: `ip route replace $route`
func RouteReplace(route *Route) error {
@@ -567,6 +669,14 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_GATEWAY, gwData))
}
+ if route.Via != nil {
+ buf, err := route.Via.Encode()
+ if err != nil {
+ return fmt.Errorf("failed to encode RTA_VIA: %v", err)
+ }
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_VIA, buf))
+ }
+
if len(route.MultiPath) > 0 {
buf := []byte{}
for _, nh := range route.MultiPath {
@@ -609,6 +719,13 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
}
children = append(children, nl.NewRtAttr(unix.RTA_ENCAP, buf))
}
+ if nh.Via != nil {
+ buf, err := nh.Via.Encode()
+ if err != nil {
+ return err
+ }
+ children = append(children, nl.NewRtAttr(unix.RTA_VIA, buf))
+ }
rtnh.Children = children
buf = append(buf, rtnh.Serialize()...)
}
@@ -834,7 +951,7 @@ func deserializeRoute(m []byte) (Route, error) {
}
route := Route{
Scope: Scope(msg.Scope),
- Protocol: int(msg.Protocol),
+ Protocol: RouteProtocol(int(msg.Protocol)),
Table: int(msg.Table),
Type: int(msg.Type),
Tos: int(msg.Tos),
@@ -907,6 +1024,12 @@ func deserializeRoute(m []byte) (Route, error) {
encapType = attr
case unix.RTA_ENCAP:
encap = attr
+ case unix.RTA_VIA:
+ d := &Via{}
+ if err := d.Decode(attr.Value); err != nil {
+ return nil, nil, err
+ }
+ info.Via = d
}
}
@@ -944,6 +1067,12 @@ func deserializeRoute(m []byte) (Route, error) {
return route, err
}
route.NewDst = d
+ case unix.RTA_VIA:
+ v := &Via{}
+ if err := v.Decode(attr.Value); err != nil {
+ return route, err
+ }
+ route.Via = v
case unix.RTA_ENCAP_TYPE:
encapType = attr
case unix.RTA_ENCAP:
@@ -1022,6 +1151,7 @@ func deserializeRoute(m []byte) (Route, error) {
// RouteGetWithOptions
type RouteGetOptions struct {
VrfName string
+ SrcAddr net.IP
}
// RouteGetWithOptions gets a route to a specific destination from the host system.
@@ -1053,23 +1183,40 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
msg := &nl.RtMsg{}
msg.Family = uint8(family)
msg.Dst_len = bitlen
+ if options != nil && options.SrcAddr != nil {
+ msg.Src_len = bitlen
+ }
+ msg.Flags = unix.RTM_F_LOOKUP_TABLE
req.AddData(msg)
rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData)
req.AddData(rtaDst)
if options != nil {
- link, err := LinkByName(options.VrfName)
- if err != nil {
- return nil, err
+ if options.VrfName != "" {
+ link, err := LinkByName(options.VrfName)
+ if err != nil {
+ return nil, err
+ }
+ var (
+ b = make([]byte, 4)
+ native = nl.NativeEndian()
+ )
+ native.PutUint32(b, uint32(link.Attrs().Index))
+
+ req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
}
- var (
- b = make([]byte, 4)
- native = nl.NativeEndian()
- )
- native.PutUint32(b, uint32(link.Attrs().Index))
- req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
+ if options.SrcAddr != nil {
+ var srcAddr []byte
+ if family == FAMILY_V4 {
+ srcAddr = options.SrcAddr.To4()
+ } else {
+ srcAddr = options.SrcAddr.To16()
+ }
+
+ req.AddData(nl.NewRtAttr(unix.RTA_SRC, srcAddr))
+ }
}
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
@@ -1190,3 +1337,54 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
return nil
}
+
+func (p RouteProtocol) String() string {
+ switch int(p) {
+ case unix.RTPROT_BABEL:
+ return "babel"
+ case unix.RTPROT_BGP:
+ return "bgp"
+ case unix.RTPROT_BIRD:
+ return "bird"
+ case unix.RTPROT_BOOT:
+ return "boot"
+ case unix.RTPROT_DHCP:
+ return "dhcp"
+ case unix.RTPROT_DNROUTED:
+ return "dnrouted"
+ case unix.RTPROT_EIGRP:
+ return "eigrp"
+ case unix.RTPROT_GATED:
+ return "gated"
+ case unix.RTPROT_ISIS:
+ return "isis"
+ //case unix.RTPROT_KEEPALIVED:
+ // return "keepalived"
+ case unix.RTPROT_KERNEL:
+ return "kernel"
+ case unix.RTPROT_MROUTED:
+ return "mrouted"
+ case unix.RTPROT_MRT:
+ return "mrt"
+ case unix.RTPROT_NTK:
+ return "ntk"
+ case unix.RTPROT_OSPF:
+ return "ospf"
+ case unix.RTPROT_RA:
+ return "ra"
+ case unix.RTPROT_REDIRECT:
+ return "redirect"
+ case unix.RTPROT_RIP:
+ return "rip"
+ case unix.RTPROT_STATIC:
+ return "static"
+ case unix.RTPROT_UNSPEC:
+ return "unspec"
+ case unix.RTPROT_XORP:
+ return "xorp"
+ case unix.RTPROT_ZEBRA:
+ return "zebra"
+ default:
+ return strconv.Itoa(int(p))
+ }
+}
diff --git a/vendor/github.com/vishvananda/netlink/route_unspecified.go b/vendor/github.com/vishvananda/netlink/route_unspecified.go
index 2701862b4..db7372689 100644
--- a/vendor/github.com/vishvananda/netlink/route_unspecified.go
+++ b/vendor/github.com/vishvananda/netlink/route_unspecified.go
@@ -2,6 +2,8 @@
package netlink
+import "strconv"
+
func (r *Route) ListFlags() []string {
return []string{}
}
@@ -9,3 +11,11 @@ func (r *Route) ListFlags() []string {
func (n *NexthopInfo) ListFlags() []string {
return []string{}
}
+
+func (s Scope) String() string {
+ return "unknown"
+}
+
+func (p RouteProtocol) String() string {
+ return strconv.Itoa(int(p))
+}
diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go
index e4e7f7ac3..9b0f4a081 100644
--- a/vendor/github.com/vishvananda/netlink/socket_linux.go
+++ b/vendor/github.com/vishvananda/netlink/socket_linux.go
@@ -184,7 +184,7 @@ func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
req.AddData(&socketRequest{
Family: family,
Protocol: unix.IPPROTO_TCP,
- Ext: INET_DIAG_INFO,
+ Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)),
States: uint32(0xfff), // All TCP states
})
s.Send(req)
@@ -220,19 +220,42 @@ loop:
if err != nil {
return nil, err
}
- var tcpInfo *TCPInfo
- for _, a := range attrs {
- if a.Attr.Type == INET_DIAG_INFO {
- tcpInfo = &TCPInfo{}
- if err := tcpInfo.deserialize(a.Value); err != nil {
- return nil, err
- }
- break
- }
+
+ res, err := attrsToInetDiagTCPInfoResp(attrs, sockInfo)
+ if err != nil {
+ return nil, err
}
- r := &InetDiagTCPInfoResp{InetDiagMsg: sockInfo, TCPInfo: tcpInfo}
- result = append(result, r)
+
+ result = append(result, res)
}
}
return result, nil
}
+
+func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) {
+ var tcpInfo *TCPInfo
+ var tcpBBRInfo *TCPBBRInfo
+ for _, a := range attrs {
+ if a.Attr.Type == INET_DIAG_INFO {
+ tcpInfo = &TCPInfo{}
+ if err := tcpInfo.deserialize(a.Value); err != nil {
+ return nil, err
+ }
+ continue
+ }
+
+ if a.Attr.Type == INET_DIAG_BBRINFO {
+ tcpBBRInfo = &TCPBBRInfo{}
+ if err := tcpBBRInfo.deserialize(a.Value); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ }
+
+ return &InetDiagTCPInfoResp{
+ InetDiagMsg: sockInfo,
+ TCPInfo: tcpInfo,
+ TCPBBRInfo: tcpBBRInfo,
+ }, nil
+}
diff --git a/vendor/github.com/vishvananda/netlink/tcp.go b/vendor/github.com/vishvananda/netlink/tcp.go
index 4a42ee5a6..23ca014d4 100644
--- a/vendor/github.com/vishvananda/netlink/tcp.go
+++ b/vendor/github.com/vishvananda/netlink/tcp.go
@@ -16,3 +16,69 @@ const (
TCP_NEW_SYN_REC
TCP_MAX_STATES
)
+
+type TCPInfo struct {
+ State uint8
+ Ca_state uint8
+ Retransmits uint8
+ Probes uint8
+ Backoff uint8
+ Options uint8
+ Snd_wscale uint8 // no uint4
+ Rcv_wscale uint8
+ Delivery_rate_app_limited uint8
+ Fastopen_client_fail uint8
+ Rto uint32
+ Ato uint32
+ Snd_mss uint32
+ Rcv_mss uint32
+ Unacked uint32
+ Sacked uint32
+ Lost uint32
+ Retrans uint32
+ Fackets uint32
+ Last_data_sent uint32
+ Last_ack_sent uint32
+ Last_data_recv uint32
+ Last_ack_recv uint32
+ Pmtu uint32
+ Rcv_ssthresh uint32
+ Rtt uint32
+ Rttvar uint32
+ Snd_ssthresh uint32
+ Snd_cwnd uint32
+ Advmss uint32
+ Reordering uint32
+ Rcv_rtt uint32
+ Rcv_space uint32
+ Total_retrans uint32
+ Pacing_rate uint64
+ Max_pacing_rate uint64
+ Bytes_acked uint64 /* RFC4898 tcpEStatsAppHCThruOctetsAcked */
+ Bytes_received uint64 /* RFC4898 tcpEStatsAppHCThruOctetsReceived */
+ Segs_out uint32 /* RFC4898 tcpEStatsPerfSegsOut */
+ Segs_in uint32 /* RFC4898 tcpEStatsPerfSegsIn */
+ Notsent_bytes uint32
+ Min_rtt uint32
+ Data_segs_in uint32 /* RFC4898 tcpEStatsDataSegsIn */
+ Data_segs_out uint32 /* RFC4898 tcpEStatsDataSegsOut */
+ Delivery_rate uint64
+ Busy_time uint64 /* Time (usec) busy sending data */
+ Rwnd_limited uint64 /* Time (usec) limited by receive window */
+ Sndbuf_limited uint64 /* Time (usec) limited by send buffer */
+ Delivered uint32
+ Delivered_ce uint32
+ Bytes_sent uint64 /* RFC4898 tcpEStatsPerfHCDataOctetsOut */
+ Bytes_retrans uint64 /* RFC4898 tcpEStatsPerfOctetsRetrans */
+ Dsack_dups uint32 /* RFC4898 tcpEStatsStackDSACKDups */
+ Reord_seen uint32 /* reordering events seen */
+ Rcv_ooopack uint32 /* Out-of-order packets received */
+ Snd_wnd uint32 /* peer's advertised receive window after * scaling (bytes) */
+}
+
+type TCPBBRInfo struct {
+ BBRBW uint64
+ BBRMinRTT uint32
+ BBRPacingGain uint32
+ BBRCwndGain uint32
+}
diff --git a/vendor/github.com/vishvananda/netlink/tcp_linux.go b/vendor/github.com/vishvananda/netlink/tcp_linux.go
index 741ea1655..293858738 100644
--- a/vendor/github.com/vishvananda/netlink/tcp_linux.go
+++ b/vendor/github.com/vishvananda/netlink/tcp_linux.go
@@ -2,67 +2,13 @@ package netlink
import (
"bytes"
+ "errors"
"io"
)
-type TCPInfo struct {
- State uint8
- Ca_state uint8
- Retransmits uint8
- Probes uint8
- Backoff uint8
- Options uint8
- Snd_wscale uint8 // no uint4
- Rcv_wscale uint8
- Delivery_rate_app_limited uint8
- Fastopen_client_fail uint8
- Rto uint32
- Ato uint32
- Snd_mss uint32
- Rcv_mss uint32
- Unacked uint32
- Sacked uint32
- Lost uint32
- Retrans uint32
- Fackets uint32
- Last_data_sent uint32
- Last_ack_sent uint32
- Last_data_recv uint32
- Last_ack_recv uint32
- Pmtu uint32
- Rcv_ssthresh uint32
- Rtt uint32
- Rttvar uint32
- Snd_ssthresh uint32
- Snd_cwnd uint32
- Advmss uint32
- Reordering uint32
- Rcv_rtt uint32
- Rcv_space uint32
- Total_retrans uint32
- Pacing_rate uint64
- Max_pacing_rate uint64
- Bytes_acked uint64 /* RFC4898 tcpEStatsAppHCThruOctetsAcked */
- Bytes_received uint64 /* RFC4898 tcpEStatsAppHCThruOctetsReceived */
- Segs_out uint32 /* RFC4898 tcpEStatsPerfSegsOut */
- Segs_in uint32 /* RFC4898 tcpEStatsPerfSegsIn */
- Notsent_bytes uint32
- Min_rtt uint32
- Data_segs_in uint32 /* RFC4898 tcpEStatsDataSegsIn */
- Data_segs_out uint32 /* RFC4898 tcpEStatsDataSegsOut */
- Delivery_rate uint64
- Busy_time uint64 /* Time (usec) busy sending data */
- Rwnd_limited uint64 /* Time (usec) limited by receive window */
- Sndbuf_limited uint64 /* Time (usec) limited by send buffer */
- Delivered uint32
- Delivered_ce uint32
- Bytes_sent uint64 /* RFC4898 tcpEStatsPerfHCDataOctetsOut */
- Bytes_retrans uint64 /* RFC4898 tcpEStatsPerfOctetsRetrans */
- Dsack_dups uint32 /* RFC4898 tcpEStatsStackDSACKDups */
- Reord_seen uint32 /* reordering events seen */
- Rcv_ooopack uint32 /* Out-of-order packets received */
- Snd_wnd uint32 /* peer's advertised receive window after * scaling (bytes) */
-}
+const (
+ tcpBBRInfoLen = 20
+)
func checkDeserErr(err error) error {
if err == io.EOF {
@@ -391,3 +337,17 @@ func (t *TCPInfo) deserialize(b []byte) error {
t.Snd_wnd = native.Uint32(next)
return nil
}
+
+func (t *TCPBBRInfo) deserialize(b []byte) error {
+ if len(b) != tcpBBRInfoLen {
+ return errors.New("Invalid length")
+ }
+
+ rb := bytes.NewBuffer(b)
+ t.BBRBW = native.Uint64(rb.Next(8))
+ t.BBRMinRTT = native.Uint32(rb.Next(4))
+ t.BBRPacingGain = native.Uint32(rb.Next(4))
+ t.BBRCwndGain = native.Uint32(rb.Next(4))
+
+ return nil
+}
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy.go b/vendor/github.com/vishvananda/netlink/xfrm_policy.go
index 6219d2772..b7532b092 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_policy.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_policy.go
@@ -58,12 +58,13 @@ func (a PolicyAction) String() string {
// policy. These rules are matched with XfrmState to determine encryption
// and authentication algorithms.
type XfrmPolicyTmpl struct {
- Dst net.IP
- Src net.IP
- Proto Proto
- Mode Mode
- Spi int
- Reqid int
+ Dst net.IP
+ Src net.IP
+ Proto Proto
+ Mode Mode
+ Spi int
+ Reqid int
+ Optional int
}
func (t XfrmPolicyTmpl) String() string {
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
index a4e132ef5..694bd74e6 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
@@ -79,6 +79,7 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi))
userTmpl.Mode = uint8(tmpl.Mode)
userTmpl.Reqid = uint32(tmpl.Reqid)
+ userTmpl.Optional = uint8(tmpl.Optional)
userTmpl.Aalgos = ^uint32(0)
userTmpl.Ealgos = ^uint32(0)
userTmpl.Calgos = ^uint32(0)
@@ -247,6 +248,7 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
resTmpl.Mode = Mode(tmpl.Mode)
resTmpl.Spi = int(nl.Swap32(tmpl.XfrmId.Spi))
resTmpl.Reqid = int(tmpl.Reqid)
+ resTmpl.Optional = int(tmpl.Optional)
policy.Tmpls = append(policy.Tmpls, resTmpl)
}
case nl.XFRMA_MARK:
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state.go b/vendor/github.com/vishvananda/netlink/xfrm_state.go
index 483d8934a..19df82c76 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_state.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_state.go
@@ -94,7 +94,7 @@ type XfrmState struct {
Limits XfrmStateLimits
Statistics XfrmStateStats
Mark *XfrmMark
- OutputMark int
+ OutputMark *XfrmMark
Ifid int
Auth *XfrmStateAlgo
Crypt *XfrmStateAlgo
@@ -104,7 +104,7 @@ type XfrmState struct {
}
func (sa XfrmState) String() string {
- return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %d, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t",
+ return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t",
sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN)
}
func (sa XfrmState) Print(stats bool) string {
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
index 66c99423c..5b1b6c31a 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
@@ -158,9 +158,13 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow))
req.AddData(out)
}
- if state.OutputMark != 0 {
- out := nl.NewRtAttr(nl.XFRMA_OUTPUT_MARK, nl.Uint32Attr(uint32(state.OutputMark)))
+ if state.OutputMark != nil {
+ out := nl.NewRtAttr(nl.XFRMA_SET_MARK, nl.Uint32Attr(state.OutputMark.Value))
req.AddData(out)
+ if state.OutputMark.Mask != 0 {
+ out = nl.NewRtAttr(nl.XFRMA_SET_MARK_MASK, nl.Uint32Attr(state.OutputMark.Mask))
+ req.AddData(out)
+ }
}
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
@@ -377,8 +381,19 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
state.Mark = new(XfrmMark)
state.Mark.Value = mark.Value
state.Mark.Mask = mark.Mask
- case nl.XFRMA_OUTPUT_MARK:
- state.OutputMark = int(native.Uint32(attr.Value))
+ case nl.XFRMA_SET_MARK:
+ if state.OutputMark == nil {
+ state.OutputMark = new(XfrmMark)
+ }
+ state.OutputMark.Value = native.Uint32(attr.Value)
+ case nl.XFRMA_SET_MARK_MASK:
+ if state.OutputMark == nil {
+ state.OutputMark = new(XfrmMark)
+ }
+ state.OutputMark.Mask = native.Uint32(attr.Value)
+ if state.OutputMark.Mask == 0xffffffff {
+ state.OutputMark.Mask = 0
+ }
case nl.XFRMA_IF_ID:
state.Ifid = int(native.Uint32(attr.Value))
}
diff --git a/vendor/github.com/vishvananda/netns/README.md b/vendor/github.com/vishvananda/netns/README.md
index 6b45cfb89..1fdb2d3e4 100644
--- a/vendor/github.com/vishvananda/netns/README.md
+++ b/vendor/github.com/vishvananda/netns/README.md
@@ -48,3 +48,14 @@ func main() {
}
```
+
+## NOTE
+
+The library can be safely used only with Go >= 1.10 due to [golang/go#20676](https://github.com/golang/go/issues/20676).
+
+After locking a goroutine to its current OS thread with `runtime.LockOSThread()`
+and changing its network namespace, any new subsequent goroutine won't be
+scheduled on that thread while it's locked. Therefore, the new goroutine
+will run in a different namespace leading to unexpected results.
+
+See [here](https://www.weave.works/blog/linux-namespaces-golang-followup) for more details.
diff --git a/vendor/github.com/vishvananda/netns/netns_linux.go b/vendor/github.com/vishvananda/netns/netns_linux.go
index c76acd087..36e64906b 100644
--- a/vendor/github.com/vishvananda/netns/netns_linux.go
+++ b/vendor/github.com/vishvananda/netns/netns_linux.go
@@ -1,4 +1,4 @@
-// +build linux
+// +build linux,go1.10
package netns
@@ -218,12 +218,18 @@ func getPidForContainer(id string) (int, error) {
filepath.Join(cgroupRoot, "system.slice", "docker-"+id+".scope", "tasks"),
// Even more recent docker versions under cgroup/systemd/docker/<id>/
filepath.Join(cgroupRoot, "..", "systemd", "docker", id, "tasks"),
- // Kubernetes with docker and CNI is even more different
+ // Kubernetes with docker and CNI is even more different. Works for BestEffort and Burstable QoS
filepath.Join(cgroupRoot, "..", "systemd", "kubepods", "*", "pod*", id, "tasks"),
- // Another flavor of containers location in recent kubernetes 1.11+
- filepath.Join(cgroupRoot, cgroupThis, "kubepods.slice", "kubepods-besteffort.slice", "*", "docker-"+id+".scope", "tasks"),
- // When runs inside of a container with recent kubernetes 1.11+
- filepath.Join(cgroupRoot, "kubepods.slice", "kubepods-besteffort.slice", "*", "docker-"+id+".scope", "tasks"),
+ // Same as above but for Guaranteed QoS
+ filepath.Join(cgroupRoot, "..", "systemd", "kubepods", "pod*", id, "tasks"),
+ // Another flavor of containers location in recent kubernetes 1.11+. Works for BestEffort and Burstable QoS
+ filepath.Join(cgroupRoot, cgroupThis, "kubepods.slice", "*.slice", "*", "docker-"+id+".scope", "tasks"),
+ // Same as above but for Guaranteed QoS
+ filepath.Join(cgroupRoot, cgroupThis, "kubepods.slice", "*", "docker-"+id+".scope", "tasks"),
+ // When runs inside of a container with recent kubernetes 1.11+. Works for BestEffort and Burstable QoS
+ filepath.Join(cgroupRoot, "kubepods.slice", "*.slice", "*", "docker-"+id+".scope", "tasks"),
+ // Same as above but for Guaranteed QoS
+ filepath.Join(cgroupRoot, "kubepods.slice", "*", "docker-"+id+".scope", "tasks"),
}
var filename string
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 287b68263..661619f98 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -45,7 +45,7 @@ github.com/blang/semver
github.com/buger/goterm
# github.com/cespare/xxhash/v2 v2.1.1
github.com/cespare/xxhash/v2
-# github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7
+# github.com/checkpoint-restore/checkpointctl v0.0.0-20210922093614-c31748bec9f2
github.com/checkpoint-restore/checkpointctl/lib
# github.com/checkpoint-restore/go-criu/v5 v5.1.0
github.com/checkpoint-restore/go-criu/v5
@@ -66,15 +66,18 @@ github.com/containerd/containerd/sys
# github.com/containerd/stargz-snapshotter/estargz v0.8.0
github.com/containerd/stargz-snapshotter/estargz
github.com/containerd/stargz-snapshotter/estargz/errorutil
-# github.com/containernetworking/cni v0.8.1
+# github.com/containernetworking/cni v1.0.1
github.com/containernetworking/cni/libcni
github.com/containernetworking/cni/pkg/invoke
github.com/containernetworking/cni/pkg/types
github.com/containernetworking/cni/pkg/types/020
-github.com/containernetworking/cni/pkg/types/current
+github.com/containernetworking/cni/pkg/types/040
+github.com/containernetworking/cni/pkg/types/100
+github.com/containernetworking/cni/pkg/types/create
+github.com/containernetworking/cni/pkg/types/internal
github.com/containernetworking/cni/pkg/utils
github.com/containernetworking/cni/pkg/version
-# github.com/containernetworking/plugins v0.9.1
+# github.com/containernetworking/plugins v1.0.1
github.com/containernetworking/plugins/pkg/ns
# github.com/containers/buildah v1.23.0
github.com/containers/buildah
@@ -94,7 +97,7 @@ github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util
github.com/containers/buildah/util
-# github.com/containers/common v0.44.1-0.20210914173811-fcaa2e0de285
+# github.com/containers/common v0.44.1-0.20210921143342-f2f10e650c73
github.com/containers/common/libimage
github.com/containers/common/libimage/manifests
github.com/containers/common/pkg/apparmor
@@ -191,7 +194,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7
github.com/containers/ocicrypt/spec
github.com/containers/ocicrypt/utils
github.com/containers/ocicrypt/utils/keyprovider
-# github.com/containers/psgo v1.6.0
+# github.com/containers/psgo v1.7.1
github.com/containers/psgo
github.com/containers/psgo/internal/capabilities
github.com/containers/psgo/internal/cgroups
@@ -432,7 +435,7 @@ github.com/matttproud/golang_protobuf_extensions/pbutil
github.com/miekg/pkcs11
# github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible
github.com/mistifyio/go-zfs
-# github.com/mitchellh/mapstructure v1.4.1
+# github.com/mitchellh/mapstructure v1.4.2
github.com/mitchellh/mapstructure
# github.com/moby/sys/mount v0.2.0
github.com/moby/sys/mount
@@ -614,10 +617,10 @@ github.com/vbauerster/mpb/v7
github.com/vbauerster/mpb/v7/cwriter
github.com/vbauerster/mpb/v7/decor
github.com/vbauerster/mpb/v7/internal
-# github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852
+# github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
github.com/vishvananda/netlink
github.com/vishvananda/netlink/nl
-# github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae
+# github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f
github.com/vishvananda/netns
# github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b
github.com/xeipuuv/gojsonpointer