diff options
261 files changed, 4149 insertions, 2044 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 @@ -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/cleanup.go b/cmd/podman/containers/cleanup.go index 98706c575..a3d339358 100644 --- a/cmd/podman/containers/cleanup.go +++ b/cmd/podman/containers/cleanup.go @@ -80,7 +80,7 @@ func cleanup(cmd *cobra.Command, args []string) error { // is via syslog. // As such, we need to logrus.Errorf our errors to ensure they // are properly printed if --syslog is set. - logrus.Errorf("Error running container cleanup: %v", err) + logrus.Errorf("Running container cleanup: %v", err) return err } for _, r := range responses { @@ -89,15 +89,15 @@ func cleanup(cmd *cobra.Command, args []string) error { continue } if r.RmErr != nil { - logrus.Errorf("Error removing container: %v", r.RmErr) + logrus.Errorf("Removing container: %v", r.RmErr) errs = append(errs, r.RmErr) } if r.RmiErr != nil { - logrus.Errorf("Error removing image: %v", r.RmiErr) + logrus.Errorf("Removing image: %v", r.RmiErr) errs = append(errs, r.RmiErr) } if r.CleanErr != nil { - logrus.Errorf("Error cleaning up container: %v", r.CleanErr) + logrus.Errorf("Cleaning up container: %v", r.CleanErr) errs = append(errs, r.CleanErr) } } 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/build.go b/cmd/podman/images/build.go index 642da0c83..4c563ed27 100644 --- a/cmd/podman/images/build.go +++ b/cmd/podman/images/build.go @@ -131,7 +131,7 @@ func buildFlags(cmd *cobra.Command) { // --pull flag flag := budFlags.Lookup("pull") if err := flag.Value.Set("true"); err != nil { - logrus.Errorf("unable to set --pull to true: %v", err) + logrus.Errorf("Unable to set --pull to true: %v", err) } flag.DefValue = "true" flag.Usage = "Always attempt to pull the image (errors are fatal)" @@ -148,13 +148,13 @@ func buildFlags(cmd *cobra.Command) { useLayersVal := useLayers() buildOpts.Layers = useLayersVal == "true" if err := flag.Value.Set(useLayersVal); err != nil { - logrus.Errorf("unable to set --layers to %v: %v", useLayersVal, err) + logrus.Errorf("Unable to set --layers to %v: %v", useLayersVal, err) } flag.DefValue = useLayersVal // --force-rm flag flag = layerFlags.Lookup("force-rm") if err := flag.Value.Set("true"); err != nil { - logrus.Errorf("unable to set --force-rm to true: %v", err) + logrus.Errorf("Unable to set --force-rm to true: %v", err) } flag.DefValue = "true" flags.AddFlagSet(&layerFlags) @@ -162,7 +162,7 @@ func buildFlags(cmd *cobra.Command) { // FromAndBud flags fromAndBudFlags, err := buildahCLI.GetFromAndBudFlags(&buildOpts.FromAndBudResults, &buildOpts.UserNSResults, &buildOpts.NameSpaceResults) if err != nil { - logrus.Errorf("error setting up build flags: %v", err) + logrus.Errorf("Setting up build flags: %v", err) os.Exit(1) } // --http-proxy flag @@ -171,7 +171,7 @@ func buildFlags(cmd *cobra.Command) { flag = fromAndBudFlags.Lookup("http-proxy") buildOpts.HTTPProxy = false if err := flag.Value.Set("false"); err != nil { - logrus.Errorf("unable to set --https-proxy to %v: %v", false, err) + logrus.Errorf("Unable to set --https-proxy to %v: %v", false, err) } flag.DefValue = "false" } @@ -184,7 +184,7 @@ func buildFlags(cmd *cobra.Command) { flag = flags.Lookup("isolation") buildOpts.Isolation = buildahDefine.OCI if err := flag.Value.Set(buildahDefine.OCI); err != nil { - logrus.Errorf("unable to set --isolation to %v: %v", buildahDefine.OCI, err) + logrus.Errorf("Unable to set --isolation to %v: %v", buildahDefine.OCI, err) } flag.DefValue = buildahDefine.OCI _ = flags.MarkHidden("disable-content-trust") @@ -228,7 +228,7 @@ func build(cmd *cobra.Command, args []string) error { // Delete it later. defer func() { if err = os.RemoveAll(tempDir); err != nil { - logrus.Errorf("error removing temporary directory %q: %v", contextDir, err) + logrus.Errorf("Removing temporary directory %q: %v", contextDir, err) } }() contextDir = filepath.Join(tempDir, subDir) 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/images/utils_linux.go b/cmd/podman/images/utils_linux.go index 5521abab4..f7c159415 100644 --- a/cmd/podman/images/utils_linux.go +++ b/cmd/podman/images/utils_linux.go @@ -24,7 +24,7 @@ func setupPipe() (string, func() <-chan error, error) { err = unix.Mkfifo(pipePath, 0600) if err != nil { if e := os.RemoveAll(pipeDir); e != nil { - logrus.Errorf("error removing named pipe: %q", e) + logrus.Errorf("Removing named pipe: %q", e) } return "", nil, errors.Wrapf(err, "error creating named pipe") } @@ -40,7 +40,7 @@ func setupPipe() (string, func() <-chan error, error) { }() return pipePath, func() <-chan error { if e := os.RemoveAll(pipeDir); e != nil { - logrus.Errorf("error removing named pipe: %q", e) + logrus.Errorf("Removing named pipe: %q", e) } return errc }, nil diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go index 4c7fa33a4..64b586388 100644 --- a/cmd/podman/inspect/inspect.go +++ b/cmd/podman/inspect/inspect.go @@ -220,7 +220,7 @@ func (i *inspector) inspect(namesOrIDs []string) error { err = printTmpl(tmpType, row, data) } if err != nil { - logrus.Errorf("Error printing inspect output: %v", err) + logrus.Errorf("Printing inspect output: %v", err) } if len(errs) > 0 { 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/machine/list.go b/cmd/podman/machine/list.go index d4360bb9b..fe9d712e3 100644 --- a/cmd/podman/machine/list.go +++ b/cmd/podman/machine/list.go @@ -40,10 +40,13 @@ type listFlagType struct { } type machineReporter struct { - Name string - Created string - LastUp string - VMType string + Name string + Created string + LastUp string + VMType string + CPUs uint64 + Memory string + DiskSize string } func init() { @@ -54,7 +57,7 @@ func init() { flags := lsCmd.Flags() formatFlagName := "format" - flags.StringVar(&listFlag.format, formatFlagName, "{{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\n", "Format volume output using Go template") + flags.StringVar(&listFlag.format, formatFlagName, "{{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\t{{.CPUs}}\t{{.Memory}}\t{{.DiskSize}}\n", "Format volume output using Go template") _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, completion.AutocompleteNone) flags.BoolVar(&listFlag.noHeading, "noheading", false, "Do not print headers") } @@ -85,8 +88,11 @@ func list(cmd *cobra.Command, args []string) error { func outputTemplate(cmd *cobra.Command, responses []*machineReporter) error { headers := report.Headers(machineReporter{}, map[string]string{ - "LastUp": "LAST UP", - "VmType": "VM TYPE", + "LastUp": "LAST UP", + "VmType": "VM TYPE", + "CPUs": "CPUS", + "Memory": "MEMORY", + "DiskSize": "DISK SIZE", }) row := report.NormalizeFormat(listFlag.format) @@ -136,6 +142,9 @@ func toHumanFormat(vms []*machine.ListResponse) ([]*machineReporter, error) { } response.Created = units.HumanDuration(time.Since(vm.CreatedAt)) + " ago" response.VMType = vm.VMType + response.CPUs = vm.CPUs + response.Memory = units.HumanSize(float64(vm.Memory) * units.MiB) + response.DiskSize = units.HumanSize(float64(vm.DiskSize) * units.GiB) humanResponses = append(humanResponses, response) } diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go index 84e9e88ab..da0a09338 100644 --- a/cmd/podman/machine/ssh.go +++ b/cmd/podman/machine/ssh.go @@ -5,6 +5,7 @@ package machine import ( "net/url" + "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/config" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/pkg/machine" @@ -15,7 +16,7 @@ import ( var ( sshCmd = &cobra.Command{ - Use: "ssh [NAME] [COMMAND [ARG ...]]", + Use: "ssh [options] [NAME] [COMMAND [ARG ...]]", Short: "SSH into an existing machine", Long: "SSH into a managed virtual machine ", RunE: ssh, @@ -35,6 +36,10 @@ func init() { Command: sshCmd, Parent: machineCmd, }) + flags := sshCmd.Flags() + usernameFlagName := "username" + flags.StringVar(&sshOpts.Username, usernameFlagName, "", "Username to use when ssh-ing into the VM.") + _ = sshCmd.RegisterFlagCompletionFunc(usernameFlagName, completion.AutocompleteNone) } func ssh(cmd *cobra.Command, args []string) error { @@ -48,13 +53,6 @@ func ssh(cmd *cobra.Command, args []string) error { // Set the VM to default vmName := defaultMachineName - // If we're not given a VM name, use the remote username from the connection config - if len(args) == 0 { - sshOpts.Username, err = remoteConnectionUsername() - if err != nil { - return err - } - } // If len is greater than 0, it means we may have been // provided the VM name. If so, we check. The VM name, // if provided, must be in args[0]. @@ -68,10 +66,6 @@ func ssh(cmd *cobra.Command, args []string) error { if validVM { vmName = args[0] } else { - sshOpts.Username, err = remoteConnectionUsername() - if err != nil { - return err - } sshOpts.Args = append(sshOpts.Args, args[0]) } } @@ -83,14 +77,17 @@ func ssh(cmd *cobra.Command, args []string) error { if validVM { sshOpts.Args = args[1:] } else { - sshOpts.Username, err = remoteConnectionUsername() - if err != nil { - return err - } sshOpts.Args = args } } + if !validVM && sshOpts.Username == "" { + sshOpts.Username, err = remoteConnectionUsername() + if err != nil { + return err + } + } + switch vmType { default: vm, err = qemu.LoadVMByName(vmName) 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/root.go b/cmd/podman/root.go index 02e6dcd27..58cab0268 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -175,7 +175,7 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error { // Hard code TMPDIR functions to use /var/tmp, if user did not override if _, ok := os.LookupEnv("TMPDIR"); !ok { if tmpdir, err := cfg.ImageCopyTmpDir(); err != nil { - logrus.Warnf("failed to retrieve default tmp dir: %s", err.Error()) + logrus.Warnf("Failed to retrieve default tmp dir: %s", err.Error()) } else { os.Setenv("TMPDIR", tmpdir) } @@ -313,7 +313,7 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) { pFlags := cmd.PersistentFlags() if registry.IsRemote() { if err := lFlags.MarkHidden("remote"); err != nil { - logrus.Warnf("unable to mark --remote flag as hidden: %s", err.Error()) + logrus.Warnf("Unable to mark --remote flag as hidden: %s", err.Error()) } opts.Remote = true } else { @@ -387,7 +387,7 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) { "trace", } { if err := pFlags.MarkHidden(f); err != nil { - logrus.Warnf("unable to mark %s flag as hidden: %s", f, err.Error()) + logrus.Warnf("Unable to mark %s flag as hidden: %s", f, err.Error()) } } } diff --git a/cmd/podman/system/service.go b/cmd/podman/system/service.go index a30f43839..99a6b1e1e 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) @@ -73,7 +74,7 @@ func service(cmd *cobra.Command, args []string) error { if err != nil { return err } - logrus.Infof("using API endpoint: '%s'", apiURI) + logrus.Infof("Using API endpoint: '%s'", apiURI) // Clean up any old existing unix domain socket if len(apiURI) > 0 { uri, err := url.Parse(apiURI) @@ -119,7 +120,7 @@ func resolveAPIURI(_url []string) (string, error) { case len(_url) > 0 && _url[0] != "": return _url[0], nil case systemd.SocketActivated(): - logrus.Info("using systemd socket activation to determine API endpoint") + logrus.Info("Using systemd socket activation to determine API endpoint") return "", nil case rootless.IsRootless(): xdg, err := util.GetRuntimeDir() 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/contrib/podmanimage/README.md b/contrib/podmanimage/README.md index b7be328c7..2452d7293 100644 --- a/contrib/podmanimage/README.md +++ b/contrib/podmanimage/README.md @@ -66,3 +66,7 @@ exit the fuse kernel module has not been loaded on your host system. Use the command `modprobe fuse` to load the module and then run the container image. To enable this automatically at boot time, you can add a configuration file to `/etc/modules.load.d`. See `man modules-load.d` for more details. + +### Blog Post with Details + +Dan Walsh wrote a blog post on the [Enable Sysadmin](https://www.redhat.com/sysadmin/) site titled [How to use Podman inside of a container](https://www.redhat.com/sysadmin/podman-inside-container). In it, he details how to use these images as a rootful and as a rootless user. Please refer to this blog for more detailed information. 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 4a20e4e45..f63f5ca9c 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -689,7 +689,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..f1fbd56ee 100644 --- a/docs/source/markdown/podman-machine-init.1.md +++ b/docs/source/markdown/podman-machine-init.1.md @@ -40,13 +40,17 @@ do these things manually or handle otherwise. #### **--image-path** Fully qualified path or URL to the VM image. -Can also be set to `testing` or `stable` to pull down default image. +Can also be set to `testing`, `next`, or `stable` to pull down default image. Defaults to `testing`. #### **--memory**, **-m**=*number* 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-machine-ssh.1.md b/docs/source/markdown/podman-machine-ssh.1.md index a5cf69107..c4c732819 100644 --- a/docs/source/markdown/podman-machine-ssh.1.md +++ b/docs/source/markdown/podman-machine-ssh.1.md @@ -4,7 +4,7 @@ podman\-machine\-ssh - SSH into a virtual machine ## SYNOPSIS -**podman machine ssh** [*name*] [*command* [*arg* ...]] +**podman machine ssh** [*options*] [*name*] [*command* [*arg* ...]] ## DESCRIPTION @@ -21,6 +21,10 @@ with the virtual machine is established. Print usage statement. +#### **--username**=*name* + +Username to use when SSH-ing into the VM. + ## EXAMPLES To get an interactive session with the default virtual machine: 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 7a2e09dab..6d68fd62b 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -710,7 +710,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> @@ -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,12 +62,12 @@ 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 golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b - k8s.io/api v0.22.1 - k8s.io/apimachinery v0.22.1 + k8s.io/api v0.22.2 + k8s.io/apimachinery v0.22.2 ) @@ -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= @@ -1444,13 +1455,13 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.22.1 h1:ISu3tD/jRhYfSW8jI/Q1e+lRxkR7w9UwQEZ7FgslrwY= -k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY= +k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= +k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.22.1 h1:DTARnyzmdHMz7bFWFDDm22AM4pLWTQECMpRTFu2d2OM= -k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= +k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= 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/hack/podman-registry-go/registry.go b/hack/podman-registry-go/registry.go index e9ec61ffe..92e3008f3 100644 --- a/hack/podman-registry-go/registry.go +++ b/hack/podman-registry-go/registry.go @@ -61,7 +61,7 @@ func Start() (*Registry, error) { case portKey: registry.Port = val default: - logrus.Errorf("unexpected podman-registry output: %q", s) + logrus.Errorf("Unexpected podman-registry output: %q", s) } } diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index 56b4bafd3..612908ac2 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -954,7 +954,7 @@ func (s *BoltState) AllContainers() ([]*Container, error) { // not worth erroring over. // If we do, a single bad container JSON // could render libpod unusable. - logrus.Errorf("Error retrieving container %s from the database: %v", string(id), err) + logrus.Errorf("Retrieving container %s from the database: %v", string(id), err) } } else { ctrs = append(ctrs, ctr) @@ -2556,7 +2556,7 @@ func (s *BoltState) AllVolumes() ([]*Volume, error) { if err := s.getVolumeFromDB(id, volume, volBucket); err != nil { if errors.Cause(err) != define.ErrNSMismatch { - logrus.Errorf("Error retrieving volume %s from the database: %v", string(id), err) + logrus.Errorf("Retrieving volume %s from the database: %v", string(id), err) } } else { volumes = append(volumes, volume) @@ -3352,7 +3352,7 @@ func (s *BoltState) AllPods() ([]*Pod, error) { if err := s.getPodFromDB(id, pod, podBucket); err != nil { if errors.Cause(err) != define.ErrNSMismatch { - logrus.Errorf("Error retrieving pod %s from the database: %v", string(id), err) + logrus.Errorf("Retrieving pod %s from the database: %v", string(id), err) } } else { pods = append(pods, pod) diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index f63876c14..3e3c17a9e 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -259,7 +259,7 @@ func (s *BoltState) getDBCon() (*bolt.DB, error) { // of a defer statement only func (s *BoltState) deferredCloseDBCon(db *bolt.DB) { if err := s.closeDBCon(db); err != nil { - logrus.Errorf("failed to close libpod db: %q", err) + logrus.Errorf("Failed to close libpod db: %q", err) } } @@ -875,7 +875,7 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error podCtrs := podDB.Bucket(containersBkt) if podCtrs == nil { // Malformed pod - logrus.Errorf("pod %s malformed in database, missing containers bucket!", pod.ID()) + logrus.Errorf("Pod %s malformed in database, missing containers bucket!", pod.ID()) } else { ctrInPod := podCtrs.Get(ctrID) if ctrInPod == nil { diff --git a/libpod/boltdb_state_linux.go b/libpod/boltdb_state_linux.go index 72243dcc5..4fb3236a0 100644 --- a/libpod/boltdb_state_linux.go +++ b/libpod/boltdb_state_linux.go @@ -31,7 +31,7 @@ func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) er return errors.Wrapf(err, "error joining network namespace of container %s", ctr.ID()) } - logrus.Errorf("error joining network namespace for container %s: %v", ctr.ID(), err) + logrus.Errorf("Joining network namespace for container %s: %v", ctr.ID(), err) ctr.state.NetNS = nil } } diff --git a/libpod/boltdb_state_unsupported.go b/libpod/boltdb_state_unsupported.go deleted file mode 100644 index 244dc51a0..000000000 --- a/libpod/boltdb_state_unsupported.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !linux - -package libpod - -// replaceNetNS is exclusive to the Linux platform and is a no-op elsewhere -func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) error { - return nil -} - -// getNetNSPath is exclusive to the Linux platform and is a no-op elsewhere -func getNetNSPath(ctr *Container) string { - return "" -} 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_api.go b/libpod/container_api.go index 637f5b686..2d5b07a35 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -53,7 +53,7 @@ func (c *Container) Init(ctx context.Context, recursive bool) error { if err := c.prepare(); err != nil { if err2 := c.cleanup(ctx); err2 != nil { - logrus.Errorf("error cleaning up container %s: %v", c.ID(), err2) + logrus.Errorf("Cleaning up container %s: %v", c.ID(), err2) } return err } diff --git a/libpod/container_commit.go b/libpod/container_commit.go index 87e5d511c..6ae225cbc 100644 --- a/libpod/container_commit.go +++ b/libpod/container_commit.go @@ -51,7 +51,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai } defer func() { if err := c.unpause(); err != nil { - logrus.Errorf("error unpausing container %q: %v", c.ID(), err) + logrus.Errorf("Unpausing container %q: %v", c.ID(), err) } }() } 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_copy_unsupported.go b/libpod/container_copy_unsupported.go deleted file mode 100644 index b2bdd3e3d..000000000 --- a/libpod/container_copy_unsupported.go +++ /dev/null @@ -1,16 +0,0 @@ -// +build !linux - -package libpod - -import ( - "context" - "io" -) - -func (c *Container) copyFromArchive(ctx context.Context, path string, reader io.Reader) (func() error, error) { - return nil, nil -} - -func (c *Container) copyToArchive(ctx context.Context, path string, writer io.Writer) (func() error, error) { - return nil, nil -} diff --git a/libpod/container_exec.go b/libpod/container_exec.go index 5d4bcb422..1cb45a118 100644 --- a/libpod/container_exec.go +++ b/libpod/container_exec.go @@ -415,7 +415,7 @@ func (c *Container) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w session.ExitCode = define.ExecErrorCodeGeneric if err := c.save(); err != nil { - logrus.Errorf("Error saving container %s exec session %s after failure to prepare: %v", err, c.ID(), session.ID()) + logrus.Errorf("Saving container %s exec session %s after failure to prepare: %v", err, c.ID(), session.ID()) } return err @@ -440,7 +440,7 @@ func (c *Container) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w session.ExitCode = define.TranslateExecErrorToExitCode(define.ExecErrorCodeGeneric, err) if err := c.save(); err != nil { - logrus.Errorf("Error saving container %s exec session %s after failure to start: %v", err, c.ID(), session.ID()) + logrus.Errorf("Saving container %s exec session %s after failure to start: %v", err, c.ID(), session.ID()) } return err @@ -549,7 +549,7 @@ func (c *Container) ExecStop(sessionID string, timeout *uint) error { if err := c.cleanupExecBundle(session.ID()); err != nil { if cleanupErr != nil { - logrus.Errorf("Error stopping container %s exec session %s: %v", c.ID(), session.ID(), cleanupErr) + logrus.Errorf("Stopping container %s exec session %s: %v", c.ID(), session.ID(), cleanupErr) } cleanupErr = err } @@ -695,7 +695,7 @@ func (c *Container) ExecResize(sessionID string, newSize define.TerminalSize) er session.State = define.ExecStateStopped if err := c.save(); err != nil { - logrus.Errorf("Error saving state of container %s: %v", c.ID(), err) + logrus.Errorf("Saving state of container %s: %v", c.ID(), err) } return errors.Wrapf(define.ErrExecSessionStateInvalid, "cannot resize container %s exec session %s as it has stopped", c.ID(), session.ID()) @@ -825,7 +825,7 @@ func (c *Container) createExecBundle(sessionID string) (retErr error) { defer func() { if retErr != nil { if err := os.RemoveAll(bundlePath); err != nil { - logrus.Warnf("error removing exec bundle after creation caused another error: %v", err) + logrus.Warnf("Error removing exec bundle after creation caused another error: %v", err) } } }() @@ -911,7 +911,7 @@ func (c *Container) getActiveExecSessions() ([]string, error) { alive, err := c.ociRuntime.ExecUpdateStatus(c, id) if err != nil { if lastErr != nil { - logrus.Errorf("Error checking container %s exec sessions: %v", c.ID(), lastErr) + logrus.Errorf("Checking container %s exec sessions: %v", c.ID(), lastErr) } lastErr = err continue @@ -926,7 +926,7 @@ func (c *Container) getActiveExecSessions() ([]string, error) { exitCode, err := c.readExecExitCode(session.ID()) if err != nil { if lastErr != nil { - logrus.Errorf("Error checking container %s exec sessions: %v", c.ID(), lastErr) + logrus.Errorf("Checking container %s exec sessions: %v", c.ID(), lastErr) } lastErr = err } @@ -940,7 +940,7 @@ func (c *Container) getActiveExecSessions() ([]string, error) { } if err := c.cleanupExecBundle(id); err != nil { if lastErr != nil { - logrus.Errorf("Error checking container %s exec sessions: %v", c.ID(), lastErr) + logrus.Errorf("Checking container %s exec sessions: %v", c.ID(), lastErr) } lastErr = err } @@ -951,7 +951,7 @@ func (c *Container) getActiveExecSessions() ([]string, error) { if needSave { if err := c.save(); err != nil { if lastErr != nil { - logrus.Errorf("Error reaping exec sessions for container %s: %v", c.ID(), lastErr) + logrus.Errorf("Reaping exec sessions for container %s: %v", c.ID(), lastErr) } lastErr = err } @@ -970,7 +970,7 @@ func (c *Container) removeAllExecSessions() error { for _, id := range knownSessions { if err := c.ociRuntime.ExecStopContainer(c, id, c.StopTimeout()); err != nil { if lastErr != nil { - logrus.Errorf("Error stopping container %s exec sessions: %v", c.ID(), lastErr) + logrus.Errorf("Stopping container %s exec sessions: %v", c.ID(), lastErr) } lastErr = err continue @@ -978,7 +978,7 @@ func (c *Container) removeAllExecSessions() error { if err := c.cleanupExecBundle(id); err != nil { if lastErr != nil { - logrus.Errorf("Error stopping container %s exec sessions: %v", c.ID(), lastErr) + logrus.Errorf("Stopping container %s exec sessions: %v", c.ID(), lastErr) } lastErr = err } @@ -987,7 +987,7 @@ func (c *Container) removeAllExecSessions() error { if err := c.runtime.state.RemoveContainerExecSessions(c); err != nil { if errors.Cause(err) != define.ErrCtrRemoved { if lastErr != nil { - logrus.Errorf("Error stopping container %s exec sessions: %v", c.ID(), lastErr) + logrus.Errorf("Stopping container %s exec sessions: %v", c.ID(), lastErr) } lastErr = err } @@ -997,7 +997,7 @@ func (c *Container) removeAllExecSessions() error { if err := c.save(); err != nil { if errors.Cause(err) != define.ErrCtrRemoved { if lastErr != nil { - logrus.Errorf("Error stopping container %s exec sessions: %v", c.ID(), lastErr) + logrus.Errorf("Stopping container %s exec sessions: %v", c.ID(), lastErr) } lastErr = err } diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 530160b2d..09e59bf53 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -151,7 +151,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver if c.config.HealthCheckConfig != nil { // This container has a healthcheck defined in it; we need to add it's state - healthCheckState, err := c.GetHealthCheckLog() + healthCheckState, err := c.getHealthCheckLog() if err != nil { // An error here is not considered fatal; no health state will be displayed logrus.Error(err) @@ -178,13 +178,13 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver if size { rootFsSize, err := c.rootFsSize() if err != nil { - logrus.Errorf("error getting rootfs size %q: %v", config.ID, err) + logrus.Errorf("Getting rootfs size %q: %v", config.ID, err) } data.SizeRootFs = rootFsSize rwSize, err := c.rwSize() if err != nil { - logrus.Errorf("error getting rw size %q: %v", config.ID, err) + logrus.Errorf("Getting rw size %q: %v", config.ID, err) } data.SizeRw = &rwSize } @@ -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.go b/libpod/container_internal.go index 9ac2cd5bd..cb691dfd8 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -176,7 +176,7 @@ func (c *Container) waitForExitFileAndSync() error { c.state.State = define.ContainerStateStopped if err2 := c.save(); err2 != nil { - logrus.Errorf("Error saving container %s state: %v", c.ID(), err2) + logrus.Errorf("Saving container %s state: %v", c.ID(), err2) } return err @@ -278,7 +278,7 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr err defer func() { if retErr != nil { if err := c.cleanup(ctx); err != nil { - logrus.Errorf("error cleaning up container %s: %v", c.ID(), err) + logrus.Errorf("Cleaning up container %s: %v", c.ID(), err) } } }() @@ -709,7 +709,7 @@ func (c *Container) export(path string) error { mountPoint = containerMount defer func() { if _, err := c.runtime.store.Unmount(c.ID(), false); err != nil { - logrus.Errorf("error unmounting container %q: %v", c.ID(), err) + logrus.Errorf("Unmounting container %q: %v", c.ID(), err) } }() } @@ -778,7 +778,7 @@ func (c *Container) prepareToStart(ctx context.Context, recursive bool) (retErr defer func() { if retErr != nil { if err := c.cleanup(ctx); err != nil { - logrus.Errorf("error cleaning up container %s: %v", c.ID(), err) + logrus.Errorf("Cleaning up container %s: %v", c.ID(), err) } } }() @@ -859,7 +859,7 @@ func (c *Container) startDependencies(ctx context.Context) error { } if len(ctrErrors) > 0 { - logrus.Errorf("error starting some container dependencies") + logrus.Errorf("Starting some container dependencies") for _, e := range ctrErrors { logrus.Errorf("%q", e) } @@ -1047,7 +1047,7 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error { // upstream in any OCI runtime. // TODO: Remove once runc supports cgroupsv2 if strings.Contains(err.Error(), "this version of runc doesn't work on cgroups v2") { - logrus.Errorf("oci runtime %q does not support CGroups V2: use system migrate to mitigate", c.ociRuntime.Name()) + logrus.Errorf("Oci runtime %q does not support CGroups V2: use system migrate to mitigate", c.ociRuntime.Name()) } return err } @@ -1057,7 +1057,7 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error { // Remove any exec sessions leftover from a potential prior run. if len(c.state.ExecSessions) > 0 { if err := c.runtime.state.RemoveContainerExecSessions(c); err != nil { - logrus.Errorf("Error removing container %s exec sessions from DB: %v", c.ID(), err) + logrus.Errorf("Removing container %s exec sessions from DB: %v", c.ID(), err) } c.state.ExecSessions = make(map[string]*ExecSession) } @@ -1164,7 +1164,7 @@ func (c *Container) initAndStart(ctx context.Context) (retErr error) { defer func() { if retErr != nil { if err := c.cleanup(ctx); err != nil { - logrus.Errorf("error cleaning up container %s: %v", c.ID(), err) + logrus.Errorf("Cleaning up container %s: %v", c.ID(), err) } } }() @@ -1211,7 +1211,7 @@ func (c *Container) start() error { payload += daemon.SdNotifyReady } if sent, err := daemon.SdNotify(false, payload); err != nil { - logrus.Errorf("Error notifying systemd of Conmon PID: %s", err.Error()) + logrus.Errorf("Notifying systemd of Conmon PID: %s", err.Error()) } else if sent { logrus.Debugf("Notify sent successfully") } @@ -1290,7 +1290,7 @@ func (c *Container) stop(timeout uint) error { return stopErr default: if stopErr != nil { - logrus.Errorf("Error syncing container %s status: %v", c.ID(), err) + logrus.Errorf("Syncing container %s status: %v", c.ID(), err) return stopErr } return err @@ -1328,7 +1328,7 @@ func (c *Container) stop(timeout uint) error { c.state.FinishedTime = time.Now() c.state.State = define.ContainerStateStopped if err := c.save(); err != nil { - logrus.Errorf("Error saving container %s status: %v", c.ID(), err) + logrus.Errorf("Saving container %s status: %v", c.ID(), err) } return errors.Wrapf(define.ErrConmonDead, "container %s conmon process missing, cannot retrieve exit code", c.ID()) @@ -1432,7 +1432,7 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (retEr defer func() { if retErr != nil { if err := c.cleanup(ctx); err != nil { - logrus.Errorf("error cleaning up container %s: %v", c.ID(), err) + logrus.Errorf("Cleaning up container %s: %v", c.ID(), err) } } }() @@ -1483,7 +1483,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { defer func() { if deferredErr != nil { if err := c.unmountSHM(c.config.ShmDir); err != nil { - logrus.Errorf("Error unmounting SHM for container %s after mount error: %v", c.ID(), err) + logrus.Errorf("Unmounting SHM for container %s after mount error: %v", c.ID(), err) } } }() @@ -1526,7 +1526,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { defer func() { if deferredErr != nil { if err := c.unmount(false); err != nil { - logrus.Errorf("Error unmounting container %s after mount error: %v", c.ID(), err) + logrus.Errorf("Unmounting container %s after mount error: %v", c.ID(), err) } } }() @@ -1554,7 +1554,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { } vol.lock.Lock() if err := vol.unmount(false); err != nil { - logrus.Errorf("Error unmounting volume %s after error mounting container %s: %v", vol.Name(), c.ID(), err) + logrus.Errorf("Unmounting volume %s after error mounting container %s: %v", vol.Name(), c.ID(), err) } vol.lock.Unlock() }() @@ -1669,7 +1669,7 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) if err := copier.Put(volMount, "", copyOpts, reader); err != nil { err2 := <-errChan if err2 != nil { - logrus.Errorf("Error streaming contents of container %s directory for volume copy-up: %v", c.ID(), err2) + logrus.Errorf("Streaming contents of container %s directory for volume copy-up: %v", c.ID(), err2) } return nil, errors.Wrapf(err, "error copying up to volume %s", vol.Name()) } @@ -1705,7 +1705,7 @@ func (c *Container) cleanupStorage() error { for _, containerMount := range c.config.Mounts { if err := c.unmountSHM(containerMount); err != nil { if cleanupErr != nil { - logrus.Errorf("Error unmounting container %s: %v", c.ID(), cleanupErr) + logrus.Errorf("Unmounting container %s: %v", c.ID(), cleanupErr) } cleanupErr = err } @@ -1730,7 +1730,7 @@ func (c *Container) cleanupStorage() error { logrus.Errorf("Storage for container %s has been removed", c.ID()) } else { if cleanupErr != nil { - logrus.Errorf("Error cleaning up container %s storage: %v", c.ID(), cleanupErr) + logrus.Errorf("Cleaning up container %s storage: %v", c.ID(), cleanupErr) } cleanupErr = err } @@ -1741,7 +1741,7 @@ func (c *Container) cleanupStorage() error { vol, err := c.runtime.state.Volume(v.Name) if err != nil { if cleanupErr != nil { - logrus.Errorf("Error unmounting container %s: %v", c.ID(), cleanupErr) + logrus.Errorf("Unmounting container %s: %v", c.ID(), cleanupErr) } cleanupErr = errors.Wrapf(err, "error retrieving named volume %s for container %s", v.Name, c.ID()) @@ -1754,7 +1754,7 @@ func (c *Container) cleanupStorage() error { vol.lock.Lock() if err := vol.unmount(false); err != nil { if cleanupErr != nil { - logrus.Errorf("Error unmounting container %s: %v", c.ID(), cleanupErr) + logrus.Errorf("Unmounting container %s: %v", c.ID(), cleanupErr) } cleanupErr = errors.Wrapf(err, "error unmounting volume %s for container %s", vol.Name(), c.ID()) } @@ -1768,7 +1768,7 @@ func (c *Container) cleanupStorage() error { if c.valid { if err := c.save(); err != nil { if cleanupErr != nil { - logrus.Errorf("Error unmounting container %s: %v", c.ID(), cleanupErr) + logrus.Errorf("Unmounting container %s: %v", c.ID(), cleanupErr) } cleanupErr = err } @@ -1785,7 +1785,7 @@ func (c *Container) cleanup(ctx context.Context) error { // Remove healthcheck unit/timer file if it execs if c.config.HealthCheckConfig != nil { if err := c.removeTimer(); err != nil { - logrus.Errorf("Error removing timer for container %s healthcheck: %v", c.ID(), err) + logrus.Errorf("Removing timer for container %s healthcheck: %v", c.ID(), err) } } @@ -1800,7 +1800,7 @@ func (c *Container) cleanup(ctx context.Context) error { // exists. if err := c.cleanupRuntime(ctx); err != nil { if lastError != nil { - logrus.Errorf("Error removing container %s from OCI runtime: %v", c.ID(), err) + logrus.Errorf("Removing container %s from OCI runtime: %v", c.ID(), err) } else { lastError = err } @@ -1809,7 +1809,7 @@ func (c *Container) cleanup(ctx context.Context) error { // Unmount storage if err := c.cleanupStorage(); err != nil { if lastError != nil { - logrus.Errorf("Error unmounting container %s storage: %v", c.ID(), err) + logrus.Errorf("Unmounting container %s storage: %v", c.ID(), err) } else { lastError = errors.Wrapf(err, "error unmounting container %s storage", c.ID()) } @@ -1823,14 +1823,14 @@ func (c *Container) cleanup(ctx context.Context) error { lastError = err continue } - logrus.Errorf("error unmounting image volume %q:%q :%v", v.Source, v.Dest, err) + logrus.Errorf("Unmounting image volume %q:%q :%v", v.Source, v.Dest, err) } if err := img.Unmount(false); err != nil { if lastError == nil { lastError = err continue } - logrus.Errorf("error unmounting image volume %q:%q :%v", v.Source, v.Dest, err) + logrus.Errorf("Unmounting image volume %q:%q :%v", v.Source, v.Dest, err) } } @@ -1874,7 +1874,7 @@ func (c *Container) postDeleteHooks(ctx context.Context) error { var stderr, stdout bytes.Buffer hookErr, err := exec.Run(ctx, &hook, state, &stdout, &stderr, exec.DefaultPostKillTimeout) if err != nil { - logrus.Warnf("container %s: poststop hook %d: %v", c.ID(), i, err) + logrus.Warnf("Container %s: poststop hook %d: %v", c.ID(), i, err) if hookErr != err { logrus.Debugf("container %s: poststop hook %d (hook error): %v", c.ID(), i, hookErr) } @@ -2010,7 +2010,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s return nil, err } if len(ociHooks) > 0 || config.Hooks != nil { - logrus.Warnf("implicit hook directories are deprecated; set --ociHooks-dir=%q explicitly to continue to load ociHooks from this directory", hDir) + logrus.Warnf("Implicit hook directories are deprecated; set --ociHooks-dir=%q explicitly to continue to load ociHooks from this directory", hDir) } for i, hook := range ociHooks { allHooks[i] = hook @@ -2030,7 +2030,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s hookErr, err := exec.RuntimeConfigFilter(ctx, allHooks["precreate"], config, exec.DefaultPostKillTimeout) if err != nil { - logrus.Warnf("container %s: precreate hook: %v", c.ID(), err) + logrus.Warnf("Container %s: precreate hook: %v", c.ID(), err) if hookErr != nil && hookErr != err { logrus.Debugf("container %s: precreate hook (hook error): %v", c.ID(), hookErr) } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 6ebbfd1f3..dd6f3878a 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -70,7 +70,7 @@ func (c *Container) unmountSHM(mount string) error { return errors.Wrapf(err, "error unmounting container %s SHM mount %s", c.ID(), mount) } // If it's just an EINVAL or ENOENT, debug logs only - logrus.Debugf("container %s failed to unmount %s : %v", c.ID(), mount, err) + logrus.Debugf("Container %s failed to unmount %s : %v", c.ID(), mount, err) } return nil } @@ -143,7 +143,7 @@ func (c *Container) prepare() error { } if mountStorageErr != nil { if createErr != nil { - logrus.Errorf("Error preparing container %s: %v", c.ID(), createErr) + logrus.Errorf("Preparing container %s: %v", c.ID(), createErr) } createErr = mountStorageErr } @@ -154,7 +154,7 @@ func (c *Container) prepare() error { if err := c.cleanupStorage(); err != nil { // createErr is guaranteed non-nil, so print // unconditionally - logrus.Errorf("Error preparing container %s: %v", c.ID(), createErr) + logrus.Errorf("Preparing container %s: %v", c.ID(), createErr) createErr = errors.Wrapf(err, "error unmounting storage for container %s after network create failure", c.ID()) } } @@ -163,7 +163,7 @@ func (c *Container) prepare() error { // isn't ready it will do nothing. if createErr != nil { if err := c.cleanupNetwork(); err != nil { - logrus.Errorf("Error preparing container %s: %v", c.ID(), createErr) + logrus.Errorf("Preparing container %s: %v", c.ID(), createErr) createErr = errors.Wrapf(err, "error cleaning up container %s network after setup failure", c.ID()) } } @@ -258,7 +258,7 @@ func (c *Container) cleanupNetwork() error { // Stop the container's network namespace (if it has one) if err := c.runtime.teardownNetNS(c); err != nil { - logrus.Errorf("unable to cleanup network for container %s: %q", c.ID(), err) + logrus.Errorf("Unable to cleanup network for container %s: %q", c.ID(), err) } c.state.NetNS = nil @@ -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. @@ -566,7 +599,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { if isGIDAvailable { g.AddProcessAdditionalGid(uint32(gid)) } else { - logrus.Warnf("additional gid=%d is not present in the user namespace, skip setting it", gid) + logrus.Warnf("Additional gid=%d is not present in the user namespace, skip setting it", gid) } } } @@ -607,7 +640,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { if err != nil { if os.IsNotExist(err) { // The kernel-provided files only exist if user namespaces are supported - logrus.Debugf("user or group ID mappings not available: %s", err) + logrus.Debugf("User or group ID mappings not available: %s", err) } else { return nil, err } @@ -748,7 +781,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } if rootPropagation != "" { - logrus.Debugf("set root propagation to %q", rootPropagation) + logrus.Debugf("Set root propagation to %q", rootPropagation) if err := g.SetLinuxRootPropagation(rootPropagation); err != nil { return nil, err } @@ -805,7 +838,7 @@ func (c *Container) mountNotifySocket(g generate.Generator) error { } notifyDir := filepath.Join(c.bundlePath(), "notify") - logrus.Debugf("checking notify %q dir", notifyDir) + logrus.Debugf("Checking notify %q dir", notifyDir) if err := os.MkdirAll(notifyDir, 0755); err != nil { if !os.IsExist(err) { return errors.Wrapf(err, "unable to create notify %q dir", notifyDir) @@ -814,7 +847,7 @@ func (c *Container) mountNotifySocket(g generate.Generator) error { if err := label.Relabel(notifyDir, c.MountLabel(), true); err != nil { return errors.Wrapf(err, "relabel failed %q", notifyDir) } - logrus.Debugf("add bindmount notify %q dir", notifyDir) + logrus.Debugf("Add bindmount notify %q dir", notifyDir) if _, ok := c.state.BindMounts["/run/notify"]; !ok { c.state.BindMounts["/run/notify"] = notifyDir } @@ -1166,7 +1199,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO for _, del := range cleanup { file := filepath.Join(c.bundlePath(), del) if err := os.Remove(file); err != nil { - logrus.Debugf("unable to remove file %s", file) + logrus.Debugf("Unable to remove file %s", file) } } } @@ -1266,7 +1299,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti var netStatus map[string]types.StatusBlock _, err := metadata.ReadJSONFile(&netStatus, c.bundlePath(), metadata.NetworkStatusFile) if err != nil { - logrus.Infof("failed to unmarshal network status, cannot restore the same ip/mac: %v", err) + logrus.Infof("Failed to unmarshal network status, cannot restore the same ip/mac: %v", err) } // If the restored container should get a new name, the IP address of // the container will not be restored. This assumes that if a new name is @@ -1316,7 +1349,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti defer func() { if retErr != nil { if err := c.cleanup(ctx); err != nil { - logrus.Errorf("error cleaning up container %s: %v", c.ID(), err) + logrus.Errorf("Cleaning up container %s: %v", c.ID(), err) } } }() @@ -1870,11 +1903,11 @@ func (c *Container) generateResolvConf() (string, error) { for _, nsIP := range status.DNSServerIPs { networkNameServers = append(networkNameServers, nsIP.String()) } - logrus.Debugf("adding nameserver(s) from network status of '%q'", status.DNSServerIPs) + logrus.Debugf("Adding nameserver(s) from network status of '%q'", status.DNSServerIPs) } if status.DNSSearchDomains != nil { networkSearchDomains = append(networkSearchDomains, status.DNSSearchDomains...) - logrus.Debugf("adding search domain(s) from network status of '%q'", status.DNSSearchDomains) + logrus.Debugf("Adding search domain(s) from network status of '%q'", status.DNSSearchDomains) } } @@ -1923,7 +1956,7 @@ func (c *Container) generateResolvConf() (string, error) { if c.config.NetMode.IsSlirp4netns() { slirp4netnsDNS, err := GetSlirp4netnsDNS(c.slirp4netnsSubnet) if err != nil { - logrus.Warn("failed to determine Slirp4netns DNS: ", err.Error()) + logrus.Warn("Failed to determine Slirp4netns DNS: ", err.Error()) } else { nameservers = append([]string{slirp4netnsDNS.String()}, nameservers...) } @@ -2025,7 +2058,7 @@ func (c *Container) getHosts() string { // When using slirp4netns, the interface gets a static IP slirp4netnsIP, err := GetSlirp4netnsIP(c.slirp4netnsSubnet) if err != nil { - logrus.Warnf("failed to determine slirp4netnsIP: %v", err.Error()) + logrus.Warnf("Failed to determine slirp4netnsIP: %v", err.Error()) } else { hosts += fmt.Sprintf("# used by slirp4netns\n%s\t%s %s\n", slirp4netnsIP.String(), c.Hostname(), c.config.Name) } @@ -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/container_internal_unsupported.go b/libpod/container_internal_unsupported.go deleted file mode 100644 index 125329ce5..000000000 --- a/libpod/container_internal_unsupported.go +++ /dev/null @@ -1,64 +0,0 @@ -// +build !linux - -package libpod - -import ( - "context" - - "github.com/containers/podman/v3/libpod/define" - "github.com/containers/podman/v3/pkg/lookup" - spec "github.com/opencontainers/runtime-spec/specs-go" -) - -func (c *Container) mountSHM(shmOptions string) error { - return define.ErrNotImplemented -} - -func (c *Container) unmountSHM(mount string) error { - return define.ErrNotImplemented -} - -func (c *Container) prepare() error { - return define.ErrNotImplemented -} - -func (c *Container) cleanupNetwork() error { - return define.ErrNotImplemented -} - -func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { - return nil, define.ErrNotImplemented -} - -func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointOptions) error { - return define.ErrNotImplemented -} - -func (c *Container) restore(ctx context.Context, options ContainerCheckpointOptions) error { - return define.ErrNotImplemented -} - -func (c *Container) copyOwnerAndPerms(source, dest string) error { - return nil -} - -func (c *Container) getOCICgroupPath() (string, error) { - return "", define.ErrNotImplemented -} - -func (c *Container) cleanupOverlayMounts() error { - return nil -} - -func (c *Container) reloadNetwork() error { - return define.ErrNotImplemented -} - -func (c *Container) getUserOverrides() *lookup.Overrides { - return nil -} - -// Fix ownership and permissions of the specified volume if necessary. -func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error { - return define.ErrNotImplemented -} diff --git a/libpod/container_log.go b/libpod/container_log.go index 89dd5e8b0..a65b2a44f 100644 --- a/libpod/container_log.go +++ b/libpod/container_log.go @@ -83,7 +83,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption } nll, err := logs.NewLogLine(line.Text) if err != nil { - logrus.Errorf("Error getting new log line: %v", err) + logrus.Errorf("Getting new log line: %v", err) continue } if nll.Partial() { @@ -108,7 +108,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption state, err := c.State() if err != nil || state != define.ContainerStateRunning { if err != nil && errors.Cause(err) != define.ErrNoSuchCtr { - logrus.Errorf("Error getting container state: %v", err) + logrus.Errorf("Getting container state: %v", err) } go func() { // Make sure to wait at least for the poll duration @@ -116,7 +116,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption time.Sleep(watch.POLL_DURATION) tailError := t.StopAtEOF() if tailError != nil && tailError.Error() != "tail: stop at eof" { - logrus.Errorf("Error stopping logger: %v", tailError) + logrus.Errorf("Stopping logger: %v", tailError) } }() return nil @@ -132,7 +132,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption } go func() { if err := c.runtime.Events(ctx, eventOptions); err != nil { - logrus.Errorf("Error waiting for container to exit: %v", err) + logrus.Errorf("Waiting for container to exit: %v", err) } }() // Now wait for the died event and signal to finish @@ -143,7 +143,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption time.Sleep(watch.POLL_DURATION) tailError := t.StopAtEOF() if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { - logrus.Errorf("Error stopping logger: %v", tailError) + logrus.Errorf("Stopping logger: %v", tailError) } }() } diff --git a/libpod/container_stat_unsupported.go b/libpod/container_stat_unsupported.go deleted file mode 100644 index c002e4d32..000000000 --- a/libpod/container_stat_unsupported.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !linux - -package libpod - -import ( - "context" - - "github.com/containers/podman/v3/libpod/define" -) - -func (c *Container) stat(ctx context.Context, containerMountPoint string, containerPath string) (*define.FileInfo, string, string, error) { - return nil, "", "", nil -} diff --git a/libpod/container_top_unsupported.go b/libpod/container_top_unsupported.go deleted file mode 100644 index 1a096d248..000000000 --- a/libpod/container_top_unsupported.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build !linux - -package libpod - -import "github.com/containers/podman/v3/libpod/define" - -// Top gathers statistics about the running processes in a container. It returns a -// []string for output -func (c *Container) Top(descriptors []string) ([]string, error) { - return nil, define.ErrNotImplemented -} - -// GetContainerPidInformation returns process-related data of all processes in -// the container. The output data can be controlled via the `descriptors` -// argument which expects format descriptors and supports all AIXformat -// descriptors of ps (1) plus some additional ones to for instance inspect the -// set of effective capabilities. Each element in the returned string slice -// is a tab-separated string. -// -// For more details, please refer to github.com/containers/psgo. -func (c *Container) GetContainerPidInformation(descriptors []string) ([]string, error) { - return nil, define.ErrNotImplemented -} diff --git a/libpod/container_unsupported.go b/libpod/container_unsupported.go deleted file mode 100644 index e214b9465..000000000 --- a/libpod/container_unsupported.go +++ /dev/null @@ -1,5 +0,0 @@ -// +build !linux - -package libpod - -type containerPlatformState struct{} 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/events.go b/libpod/events.go index 22c51aeec..342af02d2 100644 --- a/libpod/events.go +++ b/libpod/events.go @@ -33,7 +33,7 @@ func (c *Container) newContainerEvent(status events.Status) { } if err := c.runtime.eventer.Write(e); err != nil { - logrus.Errorf("unable to write pod event: %q", err) + logrus.Errorf("Unable to write pod event: %q", err) } } @@ -46,7 +46,7 @@ func (c *Container) newContainerExitedEvent(exitCode int32) { e.Type = events.Container e.ContainerExitCode = int(exitCode) if err := c.runtime.eventer.Write(e); err != nil { - logrus.Errorf("unable to write container exited event: %q", err) + logrus.Errorf("Unable to write container exited event: %q", err) } } @@ -61,7 +61,7 @@ func (c *Container) newExecDiedEvent(sessionID string, exitCode int) { e.Attributes = make(map[string]string) e.Attributes["execID"] = sessionID if err := c.runtime.eventer.Write(e); err != nil { - logrus.Errorf("unable to write exec died event: %q", err) + logrus.Errorf("Unable to write exec died event: %q", err) } } @@ -73,7 +73,7 @@ func (c *Container) newNetworkEvent(status events.Status, netName string) { e.Type = events.Network e.Network = netName if err := c.runtime.eventer.Write(e); err != nil { - logrus.Errorf("unable to write pod event: %q", err) + logrus.Errorf("Unable to write pod event: %q", err) } } @@ -84,7 +84,7 @@ func (p *Pod) newPodEvent(status events.Status) { e.Name = p.Name() e.Type = events.Pod if err := p.runtime.eventer.Write(e); err != nil { - logrus.Errorf("unable to write pod event: %q", err) + logrus.Errorf("Unable to write pod event: %q", err) } } @@ -94,7 +94,7 @@ func (r *Runtime) newSystemEvent(status events.Status) { e.Type = events.System if err := r.eventer.Write(e); err != nil { - logrus.Errorf("unable to write system event: %q", err) + logrus.Errorf("Unable to write system event: %q", err) } } @@ -104,7 +104,7 @@ func (v *Volume) newVolumeEvent(status events.Status) { e.Name = v.Name() e.Type = events.Volume if err := v.runtime.eventer.Write(e); err != nil { - logrus.Errorf("unable to write volume event: %q", err) + logrus.Errorf("Unable to write volume event: %q", err) } } diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go index 3e16d8679..72e03355a 100644 --- a/libpod/events/journal_linux.go +++ b/libpod/events/journal_linux.go @@ -195,7 +195,7 @@ func newEventFromJournalEntry(entry *sdjournal.JournalEntry) (*Event, error) { / if code, ok := entry.Fields["PODMAN_EXIT_CODE"]; ok { intCode, err := strconv.Atoi(code) if err != nil { - logrus.Errorf("Error parsing event exit code %s", code) + logrus.Errorf("Parsing event exit code %s", code) } else { newEvent.ContainerExitCode = intCode } diff --git a/libpod/healthcheck.go b/libpod/healthcheck.go index c32ba85cb..91f031513 100644 --- a/libpod/healthcheck.go +++ b/libpod/healthcheck.go @@ -162,7 +162,7 @@ func newHealthCheckLog(start, end time.Time, exitCode int, log string) define.He // updatedHealthCheckStatus updates the health status of the container // in the healthcheck log func (c *Container) updateHealthStatus(status string) error { - healthCheck, err := c.GetHealthCheckLog() + healthCheck, err := c.getHealthCheckLog() if err != nil { return err } @@ -176,7 +176,7 @@ func (c *Container) updateHealthStatus(status string) error { // UpdateHealthCheckLog parses the health check results and writes the log func (c *Container) updateHealthCheckLog(hcl define.HealthCheckLog, inStartPeriod bool) error { - healthCheck, err := c.GetHealthCheckLog() + healthCheck, err := c.getHealthCheckLog() if err != nil { return err } @@ -213,10 +213,11 @@ func (c *Container) healthCheckLogPath() string { return filepath.Join(filepath.Dir(c.state.RunDir), "healthcheck.log") } -// GetHealthCheckLog returns HealthCheck results by reading the container's +// getHealthCheckLog returns HealthCheck results by reading the container's // health check log file. If the health check log file does not exist, then // an empty healthcheck struct is returned -func (c *Container) GetHealthCheckLog() (define.HealthCheckResults, error) { +// The caller should lock the container before this function is called. +func (c *Container) getHealthCheckLog() (define.HealthCheckResults, error) { var healthCheck define.HealthCheckResults if _, err := os.Stat(c.healthCheckLogPath()); os.IsNotExist(err) { return healthCheck, nil @@ -236,7 +237,12 @@ func (c *Container) HealthCheckStatus() (string, error) { if !c.HasHealthCheck() { return "", errors.Errorf("container %s has no defined healthcheck", c.ID()) } - results, err := c.GetHealthCheckLog() + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return "", err + } + results, err := c.getHealthCheckLog() if err != nil { return "", errors.Wrapf(err, "unable to get healthcheck log for %s", c.ID()) } diff --git a/libpod/healthcheck_unsupported.go b/libpod/healthcheck_unsupported.go deleted file mode 100644 index 8b6a0209b..000000000 --- a/libpod/healthcheck_unsupported.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build !linux - -package libpod - -import "github.com/containers/podman/v3/libpod/define" - -// createTimer systemd timers for healthchecks of a container -func (c *Container) createTimer() error { - return define.ErrNotImplemented -} - -// startTimer starts a systemd timer for the healthchecks -func (c *Container) startTimer() error { - return define.ErrNotImplemented -} - -// removeTimer removes the systemd timer and unit files -// for the container -func (c *Container) removeTimer() error { - return define.ErrNotImplemented -} diff --git a/libpod/info.go b/libpod/info.go index 36dc8bc2a..a2fd18491 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -186,7 +186,7 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) { conmonInfo, ociruntimeInfo, err := r.defaultOCIRuntime.RuntimeInfo() if err != nil { - logrus.Errorf("Error getting info on OCI runtime %s: %v", r.defaultOCIRuntime.Name(), err) + logrus.Errorf("Getting info on OCI runtime %s: %v", r.defaultOCIRuntime.Name(), err) } else { info.Conmon = conmonInfo info.OCIRuntime = ociruntimeInfo diff --git a/libpod/kube.go b/libpod/kube.go index 54e8a7c50..d94108cf2 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -1,9 +1,11 @@ package libpod import ( + "context" "fmt" "math/rand" "os" + "reflect" "sort" "strconv" "strings" @@ -11,6 +13,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" @@ -26,14 +29,14 @@ import ( // GenerateForKube takes a slice of libpod containers and generates // one v1.Pod description that includes just a single container. -func GenerateForKube(ctrs []*Container) (*v1.Pod, error) { +func GenerateForKube(ctx context.Context, ctrs []*Container) (*v1.Pod, error) { // Generate the v1.Pod yaml description - return simplePodWithV1Containers(ctrs) + return simplePodWithV1Containers(ctx, ctrs) } // GenerateForKube takes a slice of libpod containers and generates // one v1.Pod description -func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) { +func (p *Pod) GenerateForKube(ctx context.Context) (*v1.Pod, []v1.ServicePort, error) { // Generate the v1.Pod yaml description var ( ports []v1.ContainerPort //nolint @@ -77,7 +80,7 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) { servicePorts = containerPortsToServicePorts(ports) hostNetwork = infraContainer.NetworkMode() == string(namespaces.NetworkMode(specgen.Host)) } - pod, err := p.podWithContainers(allContainers, ports, hostNetwork) + pod, err := p.podWithContainers(ctx, allContainers, ports, hostNetwork) if err != nil { return nil, servicePorts, err } @@ -217,7 +220,7 @@ func containersToServicePorts(containers []v1.Container) []v1.ServicePort { return sps } -func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPort, hostNetwork bool) (*v1.Pod, error) { +func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, ports []v1.ContainerPort, hostNetwork bool) (*v1.Pod, error) { deDupPodVolumes := make(map[string]*v1.Volume) first := true podContainers := make([]v1.Container, 0, len(containers)) @@ -238,7 +241,7 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor isInit := ctr.IsInitCtr() - ctr, volumes, _, err := containerToV1Container(ctr) + ctr, volumes, _, err := containerToV1Container(ctx, ctr) if err != nil { return nil, err } @@ -266,7 +269,7 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor deDupPodVolumes[vol.Name] = &vol } } else { - _, _, infraDNS, err := containerToV1Container(ctr) + _, _, infraDNS, err := containerToV1Container(ctx, ctr) if err != nil { return nil, err } @@ -336,7 +339,7 @@ func newPodObject(podName string, annotations map[string]string, initCtrs, conta // simplePodWithV1Containers is a function used by inspect when kube yaml needs to be generated // for a single container. we "insert" that container description in a pod. -func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { +func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod, error) { kubeCtrs := make([]v1.Container, 0, len(ctrs)) kubeInitCtrs := []v1.Container{} kubeVolumes := make([]v1.Volume, 0) @@ -354,7 +357,7 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { if !ctr.HostNetwork() { hostNetwork = false } - kubeCtr, kubeVols, ctrDNS, err := containerToV1Container(ctr) + kubeCtr, kubeVols, ctrDNS, err := containerToV1Container(ctx, ctr) if err != nil { return nil, err } @@ -410,7 +413,7 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { // containerToV1Container converts information we know about a libpod container // to a V1.Container specification. -func containerToV1Container(c *Container) (v1.Container, []v1.Volume, *v1.PodDNSConfig, error) { +func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []v1.Volume, *v1.PodDNSConfig, error) { kubeContainer := v1.Container{} kubeVolumes := []v1.Volume{} kubeSec, err := generateKubeSecurityContext(c) @@ -462,6 +465,17 @@ func containerToV1Container(c *Container) (v1.Container, []v1.Volume, *v1.PodDNS _, image := c.Image() kubeContainer.Image = image kubeContainer.Stdin = c.Stdin() + img, _, err := c.runtime.libimageRuntime.LookupImage(image, nil) + if err != nil { + return kubeContainer, kubeVolumes, nil, err + } + imgData, err := img.Inspect(ctx, false) + if err != nil { + return kubeContainer, kubeVolumes, nil, err + } + if reflect.DeepEqual(imgData.Config.Cmd, kubeContainer.Command) { + kubeContainer.Command = nil + } kubeContainer.WorkingDir = c.WorkingDir() kubeContainer.Ports = ports @@ -570,12 +584,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/lock/file/file_lock.go b/libpod/lock/file/file_lock.go index 2643c9211..4685872b6 100644 --- a/libpod/lock/file/file_lock.go +++ b/libpod/lock/file/file_lock.go @@ -139,7 +139,7 @@ func (locks *FileLocks) DeallocateAllLocks() error { err := os.Remove(p) if err != nil { lastErr = err - logrus.Errorf("deallocating lock %s", p) + logrus.Errorf("Deallocating lock %s", p) } } return lastErr diff --git a/libpod/lock/shm/shm_lock_nocgo.go b/libpod/lock/shm/shm_lock_nocgo.go index ea1488c90..627344d9c 100644 --- a/libpod/lock/shm/shm_lock_nocgo.go +++ b/libpod/lock/shm/shm_lock_nocgo.go @@ -16,7 +16,7 @@ type SHMLocks struct { // numLocks must not be 0, and may be rounded up to a multiple of the bitmap // size used by the underlying implementation. func CreateSHMLock(path string, numLocks uint32) (*SHMLocks, error) { - logrus.Error("locks are not supported without cgo") + logrus.Error("Locks are not supported without cgo") return &SHMLocks{}, nil } @@ -24,13 +24,13 @@ func CreateSHMLock(path string, numLocks uint32) (*SHMLocks, error) { // POSIX semaphores. numLocks must match the number of locks the shared memory // segment was created with. func OpenSHMLock(path string, numLocks uint32) (*SHMLocks, error) { - logrus.Error("locks are not supported without cgo") + logrus.Error("Locks are not supported without cgo") return &SHMLocks{}, nil } // GetMaxLocks returns the maximum number of locks in the SHM func (locks *SHMLocks) GetMaxLocks() uint32 { - logrus.Error("locks are not supported without cgo") + logrus.Error("Locks are not supported without cgo") return 0 } @@ -40,7 +40,7 @@ func (locks *SHMLocks) GetMaxLocks() uint32 { // fail to release, causing a program freeze. // Close() is only intended to be used while testing the locks. func (locks *SHMLocks) Close() error { - logrus.Error("locks are not supported without cgo") + logrus.Error("Locks are not supported without cgo") return nil } @@ -50,7 +50,7 @@ func (locks *SHMLocks) Close() error { // Allocations past the maximum number of locks given when the SHM segment was // created will result in an error, and no semaphore will be allocated. func (locks *SHMLocks) AllocateSemaphore() (uint32, error) { - logrus.Error("locks are not supported without cgo") + logrus.Error("Locks are not supported without cgo") return 0, nil } @@ -59,7 +59,7 @@ func (locks *SHMLocks) AllocateSemaphore() (uint32, error) { // If the semaphore is already in use or the index is invalid an error will be // returned. func (locks *SHMLocks) AllocateGivenSemaphore(sem uint32) error { - logrus.Error("locks are not supported without cgo") + logrus.Error("Locks are not supported without cgo") return nil } @@ -67,14 +67,14 @@ func (locks *SHMLocks) AllocateGivenSemaphore(sem uint32) error { // reallocated to another container or pod. // The given semaphore must be already allocated, or an error will be returned. func (locks *SHMLocks) DeallocateSemaphore(sem uint32) error { - logrus.Error("locks are not supported without cgo") + logrus.Error("Locks are not supported without cgo") return nil } // DeallocateAllSemaphores frees all semaphores so they can be reallocated to // other containers and pods. func (locks *SHMLocks) DeallocateAllSemaphores() error { - logrus.Error("locks are not supported without cgo") + logrus.Error("Locks are not supported without cgo") return nil } @@ -86,7 +86,7 @@ func (locks *SHMLocks) DeallocateAllSemaphores() error { // but before the caller has queried the database to determine this, will // succeed. func (locks *SHMLocks) LockSemaphore(sem uint32) error { - logrus.Error("locks are not supported without cgo") + logrus.Error("Locks are not supported without cgo") return nil } @@ -97,6 +97,6 @@ func (locks *SHMLocks) LockSemaphore(sem uint32) error { // but before the caller has queried the database to determine this, will // succeed. func (locks *SHMLocks) UnlockSemaphore(sem uint32) error { - logrus.Error("locks are not supported without cgo") + logrus.Error("Locks are not supported without cgo") return nil } diff --git a/libpod/logs/log.go b/libpod/logs/log.go index a584de0ee..19a121fe9 100644 --- a/libpod/logs/log.go +++ b/libpod/logs/log.go @@ -267,6 +267,6 @@ func (l *LogLine) Write(stdout io.Writer, stderr io.Writer, logOpts *LogOptions) } default: // Warn the user if the device type does not match. Most likely the file is corrupted. - logrus.Warnf("unknown Device type '%s' in log file from Container %s", l.Device, l.CID) + logrus.Warnf("Unknown Device type '%s' in log file from Container %s", l.Device, l.CID) } } diff --git a/libpod/network/cni/cni_conversion.go b/libpod/network/cni/cni_conversion.go index d69dd7eb3..93d871767 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" @@ -105,7 +104,7 @@ func createNetworkFromCNIConfigList(conf *libcni.NetworkConfigList, confPath str default: // A warning would be good but users would get this warning everytime so keep this at info level. - logrus.Infof("unsupported CNI config type %s in %s, this network can still be used but inspect or list cannot show all information", + logrus.Infof("Unsupported CNI config type %s in %s, this network can still be used but inspect or list cannot show all information", firstPlugin.Network.Type, confPath) } @@ -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/config.go b/libpod/network/cni/config.go index 2a6ad8eb3..670ee0c65 100644 --- a/libpod/network/cni/config.go +++ b/libpod/network/cni/config.go @@ -162,7 +162,7 @@ func (n *cniNetwork) NetworkRemove(nameOrID string) error { err = netlink.LinkDel(link) // only log the error, it is not fatal if err != nil { - logrus.Infof("failed to remove network interface %s: %v", network.libpodNet.NetworkInterface, err) + logrus.Infof("Failed to remove network interface %s: %v", network.libpodNet.NetworkInterface, err) } } } 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..0f91a407c 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) @@ -274,7 +273,7 @@ func (n *cniNetwork) teardown(namespacePath string, options types.TeardownOption if err == nil { rt = newRt } else { - logrus.Warnf("failed to load cached network config: %v, falling back to loading network %s from disk", err, name) + logrus.Warnf("Failed to load cached network config: %v, falling back to loading network %s from disk", err, name) network := n.networks[name] if network == nil { multiErr = multierror.Append(multiErr, errors.Wrapf(define.ErrNoSuchNetwork, "network %s", name)) diff --git a/libpod/network/cni/run_test.go b/libpod/network/cni/run_test.go index f6da22a76..0a2c090e1 100644 --- a/libpod/network/cni/run_test.go +++ b/libpod/network/cni/run_test.go @@ -1256,7 +1256,7 @@ var _ = Describe("run CNI", func() { Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("network somenet: network not found")) logString := logBuffer.String() - Expect(logString).To(ContainSubstring("failed to load cached network config")) + Expect(logString).To(ContainSubstring("Failed to load cached network config")) }) }) @@ -1283,7 +1283,7 @@ var _ = Describe("run CNI", func() { err = libpodNet.Teardown(netNSContainer.Path(), teardownOpts) Expect(err).To(BeNil()) logString := logBuffer.String() - Expect(logString).To(ContainSubstring("failed to load cached network config")) + Expect(logString).To(ContainSubstring("Failed to load cached network config")) }) }) }) 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/networking_linux.go b/libpod/networking_linux.go index 96b6fb298..ec9d98b56 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -320,14 +320,14 @@ func (r *RootlessCNI) Cleanup(runtime *Runtime) error { } } if err != nil { - logrus.Errorf("failed to kill slirp4netns process: %s", err) + logrus.Errorf("Failed to kill slirp4netns process: %s", err) } err = os.RemoveAll(r.dir) if err != nil { logrus.Error(err) } } else if err != nil && !os.IsNotExist(err) { - logrus.Errorf("could not read rootless cni directory, skipping cleanup: %s", err) + logrus.Errorf("Could not read rootless cni directory, skipping cleanup: %s", err) } } return nil @@ -458,7 +458,7 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) { defer func() { if err := cmd.Process.Release(); err != nil { - logrus.Errorf("unable to release command process: %q", err) + logrus.Errorf("Unable to release command process: %q", err) } }() @@ -635,10 +635,10 @@ func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q map[string]types.St defer func() { if retErr != nil { if err := netns.UnmountNS(ctrNS); err != nil { - logrus.Errorf("Error unmounting partially created network namespace for container %s: %v", ctr.ID(), err) + logrus.Errorf("Unmounting partially created network namespace for container %s: %v", ctr.ID(), err) } if err := ctrNS.Close(); err != nil { - logrus.Errorf("Error closing partially created network namespace for container %s: %v", ctr.ID(), err) + logrus.Errorf("Closing partially created network namespace for container %s: %v", ctr.ID(), err) } } }() diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go index a5c035757..cca55cb9b 100644 --- a/libpod/networking_slirp4netns.go +++ b/libpod/networking_slirp4netns.go @@ -210,7 +210,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error { var err error path, err = exec.LookPath("slirp4netns") if err != nil { - logrus.Errorf("could not find slirp4netns, the network namespace won't be configured: %v", err) + logrus.Errorf("Could not find slirp4netns, the network namespace won't be configured: %v", err) return nil } } @@ -303,7 +303,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error { defer func() { servicereaper.AddPID(cmd.Process.Pid) if err := cmd.Process.Release(); err != nil { - logrus.Errorf("unable to release command process: %q", err) + logrus.Errorf("Unable to release command process: %q", err) } }() @@ -421,7 +421,7 @@ func waitForSync(syncR *os.File, cmd *exec.Cmd, logFile io.ReadSeeker, timeout t if status.Exited() { // Seek at the beginning of the file and read all its content if _, err := logFile.Seek(0, 0); err != nil { - logrus.Errorf("could not seek log file: %q", err) + logrus.Errorf("Could not seek log file: %q", err) } logContent, err := ioutil.ReadAll(logFile) if err != nil { @@ -506,7 +506,7 @@ func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath strin defer func() { servicereaper.AddPID(cmd.Process.Pid) if err := cmd.Process.Release(); err != nil { - logrus.Errorf("unable to release rootlessport process: %q", err) + logrus.Errorf("Unable to release rootlessport process: %q", err) } }() if err := waitForSync(syncR, cmd, logFile, 3*time.Second); err != nil { @@ -559,7 +559,7 @@ func (r *Runtime) setupRootlessPortMappingViaSlirp(ctr *Container, cmd *exec.Cmd } defer func() { if err := conn.Close(); err != nil { - logrus.Errorf("unable to close connection: %q", err) + logrus.Errorf("Unable to close connection: %q", err) } }() hostIP := i.HostIP diff --git a/libpod/networking_unsupported.go b/libpod/networking_unsupported.go deleted file mode 100644 index 20c27ca7f..000000000 --- a/libpod/networking_unsupported.go +++ /dev/null @@ -1,40 +0,0 @@ -// +build !linux - -package libpod - -import ( - cnitypes "github.com/containernetworking/cni/pkg/types/current" - "github.com/containers/podman/v3/libpod/define" -) - -func (r *Runtime) setupRootlessNetNS(ctr *Container) error { - return define.ErrNotImplemented -} - -func (r *Runtime) setupSlirp4netns(ctr *Container) error { - return define.ErrNotImplemented -} - -func (r *Runtime) setupNetNS(ctr *Container) error { - return define.ErrNotImplemented -} - -func (r *Runtime) teardownNetNS(ctr *Container) error { - return define.ErrNotImplemented -} - -func (r *Runtime) createNetNS(ctr *Container) error { - return define.ErrNotImplemented -} - -func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, error) { - return nil, define.ErrNotImplemented -} - -func (r *Runtime) reloadContainerNetwork(ctr *Container) ([]*cnitypes.Result, error) { - return nil, define.ErrNotImplemented -} - -func getCNINetworksDir() (string, error) { - return "", define.ErrNotImplemented -} diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index de435b58a..9ae46eeda 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -67,7 +67,7 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <- } defer func() { if err := conn.Close(); err != nil { - logrus.Errorf("unable to close socket: %q", err) + logrus.Errorf("Unable to close socket: %q", err) } }() @@ -142,7 +142,7 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se if newSize != nil { err = c.ociRuntime.ExecAttachResize(c, sessionID, *newSize) if err != nil { - logrus.Warn("resize failed", err) + logrus.Warnf("Resize failed: %v", err) } } @@ -153,7 +153,7 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se } defer func() { if err := conn.Close(); err != nil { - logrus.Errorf("unable to close socket: %q", err) + logrus.Errorf("Unable to close socket: %q", err) } }() @@ -210,7 +210,7 @@ func setupStdioChannels(streams *define.AttachStreams, conn *net.UnixConn, detac _, err = utils.CopyDetachable(conn, streams.InputStream, detachKeys) if err == nil { if connErr := conn.CloseWrite(); connErr != nil { - logrus.Errorf("unable to close conn: %q", connErr) + logrus.Errorf("Unable to close conn: %q", connErr) } } } diff --git a/libpod/oci_attach_unsupported.go b/libpod/oci_attach_unsupported.go deleted file mode 100644 index 85e8b32e6..000000000 --- a/libpod/oci_attach_unsupported.go +++ /dev/null @@ -1,17 +0,0 @@ -//+build !linux - -package libpod - -import ( - "os" - - "github.com/containers/podman/v3/libpod/define" -) - -func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize, startContainer bool, started chan bool, attachRdy chan<- bool) error { - return define.ErrNotImplemented -} - -func (c *Container) attachToExec(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize, sessionID string, startFd *os.File, attachFd *os.File) error { - return define.ErrNotImplemented -} diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go index 5a7677b04..822377bfe 100644 --- a/libpod/oci_conmon_exec_linux.go +++ b/libpod/oci_conmon_exec_linux.go @@ -528,7 +528,7 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp if newSize != nil { err = c.ociRuntime.ExecAttachResize(c, sessionID, *newSize) if err != nil { - logrus.Warn("resize failed", err) + logrus.Warnf("Resize failed: %v", err) } } @@ -540,7 +540,7 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp } defer func() { if err := conn.Close(); err != nil { - logrus.Errorf("unable to close socket: %q", err) + logrus.Errorf("Unable to close socket: %q", err) } }() diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 831e89223..56c7a90aa 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -215,7 +215,7 @@ func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *Conta } defer func() { if err := unix.Setns(int(fd.Fd()), unix.CLONE_NEWNS); err != nil { - logrus.Errorf("unable to clone new namespace: %q", err) + logrus.Errorf("Unable to clone new namespace: %q", err) } }() @@ -524,7 +524,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http. conn = newConn defer func() { if err := conn.Close(); err != nil { - logrus.Errorf("unable to close container %s attach socket: %q", ctr.ID(), err) + logrus.Errorf("Unable to close container %s attach socket: %q", ctr.ID(), err) } }() @@ -936,7 +936,7 @@ func waitPidStop(pid int, timeout time.Duration) error { close(done) return } - logrus.Errorf("Error pinging PID %d with signal 0: %v", pid, err) + logrus.Errorf("Pinging PID %d with signal 0: %v", pid, err) } time.Sleep(100 * time.Millisecond) } @@ -1199,7 +1199,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co pid, err := readConmonPipeData(parentSyncPipe, ociLog) if err != nil { if err2 := r.DeleteContainer(ctr); err2 != nil { - logrus.Errorf("Error removing container %s from runtime after creation failed", ctr.ID()) + logrus.Errorf("Removing container %s from runtime after creation failed", ctr.ID()) } return err } @@ -1207,7 +1207,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co conmonPID, err := readConmonPidFile(ctr.config.ConmonPidFile) if err != nil { - logrus.Warnf("error reading conmon pid file for container %s: %v", ctr.ID(), err) + logrus.Warnf("Error reading conmon pid file for container %s: %v", ctr.ID(), err) } else if conmonPID > 0 { // conmon not having a pid file is a valid state, so don't set it if we don't have it logrus.Infof("Got Conmon PID as %d", conmonPID) @@ -1220,7 +1220,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co default: if sent, err := daemon.SdNotify(false, fmt.Sprintf("MAINPID=%d", conmonPID)); err != nil { - logrus.Errorf("Error notifying systemd of Conmon PID: %v", err) + logrus.Errorf("Notifying systemd of Conmon PID: %v", err) } else if sent { logrus.Debugf("Notify MAINPID sent successfully") } @@ -1346,7 +1346,7 @@ func startCommandGivenSelinux(cmd *exec.Cmd, ctr *Container) error { defer func() { if err := os.Setenv("NOTIFY_SOCKET", ctr.notifySocket); err != nil { - logrus.Errorf("Error resetting NOTIFY_SOCKET=%s", ctr.notifySocket) + logrus.Errorf("Resetting NOTIFY_SOCKET=%s", ctr.notifySocket) } }() } @@ -1385,7 +1385,7 @@ func startCommandGivenSelinux(cmd *exec.Cmd, ctr *Container) error { // Ignore error returned from SetProcessLabel("") call, // can't recover. if labelErr := label.SetProcessLabel(""); labelErr != nil { - logrus.Errorf("unable to set process label: %q", err) + logrus.Errorf("Unable to set process label: %q", err) } runtime.UnlockOSThread() return err @@ -1608,7 +1608,7 @@ func httpAttachTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter, cid numW, err2 := http.Write(buf[1:numR]) if err2 != nil { if err != nil { - logrus.Errorf("Error reading container %s STDOUT: %v", cid, err) + logrus.Errorf("Reading container %s STDOUT: %v", cid, err) } return err2 } else if numW+1 != numR { @@ -1618,7 +1618,7 @@ func httpAttachTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter, cid // there isn't a delay on the terminal side. if err2 := http.Flush(); err2 != nil { if err != nil { - logrus.Errorf("Error reading container %s STDOUT: %v", cid, err) + logrus.Errorf("Reading container %s STDOUT: %v", cid, err) } return err2 } @@ -1670,7 +1670,7 @@ func httpAttachNonTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter, numH, err2 := http.Write(headerBuf) if err2 != nil { if err != nil { - logrus.Errorf("Error reading container %s standard streams: %v", cid, err) + logrus.Errorf("Reading container %s standard streams: %v", cid, err) } return err2 @@ -1680,7 +1680,7 @@ func httpAttachNonTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter, // of the protocol. if numH != 8 { if err != nil { - logrus.Errorf("Error reading container %s standard streams: %v", cid, err) + logrus.Errorf("Reading container %s standard streams: %v", cid, err) } return io.ErrShortWrite @@ -1689,13 +1689,13 @@ func httpAttachNonTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter, numW, err2 := http.Write(buf[1:numR]) if err2 != nil { if err != nil { - logrus.Errorf("Error reading container %s standard streams: %v", cid, err) + logrus.Errorf("Reading container %s standard streams: %v", cid, err) } return err2 } else if numW+1 != numR { if err != nil { - logrus.Errorf("Error reading container %s standard streams: %v", cid, err) + logrus.Errorf("Reading container %s standard streams: %v", cid, err) } return io.ErrShortWrite @@ -1704,7 +1704,7 @@ func httpAttachNonTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter, // there isn't a delay on the terminal side. if err2 := http.Flush(); err2 != nil { if err != nil { - logrus.Errorf("Error reading container %s STDOUT: %v", cid, err) + logrus.Errorf("Reading container %s STDOUT: %v", cid, err) } return err2 } diff --git a/libpod/oci_conmon_unsupported.go b/libpod/oci_conmon_unsupported.go deleted file mode 100644 index 4de27d663..000000000 --- a/libpod/oci_conmon_unsupported.go +++ /dev/null @@ -1,132 +0,0 @@ -// +build !linux - -package libpod - -import ( - "github.com/containers/common/pkg/config" - - "github.com/containers/podman/v3/libpod/define" -) - -const ( - osNotSupported = "Not supported on this OS" -) - -// ConmonOCIRuntime is not supported on this OS. -type ConmonOCIRuntime struct { -} - -// newConmonOCIRuntime is not supported on this OS. -func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeFlags []string, runtimeCfg *config.Config) (OCIRuntime, error) { - return nil, define.ErrNotImplemented -} - -// Name is not supported on this OS. -func (r *ConmonOCIRuntime) Name() string { - return osNotSupported -} - -// Path is not supported on this OS. -func (r *ConmonOCIRuntime) Path() string { - return osNotSupported -} - -// CreateContainer is not supported on this OS. -func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) error { - return define.ErrNotImplemented -} - -// UpdateContainerStatus is not supported on this OS. -func (r *ConmonOCIRuntime) UpdateContainerStatus(ctr *Container, useRuntime bool) error { - return define.ErrNotImplemented -} - -// StartContainer is not supported on this OS. -func (r *ConmonOCIRuntime) StartContainer(ctr *Container) error { - return define.ErrNotImplemented -} - -// KillContainer is not supported on this OS. -func (r *ConmonOCIRuntime) KillContainer(ctr *Container, signal uint, all bool) error { - return define.ErrNotImplemented -} - -// StopContainer is not supported on this OS. -func (r *ConmonOCIRuntime) StopContainer(ctr *Container, timeout uint, all bool) error { - return define.ErrNotImplemented -} - -// DeleteContainer is not supported on this OS. -func (r *ConmonOCIRuntime) DeleteContainer(ctr *Container) error { - return define.ErrNotImplemented -} - -// PauseContainer is not supported on this OS. -func (r *ConmonOCIRuntime) PauseContainer(ctr *Container) error { - return define.ErrNotImplemented -} - -// UnpauseContainer is not supported on this OS. -func (r *ConmonOCIRuntime) UnpauseContainer(ctr *Container) error { - return define.ErrNotImplemented -} - -// ExecContainer is not supported on this OS. -func (r *ConmonOCIRuntime) ExecContainer(ctr *Container, sessionID string, options *ExecOptions) (int, chan error, error) { - return -1, nil, define.ErrNotImplemented -} - -// ExecStopContainer is not supported on this OS. -func (r *ConmonOCIRuntime) ExecStopContainer(ctr *Container, sessionID string, timeout uint) error { - return define.ErrNotImplemented -} - -// CheckpointContainer is not supported on this OS. -func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options ContainerCheckpointOptions) error { - return define.ErrNotImplemented -} - -// SupportsCheckpoint is not supported on this OS. -func (r *ConmonOCIRuntime) SupportsCheckpoint() bool { - return false -} - -// SupportsJSONErrors is not supported on this OS. -func (r *ConmonOCIRuntime) SupportsJSONErrors() bool { - return false -} - -// SupportsNoCgroups is not supported on this OS. -func (r *ConmonOCIRuntime) SupportsNoCgroups() bool { - return false -} - -// AttachSocketPath is not supported on this OS. -func (r *ConmonOCIRuntime) AttachSocketPath(ctr *Container) (string, error) { - return "", define.ErrNotImplemented -} - -// ExecAttachSocketPath is not supported on this OS. -func (r *ConmonOCIRuntime) ExecAttachSocketPath(ctr *Container, sessionID string) (string, error) { - return "", define.ErrNotImplemented -} - -// ExitFilePath is not supported on this OS. -func (r *ConmonOCIRuntime) ExitFilePath(ctr *Container) (string, error) { - return "", define.ErrNotImplemented -} - -// RuntimeInfo is not supported on this OS. -func (r *ConmonOCIRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) { - return nil, nil, define.ErrNotImplemented -} - -// Package is not supported on this OS. -func (r *ConmonOCIRuntime) Package() string { - return osNotSupported -} - -// ConmonPackage is not supported on this OS. -func (r *ConmonOCIRuntime) ConmonPackage() string { - return osNotSupported -} diff --git a/libpod/oci_util.go b/libpod/oci_util.go index 7db267915..c1afc0d20 100644 --- a/libpod/oci_util.go +++ b/libpod/oci_util.go @@ -72,7 +72,7 @@ func bindPorts(ports []types.OCICNIPortMapping) ([]*os.File, error) { // note that this does not affect the fd, see the godoc for server.File() err = server.Close() if err != nil { - logrus.Warnf("failed to close connection: %v", err) + logrus.Warnf("Failed to close connection: %v", err) } case "tcp": @@ -106,13 +106,13 @@ func bindPorts(ports []types.OCICNIPortMapping) ([]*os.File, error) { // note that this does not affect the fd, see the godoc for server.File() err = server.Close() if err != nil { - logrus.Warnf("failed to close connection: %v", err) + logrus.Warnf("Failed to close connection: %v", err) } case "sctp": if !notifySCTP { notifySCTP = true - logrus.Warnf("port reservation for SCTP is not supported") + logrus.Warnf("Port reservation for SCTP is not supported") } default: return nil, fmt.Errorf("unknown protocol %s", i.Protocol) 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..3ee4cd839 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -43,7 +43,7 @@ func (p *Pod) startInitContainers(ctx context.Context) error { } // Removing a container this way requires an explicit call to clean up the db if err := p.runtime.state.RemoveContainerFromPod(p, initCon); err != nil { - logrus.Errorf("Error removing container %s from database: %v", initCon.ID(), err) + logrus.Errorf("Removing container %s from database: %v", initCon.ID(), err) } icLock.Unlock() } @@ -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/libpod/pod_internal.go b/libpod/pod_internal.go index 079b631a0..d903b8719 100644 --- a/libpod/pod_internal.go +++ b/libpod/pod_internal.go @@ -71,7 +71,7 @@ func (p *Pod) refresh() error { case config.SystemdCgroupsManager: cgroupPath, err := systemdSliceFromPath(p.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", p.ID())) if err != nil { - logrus.Errorf("Error creating CGroup for pod %s: %v", p.ID(), err) + logrus.Errorf("Creating CGroup for pod %s: %v", p.ID(), err) } p.state.CgroupPath = cgroupPath case config.CgroupfsCgroupsManager: diff --git a/libpod/pod_top_unsupported.go b/libpod/pod_top_unsupported.go deleted file mode 100644 index 59d2ff9a2..000000000 --- a/libpod/pod_top_unsupported.go +++ /dev/null @@ -1,10 +0,0 @@ -// +build !linux - -package libpod - -import "github.com/containers/podman/v3/libpod/define" - -// GetPodPidInformation is exclusive to linux -func (p *Pod) GetPodPidInformation(descriptors []string) ([]string, error) { - return nil, define.ErrNotImplemented -} diff --git a/libpod/reset.go b/libpod/reset.go index 8e753e845..96fa44c2f 100644 --- a/libpod/reset.go +++ b/libpod/reset.go @@ -27,7 +27,7 @@ func (r *Runtime) Reset(ctx context.Context) error { if errors.Cause(err) == define.ErrNoSuchPod { continue } - logrus.Errorf("Error removing Pod %s: %v", p.ID(), err) + logrus.Errorf("Removing Pod %s: %v", p.ID(), err) } } @@ -42,13 +42,13 @@ func (r *Runtime) Reset(ctx context.Context) error { if errors.Cause(err) == define.ErrNoSuchCtr { continue } - logrus.Errorf("Error removing container %s: %v", c.ID(), err) + logrus.Errorf("Removing container %s: %v", c.ID(), err) } } } if err := r.stopPauseProcess(); err != nil { - logrus.Errorf("Error stopping pause process: %v", err) + logrus.Errorf("Stopping pause process: %v", err) } rmiOptions := &libimage.RemoveImagesOptions{Filters: []string{"readonly=false"}} @@ -65,7 +65,7 @@ func (r *Runtime) Reset(ctx context.Context) error { if errors.Cause(err) == define.ErrNoSuchVolume { continue } - logrus.Errorf("Error removing volume %s: %v", v.config.Name, err) + logrus.Errorf("Removing volume %s: %v", v.config.Name, err) } } diff --git a/libpod/runtime.go b/libpod/runtime.go index a2279e56d..161d5a533 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -211,7 +211,7 @@ func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...R os.Exit(1) return nil }); err != nil && errors.Cause(err) != shutdown.ErrHandlerExists { - logrus.Errorf("Error registering shutdown handler for libpod: %v", err) + logrus.Errorf("Registering shutdown handler for libpod: %v", err) } if err := shutdown.Start(); err != nil { @@ -344,7 +344,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { logrus.Warn(msg) } } else { - logrus.Warn(msg) + logrus.Warnf("%s: %v", msg, err) } } } @@ -388,7 +388,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { // Don't forcibly shut down // We could be opening a store in use by another libpod if _, err := store.Shutdown(false); err != nil { - logrus.Errorf("Error removing store for partially-created runtime: %s", err) + logrus.Errorf("Removing store for partially-created runtime: %s", err) } } }() @@ -436,7 +436,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { // This will allow us to ship configs including optional // runtimes that might not be installed (crun, kata). // Only a infof so default configs don't spec errors. - logrus.Debugf("configured OCI runtime %s initialization failed: %v", name, err) + logrus.Debugf("Configured OCI runtime %s initialization failed: %v", name, err) continue } @@ -767,7 +767,7 @@ func (r *Runtime) libimageEvents() { Type: events.Image, } if err := r.eventer.Write(e); err != nil { - logrus.Errorf("unable to write image event: %q", err) + logrus.Errorf("Unable to write image event: %q", err) } } @@ -807,11 +807,11 @@ func (r *Runtime) Shutdown(force bool) error { if force { ctrs, err := r.state.AllContainers() if err != nil { - logrus.Errorf("Error retrieving containers from database: %v", err) + logrus.Errorf("Retrieving containers from database: %v", err) } else { for _, ctr := range ctrs { if err := ctr.StopWithTimeout(r.config.Engine.StopTimeout); err != nil { - logrus.Errorf("Error stopping container %s: %v", ctr.ID(), err) + logrus.Errorf("Stopping container %s: %v", ctr.ID(), err) } } } @@ -833,7 +833,7 @@ func (r *Runtime) Shutdown(force bool) error { } if err := r.state.Close(); err != nil { if lastError != nil { - logrus.Errorf("%v", lastError) + logrus.Error(lastError) } lastError = err } @@ -879,17 +879,17 @@ func (r *Runtime) refresh(alivePath string) error { // until this has run. for _, ctr := range ctrs { if err := ctr.refresh(); err != nil { - logrus.Errorf("Error refreshing container %s: %v", ctr.ID(), err) + logrus.Errorf("Refreshing container %s: %v", ctr.ID(), err) } } for _, pod := range pods { if err := pod.refresh(); err != nil { - logrus.Errorf("Error refreshing pod %s: %v", pod.ID(), err) + logrus.Errorf("Refreshing pod %s: %v", pod.ID(), err) } } for _, vol := range vols { if err := vol.refresh(); err != nil { - logrus.Errorf("Error refreshing volume %s: %v", vol.Name(), err) + logrus.Errorf("Refreshing volume %s: %v", vol.Name(), err) } } @@ -1099,7 +1099,7 @@ func (r *Runtime) reloadContainersConf() error { return err } r.config = config - logrus.Infof("applied new containers configuration: %v", config) + logrus.Infof("Applied new containers configuration: %v", config) return nil } @@ -1110,7 +1110,7 @@ func (r *Runtime) reloadStorageConf() error { return err } storage.ReloadConfigurationFile(configFile, &r.storageConfig) - logrus.Infof("applied new storage configuration: %v", r.storageConfig) + logrus.Infof("Applied new storage configuration: %v", r.storageConfig) return nil } diff --git a/libpod/runtime_cstorage.go b/libpod/runtime_cstorage.go index cd2f226af..58bd67e6d 100644 --- a/libpod/runtime_cstorage.go +++ b/libpod/runtime_cstorage.go @@ -106,18 +106,18 @@ func (r *Runtime) removeStorageContainer(idOrName string, force bool) error { logrus.Infof("Storage for container %s already removed", ctr.ID) return nil } - return errors.Wrapf(err, "error looking up container %q mounts", idOrName) + logrus.Warnf("Checking if container %q is mounted, attempting to delete: %v", idOrName, err) } if timesMounted > 0 { return errors.Wrapf(define.ErrCtrStateInvalid, "container %q is mounted and cannot be removed without using force", idOrName) } } else if _, err := r.store.Unmount(ctr.ID, true); err != nil { - if errors.Cause(err) == storage.ErrContainerUnknown { + if errors.Is(err, storage.ErrContainerUnknown) { // Container again gone, no error logrus.Infof("Storage for container %s already removed", ctr.ID) return nil } - return errors.Wrapf(err, "error unmounting container %q", idOrName) + logrus.Warnf("Unmounting container %q while attempting to delete storage: %v", idOrName, err) } if err := r.store.DeleteContainer(ctr.ID); err != nil { diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index d4f67a115..9a4dbf626 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -59,7 +59,7 @@ func (r *Runtime) PrepareVolumeOnCreateContainer(ctx context.Context, ctr *Conta defer func() { if err := ctr.cleanupStorage(); err != nil { - logrus.Errorf("error cleaning up container storage %s: %v", ctr.ID(), err) + logrus.Errorf("Cleaning up container storage %s: %v", ctr.ID(), err) } }() @@ -69,7 +69,7 @@ func (r *Runtime) PrepareVolumeOnCreateContainer(ctx context.Context, ctr *Conta ctr.state.Mounted = true ctr.state.Mountpoint = mountPoint if err = ctr.save(); err != nil { - logrus.Errorf("Error saving container %s state: %v", ctr.ID(), err) + logrus.Errorf("Saving container %s state: %v", ctr.ID(), err) } } @@ -286,7 +286,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai defer func() { if retErr != nil { if err := ctr.lock.Free(); err != nil { - logrus.Errorf("Error freeing lock for container after creation failed: %v", err) + logrus.Errorf("Freeing lock for container after creation failed: %v", err) } } }() @@ -409,7 +409,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai defer func() { if retErr != nil { if err := ctr.teardownStorage(); err != nil { - logrus.Errorf("Error removing partially-created container root filesystem: %s", err) + logrus.Errorf("Removing partially-created container root filesystem: %s", err) } } }() @@ -696,7 +696,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo if cleanupErr == nil { cleanupErr = err } else { - logrus.Errorf("cleanup storage: %v", err) + logrus.Errorf("Cleanup storage: %v", err) } } @@ -709,7 +709,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo if cleanupErr == nil { cleanupErr = err } else { - logrus.Errorf("Error removing container %s from database: %v", c.ID(), err) + logrus.Errorf("Removing container %s from database: %v", c.ID(), err) } } } @@ -718,7 +718,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo if cleanupErr == nil { cleanupErr = err } else { - logrus.Errorf("Error removing container %s from database: %v", c.ID(), err) + logrus.Errorf("Removing container %s from database: %v", c.ID(), err) } } } @@ -728,7 +728,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo if cleanupErr == nil { cleanupErr = errors.Wrapf(err, "error freeing lock for container %s", c.ID()) } else { - logrus.Errorf("free container lock: %v", err) + logrus.Errorf("Free container lock: %v", err) } } @@ -747,7 +747,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo continue } if err := runtime.removeVolume(ctx, volume, false); err != nil && errors.Cause(err) != define.ErrNoSuchVolume { - logrus.Errorf("cleanup volume (%s): %v", v, err) + logrus.Errorf("Cleanup volume (%s): %v", v, err) } } } @@ -888,7 +888,7 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol continue } if err := r.removeVolume(ctx, volume, false); err != nil && err != define.ErrNoSuchVolume && err != define.ErrVolumeBeingUsed { - logrus.Errorf("cleanup volume (%s): %v", v, err) + logrus.Errorf("Cleanup volume (%s): %v", v, err) } } } diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go index a42f9a365..66cf7a4d5 100644 --- a/libpod/runtime_img.go +++ b/libpod/runtime_img.go @@ -54,7 +54,7 @@ func (r *Runtime) newImageBuildCompleteEvent(idOrName string) { e.Type = events.Image e.Name = idOrName if err := r.eventer.Write(e); err != nil { - logrus.Errorf("unable to write build event: %q", err) + logrus.Errorf("Unable to write build event: %q", err) } } diff --git a/libpod/runtime_migrate.go b/libpod/runtime_migrate.go index 3e63bc19e..087991e6f 100644 --- a/libpod/runtime_migrate.go +++ b/libpod/runtime_migrate.go @@ -56,7 +56,7 @@ func (r *Runtime) migrate(ctx context.Context) error { return err } - logrus.Infof("stopping all containers") + logrus.Infof("Stopping all containers") for _, ctr := range runningContainers { fmt.Printf("stopped %s\n", ctr.ID()) if err := ctr.Stop(); err != nil { @@ -77,7 +77,7 @@ func (r *Runtime) migrate(ctx context.Context) error { // Reset pause process location oldLocation := filepath.Join(ctr.state.RunDir, "conmon.pid") if ctr.config.ConmonPidFile == oldLocation { - logrus.Infof("changing conmon PID file for %s", ctr.ID()) + logrus.Infof("Changing conmon PID file for %s", ctr.ID()) ctr.config.ConmonPidFile = filepath.Join(ctr.config.StaticDir, "conmon.pid") needsWrite = true } diff --git a/libpod/runtime_migrate_unsupported.go b/libpod/runtime_migrate_unsupported.go deleted file mode 100644 index a9d351318..000000000 --- a/libpod/runtime_migrate_unsupported.go +++ /dev/null @@ -1,15 +0,0 @@ -// +build !linux - -package libpod - -import ( - "context" -) - -func (r *Runtime) migrate(ctx context.Context) error { - return nil -} - -func (r *Runtime) stopPauseProcess() error { - return nil -} diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 7571fdfff..5036dd680 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -66,7 +66,7 @@ func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, option defer func() { if deferredErr != nil { if err := pod.lock.Free(); err != nil { - logrus.Errorf("Error freeing pod lock after failed creation: %v", err) + logrus.Errorf("Freeing pod lock after failed creation: %v", err) } } }() @@ -224,7 +224,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon") conmonCgroup, err := cgroups.Load(conmonCgroupPath) if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless { - logrus.Errorf("Error retrieving pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err) + logrus.Errorf("Retrieving pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err) } // New resource limits @@ -259,7 +259,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) if removalErr == nil { removalErr = err } else { - logrus.Errorf("Error removing container %s from pod %s: %v", ctr.ID(), p.ID(), err) + logrus.Errorf("Removing container %s from pod %s: %v", ctr.ID(), p.ID(), err) } } } @@ -275,7 +275,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) for volName := range ctrNamedVolumes { volume, err := r.state.Volume(volName) if err != nil && errors.Cause(err) != define.ErrNoSuchVolume { - logrus.Errorf("Error retrieving volume %s: %v", volName, err) + logrus.Errorf("Retrieving volume %s: %v", volName, err) continue } if !volume.Anonymous() { @@ -285,7 +285,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) if errors.Cause(err) == define.ErrNoSuchVolume || errors.Cause(err) == define.ErrVolumeRemoved { continue } - logrus.Errorf("Error removing volume %s: %v", volName, err) + logrus.Errorf("Removing volume %s: %v", volName, err) } } @@ -299,7 +299,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) if removalErr == nil { removalErr = errors.Wrapf(err, "error removing pod %s cgroup", p.ID()) } else { - logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) + logrus.Errorf("Deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) } } case config.CgroupfsCgroupsManager: @@ -321,7 +321,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) if removalErr == nil { removalErr = errors.Wrapf(err, "error removing pod %s conmon cgroup", p.ID()) } else { - logrus.Errorf("Error deleting pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err) + logrus.Errorf("Deleting pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err) } } } @@ -330,7 +330,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) if removalErr == nil { removalErr = errors.Wrapf(err, "error retrieving pod %s cgroup", p.ID()) } else { - logrus.Errorf("Error retrieving pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) + logrus.Errorf("Retrieving pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) } } if err == nil { @@ -338,7 +338,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) if removalErr == nil { removalErr = errors.Wrapf(err, "error removing pod %s cgroup", p.ID()) } else { - logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) + logrus.Errorf("Deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) } } } @@ -371,7 +371,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) if removalErr == nil { removalErr = errors.Wrapf(err, "error freeing pod %s lock", p.ID()) } else { - logrus.Errorf("Error freeing pod %s lock: %v", p.ID(), err) + logrus.Errorf("Freeing pod %s lock: %v", p.ID(), err) } } diff --git a/libpod/runtime_pod_unsupported.go b/libpod/runtime_pod_unsupported.go deleted file mode 100644 index 6dbcc9214..000000000 --- a/libpod/runtime_pod_unsupported.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build !linux - -package libpod - -import ( - "context" - - "github.com/containers/podman/v3/libpod/define" -) - -// NewPod makes a new, empty pod -func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (*Pod, error) { - return nil, define.ErrOSNotSupported -} - -func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) error { - return define.ErrOSNotSupported -} diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index d1ea7d4fd..def6ca411 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -140,7 +140,7 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) defer func() { if deferredErr != nil { if err := volume.lock.Free(); err != nil { - logrus.Errorf("Error freeing volume lock after failed creation: %v", err) + logrus.Errorf("Freeing volume lock after failed creation: %v", err) } } }() @@ -246,7 +246,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error // If force is set, evict the volume, even if errors // occur. Otherwise we'll never be able to get rid of // them. - logrus.Errorf("Error unmounting volume %s: %v", v.Name(), err) + logrus.Errorf("Unmounting volume %s: %v", v.Name(), err) } else { return errors.Wrapf(err, "error unmounting volume %s", v.Name()) } @@ -290,7 +290,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error // Remove the volume from the state if err := r.state.RemoveVolume(v); err != nil { if removalErr != nil { - logrus.Errorf("Error removing volume %s from plugin %s: %v", v.Name(), v.Driver(), removalErr) + logrus.Errorf("Removing volume %s from plugin %s: %v", v.Name(), v.Driver(), removalErr) } return errors.Wrapf(err, "error removing volume %s", v.Name()) } @@ -300,7 +300,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error if removalErr == nil { removalErr = errors.Wrapf(err, "error freeing lock for volume %s", v.Name()) } else { - logrus.Errorf("Error freeing lock for volume %q: %v", v.Name(), err) + logrus.Errorf("Freeing lock for volume %q: %v", v.Name(), err) } } @@ -310,7 +310,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error if removalErr == nil { removalErr = errors.Wrapf(err, "error cleaning up volume storage for %q", v.Name()) } else { - logrus.Errorf("Error cleaning up volume storage for volume %q: %v", v.Name(), err) + logrus.Errorf("Cleaning up volume storage for volume %q: %v", v.Name(), err) } } diff --git a/libpod/runtime_volume_unsupported.go b/libpod/runtime_volume_unsupported.go deleted file mode 100644 index da7ee3552..000000000 --- a/libpod/runtime_volume_unsupported.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build !linux - -package libpod - -import ( - "context" - - "github.com/containers/podman/v3/libpod/define" -) - -func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error { - return define.ErrNotImplemented -} - -func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) (*Volume, error) { - return nil, define.ErrNotImplemented -} - -func (r *Runtime) NewVolume(ctx context.Context, options ...VolumeCreateOption) (*Volume, error) { - return nil, define.ErrNotImplemented -} diff --git a/libpod/shutdown/handler.go b/libpod/shutdown/handler.go index 1e8a9ec3b..cca74c3c4 100644 --- a/libpod/shutdown/handler.go +++ b/libpod/shutdown/handler.go @@ -61,7 +61,7 @@ func Start() error { } logrus.Infof("Invoking shutdown handler %s", name) if err := handler(sig); err != nil { - logrus.Errorf("Error running shutdown handler %s: %v", name, err) + logrus.Errorf("Running shutdown handler %s: %v", name, err) } } handlerLock.Unlock() diff --git a/libpod/stats_unsupported.go b/libpod/stats_unsupported.go deleted file mode 100644 index 44a1c8d03..000000000 --- a/libpod/stats_unsupported.go +++ /dev/null @@ -1,10 +0,0 @@ -// +build !linux - -package libpod - -import "github.com/containers/podman/v3/libpod/define" - -// GetContainerStats gets the running stats for a given container -func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*define.ContainerStats, error) { - return nil, define.ErrOSNotSupported -} diff --git a/libpod/storage.go b/libpod/storage.go index 4aa42dc8e..ad78fe191 100644 --- a/libpod/storage.go +++ b/libpod/storage.go @@ -118,22 +118,22 @@ func (r *storageService) CreateContainerStorage(ctx context.Context, systemConte container, err := r.store.CreateContainer(containerID, names, imageID, "", string(mdata), &options) if err != nil { - logrus.Debugf("failed to create container %s(%s): %v", metadata.ContainerName, containerID, err) + logrus.Debugf("Failed to create container %s(%s): %v", metadata.ContainerName, containerID, err) return ContainerInfo{}, err } - logrus.Debugf("created container %q", container.ID) + logrus.Debugf("Created container %q", container.ID) // If anything fails after this point, we need to delete the incomplete // container before returning. defer func() { if retErr != nil { if err := r.store.DeleteContainer(container.ID); err != nil { - logrus.Infof("%v deleting partially-created container %q", err, container.ID) + logrus.Infof("Error deleting partially-created container %q: %v", container.ID, err) return } - logrus.Infof("deleted partially-created container %q", container.ID) + logrus.Infof("Deleted partially-created container %q", container.ID) } }() @@ -155,13 +155,13 @@ func (r *storageService) CreateContainerStorage(ctx context.Context, systemConte if err != nil { return ContainerInfo{}, err } - logrus.Debugf("container %q has work directory %q", container.ID, containerDir) + logrus.Debugf("Container %q has work directory %q", container.ID, containerDir) containerRunDir, err := r.store.ContainerRunDirectory(container.ID) if err != nil { return ContainerInfo{}, err } - logrus.Debugf("container %q has run directory %q", container.ID, containerRunDir) + logrus.Debugf("Container %q has run directory %q", container.ID, containerRunDir) return ContainerInfo{ UIDMap: options.UIDMap, @@ -184,7 +184,7 @@ func (r *storageService) DeleteContainer(idOrName string) error { } err = r.store.DeleteContainer(container.ID) if err != nil { - logrus.Debugf("failed to delete container %q: %v", container.ID, err) + logrus.Debugf("Failed to delete container %q: %v", container.ID, err) return err } return nil @@ -193,7 +193,7 @@ func (r *storageService) DeleteContainer(idOrName string) error { func (r *storageService) SetContainerMetadata(idOrName string, metadata RuntimeContainerMetadata) error { mdata, err := json.Marshal(&metadata) if err != nil { - logrus.Debugf("failed to encode metadata for %q: %v", idOrName, err) + logrus.Debugf("Failed to encode metadata for %q: %v", idOrName, err) return err } return r.store.SetMetadata(idOrName, string(mdata)) @@ -225,10 +225,10 @@ func (r *storageService) MountContainerImage(idOrName string) (string, error) { } mountPoint, err := r.store.Mount(container.ID, metadata.MountLabel) if err != nil { - logrus.Debugf("failed to mount container %q: %v", container.ID, err) + logrus.Debugf("Failed to mount container %q: %v", container.ID, err) return "", err } - logrus.Debugf("mounted container %q at %q", container.ID, mountPoint) + logrus.Debugf("Mounted container %q at %q", container.ID, mountPoint) return mountPoint, nil } @@ -252,10 +252,10 @@ func (r *storageService) UnmountContainerImage(idOrName string, force bool) (boo } mounted, err := r.store.Unmount(container.ID, force) if err != nil { - logrus.Debugf("failed to unmount container %q: %v", container.ID, err) + logrus.Debugf("Failed to unmount container %q: %v", container.ID, err) return false, err } - logrus.Debugf("unmounted container %q", container.ID) + logrus.Debugf("Unmounted container %q", container.ID) return mounted, nil } diff --git a/libpod/util.go b/libpod/util.go index d3f7da91e..8f8303ff2 100644 --- a/libpod/util.go +++ b/libpod/util.go @@ -240,14 +240,14 @@ func hijackWriteError(toWrite error, cid string, terminal bool, httpBuf *bufio.R // We need a header. header := makeHTTPAttachHeader(2, uint32(len(errString))) if _, err := httpBuf.Write(header); err != nil { - logrus.Errorf("Error writing header for container %s attach connection error: %v", cid, err) + logrus.Errorf("Writing header for container %s attach connection error: %v", cid, err) } } if _, err := httpBuf.Write(errString); err != nil { - logrus.Errorf("Error writing error to container %s HTTP attach connection: %v", cid, err) + logrus.Errorf("Writing error to container %s HTTP attach connection: %v", cid, err) } if err := httpBuf.Flush(); err != nil { - logrus.Errorf("Error flushing HTTP buffer for container %s HTTP attach connection: %v", cid, err) + logrus.Errorf("Flushing HTTP buffer for container %s HTTP attach connection: %v", cid, err) } } } @@ -259,7 +259,7 @@ func hijackWriteErrorAndClose(toWrite error, cid string, terminal bool, httpCon hijackWriteError(toWrite, cid, terminal, httpBuf) if err := httpCon.Close(); err != nil { - logrus.Errorf("Error closing container %s HTTP attach connection: %v", cid, err) + logrus.Errorf("Closing container %s HTTP attach connection: %v", cid, err) } } diff --git a/libpod/util_linux.go b/libpod/util_linux.go index 32b058d27..e2ea97185 100644 --- a/libpod/util_linux.go +++ b/libpod/util_linux.go @@ -119,7 +119,7 @@ func LabelVolumePath(path string) error { func Unmount(mount string) { if err := unix.Unmount(mount, unix.MNT_DETACH); err != nil { if err != syscall.EINVAL { - logrus.Warnf("failed to unmount %s : %v", mount, err) + logrus.Warnf("Failed to unmount %s : %v", mount, err) } else { logrus.Debugf("failed to unmount %s : %v", mount, err) } diff --git a/libpod/util_unsupported.go b/libpod/util_unsupported.go deleted file mode 100644 index b718d36aa..000000000 --- a/libpod/util_unsupported.go +++ /dev/null @@ -1,34 +0,0 @@ -// +build !linux - -package libpod - -import ( - "github.com/containers/podman/v3/libpod/define" - "github.com/pkg/errors" -) - -func systemdSliceFromPath(parent, name string) (string, error) { - return "", errors.Wrapf(define.ErrOSNotSupported, "cgroups are not supported on non-linux OSes") -} - -func makeSystemdCgroup(path string) error { - return errors.Wrapf(define.ErrOSNotSupported, "cgroups are not supported on non-linux OSes") -} - -func deleteSystemdCgroup(path string) error { - return errors.Wrapf(define.ErrOSNotSupported, "cgroups are not supported on non-linux OSes") -} - -func assembleSystemdCgroupName(baseSlice, newSlice string) (string, error) { - return "", errors.Wrapf(define.ErrOSNotSupported, "cgroups are not supported on non-linux OSes") -} - -// LabelVolumePath takes a mount path for a volume and gives it an -// selinux label of either shared or not -func LabelVolumePath(path string) error { - return define.ErrNotImplemented -} - -func Unmount(mount string) error { - return define.ErrNotImplemented -} diff --git a/libpod/volume_internal_unsupported.go b/libpod/volume_internal_unsupported.go deleted file mode 100644 index 77452cf22..000000000 --- a/libpod/volume_internal_unsupported.go +++ /dev/null @@ -1,15 +0,0 @@ -// +build !linux - -package libpod - -import ( - "github.com/containers/podman/v3/libpod/define" -) - -func (v *Volume) mount() error { - return define.ErrNotImplemented -} - -func (v *Volume) unmount(force bool) error { - return define.ErrNotImplemented -} diff --git a/pkg/api/handlers/compat/containers_start.go b/pkg/api/handlers/compat/containers_start.go index ca2b5d84c..fb68389bc 100644 --- a/pkg/api/handlers/compat/containers_start.go +++ b/pkg/api/handlers/compat/containers_start.go @@ -25,7 +25,7 @@ func StartContainer(w http.ResponseWriter, r *http.Request) { } if len(query.DetachKeys) > 0 { // TODO - start does not support adding detach keys - logrus.Info("the detach keys parameter is not supported on start container") + logrus.Info("The detach keys parameter is not supported on start container") } runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) name := utils.GetName(r) diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go index e872f885a..0051e7235 100644 --- a/pkg/api/handlers/compat/containers_stats.go +++ b/pkg/api/handlers/compat/containers_stats.go @@ -227,10 +227,10 @@ func toBlkioStatEntry(entries []cgroups.BlkIOEntry) []docker.BlkioStatEntry { for i, e := range entries { bits, err := json.Marshal(e) if err != nil { - logrus.Errorf("unable to marshal blkio stats: %q", err) + logrus.Errorf("Unable to marshal blkio stats: %q", err) } if err := json.Unmarshal(bits, &results[i]); err != nil { - logrus.Errorf("unable to unmarshal blkio stats: %q", err) + logrus.Errorf("Unable to unmarshal blkio stats: %q", err) } } return results diff --git a/pkg/api/handlers/compat/events.go b/pkg/api/handlers/compat/events.go index a79b33ecc..901acdac4 100644 --- a/pkg/api/handlers/compat/events.go +++ b/pkg/api/handlers/compat/events.go @@ -94,7 +94,7 @@ func GetEvents(w http.ResponseWriter, r *http.Request) { } if err := coder.Encode(e); err != nil { - logrus.Errorf("unable to write json: %q", err) + logrus.Errorf("Unable to write json: %q", err) } flush() case <-r.Context().Done(): 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..7bd6d3dbf 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 @@ -186,9 +186,9 @@ func PodStop(w http.ResponseWriter, r *http.Request) { } // Try to clean up the pod - but only warn on failure, it's nonfatal. if cleanupCtrs, cleanupErr := pod.Cleanup(r.Context()); cleanupErr != nil { - logrus.Errorf("Error cleaning up pod %s: %v", pod.ID(), cleanupErr) + logrus.Errorf("Cleaning up pod %s: %v", pod.ID(), cleanupErr) for id, err := range cleanupCtrs { - logrus.Errorf("Error cleaning up pod %s container %s: %v", pod.ID(), id, err) + logrus.Errorf("Cleaning up pod %s container %s: %v", pod.ID(), id, err) } } 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/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go index 5cdb31de1..6f875fc30 100644 --- a/pkg/api/handlers/utils/containers.go +++ b/pkg/api/handlers/utils/containers.go @@ -78,7 +78,7 @@ func WaitContainerDocker(w http.ResponseWriter, r *http.Request) { exitCode, err := waitDockerCondition(ctx, name, interval, condition) var errStruct *struct{ Message string } if err != nil { - logrus.Errorf("error while waiting on condition: %q", err) + logrus.Errorf("While waiting on condition: %q", err) errStruct = &struct { Message string }{ @@ -94,7 +94,7 @@ func WaitContainerDocker(w http.ResponseWriter, r *http.Request) { enc.SetEscapeHTML(true) err = enc.Encode(&responseData) if err != nil { - logrus.Errorf("unable to write json: %q", err) + logrus.Errorf("Unable to write json: %q", err) } } diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go index 7625f9546..29139a98e 100644 --- a/pkg/api/handlers/utils/handler.go +++ b/pkg/api/handlers/utils/handler.go @@ -89,21 +89,21 @@ func WriteResponse(w http.ResponseWriter, code int, value interface{}) { w.WriteHeader(code) if _, err := fmt.Fprintln(w, v); err != nil { - logrus.Errorf("unable to send string response: %q", err) + logrus.Errorf("Unable to send string response: %q", err) } case *os.File: w.Header().Set("Content-Type", "application/octet; charset=us-ascii") w.WriteHeader(code) if _, err := io.Copy(w, v); err != nil { - logrus.Errorf("unable to copy to response: %q", err) + logrus.Errorf("Unable to copy to response: %q", err) } case io.Reader: w.Header().Set("Content-Type", "application/x-tar") w.WriteHeader(code) if _, err := io.Copy(w, v); err != nil { - logrus.Errorf("unable to copy to response: %q", err) + logrus.Errorf("Unable to copy to response: %q", err) } default: WriteJSON(w, code, value) @@ -162,7 +162,7 @@ func WriteJSON(w http.ResponseWriter, code int, value interface{}) { coder := json.NewEncoder(w) coder.SetEscapeHTML(true) if err := coder.Encode(value); err != nil { - logrus.Errorf("unable to write json: %q", err) + logrus.Errorf("Unable to write json: %q", err) } } 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/api/server/server.go b/pkg/api/server/server.go index 34d0fa246..c7174775e 100644 --- a/pkg/api/server/server.go +++ b/pkg/api/server/server.go @@ -233,7 +233,7 @@ func (s *APIServer) Serve() error { s.pprof = &http.Server{Addr: "localhost:8888", Handler: pprofMux} err := s.pprof.ListenAndServe() if err != nil && err != http.ErrServerClosed { - logrus.Warn("API profiler service failed: " + err.Error()) + logrus.Warnf("API profiler service failed: %v", err) } }() } @@ -272,7 +272,7 @@ func (s *APIServer) Shutdown() error { go func() { defer cancel() if err := s.pprof.Shutdown(ctx); err != nil { - logrus.Warn("Failed to cleanly shutdown API pprof service: " + err.Error()) + logrus.Warnf("Failed to cleanly shutdown API pprof service: %v", err) } }() <-ctx.Done() diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 6aff880f4..070e222ad 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -208,7 +208,7 @@ func RemoveAuthfile(authfile string) { return } if err := os.Remove(authfile); err != nil { - logrus.Errorf("Error removing temporary auth file %q: %v", authfile, err) + logrus.Errorf("Removing temporary auth file %q: %v", authfile, err) } } 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/containers/attach.go b/pkg/bindings/containers/attach.go index 6efbcb57b..abf58aaf9 100644 --- a/pkg/bindings/containers/attach.go +++ b/pkg/bindings/containers/attach.go @@ -102,7 +102,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri } defer func() { if err := terminal.Restore(int(file.Fd()), state); err != nil { - logrus.Errorf("unable to restore terminal: %q", err) + logrus.Errorf("Unable to restore terminal: %q", err) } logrus.SetFormatter(&logrus.TextFormatter{}) }() @@ -166,7 +166,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri _, err := utils.CopyDetachable(socket, stdin, detachKeysInBytes) if err != nil && err != define.ErrDetach { - logrus.Error("failed to write input to service: " + err.Error()) + logrus.Errorf("Failed to write input to service: %v", err) } stdinChan <- err @@ -349,7 +349,7 @@ func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, i resize := func() { w, h, err := terminal.GetSize(int(file.Fd())) if err != nil { - logrus.Warnf("failed to obtain TTY size: %v", err) + logrus.Warnf("Failed to obtain TTY size: %v", err) } var resizeErr error @@ -359,7 +359,7 @@ func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, i resizeErr = ResizeContainerTTY(ctx, id, new(ResizeTTYOptions).WithHeight(h).WithWidth(w)) } if resizeErr != nil { - logrus.Infof("failed to resize TTY: %v", resizeErr) + logrus.Infof("Failed to resize TTY: %v", resizeErr) } } @@ -443,13 +443,13 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar } defer func() { if err := terminal.Restore(int(terminalFile.Fd()), state); err != nil { - logrus.Errorf("unable to restore terminal: %q", err) + logrus.Errorf("Unable to restore terminal: %q", err) } logrus.SetFormatter(&logrus.TextFormatter{}) }() w, h, err := terminal.GetSize(int(terminalFile.Fd())) if err != nil { - logrus.Warnf("failed to obtain TTY size: %v", err) + logrus.Warnf("Failed to obtain TTY size: %v", err) } body.Width = uint16(w) body.Height = uint16(h) @@ -502,7 +502,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar logrus.Debugf("Copying STDIN to socket") _, err := utils.CopyDetachable(socket, options.InputStream, []byte{}) if err != nil { - logrus.Error("failed to write input to service: " + err.Error()) + logrus.Errorf("Failed to write input to service: %v", err) } if closeWrite, ok := socket.(CloseWriter); ok { diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index 9d5aad23b..ded97d8d6 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -312,7 +312,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO contextDir, err := filepath.Abs(options.ContextDirectory) if err != nil { - logrus.Errorf("cannot find absolute path of %v: %v", options.ContextDirectory, err) + logrus.Errorf("Cannot find absolute path of %v: %v", options.ContextDirectory, err) return nil, err } @@ -339,7 +339,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO } containerfile, err := filepath.Abs(c) if err != nil { - logrus.Errorf("cannot find absolute path of %v: %v", c, err) + logrus.Errorf("Cannot find absolute path of %v: %v", c, err) return nil, err } @@ -371,7 +371,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO } tarfile, err := nTar(append(excludes, dontexcludes...), tarContent...) if err != nil { - logrus.Errorf("cannot tar container entries %v error: %v", tarContent, err) + logrus.Errorf("Cannot tar container entries %v error: %v", tarContent, err) return nil, err } defer func() { @@ -477,7 +477,7 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) { for _, src := range sources { s, err := filepath.Abs(src) if err != nil { - logrus.Errorf("cannot stat one of source context: %v", err) + logrus.Errorf("Cannot stat one of source context: %v", err) merr = multierror.Append(merr, err) return } 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/checkpoint/checkpoint_restore.go b/pkg/checkpoint/checkpoint_restore.go index 9fdf04933..f53e31f9b 100644 --- a/pkg/checkpoint/checkpoint_restore.go +++ b/pkg/checkpoint/checkpoint_restore.go @@ -51,7 +51,7 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt } defer func() { if err := os.RemoveAll(dir); err != nil { - logrus.Errorf("could not recursively remove %s: %q", dir, err) + logrus.Errorf("Could not recursively remove %s: %q", dir, err) } }() err = archive.Untar(archiveFile, dir, options) 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..02af214a6 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -825,26 +825,12 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri }) if ctr.AutoRemove() { if err := ic.removeContainer(ctx, ctr, entities.RmOptions{}); err != nil { - logrus.Errorf("Error removing container %s: %v", ctr.ID(), err) + logrus.Errorf("Removing container %s: %v", ctr.ID(), err) } } 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, @@ -874,7 +860,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri reports = append(reports, report) if ctr.AutoRemove() { if err := ic.removeContainer(ctx, ctr, entities.RmOptions{}); err != nil { - logrus.Errorf("Error removing container %s: %v", ctr.ID(), err) + logrus.Errorf("Removing container %s: %v", ctr.ID(), err) } } continue @@ -985,34 +971,43 @@ 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 || errors.Cause(err) == define.ErrCtrRemoved { logrus.Infof("Container %s was already removed, skipping --rm", ctr.ID()) } else { - logrus.Errorf("Error removing container %s: %v", ctr.ID(), err) + logrus.Errorf("Removing container %s: %v", ctr.ID(), err) } } } 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/containers_runlabel.go b/pkg/domain/infra/abi/containers_runlabel.go index 435baa8c8..add82f0fb 100644 --- a/pkg/domain/infra/abi/containers_runlabel.go +++ b/pkg/domain/infra/abi/containers_runlabel.go @@ -87,7 +87,7 @@ func (ic *ContainerEngine) ContainerRunlabel(ctx context.Context, label string, ctr, err := ic.Libpod.LookupContainer(name) if err != nil { if errors.Cause(err) != define.ErrNoSuchCtr { - logrus.Debugf("Error occurred searching for container %s: %s", name, err.Error()) + logrus.Debugf("Error occurred searching for container %s: %v", name, err) return err } } else { @@ -167,7 +167,7 @@ func generateRunlabelCommand(runlabel string, img *libimage.Image, inputName str // I would prefer to use os.getenv but it appears PWD is not in the os env list. d, err := os.Getwd() if err != nil { - logrus.Error("unable to determine current working directory") + logrus.Error("Unable to determine current working directory") return "" } return d diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go index 2d7bc15f5..081a2464b 100644 --- a/pkg/domain/infra/abi/generate.go +++ b/pkg/domain/infra/abi/generate.go @@ -107,7 +107,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, // Generate kube pods and services from pods. if len(pods) >= 1 { - pos, svcs, err := getKubePods(pods, options.Service) + pos, svcs, err := getKubePods(ctx, pods, options.Service) if err != nil { return nil, err } @@ -120,7 +120,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, // Generate the kube pods from containers. if len(ctrs) >= 1 { - po, err := libpod.GenerateForKube(ctrs) + po, err := libpod.GenerateForKube(ctx, ctrs) if err != nil { return nil, err } @@ -153,12 +153,12 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, } // getKubePods returns kube pod and service YAML files from podman pods. -func getKubePods(pods []*libpod.Pod, getService bool) ([][]byte, [][]byte, error) { +func getKubePods(ctx context.Context, pods []*libpod.Pod, getService bool) ([][]byte, [][]byte, error) { pos := [][]byte{} svcs := [][]byte{} for _, p := range pods { - po, sp, err := p.GenerateForKube() + po, sp, err := p.GenerateForKube(ctx) if err != nil { return nil, nil, err } @@ -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..705ad7768 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 { @@ -572,7 +573,7 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie } defer func() { if err = rawSource.Close(); err != nil { - logrus.Errorf("unable to close %s image source %q", srcRef.DockerReference().Name(), err) + logrus.Errorf("Unable to close %s image source %q", srcRef.DockerReference().Name(), err) } }() topManifestBlob, manifestType, err := rawSource.GetManifest(ctx, nil) diff --git a/pkg/domain/infra/abi/manifest.go b/pkg/domain/infra/abi/manifest.go index 1dd0686ac..d1bd5e2e4 100644 --- a/pkg/domain/infra/abi/manifest.go +++ b/pkg/domain/infra/abi/manifest.go @@ -146,7 +146,7 @@ func (ir *ImageEngine) remoteManifestInspect(ctx context.Context, name string) ( switch manType { case manifest.DockerV2Schema2MediaType: - logrus.Warnf("Warning! The manifest type %s is not a manifest list but a single image.", manType) + logrus.Warnf("The manifest type %s is not a manifest list but a single image.", manType) schema2Manifest, err := manifest.Schema2FromManifest(result) if err != nil { return nil, errors.Wrapf(err, "error parsing manifest blob %q as a %q", string(result), manType) diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 87506f70c..e386c17e9 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -113,7 +113,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en report.Volumes = append(report.Volumes, r.Volumes...) validKinds++ default: - logrus.Infof("kube kind %s not supported", kind) + logrus.Infof("Kube kind %s not supported", kind) continue } } @@ -662,21 +662,21 @@ func getBuildFile(imageName string, cwd string) (string, error) { containerfilePath := filepath.Join(cwd, buildDirName, "Containerfile") dockerfilePath := filepath.Join(cwd, buildDirName, "Dockerfile") - _, err := os.Stat(filepath.Join(containerfilePath)) + _, err := os.Stat(containerfilePath) if err == nil { - logrus.Debugf("building %s with %s", imageName, containerfilePath) + logrus.Debugf("Building %s with %s", imageName, containerfilePath) return containerfilePath, nil } // If the error is not because the file does not exist, take // a mulligan and try Dockerfile. If that also fails, return that // error if err != nil && !os.IsNotExist(err) { - logrus.Errorf("%v: unable to check for %s", err, containerfilePath) + logrus.Error(err.Error()) } _, err = os.Stat(filepath.Join(dockerfilePath)) if err == nil { - logrus.Debugf("building %s with %s", imageName, dockerfilePath) + logrus.Debugf("Building %s with %s", imageName, dockerfilePath) return dockerfilePath, nil } // Strike two diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go index a9bd2d5fb..3b129f5ea 100644 --- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go +++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go @@ -42,7 +42,7 @@ func ProxySignals(ctr *libpod.Container) { if errors.Cause(err) == define.ErrCtrStateInvalid { logrus.Infof("Ceasing signal forwarding to container %s as it has stopped", ctr.ID()) } else { - logrus.Errorf("Error forwarding signal %d to container %s: %v", s, ctr.ID(), err) + logrus.Errorf("forwarding signal %d to container %s: %v", s, ctr.ID(), err) } // If the container dies, and we find out here, // we need to forward that one signal to @@ -51,7 +51,7 @@ func ProxySignals(ctr *libpod.Container) { // play out. signal.StopCatch(sigBuffer) if err := syscall.Kill(syscall.Getpid(), s.(syscall.Signal)); err != nil { - logrus.Errorf("failed to kill pid %d", syscall.Getpid()) + logrus.Errorf("Failed to kill pid %d", syscall.Getpid()) } return } diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go index 09c0f802d..ba047bf33 100644 --- a/pkg/domain/infra/abi/terminal/terminal_linux.go +++ b/pkg/domain/infra/abi/terminal/terminal_linux.go @@ -29,7 +29,7 @@ func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpo defer cancel() defer func() { if err := restoreTerminal(oldTermState); err != nil { - logrus.Errorf("unable to restore terminal: %q", err) + logrus.Errorf("Unable to restore terminal: %q", err) } }() } @@ -53,7 +53,7 @@ func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, } defer func() { if err := restoreTerminal(oldTermState); err != nil { - logrus.Errorf("unable to restore terminal: %q", err) + logrus.Errorf("Unable to restore terminal: %q", err) } }() defer cancel() diff --git a/pkg/domain/infra/abi/trust.go b/pkg/domain/infra/abi/trust.go index d3aff62ba..af7814163 100644 --- a/pkg/domain/infra/abi/trust.go +++ b/pkg/domain/infra/abi/trust.go @@ -165,7 +165,7 @@ var typeDescription = map[string]string{"insecureAcceptAnything": "accept", "sig func trustTypeDescription(trustType string) string { trustDescription, exist := typeDescription[trustType] if !exist { - logrus.Warnf("invalid trust type %s", trustType) + logrus.Warnf("Invalid trust type %s", trustType) } return trustDescription } diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go index 5cbee2e76..7ec6135ee 100644 --- a/pkg/domain/infra/runtime_libpod.go +++ b/pkg/domain/infra/runtime_libpod.go @@ -369,7 +369,7 @@ func StartWatcher(rt *libpod.Runtime) { logrus.Debugf("waiting for SIGHUP to reload configuration") <-ch if err := rt.Reload(); err != nil { - logrus.Errorf("unable to reload configuration: %v", err) + logrus.Errorf("Unable to reload configuration: %v", err) continue } } diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 81ddce42f..9fe2d163c 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -561,7 +561,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri errorhandling.Contains(err, define.ErrCtrRemoved) { logrus.Debugf("Container %s does not exist: %v", id, err) } else { - logrus.Errorf("Error removing container %s: %v", id, err) + logrus.Errorf("Removing container %s: %v", id, err) } } } @@ -646,7 +646,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri errorhandling.Contains(err, types.ErrLayerUnknown) { logrus.Debugf("Container %s does not exist: %v", ctr.ID, err) } else { - logrus.Errorf("Error removing container %s: %v", ctr.ID, err) + logrus.Errorf("Removing container %s: %v", ctr.ID, err) } } } @@ -731,7 +731,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta errorhandling.Contains(err, types.ErrLayerUnknown) { logrus.Debugf("Container %s does not exist: %v", con.ID, err) } else { - logrus.Errorf("Error removing container %s: %v", con.ID, err) + logrus.Errorf("Removing container %s: %v", con.ID, err) } } } 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/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go index 6adbc9f34..44a0c3efd 100644 --- a/pkg/errorhandling/errorhandling.go +++ b/pkg/errorhandling/errorhandling.go @@ -63,7 +63,7 @@ func StringsToErrors(strErrs []string) []error { // a defer. func SyncQuiet(f *os.File) { if err := f.Sync(); err != nil { - logrus.Errorf("unable to sync file %s: %q", f.Name(), err) + logrus.Errorf("Unable to sync file %s: %q", f.Name(), err) } } @@ -71,7 +71,7 @@ func SyncQuiet(f *os.File) { // a defer. func CloseQuiet(f *os.File) { if err := f.Close(); err != nil { - logrus.Errorf("unable to close file %s: %q", f.Name(), err) + logrus.Errorf("Unable to close file %s: %q", f.Name(), err) } } diff --git a/pkg/hooks/exec/exec.go b/pkg/hooks/exec/exec.go index f6b6636ad..2b7bc5f31 100644 --- a/pkg/hooks/exec/exec.go +++ b/pkg/hooks/exec/exec.go @@ -56,7 +56,7 @@ func Run(ctx context.Context, hook *rspec.Hook, state []byte, stdout io.Writer, return err, err case <-ctx.Done(): if err := cmd.Process.Kill(); err != nil { - logrus.Errorf("failed to kill pid %v", cmd.Process) + logrus.Errorf("Failed to kill pid %v", cmd.Process) } timer := time.NewTimer(postKillTimeout) defer timer.Stop() diff --git a/pkg/hooks/exec/runtimeconfigfilter.go b/pkg/hooks/exec/runtimeconfigfilter.go index 10b8fedc2..3ab3073b2 100644 --- a/pkg/hooks/exec/runtimeconfigfilter.go +++ b/pkg/hooks/exec/runtimeconfigfilter.go @@ -61,7 +61,7 @@ func RuntimeConfigFilter(ctx context.Context, hooks []spec.Hook, config *spec.Sp if err == nil { logrus.Debugf("precreate hook %d made configuration changes:\n%s", i, diff) } else { - logrus.Warnf("precreate hook %d made configuration changes, but we could not compute a diff: %v", i, err) + logrus.Warnf("Precreate hook %d made configuration changes, but we could not compute a diff: %v", i, err) } } diff --git a/pkg/hooks/monitor.go b/pkg/hooks/monitor.go index 6fa94cd17..ece6e52d1 100644 --- a/pkg/hooks/monitor.go +++ b/pkg/hooks/monitor.go @@ -36,7 +36,7 @@ func (m *Manager) Monitor(ctx context.Context, sync chan<- error) { for _, dir := range m.directories { err = watcher.Add(dir) if err != nil { - logrus.Errorf("failed to watch %q for hooks", dir) + logrus.Errorf("Failed to watch %q for hooks", dir) sync <- err return } @@ -52,7 +52,7 @@ func (m *Manager) Monitor(ctx context.Context, sync chan<- error) { for _, dir := range m.directories { err = ReadDir(dir, m.extensionStages, m.hooks) if err != nil { - logrus.Errorf("failed loading hooks for %s: %v", event.Name, err) + logrus.Errorf("Failed loading hooks for %s: %v", event.Name, err) } } case <-ctx.Done(): diff --git a/pkg/machine/config.go b/pkg/machine/config.go index 8db2335aa..3ff5c7fe7 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -58,6 +58,9 @@ type ListResponse struct { LastUp time.Time Running bool VMType string + CPUs uint64 + Memory uint64 + DiskSize uint64 } type SSHOptions struct { diff --git a/pkg/machine/fcos.go b/pkg/machine/fcos.go index cfcadeb02..99197ac0e 100644 --- a/pkg/machine/fcos.go +++ b/pkg/machine/fcos.go @@ -139,6 +139,8 @@ func getFCOSDownload(imageStream string) (*fcosDownloadInfo, error) { ) switch imageStream { case "testing", "": + streamType = fedoracoreos.StreamTesting + case "next": streamType = fedoracoreos.StreamNext case "stable": streamType = fedoracoreos.StreamStable diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go index 3d0fa4094..9f5f45b58 100644 --- a/pkg/machine/qemu/config.go +++ b/pkg/machine/qemu/config.go @@ -17,6 +17,8 @@ type MachineVM struct { ImagePath string // Memory in megabytes assigned to the vm Memory uint64 + // Disk size in gigabytes assigned to the vm + DiskSize uint64 // Name of the vm Name string // SSH port for user networking diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index d5f538594..09078fbfb 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -64,6 +64,7 @@ func NewMachine(opts machine.InitOptions) (machine.VM, error) { vm.CPUs = opts.CPUS vm.Memory = opts.Memory + vm.DiskSize = opts.DiskSize // Look up the executable execPath, err := exec.LookPath(QemuCommand) @@ -140,7 +141,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) error { v.IdentityPath = filepath.Join(sshDir, v.Name) switch opts.ImagePath { - case "testing", "stable", "": + case "testing", "next", "stable", "": // Get image as usual dd, err := machine.NewFcosDownloader(vmtype, v.Name, opts.ImagePath) if err != nil { @@ -366,7 +367,7 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error { return err } if _, err := os.Stat(pidFile); os.IsNotExist(err) { - logrus.Infof("pid file %s does not exist", pidFile) + logrus.Info(err) return nil } pidString, err := ioutil.ReadFile(pidFile) @@ -574,6 +575,9 @@ func GetVMInfos() ([]*machine.ListResponse, error) { listEntry.Name = vm.Name listEntry.VMType = "qemu" + listEntry.CPUs = vm.CPUs + listEntry.Memory = vm.Memory + listEntry.DiskSize = vm.DiskSize fi, err := os.Stat(fullPath) if err != nil { return err diff --git a/pkg/netns/netns_linux.go b/pkg/netns/netns_linux.go index c13ae2f4d..3e6e668b5 100644 --- a/pkg/netns/netns_linux.go +++ b/pkg/netns/netns_linux.go @@ -133,19 +133,19 @@ func NewNSWithName(name string) (ns.NetNS, error) { var origNS ns.NetNS origNS, err = ns.GetNS(threadNsPath) if err != nil { - logrus.Warnf("cannot open current network namespace %s: %q", threadNsPath, err) + logrus.Warnf("Cannot open current network namespace %s: %q", threadNsPath, err) return } defer func() { if err := origNS.Close(); err != nil { - logrus.Errorf("unable to close namespace: %q", err) + logrus.Errorf("Unable to close namespace: %q", err) } }() // create a new netns on the current thread err = unix.Unshare(unix.CLONE_NEWNET) if err != nil { - logrus.Warnf("cannot create a new network namespace: %q", err) + logrus.Warnf("Cannot create a new network namespace: %q", err) return } @@ -157,7 +157,7 @@ func NewNSWithName(name string) (ns.NetNS, error) { // the network namespace owned by root on the host. return } - logrus.Warnf("unable to reset namespace: %q", err) + logrus.Warnf("Unable to reset namespace: %q", err) } }() diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go index 54079baa1..bf3286028 100644 --- a/pkg/ps/ps.go +++ b/pkg/ps/ps.go @@ -139,11 +139,11 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities } startedTime, err = c.StartedTime() if err != nil { - logrus.Errorf("error getting started time for %q: %v", c.ID(), err) + logrus.Errorf("Getting started time for %q: %v", c.ID(), err) } exitedTime, err = c.FinishedTime() if err != nil { - logrus.Errorf("error getting exited time for %q: %v", c.ID(), err) + logrus.Errorf("Getting exited time for %q: %v", c.ID(), err) } pid, err = c.PID() @@ -170,12 +170,12 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities rootFsSize, err := c.RootFsSize() if err != nil { - logrus.Errorf("error getting root fs size for %q: %v", c.ID(), err) + logrus.Errorf("Getting root fs size for %q: %v", c.ID(), err) } rwSize, err := c.RWSize() if err != nil { - logrus.Errorf("error getting rw size for %q: %v", c.ID(), err) + logrus.Errorf("Getting rw size for %q: %v", c.ID(), err) } size.RootFsSize = rootFsSize diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index c046ecde7..7f9228666 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -61,20 +61,20 @@ func IsRootless() bool { if rootlessUIDInit != 0 { // This happens if we joined the user+mount namespace as part of if err := os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done"); err != nil { - logrus.Errorf("failed to set environment variable %s as %s", "_CONTAINERS_USERNS_CONFIGURED", "done") + logrus.Errorf("Failed to set environment variable %s as %s", "_CONTAINERS_USERNS_CONFIGURED", "done") } if err := os.Setenv("_CONTAINERS_ROOTLESS_UID", fmt.Sprintf("%d", rootlessUIDInit)); err != nil { - logrus.Errorf("failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_UID", rootlessUIDInit) + logrus.Errorf("Failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_UID", rootlessUIDInit) } if err := os.Setenv("_CONTAINERS_ROOTLESS_GID", fmt.Sprintf("%d", rootlessGIDInit)); err != nil { - logrus.Errorf("failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_GID", rootlessGIDInit) + logrus.Errorf("Failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_GID", rootlessGIDInit) } } isRootless = os.Geteuid() != 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" if !isRootless { hasCapSysAdmin, err := unshare.HasCapSysAdmin() if err != nil { - logrus.Warnf("failed to read CAP_SYS_ADMIN presence for the current process") + logrus.Warnf("Failed to read CAP_SYS_ADMIN presence for the current process") } if err == nil && !hasCapSysAdmin { isRootless = true @@ -284,12 +284,12 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo toWrite = []byte("1") } if _, err := w.Write(toWrite); err != nil { - logrus.Errorf("failed to write byte 0: %q", err) + logrus.Errorf("Failed to write byte 0: %q", err) } if retErr != nil && pid > 0 { if err := unix.Kill(pid, unix.SIGKILL); err != nil { if err != unix.ESRCH { - logrus.Errorf("failed to cleanup process %d: %v", pid, err) + logrus.Errorf("Failed to cleanup process %d: %v", pid, err) } } C.reexec_in_user_namespace_wait(C.int(pid), 0) @@ -325,7 +325,7 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo uidsMapped = err == nil } if !uidsMapped { - logrus.Warnf("using rootless single mapping into the namespace. This might break some images. Check /etc/subuid and /etc/subgid for adding sub*ids") + logrus.Warnf("Using rootless single mapping into the namespace. This might break some images. Check /etc/subuid and /etc/subgid for adding sub*ids") setgroups := fmt.Sprintf("/proc/%d/setgroups", pid) err = ioutil.WriteFile(setgroups, []byte("deny\n"), 0666) if err != nil { @@ -416,7 +416,7 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo if err := unix.Kill(int(pidC), s.(unix.Signal)); err != nil { if err != unix.ESRCH { - logrus.Errorf("failed to propagate signal to child process %d: %v", int(pidC), err) + logrus.Errorf("Failed to propagate signal to child process %d: %v", int(pidC), err) } } } diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go index 6c7b8e6d7..37fb7ce79 100644 --- a/pkg/rootlessport/rootlessport_linux.go +++ b/pkg/rootlessport/rootlessport_linux.go @@ -125,17 +125,17 @@ func parent() error { quit := make(chan struct{}) errCh := make(chan error) // start the parent driver. initComplete will be closed when the child connected to the parent. - logrus.Infof("starting parent driver") + logrus.Infof("Starting parent driver") go func() { driverErr := driver.RunParentDriver(initComplete, quit, nil) if driverErr != nil { - logrus.WithError(driverErr).Warn("parent driver exited") + logrus.WithError(driverErr).Warn("Parent driver exited") } errCh <- driverErr close(errCh) }() opaque := driver.OpaqueForChild() - logrus.Infof("opaque=%+v", opaque) + logrus.Infof("Opaque=%+v", opaque) opaqueJSON, err := json.Marshal(opaque) if err != nil { return err @@ -146,9 +146,9 @@ func parent() error { } defer func() { // stop the child - logrus.Info("stopping child driver") + logrus.Info("Stopping child driver") if err := childQuitW.Close(); err != nil { - logrus.WithError(err).Warn("unable to close childQuitW") + logrus.WithError(err).Warn("Unable to close childQuitW") } }() @@ -164,7 +164,7 @@ func parent() error { return err } if err := childNS.Do(func(_ ns.NetNS) error { - logrus.Infof("starting child driver in child netns (%q %v)", cmd.Path, cmd.Args) + logrus.Infof("Starting child driver in child netns (%q %v)", cmd.Path, cmd.Args) return cmd.Start() }); err != nil { return err @@ -179,11 +179,11 @@ func parent() error { defer func() { if err := unix.Kill(cmd.Process.Pid, unix.SIGTERM); err != nil { - logrus.WithError(err).Warn("kill child process") + logrus.WithError(err).Warn("Kill child process") } }() - logrus.Info("waiting for initComplete") + logrus.Info("Waiting for initComplete") // wait for the child to connect to the parent outer: for { @@ -203,15 +203,15 @@ outer: } defer func() { - logrus.Info("stopping parent driver") + logrus.Info("Stopping parent driver") quit <- struct{}{} if err := <-errCh; err != nil { - logrus.WithError(err).Warn("parent driver returned error on exit") + logrus.WithError(err).Warn("Parent driver returned error on exit") } }() // let parent expose ports - logrus.Infof("exposing ports %v", cfg.Mappings) + logrus.Infof("Exposing ports %v", cfg.Mappings) if err := exposePorts(driver, cfg.Mappings, cfg.ChildIP); err != nil { return err } @@ -235,13 +235,13 @@ outer: // remove the socket file on exit defer os.Remove(socketfile) if err != nil { - logrus.Warnf("failed to close the socketDir fd: %v", err) + logrus.Warnf("Failed to close the socketDir fd: %v", err) } defer socket.Close() go serve(socket, driver) } - logrus.Info("ready") + logrus.Info("Ready") // https://github.com/containers/podman/issues/11248 // Copy /dev/null to stdout and stderr to prevent SIGPIPE errors @@ -259,7 +259,7 @@ outer: } // wait for ExitFD to be closed - logrus.Info("waiting for exitfd to be closed") + logrus.Info("Waiting for exitfd to be closed") if _, err := ioutil.ReadAll(exitR); err != nil { return err } @@ -353,10 +353,10 @@ func child() error { errCh <- dErr }() defer func() { - logrus.Info("stopping child driver") + logrus.Info("Stopping child driver") quit <- struct{}{} if err := <-errCh; err != nil { - logrus.WithError(err).Warn("child driver returned error on exit") + logrus.WithError(err).Warn("Child driver returned error on exit") } }() diff --git a/pkg/servicereaper/service.go b/pkg/servicereaper/service.go index e9c4fe908..e105148f0 100644 --- a/pkg/servicereaper/service.go +++ b/pkg/servicereaper/service.go @@ -46,7 +46,7 @@ func reaper(sigc chan os.Signal) { if err != nil { // do not log error for ECHILD if err != syscall.ECHILD { - logrus.Warnf("wait for pid %d failed: %v ", pid, err) + logrus.Warnf("Wait for pid %d failed: %v ", pid, err) } delete(s.pidMap, pid) continue 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..beccd9fc2 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -62,7 +62,7 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) error { if isRootless { var rlimit unix.Rlimit if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err != nil { - logrus.Warnf("failed to return RLIMIT_NOFILE ulimit %q", err) + logrus.Warnf("Failed to return RLIMIT_NOFILE ulimit %q", err) } if rlimit.Cur < current { current = rlimit.Cur @@ -79,7 +79,7 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) error { if isRootless { var rlimit unix.Rlimit if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err != nil { - logrus.Warnf("failed to return RLIMIT_NPROC ulimit %q", err) + logrus.Warnf("Failed to return RLIMIT_NPROC ulimit %q", err) } if rlimit.Cur < current { current = rlimit.Cur @@ -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/generate/security.go b/pkg/specgen/generate/security.go index a12cc09e2..a11debdb5 100644 --- a/pkg/specgen/generate/security.go +++ b/pkg/specgen/generate/security.go @@ -139,7 +139,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, if len(privCapsRequired) == 0 { caplist = capsRequired } else { - logrus.Errorf("capabilities requested by user or image are not allowed by default: %q", strings.Join(privCapsRequired, ",")) + logrus.Errorf("Capabilities requested by user or image are not allowed by default: %q", strings.Join(privCapsRequired, ",")) } } } 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/pkg/trust/trust.go b/pkg/trust/trust.go index 18a6a1717..584d1fa02 100644 --- a/pkg/trust/trust.go +++ b/pkg/trust/trust.go @@ -188,7 +188,7 @@ func GetGPGIdFromKeyPath(path string) []string { cmd := exec.Command("gpg2", "--with-colons", path) results, err := cmd.Output() if err != nil { - logrus.Errorf("error getting key identity: %s", err) + logrus.Errorf("Getting key identity: %s", err) return nil } return parseUids(results) @@ -203,7 +203,7 @@ func GetGPGIdFromKeyData(key string) []string { } tmpfileName, err := CreateTmpFile("", "", decodeKey) if err != nil { - logrus.Errorf("error creating key date temp file %s", err) + logrus.Errorf("Creating key date temp file %s", err) } defer os.Remove(tmpfileName) return GetGPGIdFromKeyPath(tmpfileName) 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/commit_test.go b/test/e2e/commit_test.go index fbd4068f8..d40faf54b 100644 --- a/test/e2e/commit_test.go +++ b/test/e2e/commit_test.go @@ -332,7 +332,7 @@ var _ = Describe("Podman commit", func() { It("podman commit adds exposed ports", func() { name := "testcon" - s := podmanTest.Podman([]string{"run", "--name", name, "-p", "8080:80", ALPINE, "true"}) + s := podmanTest.Podman([]string{"run", "--name", name, "-p", "8585:80", ALPINE, "true"}) s.WaitWithDefaultTimeout() Expect(s).Should(Exit(0)) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 20ed72c59..7228682f3 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -311,7 +311,7 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { func (p PodmanTestIntegration) AddImageToRWStore(image string) { if err := p.RestoreArtifact(image); err != nil { - logrus.Errorf("unable to restore %s to RW store", image) + logrus.Errorf("Unable to restore %s to RW store", image) } } 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/container_inspect_test.go b/test/e2e/container_inspect_test.go index 7d05b09fb..597eeb1a4 100644 --- a/test/e2e/container_inspect_test.go +++ b/test/e2e/container_inspect_test.go @@ -47,25 +47,25 @@ var _ = Describe("Podman container inspect", func() { It("podman inspect shows exposed ports", func() { name := "testcon" - session := podmanTest.Podman([]string{"run", "-d", "--stop-timeout", "0", "--expose", "8080/udp", "--name", name, ALPINE, "sleep", "inf"}) + session := podmanTest.Podman([]string{"run", "-d", "--stop-timeout", "0", "--expose", "8787/udp", "--name", name, ALPINE, "sleep", "inf"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) data := podmanTest.InspectContainer(name) Expect(data).To(HaveLen(1)) Expect(data[0].NetworkSettings.Ports). - To(Equal(map[string][]define.InspectHostPort{"8080/udp": nil})) + To(Equal(map[string][]define.InspectHostPort{"8787/udp": nil})) }) It("podman inspect shows exposed ports on image", func() { name := "testcon" - session := podmanTest.Podman([]string{"run", "-d", "--expose", "8080", "--name", name, nginx}) + session := podmanTest.Podman([]string{"run", "-d", "--expose", "8989", "--name", name, nginx}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) data := podmanTest.InspectContainer(name) Expect(data).To(HaveLen(1)) Expect(data[0].NetworkSettings.Ports). - To(Equal(map[string][]define.InspectHostPort{"80/tcp": nil, "8080/tcp": nil})) + To(Equal(map[string][]define.InspectHostPort{"80/tcp": nil, "8989/tcp": nil})) }) }) 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/create_test.go b/test/e2e/create_test.go index 32d98c2a9..d20dc8874 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -618,7 +618,7 @@ var _ = Describe("Podman create", func() { pod.WaitWithDefaultTimeout() Expect(pod).Should(Exit(0)) - session := podmanTest.Podman([]string{"create", "--pod", name, "-p", "8080:80", ALPINE, "top"}) + session := podmanTest.Podman([]string{"create", "--pod", name, "-p", "8086:80", ALPINE, "top"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitWithError()) }) diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go index bf89a0708..cb556991c 100644 --- a/test/e2e/generate_kube_test.go +++ b/test/e2e/generate_kube_test.go @@ -792,6 +792,45 @@ var _ = Describe("Podman generate kube", func() { Expect(containers[0].Args).To(Equal([]string{"10s"})) }) + It("podman generate kube - no command", func() { + session := podmanTest.Podman([]string{"create", "--name", "test", ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"generate", "kube", "test"}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + // Now make sure that the container's command is not set to the + // entrypoint and it's arguments to "10s". + pod := new(v1.Pod) + err := yaml.Unmarshal(kube.Out.Contents(), pod) + Expect(err).To(BeNil()) + + containers := pod.Spec.Containers + Expect(len(containers)).To(Equal(1)) + Expect(len(containers[0].Command)).To(Equal(0)) + + cmd := []string{"echo", "hi"} + session = podmanTest.Podman(append([]string{"create", "--name", "test1", ALPINE}, cmd...)) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube = podmanTest.Podman([]string{"generate", "kube", "test1"}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + // Now make sure that the container's command is not set to the + // entrypoint and it's arguments to "10s". + pod = new(v1.Pod) + err = yaml.Unmarshal(kube.Out.Contents(), pod) + Expect(err).To(BeNil()) + + containers = pod.Spec.Containers + Expect(len(containers)).To(Equal(1)) + Expect(containers[0].Command).To(Equal(cmd)) + }) + It("podman generate kube - use entrypoint from image", func() { // Build an image with an entrypoint. containerfile := `FROM quay.io/libpod/alpine:latest diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go index 87f042ed9..1445a634b 100644 --- a/test/e2e/healthcheck_run_test.go +++ b/test/e2e/healthcheck_run_test.go @@ -214,5 +214,12 @@ var _ = Describe("Podman healthcheck run", func() { inspect = podmanTest.InspectContainer("hc") Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckHealthy)) + + // Test podman ps --filter heath is working (#11687) + ps := podmanTest.Podman([]string{"ps", "--filter", "health=healthy"}) + ps.WaitWithDefaultTimeout() + Expect(ps).Should(Exit(0)) + Expect(len(ps.OutputToStringArray())).To(Equal(2)) + Expect(ps.OutputToString()).To(ContainSubstring("hc")) }) }) diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go index 12165d92d..63a54a5ca 100644 --- a/test/e2e/inspect_test.go +++ b/test/e2e/inspect_test.go @@ -451,14 +451,14 @@ var _ = Describe("Podman inspect", func() { It("podman inspect --format json .NetworkSettings.Ports", func() { ctnrName := "Ctnr_" + RandomString(25) - create := podmanTest.Podman([]string{"create", "--name", ctnrName, "-p", "8080:80", ALPINE}) + create := podmanTest.Podman([]string{"create", "--name", ctnrName, "-p", "8084:80", ALPINE}) create.WaitWithDefaultTimeout() Expect(create).Should(Exit(0)) inspect := podmanTest.Podman([]string{"inspect", `--format="{{json .NetworkSettings.Ports}}"`, ctnrName}) inspect.WaitWithDefaultTimeout() Expect(inspect).Should(Exit(0)) - Expect(inspect.OutputToString()).To(Equal(`"{"80/tcp":[{"HostIp":"","HostPort":"8080"}]}"`)) + Expect(inspect.OutputToString()).To(Equal(`"{"80/tcp":[{"HostIp":"","HostPort":"8084"}]}"`)) }) It("Verify container inspect has default network", func() { 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..c9924be72 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -108,7 +108,7 @@ var _ = Describe("Podman pod create", func() { It("podman create pod with network portbindings", func() { name := "test" - session := podmanTest.Podman([]string{"pod", "create", "--name", name, "-p", "8080:80"}) + session := podmanTest.Podman([]string{"pod", "create", "--name", name, "-p", "8081:80"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) pod := session.OutputToString() @@ -117,14 +117,14 @@ var _ = Describe("Podman pod create", func() { webserver.WaitWithDefaultTimeout() Expect(webserver).Should(Exit(0)) - check := SystemExec("nc", []string{"-z", "localhost", "8080"}) + check := SystemExec("nc", []string{"-z", "localhost", "8081"}) Expect(check).Should(Exit(0)) }) It("podman create pod with id file with network portbindings", func() { file := filepath.Join(podmanTest.TempDir, "pod.id") name := "test" - session := podmanTest.Podman([]string{"pod", "create", "--name", name, "--pod-id-file", file, "-p", "8080:80"}) + session := podmanTest.Podman([]string{"pod", "create", "--name", name, "--pod-id-file", file, "-p", "8082:80"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -132,7 +132,7 @@ var _ = Describe("Podman pod create", func() { webserver.WaitWithDefaultTimeout() Expect(webserver).Should(Exit(0)) - check := SystemExec("nc", []string{"-z", "localhost", "8080"}) + check := SystemExec("nc", []string{"-z", "localhost", "8082"}) Expect(check).Should(Exit(0)) }) @@ -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/pod_inspect_test.go b/test/e2e/pod_inspect_test.go index 6633b228c..5728cf9b9 100644 --- a/test/e2e/pod_inspect_test.go +++ b/test/e2e/pod_inspect_test.go @@ -85,7 +85,7 @@ var _ = Describe("Podman pod inspect", func() { It("podman pod inspect outputs port bindings", func() { podName := "testPod" - create := podmanTest.Podman([]string{"pod", "create", "--name", podName, "-p", "8080:80"}) + create := podmanTest.Podman([]string{"pod", "create", "--name", podName, "-p", "8383:80"}) create.WaitWithDefaultTimeout() Expect(create).Should(Exit(0)) @@ -98,7 +98,7 @@ var _ = Describe("Podman pod inspect", func() { Expect(err).To(BeNil()) Expect(inspectJSON.InfraConfig).To(Not(BeNil())) Expect(len(inspectJSON.InfraConfig.PortBindings["80/tcp"])).To(Equal(1)) - Expect(inspectJSON.InfraConfig.PortBindings["80/tcp"][0].HostPort).To(Equal("8080")) + Expect(inspectJSON.InfraConfig.PortBindings["80/tcp"][0].HostPort).To(Equal("8383")) }) It("podman pod inspect outputs show correct MAC", func() { diff --git a/test/e2e/pod_start_test.go b/test/e2e/pod_start_test.go index 93c200389..e895b5598 100644 --- a/test/e2e/pod_start_test.go +++ b/test/e2e/pod_start_test.go @@ -92,7 +92,7 @@ var _ = Describe("Podman pod start", func() { pod, _, podid1 := podmanTest.CreatePod(map[string][]string{ "--infra": {"true"}, "--name": {podName[0]}, - "--publish": {"127.0.0.1:8080:80"}, + "--publish": {"127.0.0.1:8083:80"}, }) Expect(pod).To(Exit(0)) @@ -103,7 +103,7 @@ var _ = Describe("Podman pod start", func() { pod, _, podid2 := podmanTest.CreatePod(map[string][]string{ "--infra": {"true"}, "--name": {podName[1]}, - "--publish": {"127.0.0.1:8080:80"}, + "--publish": {"127.0.0.1:8083:80"}, }) Expect(pod).To(Exit(0)) diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go index aeb88e481..881d9fcf0 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() { @@ -597,7 +609,7 @@ var _ = Describe("Podman ps", func() { It("podman ps test with port shared with pod", func() { podName := "testPod" - pod := podmanTest.Podman([]string{"pod", "create", "-p", "8080:80", "--name", podName}) + pod := podmanTest.Podman([]string{"pod", "create", "-p", "8085:80", "--name", podName}) pod.WaitWithDefaultTimeout() Expect(pod).Should(Exit(0)) @@ -609,7 +621,7 @@ var _ = Describe("Podman ps", func() { ps := podmanTest.Podman([]string{"ps", "--filter", fmt.Sprintf("name=%s", ctrName), "--format", "{{.Ports}}"}) ps.WaitWithDefaultTimeout() Expect(ps).Should(Exit(0)) - Expect(ps.OutputToString()).To(ContainSubstring("0.0.0.0:8080->80/tcp")) + Expect(ps.OutputToString()).To(ContainSubstring("0.0.0.0:8085->80/tcp")) }) It("podman ps truncate long create command", 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_networking_test.go b/test/e2e/run_networking_test.go index c7ffdaf4c..84707732b 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -98,9 +98,9 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) - It("podman run -p 80-82 -p 8080:8080", func() { + It("podman run -p 80-82 -p 8090:8090", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "80-82", "-p", "8080:8080", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "80-82", "-p", "8090:8090", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) @@ -114,14 +114,14 @@ var _ = Describe("Podman run networking", func() { Expect(len(inspectOut[0].NetworkSettings.Ports["82/tcp"])).To(Equal(1)) Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"][0].HostPort).To(Not(Equal("82"))) Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"][0].HostIP).To(Equal("")) - Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort).To(Equal("8080")) - Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["8090/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"][0].HostPort).To(Equal("8090")) + Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"][0].HostIP).To(Equal("")) }) - It("podman run -p 80-81 -p 8080-8081", func() { + It("podman run -p 80-81 -p 8180-8181", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "80-81", "-p", "8080-8081", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "80-81", "-p", "8180-8181", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) @@ -132,17 +132,17 @@ var _ = Describe("Podman run networking", func() { Expect(len(inspectOut[0].NetworkSettings.Ports["81/tcp"])).To(Equal(1)) Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostPort).To(Not(Equal("81"))) Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostIP).To(Equal("")) - Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort).To(Not(Equal("8080"))) - Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostIP).To(Equal("")) - Expect(len(inspectOut[0].NetworkSettings.Ports["8081/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8081/tcp"][0].HostPort).To(Not(Equal("8081"))) - Expect(inspectOut[0].NetworkSettings.Ports["8081/tcp"][0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["8180/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"][0].HostPort).To(Not(Equal("8180"))) + Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"][0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["8181/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostPort).To(Not(Equal("8181"))) + Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostIP).To(Equal("")) }) - It("podman run -p 80 -p 8080-8082:8080-8082", func() { + It("podman run -p 80 -p 8280-8282:8280-8282", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "80", "-p", "8080-8082:8080-8082", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "80", "-p", "8280-8282:8280-8282", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) @@ -150,40 +150,40 @@ var _ = Describe("Podman run networking", func() { Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80"))) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) - Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort).To(Equal("8080")) - Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostIP).To(Equal("")) - Expect(len(inspectOut[0].NetworkSettings.Ports["8081/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8081/tcp"][0].HostPort).To(Equal("8081")) - Expect(inspectOut[0].NetworkSettings.Ports["8081/tcp"][0].HostIP).To(Equal("")) - Expect(len(inspectOut[0].NetworkSettings.Ports["8082/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8082/tcp"][0].HostPort).To(Equal("8082")) - Expect(inspectOut[0].NetworkSettings.Ports["8082/tcp"][0].HostIP).To(Equal("")) - }) - - It("podman run -p 8080:80", func() { + Expect(len(inspectOut[0].NetworkSettings.Ports["8280/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"][0].HostPort).To(Equal("8280")) + Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"][0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["8281/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"][0].HostPort).To(Equal("8281")) + Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"][0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["8282/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"][0].HostPort).To(Equal("8282")) + Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"][0].HostIP).To(Equal("")) + }) + + It("podman run -p 8380:80", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "8080:80", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "8380:80", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8380")) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) - It("podman run -p 8080:80/TCP", func() { + It("podman run -p 8480:80/TCP", func() { name := "testctr" // "TCP" in upper characters - session := podmanTest.Podman([]string{"create", "-t", "-p", "8080:80/TCP", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "8480:80/TCP", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) // "tcp" in lower characters Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8480")) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) @@ -199,51 +199,51 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("")) }) - It("podman run -p 127.0.0.1:8080:80", func() { + It("podman run -p 127.0.0.1:8580:80", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1:8080:80", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1:8580:80", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8580")) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("127.0.0.1")) }) - It("podman run -p 127.0.0.1:8080:80/udp", func() { + It("podman run -p 127.0.0.1:8680:80/udp", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1:8080:80/udp", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1:8680:80/udp", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8680")) Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("127.0.0.1")) }) - It("podman run -p [::1]:8080:80/udp", func() { + It("podman run -p [::1]:8780:80/udp", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "[::1]:8080:80/udp", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "[::1]:8780:80/udp", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8780")) Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("::1")) }) - It("podman run -p [::1]:8080:80/tcp", func() { + It("podman run -p [::1]:8880:80/tcp", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "[::1]:8080:80/tcp", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "[::1]:8880:80/tcp", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8880")) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("::1")) }) @@ -283,33 +283,33 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) - It("podman run -p 127.0.0.1::8080/udp", func() { + It("podman run -p 127.0.0.1::8980/udp", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1::8080/udp", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1::8980/udp", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(len(inspectOut[0].NetworkSettings.Ports["8080/udp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8080/udp"][0].HostPort).To(Not(Equal("8080"))) - Expect(inspectOut[0].NetworkSettings.Ports["8080/udp"][0].HostIP).To(Equal("127.0.0.1")) + Expect(len(inspectOut[0].NetworkSettings.Ports["8980/udp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"][0].HostPort).To(Not(Equal("8980"))) + Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"][0].HostIP).To(Equal("127.0.0.1")) }) - It("podman run -p :8080", func() { + It("podman run -p :8181", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", ":8080", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", ":8181", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort).To(Not(Equal("8080"))) - Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["8181/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostPort).To(Not(Equal("8181"))) + Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostIP).To(Equal("")) }) - It("podman run -p 8080:8080 -p 8081:8080", func() { + It("podman run -p xxx:8080 -p yyy:8080", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "4000:8080", "-p", "8000:8080", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "4444:8080", "-p", "5555:8080", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) @@ -320,18 +320,18 @@ var _ = Describe("Podman run networking", func() { hp2 := inspectOut[0].NetworkSettings.Ports["8080/tcp"][1].HostPort // We can't guarantee order - Expect((hp1 == "4000" && hp2 == "8000") || (hp1 == "8000" && hp2 == "4000")).To(BeTrue()) + Expect((hp1 == "4444" && hp2 == "5555") || (hp1 == "5555" && hp2 == "4444")).To(BeTrue()) }) - It("podman run -p 0.0.0.0:8080:80", func() { + It("podman run -p 0.0.0.0:9280:80", func() { name := "testctr" - session := podmanTest.Podman([]string{"create", "-t", "-p", "0.0.0.0:8080:80", "--name", name, ALPINE, "/bin/sh"}) + session := podmanTest.Podman([]string{"create", "-t", "-p", "0.0.0.0:9280:80", "--name", name, ALPINE, "/bin/sh"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("9280")) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) @@ -348,20 +348,20 @@ var _ = Describe("Podman run networking", func() { Expect(ncBusy).To(ExitWithError()) }) - It("podman run network expose host port 8081 to container port 8000 using rootlesskit port handler", func() { - session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=rootlesskit", "-dt", "-p", "8081:8000", ALPINE, "/bin/sh"}) + It("podman run network expose host port 18081 to container port 8000 using rootlesskit port handler", func() { + session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=rootlesskit", "-dt", "-p", "18081:8000", ALPINE, "/bin/sh"}) session.Wait(30) Expect(session).Should(Exit(0)) - ncBusy := SystemExec("nc", []string{"-l", "-p", "8081"}) + ncBusy := SystemExec("nc", []string{"-l", "-p", "18081"}) Expect(ncBusy).To(ExitWithError()) }) - It("podman run network expose host port 8082 to container port 8000 using slirp4netns port handler", func() { - session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=slirp4netns", "-dt", "-p", "8082:8000", ALPINE, "/bin/sh"}) + It("podman run network expose host port 18082 to container port 8000 using slirp4netns port handler", func() { + session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=slirp4netns", "-dt", "-p", "18082:8000", ALPINE, "/bin/sh"}) session.Wait(30) Expect(session).Should(Exit(0)) - ncBusy := SystemExec("nc", []string{"-l", "-p", "8082"}) + ncBusy := SystemExec("nc", []string{"-l", "-p", "18082"}) Expect(ncBusy).To(ExitWithError()) }) @@ -650,13 +650,13 @@ var _ = Describe("Podman run networking", func() { defer podmanTest.removeCNINetwork(netName) name := "nc-server" - run := podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "-d", "--name", name, "--net", netName, ALPINE, "nc", "-l", "-p", "8080"}) + run := podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "-d", "--name", name, "--net", netName, ALPINE, "nc", "-l", "-p", "9480"}) run.WaitWithDefaultTimeout() Expect(run).Should(Exit(0)) // NOTE: we force the k8s-file log driver to make sure the // tests are passing inside a container. - run = podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "--rm", "--net", netName, "--uidmap", "0:1:4096", ALPINE, "sh", "-c", fmt.Sprintf("echo podman | nc -w 1 %s.dns.podman 8080", name)}) + run = podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "--rm", "--net", netName, "--uidmap", "0:1:4096", ALPINE, "sh", "-c", fmt.Sprintf("echo podman | nc -w 1 %s.dns.podman 9480", name)}) run.WaitWithDefaultTimeout() Expect(run).Should(Exit(0)) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index ec4b0d997..b6743f4b7 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1148,11 +1148,11 @@ USER mail`, BB) }) It("podman run --pod automatically", func() { - session := podmanTest.Podman([]string{"run", "-d", "--pod", "new:foobar", ALPINE, "nc", "-l", "-p", "8080"}) + session := podmanTest.Podman([]string{"run", "-d", "--pod", "new:foobar", ALPINE, "nc", "-l", "-p", "8686"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"run", "--pod", "foobar", ALPINE, "/bin/sh", "-c", "echo test | nc -w 1 127.0.0.1 8080"}) + session = podmanTest.Podman([]string{"run", "--pod", "foobar", ALPINE, "/bin/sh", "-c", "echo test | nc -w 1 127.0.0.1 8686"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index 690c53de6..f1baa7780 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/system_connection_test.go b/test/e2e/system_connection_test.go index 21398887a..6cdb78c5e 100644 --- a/test/e2e/system_connection_test.go +++ b/test/e2e/system_connection_test.go @@ -138,7 +138,7 @@ var _ = Describe("podman system connection", func() { It("add tcp", func() { cmd := []string{"system", "connection", "add", "QA-TCP", - "tcp://localhost:8080", + "tcp://localhost:8888", } session := podmanTest.Podman(cmd) session.WaitWithDefaultTimeout() @@ -150,7 +150,7 @@ var _ = Describe("podman system connection", func() { Expect(cfg.Engine.ActiveService).To(Equal("QA-TCP")) Expect(cfg.Engine.ServiceDestinations["QA-TCP"]).To(Equal( config.Destination{ - URI: "tcp://localhost:8080", + URI: "tcp://localhost:8888", Identity: "", }, )) 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/070-build.bats b/test/system/070-build.bats index 03c7984e2..0e1396fc6 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -285,21 +285,11 @@ EOF build_arg_implicit+="=$arg_implicit_value" fi - # FIXME FIXME FIXME: 2021-03-15: workaround for #9567 (slow ubuntu 2004): - # we're seeing lots of timeouts in CI. Until/unless #9567 gets fixed, - # let's get CI passing by extending the timeout when remote on ubuntu - local localtimeout=${PODMAN_TIMEOUT} - if is_remote; then - if grep -qi ubuntu /etc/os-release; then - localtimeout=$(( 2 * $localtimeout )) - fi - fi - # cd to the dir, so we test relative paths (important for podman-remote) cd $PODMAN_TMPDIR export arg_explicit="THIS SHOULD BE OVERRIDDEN BY COMMAND LINE!" export arg_implicit=${arg_implicit_value} - PODMAN_TIMEOUT=$localtimeout run_podman ${MOUNTS_CONF} build \ + run_podman ${MOUNTS_CONF} build \ --build-arg arg_explicit=${arg_explicit_value} \ $build_arg_implicit \ --dns-search $nosuchdomain \ @@ -456,16 +446,24 @@ Labels.$label_name | $label_value @test "podman build - COPY with ignore" { local tmpdir=$PODMAN_TMPDIR/build-test-$(random_string 10) - mkdir -p $tmpdir/subdir + mkdir -p $tmpdir/subdir{1,2} # Create a bunch of files. Declare this as an array to avoid duplication # because we iterate over that list below, checking for each file. # A leading "-" indicates that the file SHOULD NOT exist in the built image + # + # Weird side effect of Buildah 3486, relating to subdirectories and + # wildcard patterns. See that PR for details, it's way too confusing + # to explain in a comment. local -a files=( -test1 -test1.txt test2 test2.txt - -subdir/sub1 -subdir/sub1.txt - -subdir/sub2 -subdir/sub2.txt + subdir1/sub1 subdir1/sub1.txt + -subdir1/sub2 -subdir1/sub2.txt + subdir1/sub3 subdir1/sub3.txt + -subdir2/sub1 -subdir2/sub1.txt + -subdir2/sub2 -subdir2/sub2.txt + -subdir2/sub3 -subdir2/sub3.txt this-file-does-not-match-anything-in-ignore-file comment ) @@ -492,8 +490,10 @@ EOF # comment test* !test2* -subdir +subdir1 +subdir2 !*/sub1* +!subdir1/sub3* EOF # Build an image. For .dockerignore 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/system/160-volumes.bats b/test/system/160-volumes.bats index f6dc3f0af..e21be9ea4 100644 --- a/test/system/160-volumes.bats +++ b/test/system/160-volumes.bats @@ -21,8 +21,6 @@ function teardown() { # Simple volume tests: share files between host and container @test "podman run --volumes : basic" { - skip_if_remote "volumes cannot be shared across hosts" - run_podman volume list --noheading is "$output" "" "baseline: empty results from list --noheading" @@ -192,9 +190,12 @@ EOF run_podman volume create my_vol run_podman run --rm -v my_vol:/data $IMAGE sh -c "echo hello >> /data/test" run_podman volume create my_vol2 - run_podman volume export my_vol --output=hello.tar + + tarfile=hello$(random_string | tr A-Z a-z).tar + run_podman volume export my_vol --output=$tarfile # we want to use `run_podman volume export my_vol` but run_podman is wrapping EOF - cat hello.tar | run_podman volume import my_vol2 - + run_podman volume import my_vol2 - < $tarfile + rm -f $tarfile run_podman run --rm -v my_vol2:/data $IMAGE sh -c "cat /data/test" is "$output" "hello" "output from second container" run_podman volume rm my_vol diff --git a/test/testvol/main.go b/test/testvol/main.go index 721f47bcd..a0f58348b 100644 --- a/test/testvol/main.go +++ b/test/testvol/main.go @@ -59,7 +59,7 @@ func before(cmd *cobra.Command, args []string) error { func main() { if err := rootCmd.Execute(); err != nil { - logrus.Errorf("Error running volume plugin: %v", err) + logrus.Errorf("Running volume plugin: %v", err) os.Exit(1) } 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/k8s.io/apimachinery/third_party/forked/golang/LICENSE b/vendor/k8s.io/apimachinery/third_party/forked/golang/LICENSE new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/vendor/k8s.io/apimachinery/third_party/forked/golang/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/k8s.io/apimachinery/third_party/forked/golang/PATENTS b/vendor/k8s.io/apimachinery/third_party/forked/golang/PATENTS new file mode 100644 index 000000000..733099041 --- /dev/null +++ b/vendor/k8s.io/apimachinery/third_party/forked/golang/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/modules.txt b/vendor/modules.txt index 324487b7c..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 @@ -797,10 +800,10 @@ gopkg.in/tomb.v1 gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gopkg.in/yaml.v3 -# k8s.io/api v0.22.1 +# k8s.io/api v0.22.2 k8s.io/api/apps/v1 k8s.io/api/core/v1 -# k8s.io/apimachinery v0.22.1 +# k8s.io/apimachinery v0.22.2 k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/apis/meta/v1 k8s.io/apimachinery/pkg/conversion |