diff options
40 files changed, 344 insertions, 178 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 324fd32f6..ee0131279 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -7,9 +7,11 @@ env: #### # Name of the ultimate destination branch for this CI run, PR or post-merge. DEST_BRANCH: "main" + # Sane (default) value for GOPROXY and GOSUMDB. + GOPROXY: "https://proxy.golang.org,direct" + GOSUMDB: "sum.golang.org" # Overrides default location (/tmp/cirrus) for repo clone GOPATH: &gopath "/var/tmp/go" - GOBIN: "${GOPATH}/bin" GOCACHE: "${GOPATH}/cache" GOSRC: &gosrc "/var/tmp/go/src/github.com/containers/podman" CIRRUS_WORKING_DIR: *gosrc diff --git a/.gitignore b/.gitignore index f6eee2fe0..b8059e69a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /build/ /conmon/ contrib/spec/podman.spec +contrib/systemd/*/*.service *.coverprofile coverprofile /.coverage @@ -39,5 +40,4 @@ tags result # Necessary to prevent hack/tree-status.sh false-positive /*runner_stats.log -.install.goimports .generate-bindings diff --git a/.golangci.yml b/.golangci.yml index 7eb6ea57e..15700cee7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -44,7 +44,6 @@ linters: - goconst - gocyclo - lll - - unconvert - gosec - maligned - gomoddirectives @@ -20,8 +20,6 @@ ### Variables & Definitions ### -export GOPROXY=https://proxy.golang.org - GO ?= go GO_LDFLAGS:= $(shell if $(GO) version|grep -q gccgo ; then echo "-gccgoflags"; else echo "-ldflags"; fi) GOCMD = CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO) @@ -29,8 +27,6 @@ COVERAGE_PATH ?= .coverage DESTDIR ?= EPOCH_TEST_COMMIT ?= $(shell git merge-base $${DEST_BRANCH:-main} HEAD) HEAD ?= HEAD -CHANGELOG_BASE ?= HEAD~ -CHANGELOG_TARGET ?= HEAD PROJECT := github.com/containers/podman GIT_BASE_BRANCH ?= origin/main GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null) @@ -69,8 +65,6 @@ PRE_COMMIT = $(shell command -v bin/venv/bin/pre-commit ~/.local/bin/pre-commit # triggered. SOURCES = $(shell find . -path './.*' -prune -o \( \( -name '*.go' -o -name '*.c' \) -a ! -name '*_test.go' \) -print) -BUILDFLAGS := -mod=vendor $(BUILDFLAGS) - BUILDTAGS_CROSS ?= containers_image_openpgp exclude_graphdriver_btrfs exclude_graphdriver_devicemapper exclude_graphdriver_overlay CONTAINER_RUNTIME := $(shell command -v podman 2> /dev/null || echo docker) OCI_RUNTIME ?= "" @@ -90,10 +84,8 @@ GIT_COMMIT ?= $(if $(shell git status --porcelain --untracked-files=no),${COMMIT DATE_FMT = %s ifdef SOURCE_DATE_EPOCH BUILD_INFO ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+$(DATE_FMT)" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+$(DATE_FMT)" 2>/dev/null || date -u "+$(DATE_FMT)") - ISODATE ?= $(shell date -d "@$(SOURCE_DATE_EPOCH)" --iso-8601) else BUILD_INFO ?= $(shell date "+$(DATE_FMT)") - ISODATE ?= $(shell date --iso-8601) endif LIBPOD := ${PROJECT}/v4/libpod GOFLAGS ?= -trimpath @@ -120,22 +112,10 @@ 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 ?= -# If GOPATH not specified, use one in the local directory -ifeq ($(GOPATH),) -export GOPATH := $(HOME)/go -unexport GOBIN -endif -FIRST_GOPATH := $(firstword $(subst :, ,$(GOPATH))) -GOPKGDIR := $(FIRST_GOPATH)/src/$(PROJECT) -GOPKGBASEDIR ?= $(shell dirname "$(GOPKGDIR)") - -GOBIN := $(shell $(GO) env GOBIN) -ifeq ($(GOBIN),) -GOBIN := $(FIRST_GOPATH)/bin -endif - +# Ensure GOBIN is not set so the default (`go env GOPATH`/bin) is used. +override undefine GOBIN # This must never include the 'hack' directory -export PATH := $(PATH):$(GOBIN) +export PATH := $(shell $(GO) env GOPATH)/bin:$(PATH) GOMD2MAN ?= $(shell command -v go-md2man || echo './test/tools/build/go-md2man') @@ -223,15 +203,8 @@ help: ## (Default) Print listing of key targets with their descriptions ### Linting/Formatting/Code Validation targets ### -.gopathok: -ifeq ("$(wildcard $(GOPKGDIR))","") - mkdir -p "$(GOPKGBASEDIR)" - ln -sfn "$(CURDIR)" "$(GOPKGDIR)" -endif - touch $@ - .PHONY: .gitvalidation -.gitvalidation: .gopathok +.gitvalidation: @echo "Validating vs commit '$(call err_if_empty,EPOCH_TEST_COMMIT)'" GIT_CHECK_EXCLUDE="./vendor:./test/tools/vendor:docs/make.bat:test/buildah-bud/buildah-tests.diff" ./test/tools/build/git-validation -run DCO,short-subject,dangling-whitespace -range $(EPOCH_TEST_COMMIT)..$(HEAD) @@ -245,27 +218,15 @@ endif $(PRE_COMMIT) run -a .PHONY: golangci-lint -golangci-lint: .gopathok .install.golangci-lint +golangci-lint: .install.golangci-lint hack/golangci-lint.sh run -.PHONY: gofmt -gofmt: ## Verify the source code gofmt - find . -name '*.go' -type f \ - -not \( \ - -name '.golangci.yml' -o \ - -name 'Makefile' -o \ - -path './vendor/*' -prune -o \ - -path './test/tools/vendor/*' -prune -o \ - -path './contrib/*' -prune \ - \) -exec gofmt -d -e -s -w {} \+ - git diff --exit-code - .PHONY: test/checkseccomp/checkseccomp -test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go) +test/checkseccomp/checkseccomp: $(wildcard test/checkseccomp/*.go) $(GOCMD) build $(BUILDFLAGS) $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp .PHONY: test/testvol/testvol -test/testvol/testvol: .gopathok $(wildcard test/testvol/*.go) +test/testvol/testvol: $(wildcard test/testvol/*.go) $(GOCMD) build $(BUILDFLAGS) $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol .PHONY: volume-plugin-test-image @@ -273,10 +234,10 @@ volume-plugin-test-img: podman build -t quay.io/libpod/volume-plugin-test-img -f Containerfile-testvol . .PHONY: test/goecho/goecho -test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go) +test/goecho/goecho: $(wildcard test/goecho/*.go) $(GOCMD) build $(BUILDFLAGS) $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho -test/version/version: .gopathok version/version.go +test/version/version: version/version.go $(GO) build -o $@ ./test/version/ .PHONY: codespell @@ -284,7 +245,7 @@ codespell: codespell -S bin,vendor,.git,go.sum,.cirrus.yml,"RELEASE_NOTES.md,*.xz,*.gz,*.ps1,*.tar,swagger.yaml,*.tgz,bin2img,*ico,*.png,*.1,*.5,copyimg,*.orig,apidoc.go" -L uint,iff,od,seeked,splitted,marge,ERRO,hist,ether -w .PHONY: validate -validate: gofmt lint .gitvalidation validate.completions man-page-check swagger-check tests-included tests-expect-exit +validate: lint .gitvalidation validate.completions man-page-check swagger-check tests-included tests-expect-exit .PHONY: build-all-new-commits build-all-new-commits: @@ -293,9 +254,9 @@ build-all-new-commits: .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: vendor-in-container vendor-in-container: @@ -309,7 +270,7 @@ vendor-in-container: ### # Make sure to warn in case we're building without the systemd buildtag. -bin/podman: .gopathok $(SOURCES) go.mod go.sum +bin/podman: $(SOURCES) go.mod go.sum ifeq (,$(findstring systemd,$(BUILDTAGS))) @echo "Podman is being compiled without the systemd build tag. \ Install libsystemd on Ubuntu or systemd-devel on rpm based \ @@ -325,14 +286,14 @@ endif $(SRCBINDIR): mkdir -p $(SRCBINDIR) -$(SRCBINDIR)/podman$(BINSFX): $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum +$(SRCBINDIR)/podman$(BINSFX): $(SRCBINDIR) $(SOURCES) go.mod go.sum $(GOCMD) build \ $(BUILDFLAGS) \ $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' \ -tags "${REMOTETAGS}" \ -o $@ ./cmd/podman -$(SRCBINDIR)/podman-remote-static: $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum +$(SRCBINDIR)/podman-remote-static: $(SRCBINDIR) $(SOURCES) go.mod go.sum CGO_ENABLED=0 \ GOOS=$(GOOS) \ GOARCH=$(GOARCH) \ @@ -368,7 +329,7 @@ podman-remote-windows: ## Build podman-remote for Windows bin/windows/podman.exe .PHONY: podman-winpath -podman-winpath: .gopathok $(SOURCES) go.mod go.sum +podman-winpath: $(SOURCES) go.mod go.sum CGO_ENABLED=0 \ GOOS=windows \ $(GO) build \ @@ -395,7 +356,7 @@ podman-mac-helper: ## Build podman-mac-helper for macOS -o bin/darwin/podman-mac-helper \ ./cmd/podman-mac-helper -bin/rootlessport: .gopathok $(SOURCES) go.mod go.sum +bin/rootlessport: $(SOURCES) go.mod go.sum CGO_ENABLED=$(CGO_ENABLED) \ $(GO) build \ $(BUILDFLAGS) \ @@ -411,11 +372,11 @@ rootlessport: bin/rootlessport .PHONY: generate-bindings generate-bindings: ifneq ($(GOOS),darwin) - GO111MODULE=off $(GOCMD) generate ./pkg/bindings/... ; + $(GOCMD) generate ./pkg/bindings/... ; endif # DO NOT USE: use local-cross instead -bin/podman.cross.%: .gopathok +bin/podman.cross.%: TARGET="$*"; \ GOOS="$${TARGET%%.*}"; \ GOARCH="$${TARGET##*.}"; \ @@ -455,7 +416,7 @@ completions: podman podman-remote ### Documentation targets ### -pkg/api/swagger.yaml: .gopathok +pkg/api/swagger.yaml: make -C pkg/api $(MANPAGES): %: %.md .install.md2man docdir @@ -531,7 +492,7 @@ run-docker-py-tests: .PHONY: localunit localunit: test/goecho/goecho test/version/version rm -rf ${COVERAGE_PATH} && mkdir -p ${COVERAGE_PATH} - UNIT=1 $(GOBIN)/ginkgo \ + UNIT=1 ginkgo \ -r \ $(TESTFLAGS) \ --skipPackage test/e2e,pkg/apparmor,pkg/bindings,hack,pkg/machine/e2e \ @@ -550,8 +511,8 @@ test: localunit localintegration remoteintegration localsystem remotesystem ## .PHONY: ginkgo-run ginkgo-run: - ACK_GINKGO_RC=true $(GOBIN)/ginkgo version - ACK_GINKGO_RC=true $(GOBIN)/ginkgo -v $(TESTFLAGS) -tags "$(TAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -nodes 3 -debug test/e2e/. $(HACK) + ACK_GINKGO_RC=true ginkgo version + ACK_GINKGO_RC=true ginkgo -v $(TESTFLAGS) -tags "$(TAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -nodes 3 -debug test/e2e/. $(HACK) .PHONY: ginkgo ginkgo: @@ -569,7 +530,7 @@ remoteintegration: test-binaries ginkgo-remote .PHONY: localbenchmarks localbenchmarks: test-binaries - PATH=$(PATH):$(shell pwd)/hack ACK_GINKGO_RC=true $(GOBIN)/ginkgo \ + PATH=$(PATH):$(shell pwd)/hack ACK_GINKGO_RC=true ginkgo \ -focus "Podman Benchmark Suite" \ -tags "$(BUILDTAGS) benchmarks" -noColor \ -noisySkippings=false -noisyPendings=false \ @@ -759,7 +720,7 @@ package-install: package ## Install rpm packages /usr/bin/podman info # will catch a broken conmon .PHONY: install -install: .gopathok install.bin install.remote install.man install.systemd ## Install binaries to system locations +install: install.bin install.remote install.man install.systemd ## Install binaries to system locations .PHONY: install.catatonit install.catatonit: @@ -832,7 +793,8 @@ install.docker-full: install.docker install.docker-docs ifneq (,$(findstring systemd,$(BUILDTAGS))) PODMAN_UNIT_FILES = contrib/systemd/auto-update/podman-auto-update.service \ contrib/systemd/system/podman.service \ - contrib/systemd/system/podman-restart.service + contrib/systemd/system/podman-restart.service \ + contrib/systemd/system/podman-play-kube@.service %.service: %.service.in sed -e 's;@@PODMAN@@;$(BINDIR)/podman;g' $< >$@.tmp.$$ \ @@ -846,12 +808,14 @@ install.systemd: $(PODMAN_UNIT_FILES) install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.socket ${DESTDIR}${USERSYSTEMDDIR}/podman.socket install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.service ${DESTDIR}${USERSYSTEMDDIR}/podman.service install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-restart.service ${DESTDIR}${USERSYSTEMDDIR}/podman-restart.service + install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-play-kube@.service ${DESTDIR}${USERSYSTEMDDIR}/podman-play-kube@.service # System services install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.service ${DESTDIR}${SYSTEMDDIR}/podman-auto-update.service install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.timer ${DESTDIR}${SYSTEMDDIR}/podman-auto-update.timer install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.socket ${DESTDIR}${SYSTEMDDIR}/podman.socket install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.service ${DESTDIR}${SYSTEMDDIR}/podman.service install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-restart.service ${DESTDIR}${SYSTEMDDIR}/podman-restart.service + install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-play-kube@.service ${DESTDIR}${SYSTEMDDIR}/podman-play-kube@.service rm -f $(PODMAN_UNIT_FILES) else install.systemd: @@ -862,14 +826,12 @@ install.tools: .install.ginkgo .install.golangci-lint .install.bats ## Install n make -C test/tools .PHONY: .install.ginkgo -.install.ginkgo: .gopathok - if [ ! -x "$(GOBIN)/ginkgo" ]; then \ - $(GO) install $(BUILDFLAGS) ./vendor/github.com/onsi/ginkgo/ginkgo ; \ - fi +.install.ginkgo: + $(GO) install $(BUILDFLAGS) ./vendor/github.com/onsi/ginkgo/ginkgo .PHONY: .install.golangci-lint -.install.golangci-lint: .gopathok - VERSION=1.45.2 GOBIN=$(GOBIN) ./hack/install_golangci.sh +.install.golangci-lint: + VERSION=1.45.2 ./hack/install_golangci.sh .PHONY: .install.md2man .install.md2man: @@ -878,7 +840,7 @@ install.tools: .install.ginkgo .install.golangci-lint .install.bats ## Install n fi .PHONY: .install.bats -.install.bats: .gopathok +.install.bats: VERSION=v1.1.0 ./hack/install_bats.sh .PHONY: .install.pre-commit @@ -887,13 +849,6 @@ install.tools: .install.ginkgo .install.golangci-lint .install.bats ## Install n python3 -m pip install --user pre-commit; \ fi -# $BUILD_TAGS variable is used in hack/golangci-lint.sh -.PHONY: install.libseccomp.sudo -install.libseccomp.sudo: - rm -rf ../../seccomp/libseccomp - git clone https://github.com/seccomp/libseccomp ../../seccomp/libseccomp - cd ../../seccomp/libseccomp && git checkout --detach $(LIBSECCOMP_COMMIT) && ./autogen.sh && ./configure --prefix=/usr && make all && make install - .PHONY: uninstall uninstall: for i in $(filter %.1,$(MANPAGES_DEST)); do \ @@ -924,7 +879,6 @@ clean-binaries: ## Remove platform/architecture specific binary files .PHONY: clean clean: clean-binaries ## Clean all make artifacts rm -rf \ - .gopathok \ _output \ $(wildcard podman-*.msi) \ $(wildcard podman-remote*.zip) \ @@ -940,7 +894,6 @@ clean: clean-binaries ## Clean all make artifacts libpod/pod_ffjson.go \ libpod/container_easyjson.go \ libpod/pod_easyjson.go \ - .install.goimports \ docs/build \ .venv make -C docs clean diff --git a/cmd/podman/common/create_test.go b/cmd/podman/common/create_test.go index ab41f81ad..80e6cbf54 100644 --- a/cmd/podman/common/create_test.go +++ b/cmd/podman/common/create_test.go @@ -28,8 +28,8 @@ func TestPodOptions(t *testing.T) { 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] + tagPod := strings.Split(podType.Tag.Get("json"), ",")[0] + tagContainer := strings.Split(containerType.Tag.Get("json"), ",")[0] if tagPod == tagContainer && (tagPod != "" && tagContainer != "") { areEqual := true if containerField.Kind() == podField.Kind() { diff --git a/cmd/podman/containers/kill.go b/cmd/podman/containers/kill.go index 32f9899cd..e994fbf2c 100644 --- a/cmd/podman/containers/kill.go +++ b/cmd/podman/containers/kill.go @@ -95,7 +95,7 @@ func kill(_ *cobra.Command, args []string) error { return errors.New("valid signals are 1 through 64") } for _, cidFile := range cidFiles { - content, err := ioutil.ReadFile(string(cidFile)) + content, err := ioutil.ReadFile(cidFile) if err != nil { return errors.Wrap(err, "error reading CIDFile") } diff --git a/cmd/podman/containers/rm.go b/cmd/podman/containers/rm.go index 7e0955863..420e3c38d 100644 --- a/cmd/podman/containers/rm.go +++ b/cmd/podman/containers/rm.go @@ -102,7 +102,7 @@ func rm(cmd *cobra.Command, args []string) error { rmOptions.Timeout = &stopTimeout } for _, cidFile := range cidFiles { - content, err := ioutil.ReadFile(string(cidFile)) + content, err := ioutil.ReadFile(cidFile) if err != nil { return errors.Wrap(err, "error reading CIDFile") } diff --git a/cmd/podman/containers/stop.go b/cmd/podman/containers/stop.go index 381997fee..af2250abb 100644 --- a/cmd/podman/containers/stop.go +++ b/cmd/podman/containers/stop.go @@ -100,7 +100,7 @@ func stop(cmd *cobra.Command, args []string) error { } for _, cidFile := range cidFiles { - content, err := ioutil.ReadFile(string(cidFile)) + content, err := ioutil.ReadFile(cidFile) if err != nil { return errors.Wrap(err, "error reading CIDFile") } diff --git a/contrib/cirrus/pr-should-include-tests b/contrib/cirrus/pr-should-include-tests index 57ca39d9b..9409a1d49 100755 --- a/contrib/cirrus/pr-should-include-tests +++ b/contrib/cirrus/pr-should-include-tests @@ -34,9 +34,11 @@ filtered_changes=$(git diff --name-only $base $head | fgrep -vx .cirrus.yml | fgrep -vx .pre-commit-config.yaml | fgrep -vx .gitignore | - fgrep -vx Makefile | fgrep -vx go.mod | fgrep -vx go.sum | + fgrep -vx podman.spec.rpkg | + fgrep -vx .golangci.yml | + egrep -v '/*Makefile$' | egrep -v '^[^/]+\.md$' | egrep -v '^.github' | egrep -v '^contrib/' | diff --git a/contrib/systemd/system/podman-play-kube@.service.in b/contrib/systemd/system/podman-play-kube@.service.in new file mode 100644 index 000000000..824f71eb0 --- /dev/null +++ b/contrib/systemd/system/podman-play-kube@.service.in @@ -0,0 +1,18 @@ +[Unit] +Description=A template for running K8s workloads via podman-play-kube +Documentation=man:podman-play-kube(1) +Wants=network-online.target +After=network-online.target +RequiresMountsFor=%t/containers + +[Service] +Environment=PODMAN_SYSTEMD_UNIT=%n +Restart=never +TimeoutStopSec=70 +ExecStart=@@PODMAN@@ play kube --replace --service-container=true %I +ExecStop=@@PODMAN@@ play kube --down %I +Type=notify +NotifyAccess=all + +[Install] +WantedBy=default.target diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 5d809644d..93240812d 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -171,7 +171,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver Mounts: inspectMounts, Dependencies: c.Dependencies(), IsInfra: c.IsInfra(), - IsService: c.isService(), + IsService: c.IsService(), } if c.state.ConfigPath != "" { diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 4742b22ab..d7683cce9 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -3282,7 +3282,7 @@ func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error { return err } stat := st.Sys().(*syscall.Stat_t) - atime := time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) + atime := time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) // nolint: unconvert if err := os.Chtimes(mountPoint, atime, st.ModTime()); err != nil { return err } diff --git a/libpod/container_validate.go b/libpod/container_validate.go index d939c94e6..cfbdd2b1e 100644 --- a/libpod/container_validate.go +++ b/libpod/container_validate.go @@ -31,7 +31,7 @@ func (c *Container) validate() error { // A container cannot be marked as an infra and service container at // the same time. - if c.IsInfra() && c.isService() { + if c.IsInfra() && c.IsService() { return fmt.Errorf("cannot be infra and service container at the same time: %w", define.ErrInvalidArg) } diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 7e8a21a8c..2eaa77572 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -644,6 +644,16 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo return err } + if c.IsService() { + canStop, err := c.canStopServiceContainer() + if err != nil { + return err + } + if !canStop { + return fmt.Errorf("container %s is the service container of pod(s) %s and cannot be removed without removing the pod(s)", c.ID(), strings.Join(c.state.Service.Pods, ",")) + } + } + // If we're not force-removing, we need to check if we're in a good // state to remove. if !force { @@ -907,6 +917,16 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol } } + if c.IsService() { + canStop, err := c.canStopServiceContainer() + if err != nil { + return id, err + } + if !canStop { + return id, fmt.Errorf("container %s is the service container of pod(s) %s and cannot be removed without removing the pod(s)", c.ID(), strings.Join(c.state.Service.Pods, ",")) + } + } + var cleanupErr error // Remove the container from the state if c.config.Pod != "" { diff --git a/libpod/service.go b/libpod/service.go index ad147e87b..c14f5e51d 100644 --- a/libpod/service.go +++ b/libpod/service.go @@ -54,11 +54,12 @@ func (c *Container) addServicePodLocked(id string) error { return c.save() } -func (c *Container) isService() bool { +// IsService returns true when the container is a "service container". +func (c *Container) IsService() bool { return c.config.IsService } -// canStopServiceContainer returns true if all pods of the service are stopped. +// canStopServiceContainerLocked returns true if all pods of the service are stopped. // Note that the method acquires the container lock. func (c *Container) canStopServiceContainerLocked() (bool, error) { c.lock.Lock() @@ -67,10 +68,16 @@ func (c *Container) canStopServiceContainerLocked() (bool, error) { return false, err } - if !c.isService() { + if !c.IsService() { return false, fmt.Errorf("internal error: checking service: container %s is not a service container", c.ID()) } + return c.canStopServiceContainer() +} + +// canStopServiceContainer returns true if all pods of the service are stopped. +// Note that the method expects the container to be locked. +func (c *Container) canStopServiceContainer() (bool, error) { for _, id := range c.state.Service.Pods { pod, err := c.runtime.LookupPod(id) if err != nil { @@ -163,7 +170,7 @@ func (c *Container) canRemoveServiceContainerLocked() (bool, error) { return false, err } - if !c.isService() { + if !c.IsService() { return false, fmt.Errorf("internal error: checking service: container %s is not a service container", c.ID()) } diff --git a/pkg/api/Makefile b/pkg/api/Makefile index 6da5fb57e..d07cf6f93 100644 --- a/pkg/api/Makefile +++ b/pkg/api/Makefile @@ -1,5 +1,3 @@ -export GO111MODULE=off - SWAGGER_OUT ?= swagger.yaml validate: ${SWAGGER_OUT} diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index 1c339730e..e3d51fadf 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -254,7 +254,7 @@ func KillContainer(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) return } - if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL { + if sig == 0 || sig == syscall.SIGKILL { opts := entities.WaitOptions{ Condition: []define.ContainerStatus{define.ContainerStateExited, define.ContainerStateStopped}, Interval: time.Millisecond * 250, @@ -341,8 +341,8 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error for idx, portMapping := range portMappings { ports[idx] = types.Port{ IP: portMapping.HostIP, - PrivatePort: uint16(portMapping.ContainerPort), - PublicPort: uint16(portMapping.HostPort), + PrivatePort: portMapping.ContainerPort, + PublicPort: portMapping.HostPort, Type: portMapping.Protocol, } } diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 318688222..1a0ac6801 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -605,7 +605,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { Output: output, OutputFormat: format, PullPolicy: pullPolicy, - PullPushRetryDelay: time.Duration(2 * time.Second), + PullPushRetryDelay: 2 * time.Second, Quiet: query.Quiet, Registry: registry, RemoveIntermediateCtrs: query.Rm, diff --git a/pkg/api/handlers/compat/images_remove.go b/pkg/api/handlers/compat/images_remove.go index f45b38c66..35bcb36aa 100644 --- a/pkg/api/handlers/compat/images_remove.go +++ b/pkg/api/handlers/compat/images_remove.go @@ -52,7 +52,10 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) { utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name)) return } - + if errors.Cause(err) == storage.ErrImageUsedByContainer { + utils.Error(w, http.StatusConflict, errors.Wrapf(err, "image %s is in use", name)) + return + } utils.Error(w, http.StatusInternalServerError, err) return } diff --git a/pkg/bindings/images/build_unix.go b/pkg/bindings/images/build_unix.go index 67a5e2998..32e2ba9af 100644 --- a/pkg/bindings/images/build_unix.go +++ b/pkg/bindings/images/build_unix.go @@ -11,7 +11,7 @@ import ( func checkHardLink(fi os.FileInfo) (devino, bool) { st := fi.Sys().(*syscall.Stat_t) return devino{ - Dev: uint64(st.Dev), - Ino: uint64(st.Ino), + Dev: uint64(st.Dev), // nolint: unconvert + Ino: st.Ino, }, st.Nlink > 1 } diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 5ca678d6f..d2fafccb1 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -292,7 +292,13 @@ func (ic *ContainerEngine) removeContainer(ctx context.Context, ctr *libpod.Cont logrus.Debugf("Failed to remove container %s: %s", ctr.ID(), err.Error()) switch errors.Cause(err) { case define.ErrNoSuchCtr: - if options.Ignore { + // Ignore if the container does not exist (anymore) when either + // it has been requested by the user of if the container is a + // service one. Service containers are removed along with its + // pods which in turn are removed along with their infra + // container. Hence, there is an inherent race when removing + // infra containers with service containers in parallel. + if options.Ignore || ctr.IsService() { logrus.Debugf("Ignoring error (--allow-missing): %v", err) return nil } @@ -1107,7 +1113,7 @@ func (ic *ContainerEngine) GetContainerExitCode(ctx context.Context, ctr *libpod time.Sleep(250 * time.Millisecond) continue } - return int(event.ContainerExitCode) + return event.ContainerExitCode } logrus.Errorf("Could not retrieve exit code from event: %v", err) return define.ExecErrorCodeNotFound diff --git a/pkg/domain/infra/abi/parse/parse.go b/pkg/domain/infra/abi/parse/parse.go index 3bac2ef99..66794e592 100644 --- a/pkg/domain/infra/abi/parse/parse.go +++ b/pkg/domain/infra/abi/parse/parse.go @@ -43,7 +43,7 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) if err != nil { return nil, errors.Wrapf(err, "cannot convert inodes %s to integer", splitO[1]) } - libpodOptions = append(libpodOptions, libpod.WithVolumeInodes(uint64(inodes))) + libpodOptions = append(libpodOptions, libpod.WithVolumeInodes(inodes)) finalVal = append(finalVal, o) // set option "INODES": "$size" volumeOptions["INODES"] = splitO[1] diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 420d51483..e04ab3a1a 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -37,7 +37,15 @@ import ( // createServiceContainer creates a container that can later on // be associated with the pods of a K8s yaml. It will be started along with // the first pod. -func (ic *ContainerEngine) createServiceContainer(ctx context.Context, name string) (*libpod.Container, error) { +func (ic *ContainerEngine) createServiceContainer(ctx context.Context, name string, options entities.PlayKubeOptions) (*libpod.Container, error) { + // Make sure to replace the service container as well if requested by + // the user. + if options.Replace { + if _, err := ic.ContainerRm(ctx, []string{name}, entities.RmOptions{Force: true, Ignore: true}); err != nil { + return nil, fmt.Errorf("replacing service container: %w", err) + } + } + // Similar to infra containers, a service container is using the pause image. image, err := generate.PullOrBuildInfraImage(ic.Libpod, "") if err != nil { @@ -65,6 +73,7 @@ func (ic *ContainerEngine) createServiceContainer(ctx context.Context, name stri return nil, fmt.Errorf("creating runtime spec for service container: %w", err) } opts = append(opts, libpod.WithIsService()) + opts = append(opts, libpod.WithSdNotifyMode(define.SdNotifyModeConmon)) // Create a new libpod container based on the spec. ctr, err := ic.Libpod.NewContainer(ctx, runtimeSpec, spec, false, opts...) @@ -75,6 +84,17 @@ func (ic *ContainerEngine) createServiceContainer(ctx context.Context, name stri return ctr, nil } +// Creates the name for a service container based on the provided content of a +// K8s yaml file. +func serviceContainerName(content []byte) string { + // The name of the service container is the first 12 + // characters of the yaml file's hash followed by the + // '-service' suffix to guarantee a predictable and + // discoverable name. + hash := digest.FromBytes(content).Encoded() + return hash[0:12] + "-service" +} + func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options entities.PlayKubeOptions) (_ *entities.PlayKubeReport, finalErr error) { report := &entities.PlayKubeReport{} validKinds := 0 @@ -112,12 +132,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options // TODO: create constants for the various "kinds" of yaml files. var serviceContainer *libpod.Container if options.ServiceContainer && (kind == "Pod" || kind == "Deployment") { - // The name of the service container is the first 12 - // characters of the yaml file's hash followed by the - // '-service' suffix to guarantee a predictable and - // discoverable name. - hash := digest.FromBytes(content).Encoded() - ctr, err := ic.createServiceContainer(ctx, hash[0:12]+"-service") + ctr, err := ic.createServiceContainer(ctx, serviceContainerName(content), options) if err != nil { return nil, err } @@ -433,6 +448,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY podSpec.PodSpecGen.NoInfra = false podSpec.PodSpecGen.InfraContainerSpec = specgen.NewSpecGenerator(infraImage, false) podSpec.PodSpecGen.InfraContainerSpec.NetworkOptions = p.NetworkOptions + podSpec.PodSpecGen.InfraContainerSpec.SdNotifyMode = define.SdNotifyModeIgnore err = specgenutil.FillOutSpecGen(podSpec.PodSpecGen.InfraContainerSpec, &infraOptions, []string{}) if err != nil { @@ -516,10 +532,12 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY if err != nil { return nil, err } + specGen.SdNotifyMode = define.SdNotifyModeIgnore rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen, false, nil) if err != nil { return nil, err } + opts = append(opts, libpod.WithSdNotifyMode(define.SdNotifyModeIgnore)) ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...) if err != nil { return nil, err @@ -570,6 +588,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY if err != nil { return nil, err } + opts = append(opts, libpod.WithSdNotifyMode(define.SdNotifyModeIgnore)) ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...) if err != nil { return nil, err @@ -942,5 +961,6 @@ func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, _ e if err != nil { return nil, err } + return reports, nil } diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 17df0e3f8..10f3e70b1 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -216,9 +216,9 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System Tag: stat.Tag, ImageID: stat.ID, Created: stat.Created, - Size: int64(stat.Size), - SharedSize: int64(stat.SharedSize), - UniqueSize: int64(stat.UniqueSize), + Size: stat.Size, + SharedSize: stat.SharedSize, + UniqueSize: stat.UniqueSize, Containers: stat.Containers, } dfImages = append(dfImages, &report) diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go b/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go index 9f76f9154..d05984dac 100644 --- a/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go +++ b/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go @@ -221,7 +221,7 @@ func (a int64Amount) AsCanonicalBytes(out []byte) (result []byte, exponent int32 exponent = int32(a.scale) amount, times := removeInt64Factors(mantissa, 10) - exponent += int32(times) + exponent += times // make sure exponent is a multiple of 3 var ok bool diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go b/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go index 965d2ccaf..dcc5df219 100644 --- a/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go +++ b/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go @@ -293,7 +293,7 @@ func ParseQuantity(str string) (Quantity, error) { switch { case exponent >= 0 && len(denom) == 0: // only handle positive binary numbers with the fast path - mantissa = int64(int64(mantissa) << uint64(exponent)) + mantissa <<= uint64(exponent) // 1Mi (2^20) has ~6 digits of decimal precision, so exponent*3/10 -1 is roughly the precision precision = 15 - int32(len(num)) - int32(float32(exponent)*3/10) - 1 default: @@ -313,7 +313,7 @@ func ParseQuantity(str string) (Quantity, error) { if err != nil { return Quantity{}, ErrNumeric } - if result, ok := int64Multiply(value, int64(mantissa)); ok { + if result, ok := int64Multiply(value, mantissa); ok { if !positive { result = -result } diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go index 8f83fc09b..ed2e5408d 100644 --- a/pkg/specgen/generate/config_linux.go +++ b/pkg/specgen/generate/config_linux.go @@ -327,7 +327,7 @@ func deviceFromPath(path string) (*spec.LinuxDevice, error) { var ( devType string mode = stat.Mode - devNumber = uint64(stat.Rdev) + devNumber = uint64(stat.Rdev) // nolint: unconvert m = os.FileMode(mode) ) diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index d8008b10b..cc376125f 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -303,8 +303,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error { if err := unix.Stat(k, &statT); err != nil { return err } - v.Major = (int64(unix.Major(uint64(statT.Rdev)))) - v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) + v.Major = (int64(unix.Major(uint64(statT.Rdev)))) // nolint: unconvert + v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) // nolint: unconvert if s.ResourceLimits.BlockIO == nil { s.ResourceLimits.BlockIO = new(spec.LinuxBlockIO) } @@ -317,8 +317,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error { if err := unix.Stat(k, &statT); err != nil { return err } - v.Major = (int64(unix.Major(uint64(statT.Rdev)))) - v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) + v.Major = (int64(unix.Major(uint64(statT.Rdev)))) // nolint: unconvert + v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) // nolint: unconvert s.ResourceLimits.BlockIO.ThrottleWriteBpsDevice = append(s.ResourceLimits.BlockIO.ThrottleWriteBpsDevice, v) } } @@ -328,8 +328,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error { if err := unix.Stat(k, &statT); err != nil { return err } - v.Major = (int64(unix.Major(uint64(statT.Rdev)))) - v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) + v.Major = (int64(unix.Major(uint64(statT.Rdev)))) // nolint: unconvert + v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) // nolint: unconvert s.ResourceLimits.BlockIO.ThrottleReadIOPSDevice = append(s.ResourceLimits.BlockIO.ThrottleReadIOPSDevice, v) } } @@ -339,8 +339,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error { if err := unix.Stat(k, &statT); err != nil { return err } - v.Major = (int64(unix.Major(uint64(statT.Rdev)))) - v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) + v.Major = (int64(unix.Major(uint64(statT.Rdev)))) // nolint: unconvert + v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) // nolint: unconvert s.ResourceLimits.BlockIO.ThrottleWriteIOPSDevice = append(s.ResourceLimits.BlockIO.ThrottleWriteIOPSDevice, v) } } diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index b77c00f50..081df0441 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -377,7 +377,7 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt if err := unix.Stat(k, &statT); err != nil { return nil, errors.Wrapf(err, "failed to inspect '%s' in --blkio-weight-device", k) } - g.AddLinuxResourcesBlockIOWeightDevice((int64(unix.Major(uint64(statT.Rdev)))), (int64(unix.Minor(uint64(statT.Rdev)))), *v.Weight) + g.AddLinuxResourcesBlockIOWeightDevice((int64(unix.Major(uint64(statT.Rdev)))), (int64(unix.Minor(uint64(statT.Rdev)))), *v.Weight) // nolint: unconvert } BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), s.Mask, s.Unmask, &g) diff --git a/podman.spec.rpkg b/podman.spec.rpkg index 937253918..c9127c2d9 100644 --- a/podman.spec.rpkg +++ b/podman.spec.rpkg @@ -13,17 +13,9 @@ %endif %if ! 0%{?gobuild:1} -%define gobuild(o:) GO111MODULE=off go build -buildmode pie -compiler gc -tags="rpm_crashtraceback ${BUILDTAGS:-}" -ldflags "${LDFLAGS:-} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \\n') -extldflags '-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld '" -a -v -x %{?**}; +%define gobuild(o:) go build -buildmode pie -compiler gc -tags="rpm_crashtraceback ${BUILDTAGS:-}" -ldflags "${LDFLAGS:-} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \\n') -extldflags '-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld '" -a -v -x %{?**}; %endif -%global provider github -%global provider_tld com -%global project containers -%global repo %{name} -# https://github.com/containers/%%{name} -%global import_path %{provider}.%{provider_tld}/%{project}/%{repo} -%global git0 https://%{import_path} - # git_dir_name returns repository name derived from remote Git repository URL Name: {{{ git_dir_name }}} @@ -156,8 +148,7 @@ connections as well. # This will invoke `make` command in the directory with the extracted sources. %build %set_build_flags -export GO111MODULE=off -export GOPATH=$(pwd)/_build:$(pwd) +%global gomodulesmode GO111MODULE=on export CGO_CFLAGS=$CFLAGS # These extra flags present in $CFLAGS have been skipped for now as they break the build CGO_CFLAGS=$(echo $CGO_CFLAGS | sed 's/-flto=auto//g') @@ -168,33 +159,26 @@ CGO_CFLAGS=$(echo $CGO_CFLAGS | sed 's/-specs=\/usr\/lib\/rpm\/redhat\/redhat-an export CGO_CFLAGS+=" -m64 -mtune=generic -fcf-protection=full" %endif -mkdir _build -pushd _build -mkdir -p src/%{provider}.%{provider_tld}/%{project} -ln -s ../../../../ src/%{import_path} -popd -ln -s vendor src - %if 0%{?rhel} rm -rf vendor/github.com/containers/storage/drivers/register/register_btrfs.go %endif # build date. FIXME: Makefile uses '/v2/libpod', that doesn't work here? -LDFLAGS="-X %{import_path}/libpod/define.buildInfo=$(date +%s)" +LDFLAGS="-X ./libpod/define.buildInfo=$(date +%s)" # build rootlessport first -%gobuild -o bin/rootlessport %{import_path}/cmd/rootlessport +%gobuild -o bin/rootlessport ./cmd/rootlessport # set base buildtags common to both %%{name} and %%{name}-remote export BASEBUILDTAGS="seccomp exclude_graphdriver_devicemapper $(hack/selinux_tag.sh) $(hack/systemd_tag.sh) $(hack/libsubid_tag.sh)" # build %%{name} export BUILDTAGS="$BASEBUILDTAGS $(hack/btrfs_installed_tag.sh) $(hack/btrfs_tag.sh)" -%gobuild -o bin/%{name} %{import_path}/cmd/%{name} +%gobuild -o bin/%{name} ./cmd/%{name} # build %%{name}-remote export BUILDTAGS="$BASEBUILDTAGS exclude_graphdriver_btrfs btrfs_noversion remote" -%gobuild -o bin/%{name}-remote %{import_path}/cmd/%{name} +%gobuild -o bin/%{name}-remote ./cmd/%{name} make docs docker-docs @@ -242,11 +226,13 @@ done %{_unitdir}/%{name}.service %{_unitdir}/%{name}.socket %{_unitdir}/%{name}-restart.service +%{_unitdir}/%{name}-play-kube@.service %{_userunitdir}/%{name}-auto-update.service %{_userunitdir}/%{name}-auto-update.timer %{_userunitdir}/%{name}.service %{_userunitdir}/%{name}.socket %{_userunitdir}/%{name}-restart.service +%{_userunitdir}/%{name}-play-kube@.service %{_tmpfilesdir}/%{name}.conf %if 0%{?fedora} >= 36 %{_modulesloaddir}/%{name}-iptables.conf diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at index a994f8e11..fd04e3f1b 100644 --- a/test/apiv2/10-images.at +++ b/test/apiv2/10-images.at @@ -156,6 +156,17 @@ t GET images/json?filters='{"reference":["test1"]}' 200 length=1 t DELETE libpod/images/test1:latest 200 +# to be used in prune until filter tests +podman image build -t docker.io/library/test1:latest -<<EOF +from alpine +RUN >file4 +EOF +podman create --name test1 test1 echo hi + +t DELETE images/test1:latest 409 +podman rm test1 +t DELETE images/test1:latest 200 + t GET "images/get?names=alpine" 200 '[POSIX tar archive]' podman pull busybox diff --git a/test/e2e/login_logout_test.go b/test/e2e/login_logout_test.go index bce8b78c6..3ae130c6d 100644 --- a/test/e2e/login_logout_test.go +++ b/test/e2e/login_logout_test.go @@ -142,7 +142,7 @@ var _ = Describe("Podman login and logout", func() { defer registriesConf.Close() defer os.Remove(registriesConf.Name()) - err = ioutil.WriteFile(registriesConf.Name(), []byte(registriesConfWithSearch), os.ModePerm) + err = ioutil.WriteFile(registriesConf.Name(), registriesConfWithSearch, os.ModePerm) Expect(err).To(BeNil()) // Environment is per-process, so this looks very unsafe; actually it seems fine because tests are not diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go index c67a4baed..715455521 100644 --- a/test/e2e/network_test.go +++ b/test/e2e/network_test.go @@ -475,7 +475,7 @@ var _ = Describe("Podman network", func() { defer podmanTest.removeNetwork(netName) Expect(session).Should(Exit(0)) - interval := time.Duration(250 * time.Millisecond) + interval := 250 * time.Millisecond for i := 0; i < 6; i++ { n := podmanTest.Podman([]string{"network", "exists", netName}) n.WaitWithDefaultTimeout() @@ -490,7 +490,7 @@ var _ = Describe("Podman network", func() { top := podmanTest.Podman([]string{"run", "-dt", "--name=web", "--network=" + netName, "--network-alias=web1", "--network-alias=web2", nginx}) top.WaitWithDefaultTimeout() Expect(top).Should(Exit(0)) - interval = time.Duration(250 * time.Millisecond) + interval = 250 * time.Millisecond // Wait for the nginx service to be running for i := 0; i < 6; i++ { // Test curl against the container's name @@ -526,7 +526,7 @@ var _ = Describe("Podman network", func() { defer podmanTest.removeNetwork(netName) Expect(session).Should(Exit(0)) - interval := time.Duration(250 * time.Millisecond) + interval := 250 * time.Millisecond for i := 0; i < 6; i++ { n := podmanTest.Podman([]string{"network", "exists", netName}) n.WaitWithDefaultTimeout() @@ -541,7 +541,7 @@ var _ = Describe("Podman network", func() { top := podmanTest.Podman([]string{"run", "-dt", "--name=web", "--network=" + netName, "--network-alias=web1", "--network-alias=web2", nginx}) top.WaitWithDefaultTimeout() Expect(top).Should(Exit(0)) - interval = time.Duration(250 * time.Millisecond) + interval = 250 * time.Millisecond // Wait for the nginx service to be running for i := 0; i < 6; i++ { // Test curl against the container's name diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index c9990b70f..3b32b4b82 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -731,7 +731,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) linkAttr.Name = name m, err := net.ParseMAC(mac) Expect(err).To(BeNil()) - linkAttr.HardwareAddr = net.HardwareAddr(m) + linkAttr.HardwareAddr = m eth := &netlink.Dummy{LinkAttrs: linkAttr} err = netlink.LinkAdd(eth) Expect(err).To(BeNil()) diff --git a/test/e2e/system_df_test.go b/test/e2e/system_df_test.go index ba4a40ab4..5a23fc0bb 100644 --- a/test/e2e/system_df_test.go +++ b/test/e2e/system_df_test.go @@ -66,7 +66,7 @@ var _ = Describe("podman system df", func() { images := strings.Fields(session.OutputToStringArray()[1]) containers := strings.Fields(session.OutputToStringArray()[2]) volumes := strings.Fields(session.OutputToStringArray()[3]) - Expect(images[1]).To(Equal(string(totImages)), "total images expected") + Expect(images[1]).To(Equal(totImages), "total images expected") Expect(containers[1]).To(Equal("2"), "total containers expected") Expect(volumes[2]).To(Equal("2"), "total volumes expected") Expect(volumes[6]).To(Equal("(50%)"), "percentage usage expected") diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats index d0da654ad..567fa89c1 100644 --- a/test/system/250-systemd.bats +++ b/test/system/250-systemd.bats @@ -292,4 +292,80 @@ LISTEN_FDNAMES=listen_fdnames" | sort) run_podman network rm -f $netname } +@test "podman-play-kube@.service template" { + skip_if_remote "systemd units do not work with remote clients" + + # If running from a podman source directory, build and use the source + # version of the play-kube-@ unit file + unit_name="podman-play-kube@.service" + unit_file="contrib/systemd/system/${unit_name}" + if [[ -e ${unit_file}.in ]]; then + echo "# [Building & using $unit_name from source]" >&3 + BINDIR=$(dirname $PODMAN) make $unit_file + cp $unit_file $UNIT_DIR/$unit_name + fi + + # Create the YAMl file + yaml_source="$PODMAN_TMPDIR/test.yaml" + cat >$yaml_source <<EOF +apiVersion: v1 +kind: Pod +metadata: + labels: + app: test + name: test_pod +spec: + containers: + - command: + - top + image: $IMAGE + name: test + resources: {} +EOF + + # Dispatch the YAML file + service_name="podman-play-kube@$(systemd-escape $yaml_source).service" + systemctl start $service_name + systemctl is-active $service_name + + # The name of the service container is predictable: the first 12 characters + # of the hash of the YAML file followed by the "-service" suffix + yaml_sha=$(sha256sum $yaml_source) + service_container="${yaml_sha:0:12}-service" + + # Make sure that the service container exists and runs. + run_podman container inspect $service_container --format "{{.State.Running}}" + is "$output" "true" + + # Check for an error when trying to remove the service container + run_podman 125 container rm $service_container + is "$output" "Error: container .* is the service container of pod(s) .* and cannot be removed without removing the pod(s)" + + # Kill the pod and make sure the service is not running. + # The restart policy is set to "never" since there is no + # design yet for propagating exit codes up to the service + # container. + run_podman pod kill test_pod + for i in {0..5}; do + run systemctl is-failed $service_name + if [[ $output == "failed" ]]; then + break + fi + sleep 0.5 + done + is "$output" "failed" "systemd service transitioned to 'failed' state" + + # Now stop and start the service again. + systemctl stop $service_name + systemctl start $service_name + systemctl is-active $service_name + run_podman container inspect $service_container --format "{{.State.Running}}" + is "$output" "true" + + # Clean up + systemctl stop $service_name + run_podman 1 container exists $service_container + run_podman 1 pod exists test_pod +} + # vim: filetype=sh diff --git a/test/system/260-sdnotify.bats b/test/system/260-sdnotify.bats index 88d84c86f..59456de24 100644 --- a/test/system/260-sdnotify.bats +++ b/test/system/260-sdnotify.bats @@ -172,4 +172,52 @@ READY=1" "sdnotify sent MAINPID and READY" _stop_socat } +@test "sdnotify : play kube" { + # Create the YAMl file + yaml_source="$PODMAN_TMPDIR/test.yaml" + cat >$yaml_source <<EOF +apiVersion: v1 +kind: Pod +metadata: + labels: + app: test + name: test_pod +spec: + containers: + - command: + - top + image: $IMAGE + name: test + resources: {} +EOF + + # The name of the service container is predictable: the first 12 characters + # of the hash of the YAML file followed by the "-service" suffix + yaml_sha=$(sha256sum $yaml_source) + service_container="${yaml_sha:0:12}-service" + + + export NOTIFY_SOCKET=$PODMAN_TMPDIR/conmon.sock + _start_socat + + run_podman play kube --service-container=true $yaml_source + run_podman container inspect $service_container --format "{{.State.ConmonPid}}" + mainPID="$output" + # The 'echo's help us debug failed runs + run cat $_SOCAT_LOG + echo "socat log:" + echo "$output" + + is "$output" "MAINPID=$mainPID +READY=1" "sdnotify sent MAINPID and READY" + + _stop_socat + + # Clean up pod and pause image + run_podman play kube --down $PODMAN_TMPDIR/test.yaml + run_podman version --format "{{.Server.Version}}-{{.Server.Built}}" + podman rmi -f localhost/podman-pause:$output +} + + # vim: filetype=sh diff --git a/test/system/700-play.bats b/test/system/700-play.bats index 2e5327a85..6c2a8c8b1 100644 --- a/test/system/700-play.bats +++ b/test/system/700-play.bats @@ -103,10 +103,9 @@ RELABEL="system_u:object_r:container_file_t:s0" @test "podman play --service-container" { skip_if_remote "service containers only work locally" - TESTDIR=$PODMAN_TMPDIR/testdir - mkdir -p $TESTDIR - -yaml=" + # Create the YAMl file + yaml_source="$PODMAN_TMPDIR/test.yaml" + cat >$yaml_source <<EOF apiVersion: v1 kind: Pod metadata: @@ -120,13 +119,16 @@ spec: image: $IMAGE name: test resources: {} -" +EOF + run_podman play kube --service-container=true $yaml_source - echo "$yaml" > $PODMAN_TMPDIR/test.yaml - run_podman play kube --service-container=true $PODMAN_TMPDIR/test.yaml + # The name of the service container is predictable: the first 12 characters + # of the hash of the YAML file followed by the "-service" suffix + yaml_sha=$(sha256sum $yaml_source) + service_container="${yaml_sha:0:12}-service" # Make sure that the service container exists and runs. - run_podman container inspect "352a88685060-service" --format "{{.State.Running}}" + run_podman container inspect $service_container --format "{{.State.Running}}" is "$output" "true" # Stop the *main* container and make sure that @@ -135,24 +137,26 @@ spec: # #) The service container is marked as an service container run_podman stop test_pod-test _ensure_pod_state test_pod Exited - run_podman container inspect "352a88685060-service" --format "{{.State.Running}}" - is "$output" "false" - run_podman container inspect "352a88685060-service" --format "{{.IsService}}" + _ensure_container_running $service_container false + run_podman container inspect $service_container --format "{{.IsService}}" is "$output" "true" # Restart the pod, make sure the service is running again run_podman pod restart test_pod - run_podman container inspect "352a88685060-service" --format "{{.State.Running}}" + run_podman container inspect $service_container --format "{{.State.Running}}" is "$output" "true" + # Check for an error when trying to remove the service container + run_podman 125 container rm $service_container + is "$output" "Error: container .* is the service container of pod(s) .* and cannot be removed without removing the pod(s)" + # Kill the pod and make sure the service is not running run_podman pod kill test_pod - run_podman container inspect "352a88685060-service" --format "{{.State.Running}}" - is "$output" "false" + _ensure_container_running $service_container false # Remove the pod and make sure the service is removed along with it run_podman pod rm test_pod - run_podman 1 container exists "352a88685060-service" + run_podman 1 container exists $service_container } @test "podman play --network" { diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 072131202..6868f2691 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -405,6 +405,19 @@ function _ensure_pod_state() { is "$output" "$2" "unexpected pod state" } +# Wait for the container's (1st arg) running state (2nd arg) +function _ensure_container_running() { + for i in {0..5}; do + run_podman container inspect $1 --format "{{.State.Running}}" + if [[ $output == "$2" ]]; then + break + fi + sleep 0.5 + done + + is "$output" "$2" "unexpected pod state" +} + ########################### # _add_label_if_missing # make sure skip messages include rootless/remote ########################### diff --git a/utils/utils.go b/utils/utils.go index d0e3dbb46..fd66ac2ed 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -192,7 +192,7 @@ func moveProcessPIDFileToScope(pidPath, slice, scope string) error { } func moveProcessToScope(pid int, slice, scope string) error { - err := RunUnderSystemdScope(int(pid), slice, scope) + err := RunUnderSystemdScope(pid, slice, scope) // If the PID is not valid anymore, do not return an error. if dbusErr, ok := err.(dbus.Error); ok { if dbusErr.Name == "org.freedesktop.DBus.Error.UnixProcessIdUnknown" { |