diff options
172 files changed, 1590 insertions, 715 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 968854771..9897a9f7f 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -637,6 +637,33 @@ rootless_system_test_task: main_script: *main always: *logs_artifacts +rootless_gitlab_test_task: + name: *std_name_fmt + alias: rootless_gitlab_test + skip: *tags + only_if: *not_docs + # Community-maintained downstream test may fail unexpectedly. + # Ref. repository: https://gitlab.com/gitlab-org/gitlab-runner + # If necessary, uncomment the next line and file issue(s) with details. + # allow_failures: $CI == $CI + depends_on: + - rootless_integration_test + gce_instance: *standardvm + env: + <<: *ubuntu_envvars + TEST_FLAVOR: 'gitlab' + PRIV_NAME: rootless + clone_script: *noop # Comes from cache + gopath_cache: *ro_gopath_cache + setup_script: *setup + main_script: *main + always: + <<: *logs_artifacts + junit_artifacts: + path: gitlab-runner-podman.xml + type: text/xml + format: junit + upgrade_test_task: name: "Upgrade test: from $PODMAN_UPGRADE_FROM" alias: upgrade_test @@ -720,6 +747,7 @@ success_task: - local_system_test - remote_system_test - rootless_system_test + - rootless_gitlab_test - upgrade_test - buildah_bud_test - meta diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 568cf7240..f5f0b21be 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,41 @@ <!-- Thanks for sending a pull request! -Please make sure you've read our contributing guidelines and how to submit a pull request (https://github.com/containers/podman/blob/master/CONTRIBUTING.md#submitting-pull-requests). +Please make sure you've read our contributing guidelines and how to submit a pull request (https://github.com/containers/podman/blob/main/CONTRIBUTING.md#submitting-pull-requests). In case you're only changing docs, make sure to prefix the pull-request title with "[CI:DOCS]". That will prevent functional tests from running and save time and energy. + +Finally, be sure to sign commits with your real name. Since by opening +a PR you already have commits, you can add signatures if needed with +something like `git commit -s --amend`. --> + +#### What this PR does / why we need it: + +<!--- +Please put your overall PR description here +--> + +#### How to verify it + +<!--- +Please specify the precise conditions and/or the specific test(s) which must pass. +--> + +#### Which issue(s) this PR fixes: + +<!-- +Please uncomment this block and include only one of the following on a +line by itself: + +None + +-OR- + +Fixes #<issue number> + +*** Please also put 'Fixes #' in the commit and PR description*** + +--> + +#### Special notes for your reviewer: @@ -23,6 +23,7 @@ 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) COVERAGE_PATH ?= .coverage DESTDIR ?= @@ -244,11 +245,11 @@ gofmt: ## Verify the source code gofmt .PHONY: test/checkseccomp/checkseccomp test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go) - $(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp + $(GOCMD) build $(BUILDFLAGS) $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp .PHONY: test/testvol/testvol test/testvol/testvol: .gopathok $(wildcard test/testvol/*.go) - $(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol + $(GOCMD) build $(BUILDFLAGS) $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol .PHONY: volume-plugin-test-image volume-plugin-test-img: @@ -256,7 +257,7 @@ volume-plugin-test-img: .PHONY: test/goecho/goecho test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go) - $(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho + $(GOCMD) build $(BUILDFLAGS) $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho test/version/version: .gopathok version/version.go $(GO) build -o $@ ./test/version/ @@ -299,7 +300,7 @@ ifeq (,$(findstring systemd,$(BUILDTAGS))) endif $(GOCMD) build \ $(BUILDFLAGS) \ - -ldflags '$(LDFLAGS_PODMAN)' \ + $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' \ -tags "$(BUILDTAGS)" \ -o $@ ./cmd/podman @@ -310,14 +311,14 @@ $(SRCBINDIR): $(SRCBINDIR)/podman$(BINSFX): $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum $(GOCMD) build \ $(BUILDFLAGS) \ - -ldflags '$(LDFLAGS_PODMAN)' \ + $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' \ -tags "${REMOTETAGS}" \ -o $@ ./cmd/podman $(SRCBINDIR)/podman-remote-static: $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum $(GOCMD) build \ $(BUILDFLAGS) \ - -ldflags '$(LDFLAGS_PODMAN_STATIC)' \ + $(GO_LDFLAGS) '$(LDFLAGS_PODMAN_STATIC)' \ -tags "${REMOTETAGS}" \ -o $@ ./cmd/podman @@ -372,7 +373,7 @@ bin/podman.cross.%: .gopathok CGO_ENABLED=0 \ $(GO) build \ $(BUILDFLAGS) \ - -ldflags '$(LDFLAGS_PODMAN)' \ + $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' \ -tags '$(BUILDTAGS_CROSS)' \ -o "$@" ./cmd/podman @@ -411,9 +412,9 @@ completions: podman podman-remote declare -A outfiles=([bash]=%s [zsh]=_%s [fish]=%s.fish [powershell]=%s.ps1);\ for shell in $${!outfiles[*]}; do \ for remote in "" "-remote"; do \ - podman="podman$$remote"; \ - outfile=$$(printf "completions/$$shell/$${outfiles[$$shell]}" $$podman); \ - ./bin/$$podman completion $$shell >| $$outfile; \ + podman="podman$$remote"; \ + outfile=$$(printf "completions/$$shell/$${outfiles[$$shell]}" $$podman); \ + ./bin/$$podman completion $$shell >| $$outfile; \ done;\ done @@ -431,10 +432,10 @@ $(MANPAGES): %: %.md .install.md2man docdir ### this ensures that manpages are renderd correctly @sed -e 's/\((podman[^)]*\.md\(#.*\)\?)\)//g' \ - -e 's/\[\(podman[^]]*\)\]/\1/g' \ + -e 's/\[\(podman[^]]*\)\]/\1/g' \ -e 's/\[\([^]]*\)](http[^)]\+)/\1/g' \ - -e 's;<\(/\)\?\(a\|a\s\+[^>]*\|sup\)>;;g' \ - -e 's/\\$$/ /g' $< | \ + -e 's;<\(/\)\?\(a\|a\s\+[^>]*\|sup\)>;;g' \ + -e 's/\\$$/ /g' $< | \ $(GOMD2MAN) -in /dev/stdin -out $(subst source/markdown,build/man,$@) .PHONY: docdir @@ -671,7 +672,7 @@ podman-v$(RELEASE_NUMBER).msi: podman-remote-windows podman-remote-windows-docs --directory-ref INSTALLDIR --prefix $(DOCFILE)/ > \ $(DOCFILE)/pages.wsx wixl -D VERSION=$(call err_if_empty,RELEASE_VERSION) -D ManSourceDir=$(DOCFILE) \ - -o $@ contrib/msi/podman.wxs $(DOCFILE)/pages.wsx + -o $@ contrib/msi/podman.wxs $(DOCFILE)/pages.wsx --arch x64 .PHONY: package package: ## Build rpm packages @@ -758,6 +759,8 @@ install.docker: install.docker-docs-nobuild: install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man1 install ${SELINUXOPT} -m 644 docs/build/man/docker*.1 -t $(DESTDIR)$(MANDIR)/man1 + install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man5 + install ${SELINUXOPT} -m 644 docs/build/man/docker*.5 -t $(DESTDIR)$(MANDIR)/man5 .PHONY: install.docker-docs install.docker-docs: docker-docs install.docker-docs-nobuild @@ -808,7 +811,7 @@ install.tools: .install.goimports .install.gitvalidation .install.md2man .instal .PHONY: .install.golangci-lint .install.golangci-lint: .gopathok - VERSION=1.36.0 GOBIN=$(GOBIN) sh ./hack/install_golangci.sh + VERSION=1.36.0 GOBIN=$(GOBIN) ./hack/install_golangci.sh .PHONY: .install.bats .install.bats: .gopathok diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index 2ea5fa10f..90522438d 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -194,21 +194,14 @@ func getImages(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellComp } else { // suggested "registry.fedoraproject.org/f29/httpd:latest" as // - "registry.fedoraproject.org/f29/httpd:latest" - // - "registry.fedoraproject.org/f29/httpd" // - "f29/httpd:latest" - // - "f29/httpd" // - "httpd:latest" - // - "httpd" paths := strings.Split(repo, "/") for i := range paths { suggestionWithTag := strings.Join(paths[i:], "/") if strings.HasPrefix(suggestionWithTag, toComplete) { suggestions = append(suggestions, suggestionWithTag) } - suggestionWithoutTag := strings.SplitN(strings.SplitN(suggestionWithTag, ":", 2)[0], "@", 2)[0] - if strings.HasPrefix(suggestionWithoutTag, toComplete) { - suggestions = append(suggestions, suggestionWithoutTag) - } } } } 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 afb8edd91..9687cd5bd 100644 --- a/cmd/podman/containers/ps.go +++ b/cmd/podman/containers/ps.go @@ -375,6 +375,10 @@ func (l psReporter) State() string { // Status is a synonym for State() func (l psReporter) Status() string { + hc := l.ListContainer.Status + if hc != "" { + return l.State() + " (" + hc + ")" + } return l.State() } diff --git a/cmd/podman/generate/generate.go b/cmd/podman/generate/generate.go index 6b48a342e..a42aa9f21 100644 --- a/cmd/podman/generate/generate.go +++ b/cmd/podman/generate/generate.go @@ -11,7 +11,7 @@ var ( // Command: podman _generate_ generateCmd = &cobra.Command{ Use: "generate", - Short: "Generate structured data based on containers, pods or volumes.", + Short: "Generate structured data based on containers, pods or volumes", Long: "Generate structured data (e.g., Kubernetes YAML or systemd units) based on containers, pods or volumes.", RunE: validate.SubCommandExists, } 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/prune.go b/cmd/podman/images/prune.go index 8a484495a..6c39e5c69 100644 --- a/cmd/podman/images/prune.go +++ b/cmd/podman/images/prune.go @@ -41,6 +41,7 @@ func init() { flags := pruneCmd.Flags() flags.BoolVarP(&pruneOpts.All, "all", "a", false, "Remove all images not in use by containers, not just dangling ones") + flags.BoolVarP(&pruneOpts.External, "external", "", false, "Remove images even when they are used by external containers (e.g., by build containers)") flags.BoolVarP(&force, "force", "f", false, "Do not prompt for confirmation") filterFlagName := "filter" @@ -80,7 +81,7 @@ func prune(cmd *cobra.Command, args []string) error { func createPruneWarningMessage(pruneOpts entities.ImagePruneOptions) string { question := "Are you sure you want to continue? [y/N] " if pruneOpts.All { - return "WARNING! This will remove all images without at least one container associated to them.\n" + question + return "WARNING! This command removes all images without at least one container associated with them.\n" + question } - return "WARNING! This will remove all dangling images.\n" + question + return "WARNING! This command removes all dangling images.\n" + question } 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 19f31d1a6..adde887f7 100644 --- a/cmd/podman/machine/init.go +++ b/cmd/podman/machine/init.go @@ -42,7 +42,7 @@ func init() { cpusFlagName := "cpus" flags.Uint64Var( &initOpts.CPUS, - cpusFlagName, 1, + cpusFlagName, cfg.Machine.CPUs, "Number of CPUs", ) _ = initCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone) @@ -50,7 +50,7 @@ func init() { diskSizeFlagName := "disk-size" flags.Uint64Var( &initOpts.DiskSize, - diskSizeFlagName, 10, + diskSizeFlagName, cfg.Machine.DiskSize, "Disk size in GB", ) @@ -59,7 +59,7 @@ func init() { memoryFlagName := "memory" flags.Uint64VarP( &initOpts.Memory, - memoryFlagName, "m", 2048, + memoryFlagName, "m", cfg.Machine.Memory, "Memory in MB", ) _ = initCmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone) @@ -71,7 +71,7 @@ func init() { ) ImagePathFlagName := "image-path" - flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Engine.MachineImage, "Path to qcow image") + flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Machine.Image, "Path to qcow image") _ = initCmd.RegisterFlagCompletionFunc(ImagePathFlagName, completion.AutocompleteDefault) IgnitionPathFlagName := "ignition-path" diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go index d4360bb9b..95b7d860f 100644 --- a/cmd/podman/machine/list.go +++ b/cmd/podman/machine/list.go @@ -3,13 +3,16 @@ package machine import ( + "encoding/json" "os" "sort" + "strconv" "time" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/report" + "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/pkg/machine" @@ -40,10 +43,15 @@ type listFlagType struct { } type machineReporter struct { - Name string - Created string - LastUp string - VMType string + Name string + Default bool + Created string + Running bool + LastUp string + VMType string + CPUs uint64 + Memory string + DiskSize string } func init() { @@ -54,8 +62,8 @@ 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") - _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, completion.AutocompleteNone) + flags.StringVar(&listFlag.format, formatFlagName, "{{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\t{{.CPUs}}\t{{.Memory}}\t{{.DiskSize}}\n", "Format volume output using JSON or a Go template") + _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(machineReporter{})) flags.BoolVar(&listFlag.noHeading, "noheading", false, "Do not print headers") } @@ -75,6 +83,21 @@ func list(cmd *cobra.Command, args []string) error { sort.Slice(listResponse, func(i, j int) bool { return listResponse[i].Running }) + + if report.IsJSON(listFlag.format) { + machineReporter, err := toMachineFormat(listResponse) + if err != nil { + return err + } + + b, err := json.Marshal(machineReporter) + if err != nil { + return err + } + os.Stdout.Write(b) + return nil + } + machineReporter, err := toHumanFormat(listResponse) if err != nil { return err @@ -85,8 +108,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) @@ -115,6 +141,42 @@ func outputTemplate(cmd *cobra.Command, responses []*machineReporter) error { return tmpl.Execute(w, responses) } +func strTime(t time.Time) string { + iso, err := t.MarshalText() + if err != nil { + return "" + } + return string(iso) +} + +func strUint(u uint64) string { + return strconv.FormatUint(u, 10) +} + +func toMachineFormat(vms []*machine.ListResponse) ([]*machineReporter, error) { + cfg, err := config.ReadCustomConfig() + if err != nil { + return nil, err + } + + machineResponses := make([]*machineReporter, 0, len(vms)) + for _, vm := range vms { + response := new(machineReporter) + response.Default = vm.Name == cfg.Engine.ActiveService + response.Name = vm.Name + response.Running = vm.Running + response.LastUp = strTime(vm.LastUp) + response.Created = strTime(vm.CreatedAt) + response.VMType = vm.VMType + response.CPUs = vm.CPUs + response.Memory = strUint(vm.Memory * units.MiB) + response.DiskSize = strUint(vm.DiskSize * units.GiB) + + machineResponses = append(machineResponses, response) + } + return machineResponses, nil +} + func toHumanFormat(vms []*machine.ListResponse) ([]*machineReporter, error) { cfg, err := config.ReadCustomConfig() if err != nil { @@ -136,6 +198,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/play/play.go b/cmd/podman/play/play.go index f121d6a2d..d676bd701 100644 --- a/cmd/podman/play/play.go +++ b/cmd/podman/play/play.go @@ -10,7 +10,7 @@ var ( // Command: podman _play_ playCmd = &cobra.Command{ Use: "play", - Short: "Play containers, pods or volumes from a structured file.", + Short: "Play containers, pods or volumes from a structured file", Long: "Play structured data (e.g., Kubernetes YAML) based on containers, pods or volumes.", RunE: validate.SubCommandExists, } diff --git a/cmd/podman/registry/config.go b/cmd/podman/registry/config.go index 50e488b02..b512ba341 100644 --- a/cmd/podman/registry/config.go +++ b/cmd/podman/registry/config.go @@ -89,12 +89,7 @@ func newPodmanConfig() { // use for the containers.conf configuration file. func setXdgDirs() error { if !rootless.IsRootless() { - // unset XDG_RUNTIME_DIR for root - // Sometimes XDG_RUNTIME_DIR is set to /run/user/0 sometimes it is unset, - // the inconsistency is causing issues for the dnsname plugin. - // It is already set to an empty string for conmon so lets do the same - // for podman. see #10806 and #10745 - return os.Unsetenv("XDG_RUNTIME_DIR") + return nil } // Setup XDG_RUNTIME_DIR diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 02e6dcd27..eb30f1ef6 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -92,6 +92,11 @@ func Execute() { if registry.GetExitCode() == 0 { registry.SetExitCode(define.ExecErrorCodeGeneric) } + if registry.IsRemote() { + if strings.Contains(err.Error(), "unable to connect to Podman") { + fmt.Fprintln(os.Stderr, "Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM") + } + } fmt.Fprintln(os.Stderr, formatError(err)) } os.Exit(registry.GetExitCode()) @@ -175,7 +180,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 +318,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 +392,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/prune.go b/cmd/podman/system/prune.go index e09e2d5e5..5565ea2f9 100644 --- a/cmd/podman/system/prune.go +++ b/cmd/podman/system/prune.go @@ -113,15 +113,15 @@ func prune(cmd *cobra.Command, args []string) error { func createPruneWarningMessage(pruneOpts entities.SystemPruneOptions) string { if pruneOpts.All { - return `WARNING! This will remove: + return `WARNING! This command removes: - all stopped containers - all networks not used by at least one container%s - - all images without at least one container associated to them + - all images without at least one container associated with them - all build cache %s` } - return `WARNING! This will remove: + return `WARNING! This command removes: - all stopped containers - all networks not used by at least one container%s - all dangling images diff --git a/cmd/podman/system/service.go b/cmd/podman/system/service.go index d6fe8837b..99a6b1e1e 100644 --- a/cmd/podman/system/service.go +++ b/cmd/podman/system/service.go @@ -74,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) @@ -120,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 128398c38..22a66dd08 100755 --- a/contrib/cirrus/runner.sh +++ b/contrib/cirrus/runner.sh @@ -286,6 +286,23 @@ function _run_release() { msg "All OK" } + +function _run_gitlab() { + rootless_uid=$(id -u) + systemctl enable --now --user podman.socket + export DOCKER_HOST=unix:///run/user/${rootless_uid}/podman/podman.sock + export CONTAINER_HOST=$DOCKER_HOST + cd $GOPATH/src/gitlab.com/gitlab-org/gitlab-runner + set +e + go test -v ./executors/docker |& tee $GOSRC/gitlab-runner-podman.log + ret=$? + set -e + # This file is collected and parsed by Cirrus-CI so must be in $GOSRC + cat $GOSRC/gitlab-runner-podman.log | \ + go-junit-report > $GOSRC/gitlab-runner-podman.xml + return $ret +} + logformatter() { if [[ "$CI" == "true" ]]; then # Use similar format as human-friendly task name from .cirrus.yml diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 41b155943..ef1f83024 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -243,6 +243,44 @@ case "$TEST_FLAVOR" in install_test_configs ;; + gitlab) + # This only runs on Ubuntu for now + if [[ "$OS_RELEASE_ID" != "ubuntu" ]]; then + die "This test only runs on Ubuntu due to sheer laziness" + fi + + # Ref: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27270#note_499585550 + + remove_packaged_podman_files + make install PREFIX=/usr ETCDIR=/etc + + # Need to re-build lists (removed during image production) + ooe.sh apt-get -qq -y update + msg "Installing previously downloaded/cached packages" + # N/B: Tests check/expect `docker info` output, and this `!= podman info` + ooe.sh apt-get install --yes --no-download --ignore-missing containerd.io docker-ce docker-ce-cli + + msg "Disabling docker service and socket activation" + systemctl stop docker.service docker.socket + systemctl disable docker.service docker.socket + rm -rf /run/docker* + # Guarantee the docker daemon can't be started, even by accident + rm -vf $(type -P dockerd) + + msg "Obtaining necessary gitlab-runner testing bits" + slug="gitlab.com/gitlab-org/gitlab-runner" + helper_fqin="registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helper:x86_64-latest-pwsh" + ssh="ssh $ROOTLESS_USER@localhost -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no env GOPATH=$GOPATH" + showrun $ssh go get -u github.com/jstemmer/go-junit-report + showrun $ssh git clone https://$slug $GOPATH/src/$slug + showrun $ssh make -C $GOPATH/src/$slug development_setup + showrun $ssh bash -c "'cd $GOPATH/src/$slug && GOPATH=$GOPATH go get .'" + + showrun $ssh podman pull $helper_fqin + # Tests expect image with this exact name + showrun $ssh podman tag $helper_fqin \ + docker.io/gitlab/gitlab-runner-helper:x86_64-latest-pwsh + ;; swagger) ;& # use next item consistency) make clean ;; release) ;; diff --git a/contrib/msi/podman.wxs b/contrib/msi/podman.wxs index 451dd565d..4136e2cc4 100644 --- a/contrib/msi/podman.wxs +++ b/contrib/msi/podman.wxs @@ -11,19 +11,19 @@ <Product Name="Podman $(var.VERSION)" Id="*" UpgradeCode="696BAB5D-CA1F-4B05-B123-320F245B8D6D" Version="$(var.VERSION)" Language="1033" Manufacturer="Red Hat Inc."> - <Package Id="*" Keywords="Installer" Description="Red Hat's Podman $(var.VERSION) Installer" Comments="Apache 2.0 License" Manufacturer="Red Hat Inc." InstallScope="perMachine" InstallerVersion="100" Compressed="yes"/> + <Package Id="*" Keywords="Installer" Description="Red Hat's Podman $(var.VERSION) Installer" Comments="Apache 2.0 License" Manufacturer="Red Hat Inc." InstallScope="perMachine" InstallerVersion="200" Compressed="yes"/> <Media Id="1" Cabinet="Podman.cab" EmbedCab="yes"/> <Property Id="DiskPrompt" Value="Red Hat's Podman $(var.VERSION) Installation"/> <Directory Id="TARGETDIR" Name="SourceDir"> - <Directory Id="ProgramFilesFolder" Name="PFiles"> + <Directory Id="ProgramFiles64Folder" Name="PFiles"> <Directory Id="RedHatPFiles" Name="RedHat"> <Directory Id="INSTALLDIR" Name="Podman"> - <Component Id="INSTALLDIR_Component" Guid="14B310C4-9B5D-4DA5-ADF9-B9D008E4CD82"> + <Component Id="INSTALLDIR_Component" Guid="14B310C4-9B5D-4DA5-ADF9-B9D008E4CD82" Win64="Yes"> <CreateFolder/> </Component> - <Component Id="MainExecutable" Guid="73752F94-6589-4C7B-ABED-39D655A19714"> + <Component Id="MainExecutable" Guid="73752F94-6589-4C7B-ABED-39D655A19714" Win64="Yes"> <File Id="520C6E17-77A2-4F41-9611-30FA763A0702" Name="podman.exe" Source="bin/windows/podman.exe" KeyPath="yes"/> </Component> </Directory> 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/dckrman.sh b/docs/dckrman.sh index c69524a7e..18fb364bf 100755 --- a/docs/dckrman.sh +++ b/docs/dckrman.sh @@ -4,3 +4,4 @@ for i in $@; do filename=$(echo $i | sed 's/podman/docker/g') echo .so man1/$b > $filename done +echo .so man5/containerfile.5 > $(dirname $1)/dockerfile.5 diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md index 98c8251b4..15d936d17 100644 --- a/docs/source/markdown/podman-build.1.md +++ b/docs/source/markdown/podman-build.1.md @@ -64,8 +64,10 @@ discarded when writing images in Docker formats. #### **--arch**=*arch* -Set the ARCH of the image to the provided value instead of the architecture of -the host. +Set the architecture of the image to be built, and that of the base image to be +pulled, if the build uses one, to the provided value instead of using the +architecture of the build host. (Examples: arm, arm64, 386, amd64, ppc64le, +s390x) #### **--authfile**=*path* @@ -321,7 +323,8 @@ Pass through HTTP Proxy environment variables. #### **--iidfile**=*ImageIDfile* -Write the image ID to the file. +Write the built image's ID to the file. When `--platform` is specified more +than once, attempting to use this option will trigger an error. #### **--ignorefile** @@ -389,6 +392,7 @@ Name of the manifest list to which the image will be added. Creates the manifest if it does not exist. This option is useful for building multi architecture images. #### **--memory**, **-m**=*LIMIT* + Memory limit (format: `<number>[<unit>]`, where unit = b (bytes), k (kilobytes), m (megabytes), or g (gigabytes)) @@ -430,8 +434,9 @@ with a new set of cached layers. #### **--os**=*string* -Set the OS to the provided value instead of the current operating system of the -host. +Set the OS of the image to be built, and that of the base image to be pulled, +if the build uses one, instead of using the current operating system of the +build host. #### **--pid**=*pid* @@ -442,11 +447,28 @@ that the PID namespace in which `podman` itself is being run should be reused, or it can be the path to a PID namespace which is already in use by another process. -#### **--platform**="Linux" +#### **--platform**="OS/ARCH[/VARIANT][,...]" + +Set the OS/ARCH of the built image (and its base image, if your build uses one) +to the provided value instead of using the current operating system and +architecture of the host (for example `linux/arm`). If `--platform` is set, +then the values of the `--arch`, `--os`, and `--variant` options will be +overridden. + +The `--platform` flag can be specified more than once, or given a +comma-separated list of values as its argument. When more than one platform is +specified, the `--manifest` option should be used instead of the `--tag` +option. + +OS/ARCH pairs are those used by the Go Programming Language. In several cases +the ARCH value for a platform differs from one produced by other tools such as +the `arch` command. Valid OS and architecture name combinations are listed as +values for $GOOS and $GOARCH at https://golang.org/doc/install/source#environment, +and can also be found by running `go tool dist list`. -This option has no effect on the build. Other container engines use this option -to control the execution platform for the build (e.g., Windows, Linux) which is -not required for Buildah as it supports only Linux. +While `podman build` is happy to use base images and build images for any +platform that exists, `RUN` instructions will not be able to succeed without +the help of emulation provided by packages like `qemu-user-static`. #### **--pull** @@ -486,7 +508,6 @@ commands specified by the **RUN** instruction. Note: You can also override the default runtime by setting the BUILDAH\_RUNTIME environment variable. `export BUILDAH_RUNTIME=/usr/local/bin/runc` - #### **--secret**=**id=id,src=path** Pass secret information to be used in the Containerfile for building images @@ -497,7 +518,6 @@ To later use the secret, use the --mount flag in a `RUN` instruction within a `C `RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret` - #### **--security-opt**=*option* Security Options @@ -697,7 +717,9 @@ process. #### **--variant**="" -Set the architecture variant of the image to be pulled. +Set the architecture variant of the image to be built, and that of the base +image to be pulled, if the build uses one, to the provided value instead of +using the architecture variant of the build host. #### **--volume**, **-v**[=*[HOST-DIR:CONTAINER-DIR[:OPTIONS]]*] @@ -858,7 +880,7 @@ $ podman build --layers --force-rm -t imageName . $ podman build --no-cache --rm=false -t imageName . ``` -### Building an multi-architecture image using a --manifest option (Requires emulation software) +### Building a multi-architecture image using the --manifest option (requires emulation software) ``` $ podman build --arch arm --manifest myimage /tmp/mysrc @@ -866,6 +888,10 @@ $ podman build --arch arm --manifest myimage /tmp/mysrc $ podman build --arch amd64 --manifest myimage /tmp/mysrc $ podman build --arch s390x --manifest myimage /tmp/mysrc + +$ podman build --platform linux/s390x,linux/ppc64le,linux/amd64 --manifest myimage /tmp/mysrc + +$ podman build --platform linux/arm64 --platform linux/amd64 --manifest myimage /tmp/mysrc ``` ### Building an image using a URL, Git repo, or archive diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index c3e2bbfca..f63f5ca9c 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -595,6 +595,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared + type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared,U=true + type=volume,source=vol1,destination=/path/in/container,ro=true type=tmpfs,tmpfs-size=512M,destination=/path/in/container @@ -613,6 +615,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and · ro, readonly: true or false (default). + . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container. + Options specific to image: · rw, readwrite: true or false (default). @@ -627,6 +631,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and . relabel: shared, private. + . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container. + Options specific to tmpfs: · ro, readonly: true or false (default). @@ -639,6 +645,7 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and · notmpcopyup: Disable copying files from the image to the tmpfs. + . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container. #### **--name**=*name* diff --git a/docs/source/markdown/podman-image-prune.1.md b/docs/source/markdown/podman-image-prune.1.md index bd08d18fc..493332ec0 100644 --- a/docs/source/markdown/podman-image-prune.1.md +++ b/docs/source/markdown/podman-image-prune.1.md @@ -17,6 +17,10 @@ The image prune command does not prune cache images that only use layers that ar Remove dangling images and images that have no associated containers. +#### **--external** + +Remove images even when they are used by external containers (e.g., build containers). + #### **--filter**=*filters* Provide filter values. diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md index 1236db602..f1fbd56ee 100644 --- a/docs/source/markdown/podman-machine-init.1.md +++ b/docs/source/markdown/podman-machine-init.1.md @@ -40,7 +40,7 @@ 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* diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index a369ce5ea..6d68fd62b 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -615,6 +615,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared + type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared,U=true + type=volume,source=vol1,destination=/path/in/container,ro=true type=tmpfs,tmpfs-size=512M,destination=/path/in/container @@ -633,6 +635,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and · ro, readonly: true or false (default). + . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container. + Options specific to image: · rw, readwrite: true or false (default). @@ -647,6 +651,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and . relabel: shared, private. + . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container. + Options specific to tmpfs: · ro, readonly: true or false (default). @@ -659,6 +665,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and · notmpcopyup: Disable copying files from the image to the tmpfs. + . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container. + #### **--name**=*name* Assign a name to the container. @@ -12,7 +12,7 @@ require ( 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.20210921143342-f2f10e650c73 + github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6 github.com/containers/conmon v2.0.20+incompatible github.com/containers/image/v5 v5.16.0 github.com/containers/ocicrypt v1.1.2 @@ -61,7 +61,6 @@ require ( github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 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.20210330154013-f5de75959ad5 go.etcd.io/bbolt v1.3.6 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 @@ -250,8 +250,8 @@ github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNB 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.20210921143342-f2f10e650c73 h1:+qKOyTHbuFo3GPsrUksphfHxYMIJQmPgwpDdQnARGAI= -github.com/containers/common v0.44.1-0.20210921143342-f2f10e650c73/go.mod h1:zxv7KjdYddSGoWuLUVp6eSb++Ow1zmSMB2jwxuNB4cU= +github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6 h1:DojkCc4a9f3WB25Fk0GDap1/OkKU9UmDLvPJyqw3TBc= +github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6/go.mod h1:L4+sJlqi+R7frlbiWBW0baPra/cH8u5ZYwbxkukw3Lk= 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= 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..1242a8d6b 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) @@ -1756,6 +1756,23 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName if err := allCtrsBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil { return errors.Wrapf(err, "error renaming container %s in all containers bucket in DB", ctr.ID()) } + if ctr.config.Pod != "" { + podsBkt, err := getPodBucket(tx) + if err != nil { + return err + } + podBkt := podsBkt.Bucket([]byte(ctr.config.Pod)) + if podBkt == nil { + return errors.Wrapf(define.ErrInternal, "bucket for pod %s does not exist", ctr.config.Pod) + } + podCtrBkt := podBkt.Bucket(containersBkt) + if podCtrBkt == nil { + return errors.Wrapf(define.ErrInternal, "pod %s does not have a containers bucket", ctr.config.Pod) + } + if err := podCtrBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil { + return errors.Wrapf(err, "error renaming container %s in pod %s members bucket", ctr.ID(), ctr.config.Pod) + } + } } } @@ -2556,7 +2573,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 +3369,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/container.go b/libpod/container.go index 5c56ff036..4d15c04c5 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -774,9 +774,9 @@ func (c *Container) ExecSessions() ([]string, error) { return ids, nil } -// ExecSession retrieves detailed information on a single active exec session in -// a container -func (c *Container) ExecSession(id string) (*ExecSession, error) { +// execSessionNoCopy returns the associated exec session to id. +// Note that the session is not a deep copy. +func (c *Container) execSessionNoCopy(id string) (*ExecSession, error) { if !c.batched { c.lock.Lock() defer c.lock.Unlock() @@ -791,6 +791,17 @@ func (c *Container) ExecSession(id string) (*ExecSession, error) { return nil, errors.Wrapf(define.ErrNoSuchExecSession, "no exec session with ID %s found in container %s", id, c.ID()) } + return session, nil +} + +// ExecSession retrieves detailed information on a single active exec session in +// a container +func (c *Container) ExecSession(id string) (*ExecSession, error) { + session, err := c.execSessionNoCopy(id) + if err != nil { + return nil, err + } + returnSession := new(ExecSession) if err := JSONDeepCopy(session, returnSession); err != nil { return nil, errors.Wrapf(err, "error copying contents of container %s exec session %s", c.ID(), session.ID()) @@ -1095,7 +1106,7 @@ func (c *Container) AutoRemove() bool { if spec.Annotations == nil { return false } - return c.Spec().Annotations[define.InspectAnnotationAutoremove] == define.InspectResponseTrue + return spec.Annotations[define.InspectAnnotationAutoremove] == define.InspectResponseTrue } // Timezone returns the timezone configured inside the container. 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_copy_linux.go b/libpod/container_copy_linux.go index a35824289..7d4dd0d46 100644 --- a/libpod/container_copy_linux.go +++ b/libpod/container_copy_linux.go @@ -174,7 +174,7 @@ func (c *Container) copyToArchive(ctx context.Context, path string, writer io.Wr // getContainerUser returns the specs.User and ID mappings of the container. func getContainerUser(container *Container, mountPoint string) (specs.User, error) { - userspec := container.Config().User + userspec := container.config.User uid, gid, _, err := chrootuser.GetUser(mountPoint, userspec) u := specs.User{ diff --git a/libpod/container_exec.go b/libpod/container_exec.go index 5d4bcb422..f99fb7d3f 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()) @@ -747,7 +747,7 @@ func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resi return -1, err } - session, err := c.ExecSession(sessionID) + session, err := c.execSessionNoCopy(sessionID) if err != nil { if errors.Cause(err) == define.ErrNoSuchExecSession { // TODO: If a proper Context is ever plumbed in here, we @@ -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 42d8da52d..ab79d82d9 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -156,7 +156,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver // An error here is not considered fatal; no health state will be displayed logrus.Error(err) } else { - data.State.Healthcheck = healthCheckState + data.State.Health = healthCheckState } } @@ -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 } diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 9ac2cd5bd..3f9738411 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) } @@ -923,12 +923,11 @@ func (c *Container) checkDependenciesRunning() ([]string, error) { } // Check the status - conf := depCtr.Config() state, err := depCtr.State() if err != nil { return nil, errors.Wrapf(err, "error retrieving state of dependency %s of container %s", dep, c.ID()) } - if state != define.ContainerStateRunning && !conf.IsInfra { + if state != define.ContainerStateRunning && !depCtr.config.IsInfra { notRunning = append(notRunning, dep) } depCtrs[dep] = depCtr @@ -1003,7 +1002,7 @@ func (c *Container) cniHosts() string { for _, status := range c.getNetworkStatus() { for _, netInt := range status.Interfaces { for _, netAddress := range netInt.Networks { - hosts += fmt.Sprintf("%s\t%s %s\n", netAddress.Subnet.IP.String(), c.Hostname(), c.Config().Name) + hosts += fmt.Sprintf("%s\t%s %s\n", netAddress.Subnet.IP.String(), c.Hostname(), c.config.Name) } } } @@ -1047,7 +1046,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 +1056,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 +1163,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 +1210,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 +1289,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 +1327,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 +1431,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 +1482,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 +1525,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 +1553,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 +1668,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 +1704,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 +1729,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 +1740,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 +1753,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 +1767,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 +1784,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 +1799,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 +1808,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 +1822,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 +1873,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) } @@ -2005,12 +2004,12 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s } return nil, err } - ociHooks, err := manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0) + ociHooks, err := manager.Hooks(config, c.config.Spec.Annotations, len(c.config.UserVolumes) > 0) if err != nil { 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 @@ -2022,7 +2021,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s return nil, err } - allHooks, err = manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0) + allHooks, err = manager.Hooks(config, c.config.Spec.Annotations, len(c.config.UserVolumes) > 0) if err != nil { return nil, err } @@ -2030,7 +2029,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) } @@ -2106,7 +2105,7 @@ func (c *Container) canWithPrevious() error { // JSON files for later export func (c *Container) prepareCheckpointExport() error { // save live config - if _, err := metadata.WriteJSONFile(c.Config(), c.bundlePath(), metadata.ConfigDumpFile); err != nil { + if _, err := metadata.WriteJSONFile(c.config, c.bundlePath(), metadata.ConfigDumpFile); err != nil { return err } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 0a663200a..867ecc2ad 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 @@ -599,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) } } } @@ -640,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 } @@ -781,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 } @@ -838,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) @@ -847,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 } @@ -1199,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) } } } @@ -1299,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 @@ -1310,7 +1310,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if err == nil && options.Name == "" && (!options.IgnoreStaticIP || !options.IgnoreStaticMAC) { // The file with the network.status does exist. Let's restore the // container with the same networks settings as during checkpointing. - aliases, err := c.runtime.state.GetAllNetworkAliases(c) + aliases, err := c.GetAllNetworkAliases() if err != nil { return err } @@ -1349,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) } } }() @@ -1903,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) } } @@ -1956,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...) } @@ -2058,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) } @@ -2109,12 +2109,12 @@ func (c *Container) getHosts() string { } else if c.config.NetMode.IsSlirp4netns() { gatewayIP, err := GetSlirp4netnsGateway(c.slirp4netnsSubnet) if err != nil { - logrus.Warn("failed to determine gatewayIP: ", err.Error()) + logrus.Warn("Failed to determine gatewayIP: ", err.Error()) } else { hosts += fmt.Sprintf("%s host.containers.internal\n", gatewayIP.String()) } } else { - logrus.Debug("network configuration does not support host.containers.internal address") + logrus.Debug("Network configuration does not support host.containers.internal address") } } 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_path_resolution.go b/libpod/container_path_resolution.go index ec7306ca1..bb2ef1a73 100644 --- a/libpod/container_path_resolution.go +++ b/libpod/container_path_resolution.go @@ -112,7 +112,7 @@ func (c *Container) resolvePath(mountPoint string, containerPath string) (string func findVolume(c *Container, containerPath string) (*Volume, error) { runtime := c.Runtime() cleanedContainerPath := filepath.Clean(containerPath) - for _, vol := range c.Config().NamedVolumes { + for _, vol := range c.config.NamedVolumes { if cleanedContainerPath == filepath.Clean(vol.Dest) { return runtime.GetVolume(vol.Name) } @@ -124,7 +124,7 @@ func findVolume(c *Container, containerPath string) (*Volume, error) { // Volume's destination. func isPathOnVolume(c *Container, containerPath string) bool { cleanedContainerPath := filepath.Clean(containerPath) - for _, vol := range c.Config().NamedVolumes { + for _, vol := range c.config.NamedVolumes { if cleanedContainerPath == filepath.Clean(vol.Dest) { return true } @@ -141,7 +141,7 @@ func isPathOnVolume(c *Container, containerPath string) bool { // path of a Mount. Returns a matching Mount or nil. func findBindMount(c *Container, containerPath string) *specs.Mount { cleanedPath := filepath.Clean(containerPath) - for _, m := range c.Config().Spec.Mounts { + for _, m := range c.config.Spec.Mounts { if m.Type != "bind" { continue } @@ -157,7 +157,7 @@ func findBindMount(c *Container, containerPath string) *specs.Mount { // Mount's destination. func isPathOnBindMount(c *Container, containerPath string) bool { cleanedContainerPath := filepath.Clean(containerPath) - for _, m := range c.Config().Spec.Mounts { + for _, m := range c.config.Spec.Mounts { if cleanedContainerPath == filepath.Clean(m.Destination) { return true } diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go index 90703a807..7decb18a8 100644 --- a/libpod/define/container_inspect.go +++ b/libpod/define/container_inspect.go @@ -202,10 +202,16 @@ type InspectContainerState struct { Error string `json:"Error"` // TODO StartedAt time.Time `json:"StartedAt"` FinishedAt time.Time `json:"FinishedAt"` - Healthcheck HealthCheckResults `json:"Healthcheck,omitempty"` + Health HealthCheckResults `json:"Health,omitempty"` Checkpointed bool `json:"Checkpointed,omitempty"` } +// Healthcheck returns the HealthCheckResults. This is used for old podman compat +// to make the "Healthcheck" key available in the go template. +func (s *InspectContainerState) Healthcheck() HealthCheckResults { + return s.Health +} + // HealthCheckResults describes the results/logs from a healthcheck type HealthCheckResults struct { // Status healthy or unhealthy 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/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 9b96dd99d..57d99f3ef 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" @@ -27,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 @@ -78,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 } @@ -88,7 +90,7 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) { // so set it at here for _, ctr := range allContainers { if !ctr.IsInfra() { - switch ctr.Config().RestartPolicy { + switch ctr.config.RestartPolicy { case define.RestartPolicyAlways: pod.Spec.RestartPolicy = v1.RestartPolicyAlways case define.RestartPolicyOnFailure: @@ -218,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)) @@ -239,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 } @@ -251,7 +253,9 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor // We add the original port declarations from the libpod infra container // to the first kubernetes container description because otherwise we loose // the original container/port bindings. - if first && len(ports) > 0 { + // Add the port configuration to the first regular container or the first + // init container if only init containers have been created in the pod. + if first && len(ports) > 0 && (!isInit || len(containers) == 2) { ctr.Ports = ports first = false } @@ -267,7 +271,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 } @@ -337,7 +341,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) @@ -355,7 +359,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 } @@ -411,7 +415,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) @@ -422,7 +426,7 @@ func containerToV1Container(c *Container) (v1.Container, []v1.Volume, *v1.PodDNS // NOTE: a privileged container mounts all of /dev/*. if !c.Privileged() && len(c.config.Spec.Linux.Devices) > 0 { // TODO Enable when we can support devices and their names - kubeContainer.VolumeDevices = generateKubeVolumeDeviceFromLinuxDevice(c.Spec().Linux.Devices) + kubeContainer.VolumeDevices = generateKubeVolumeDeviceFromLinuxDevice(c.config.Spec.Linux.Devices) return kubeContainer, kubeVolumes, nil, errors.Wrapf(define.ErrNotImplemented, "linux devices") } @@ -463,6 +467,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 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 7a73b874a..93d871767 100644 --- a/libpod/network/cni/cni_conversion.go +++ b/libpod/network/cni/cni_conversion.go @@ -104,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) } diff --git a/libpod/network/cni/cni_exec.go b/libpod/network/cni/cni_exec.go index c4d7f49f7..ae857bcfb 100644 --- a/libpod/network/cni/cni_exec.go +++ b/libpod/network/cni/cni_exec.go @@ -30,6 +30,7 @@ import ( "github.com/containernetworking/cni/pkg/invoke" "github.com/containernetworking/cni/pkg/version" + "github.com/containers/podman/v3/pkg/rootless" ) type cniExec struct { @@ -67,6 +68,17 @@ func (e *cniExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData [ c.Stdout = stdout c.Stderr = stderr + // The dnsname plugin tries to use XDG_RUNTIME_DIR to store files. + // podman run will have XDG_RUNTIME_DIR set and thus the cni plugin can use + // it. The problem is that XDG_RUNTIME_DIR is unset for the conmon process + // for rootful users. This causes issues since the cleanup process is spawned + // by conmon and thus not have XDG_RUNTIME_DIR set to same value as podman run. + // Because of it dnsname will not find the config files and cannot correctly cleanup. + // To fix this we should also unset XDG_RUNTIME_DIR for the cni plugins as rootful. + if !rootless.IsRootless() { + c.Env = append(c.Env, "XDG_RUNTIME_DIR=") + } + err := c.Run() if err != nil { return nil, annotatePluginError(err, pluginPath, stdout.Bytes(), stderr.Bytes()) diff --git a/libpod/network/cni/config.go b/libpod/network/cni/config.go index 2a6ad8eb3..3df155637 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) } } } @@ -170,7 +170,11 @@ func (n *cniNetwork) NetworkRemove(nameOrID string) error { file := network.filename delete(n.networks, network.libpodNet.Name) - return os.Remove(file) + // make sure to not error for ErrNotExist + if err := os.Remove(file); err != nil && !errors.Is(err, os.ErrNotExist) { + return err + } + return nil } // NetworkList will return all known Networks. Optionally you can diff --git a/libpod/network/cni/config_test.go b/libpod/network/cni/config_test.go index a0a0ea1af..288cf4626 100644 --- a/libpod/network/cni/config_test.go +++ b/libpod/network/cni/config_test.go @@ -1021,6 +1021,27 @@ var _ = Describe("Config", func() { Expect(err.Error()).To(ContainSubstring("subnet 10.10.0.0/24 is already used on the host or by another config")) }) + It("remove network should not error when config file does not exists on disk", func() { + name := "mynet" + network := types.Network{Name: name} + _, err := libpodNet.NetworkCreate(network) + Expect(err).To(BeNil()) + + path := filepath.Join(cniConfDir, name+".conflist") + Expect(path).To(BeARegularFile()) + + err = os.Remove(path) + Expect(err).To(BeNil()) + Expect(path).ToNot(BeARegularFile()) + + err = libpodNet.NetworkRemove(name) + Expect(err).To(BeNil()) + + nets, err := libpodNet.NetworkList() + Expect(err).To(BeNil()) + Expect(nets).To(HaveLen(1)) + Expect(nets).ToNot(ContainElement(HaveNetworkName(name))) + }) }) Context("network load valid existing ones", func() { diff --git a/libpod/network/cni/run.go b/libpod/network/cni/run.go index 834e7c867..bd873f89b 100644 --- a/libpod/network/cni/run.go +++ b/libpod/network/cni/run.go @@ -186,9 +186,6 @@ outer: } return errors.Errorf("requested static ip %s not in any subnet on network %s", ip.String(), network.libpodNet.Name) } - if len(netOpts.Aliases) > 0 && !network.libpodNet.DNSEnabled { - return errors.New("cannot set aliases on a network without dns enabled") - } return nil } @@ -273,7 +270,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..965203c2a 100644 --- a/libpod/network/cni/run_test.go +++ b/libpod/network/cni/run_test.go @@ -966,6 +966,26 @@ var _ = Describe("run CNI", func() { }) }) + It("setup with aliases but dns disabled should work", func() { + runTest(func() { + defNet := types.DefaultNetworkName + intName := "eth0" + setupOpts := types.SetupOptions{ + NetworkOptions: types.NetworkOptions{ + ContainerID: stringid.GenerateNonCryptoID(), + Networks: map[string]types.PerNetworkOptions{ + defNet: { + InterfaceName: intName, + Aliases: []string{"somealias"}, + }, + }, + }, + } + _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) + Expect(err).ToNot(HaveOccurred()) + }) + }) + }) Context("invalid network setup test", func() { @@ -1052,27 +1072,6 @@ var _ = Describe("run CNI", func() { }) }) - It("setup with aliases but dns disabled", func() { - runTest(func() { - defNet := types.DefaultNetworkName - intName := "eth0" - setupOpts := types.SetupOptions{ - NetworkOptions: types.NetworkOptions{ - ContainerID: stringid.GenerateNonCryptoID(), - Networks: map[string]types.PerNetworkOptions{ - defNet: { - InterfaceName: intName, - Aliases: []string{"somealias"}, - }, - }, - }, - } - _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("cannot set aliases on a network without dns enabled")) - }) - }) - It("setup without networks", func() { runTest(func() { setupOpts := types.SetupOptions{ @@ -1256,7 +1255,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 +1282,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 68a32d499..2fe4f3da2 100644 --- a/libpod/network/types/network.go +++ b/libpod/network/types/network.go @@ -151,7 +151,9 @@ type PerNetworkOptions struct { // StaticIPv4 for this container. Optional. StaticIPs []net.IP `json:"static_ips,omitempty"` // Aliases contains a list of names which the dns server should resolve - // to this container. Can only be set when DNSEnabled is true on the Network. + // to this container. Should only be set when DNSEnabled is true on the Network. + // If aliases are set but there is no dns support for this network the + // network interface implementation should ignore this and NOT error. // Optional. Aliases []string `json:"aliases,omitempty"` // StaticMac for this container. Optional. diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 96b6fb298..e792a410c 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -48,6 +48,41 @@ const ( persistentCNIDir = "/var/lib/cni" ) +// GetAllNetworkAliases returns all configured aliases for this container. +// It also adds the container short ID as alias to match docker. +func (c *Container) GetAllNetworkAliases() (map[string][]string, error) { + allAliases, err := c.runtime.state.GetAllNetworkAliases(c) + if err != nil { + return nil, err + } + + // get the all attached networks, we cannot use GetAllNetworkAliases() + // since it returns nil if there are no aliases + nets, _, err := c.networks() + if err != nil { + return nil, err + } + + // add container short ID as alias to match docker + for _, net := range nets { + allAliases[net] = append(allAliases[net], c.config.ID[:12]) + } + return allAliases, nil +} + +// GetNetworkAliases returns configured aliases for this network. +// It also adds the container short ID as alias to match docker. +func (c *Container) GetNetworkAliases(netName string) ([]string, error) { + aliases, err := c.runtime.state.GetNetworkAliases(c, netName) + if err != nil { + return nil, err + } + + // add container short ID as alias to match docker + aliases = append(aliases, c.config.ID[:12]) + return aliases, nil +} + func (c *Container) getNetworkOptions() (types.NetworkOptions, error) { opts := types.NetworkOptions{ ContainerID: c.config.ID, @@ -61,7 +96,7 @@ func (c *Container) getNetworkOptions() (types.NetworkOptions, error) { if err != nil { return opts, err } - aliases, err := c.runtime.state.GetAllNetworkAliases(c) + aliases, err := c.GetAllNetworkAliases() if err != nil { return opts, err } @@ -320,14 +355,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 +493,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 +670,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) } } }() @@ -872,7 +907,7 @@ func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.Statu } } - aliases, err := ctr.runtime.state.GetAllNetworkAliases(ctr) + aliases, err := ctr.GetAllNetworkAliases() if err != nil { return nil, err } @@ -975,6 +1010,11 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e for _, net := range networks { cniNet := new(define.InspectAdditionalNetwork) cniNet.NetworkID = net + aliases, err := c.GetNetworkAliases(net) + if err != nil { + return nil, err + } + cniNet.Aliases = aliases settings.Networks[net] = cniNet } } @@ -1009,7 +1049,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e return nil, err } - aliases, err := c.runtime.state.GetNetworkAliases(c, name) + aliases, err := c.GetNetworkAliases(name) if err != nil { return nil, err } @@ -1222,6 +1262,14 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e // get network status before we connect networkStatus := c.getNetworkStatus() + network, err := c.runtime.network.NetworkInspect(netName) + if err != nil { + return err + } + if !network.DNSEnabled && len(aliases) > 0 { + return errors.Wrapf(define.ErrInvalidArg, "cannot set network aliases for network %q because dns is disabled", netName) + } + if err := c.runtime.state.NetworkConnect(c, netName, aliases); err != nil { return err } @@ -1253,6 +1301,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e if !exists { return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName) } + aliases = append(aliases, c.config.ID[:12]) opts.Networks = map[string]types.PerNetworkOptions{ netName: { Aliases: aliases, diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go index a5c035757..46cda89a9 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 } } @@ -222,7 +222,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error { defer errorhandling.CloseQuiet(syncR) defer errorhandling.CloseQuiet(syncW) - havePortMapping := len(ctr.Config().PortMappings) > 0 + havePortMapping := len(ctr.config.PortMappings) > 0 logPath := filepath.Join(ctr.runtime.config.Engine.TmpDir, fmt.Sprintf("slirp4netns-%s.log", ctr.config.ID)) ctrNetworkSlipOpts := []string{} @@ -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/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_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..f82fc4ce6 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) } @@ -1150,7 +1150,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co if ctr.config.NetMode.IsSlirp4netns() || rootless.IsRootless() { if ctr.config.PostConfigureNetNS { - havePortMapping := len(ctr.Config().PortMappings) > 0 + havePortMapping := len(ctr.config.PortMappings) > 0 if havePortMapping { ctr.rootlessPortSyncR, ctr.rootlessPortSyncW, err = os.Pipe() if err != nil { @@ -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_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/pod.go b/libpod/pod.go index e4516b354..c0b0a974b 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -164,8 +164,7 @@ func (p *Pod) PidMode() string { if err != nil { return "" } - conf := infra.Config() - ctrSpec := conf.Spec + ctrSpec := infra.config.Spec if ctrSpec != nil && ctrSpec.Linux != nil { for _, ns := range ctrSpec.Linux.Namespaces { if ns.Type == specs.PIDNamespace { @@ -186,8 +185,7 @@ func (p *Pod) UserNSMode() string { if err != nil { return "" } - conf := infra.Config() - ctrSpec := conf.Spec + ctrSpec := infra.config.Spec if ctrSpec != nil && ctrSpec.Linux != nil { for _, ns := range ctrSpec.Linux.Namespaces { if ns.Type == specs.UserNamespace { diff --git a/libpod/pod_api.go b/libpod/pod_api.go index ff818edc2..971309f77 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -34,7 +34,7 @@ func (p *Pod) startInitContainers(ctx context.Context) error { } // If the container is a once init container, we need to remove it // after it runs - if initCon.Config().InitContainerType == define.OneShotInitContainer { + if initCon.config.InitContainerType == define.OneShotInitContainer { icLock := initCon.lock icLock.Lock() if err := p.runtime.removeContainer(ctx, initCon, false, false, true); err != nil { @@ -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() } @@ -590,16 +590,16 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) { return nil, err } infraConfig = new(define.InspectPodInfraConfig) - infraConfig.HostNetwork = !infra.Config().ContainerNetworkConfig.UseImageHosts - infraConfig.StaticIP = infra.Config().ContainerNetworkConfig.StaticIP - infraConfig.NoManageResolvConf = infra.Config().UseImageResolvConf - infraConfig.NoManageHosts = infra.Config().UseImageHosts + infraConfig.HostNetwork = !infra.config.ContainerNetworkConfig.UseImageHosts + infraConfig.StaticIP = infra.config.ContainerNetworkConfig.StaticIP + infraConfig.NoManageResolvConf = infra.config.UseImageResolvConf + infraConfig.NoManageHosts = infra.config.UseImageHosts infraConfig.CPUPeriod = p.CPUPeriod() infraConfig.CPUQuota = p.CPUQuota() infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus infraConfig.PidNS = p.PidMode() infraConfig.UserNS = p.UserNSMode() - namedVolumes, mounts := infra.sortUserVolumes(infra.Config().Spec) + namedVolumes, mounts := infra.sortUserVolumes(infra.config.Spec) inspectMounts, err = infra.GetInspectMounts(namedVolumes, infra.config.ImageVolumes, mounts) if err != nil { return nil, err @@ -611,30 +611,30 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) { 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 { + if len(infra.config.ContainerNetworkConfig.DNSServer) > 0 { + infraConfig.DNSServer = make([]string, 0, len(infra.config.ContainerNetworkConfig.DNSServer)) + for _, entry := range infra.config.ContainerNetworkConfig.DNSServer { infraConfig.DNSServer = append(infraConfig.DNSServer, entry.String()) } } - if len(infra.Config().ContainerNetworkConfig.DNSSearch) > 0 { - infraConfig.DNSSearch = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSSearch)) - infraConfig.DNSSearch = append(infraConfig.DNSSearch, infra.Config().ContainerNetworkConfig.DNSSearch...) + if len(infra.config.ContainerNetworkConfig.DNSSearch) > 0 { + infraConfig.DNSSearch = make([]string, 0, len(infra.config.ContainerNetworkConfig.DNSSearch)) + infraConfig.DNSSearch = append(infraConfig.DNSSearch, infra.config.ContainerNetworkConfig.DNSSearch...) } - if len(infra.Config().ContainerNetworkConfig.DNSOption) > 0 { - infraConfig.DNSOption = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSOption)) - infraConfig.DNSOption = append(infraConfig.DNSOption, infra.Config().ContainerNetworkConfig.DNSOption...) + if len(infra.config.ContainerNetworkConfig.DNSOption) > 0 { + infraConfig.DNSOption = make([]string, 0, len(infra.config.ContainerNetworkConfig.DNSOption)) + infraConfig.DNSOption = append(infraConfig.DNSOption, infra.config.ContainerNetworkConfig.DNSOption...) } - if len(infra.Config().HostAdd) > 0 { - infraConfig.HostAdd = make([]string, 0, len(infra.Config().HostAdd)) - infraConfig.HostAdd = append(infraConfig.HostAdd, infra.Config().HostAdd...) + if len(infra.config.HostAdd) > 0 { + infraConfig.HostAdd = make([]string, 0, len(infra.config.HostAdd)) + infraConfig.HostAdd = append(infraConfig.HostAdd, infra.config.HostAdd...) } - if len(infra.Config().ContainerNetworkConfig.Networks) > 0 { - infraConfig.Networks = make([]string, 0, len(infra.Config().ContainerNetworkConfig.Networks)) - infraConfig.Networks = append(infraConfig.Networks, infra.Config().ContainerNetworkConfig.Networks...) + if len(infra.config.ContainerNetworkConfig.Networks) > 0 { + infraConfig.Networks = make([]string, 0, len(infra.config.ContainerNetworkConfig.Networks)) + infraConfig.Networks = append(infraConfig.Networks, infra.config.ContainerNetworkConfig.Networks...) } - infraConfig.NetworkOptions = infra.Config().ContainerNetworkConfig.NetworkOptions - infraConfig.PortBindings = makeInspectPortBindings(infra.Config().ContainerNetworkConfig.PortMappings, nil) + infraConfig.NetworkOptions = infra.config.ContainerNetworkConfig.NetworkOptions + infraConfig.PortBindings = makeInspectPortBindings(infra.config.ContainerNetworkConfig.PortMappings, nil) } inspectData := define.InspectPodData{ 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/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..27885bf5c 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 } @@ -706,19 +706,32 @@ func (r *Runtime) TmpDir() (string, error) { return r.config.Engine.TmpDir, nil } -// GetConfig returns a copy of the configuration used by the runtime -func (r *Runtime) GetConfig() (*config.Config, error) { +// GetConfig returns the configuration used by the runtime. +// Note that the returned value is not a copy and must hence +// only be used in a reading fashion. +func (r *Runtime) GetConfigNoCopy() (*config.Config, error) { r.lock.RLock() defer r.lock.RUnlock() if !r.valid { return nil, define.ErrRuntimeStopped } + return r.config, nil +} + +// GetConfig returns a copy of the configuration used by the runtime. +// Please use GetConfigNoCopy() in case you only want to read from +// but not write to the returned config. +func (r *Runtime) GetConfig() (*config.Config, error) { + rtConfig, err := r.GetConfigNoCopy() + if err != nil { + return nil, err + } config := new(config.Config) // Copy so the caller won't be able to modify the actual config - if err := JSONDeepCopy(r.config, config); err != nil { + if err := JSONDeepCopy(rtConfig, config); err != nil { return nil, errors.Wrapf(err, "error copying config") } @@ -767,7 +780,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 +820,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 +846,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 +892,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 +1112,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 +1123,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..7cda9aa8b 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) } } @@ -193,10 +193,7 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf ctr.config.LogPath = "" } - ctr.config.Spec = new(spec.Spec) - if err := JSONDeepCopy(rSpec, ctr.config.Spec); err != nil { - return nil, errors.Wrapf(err, "error copying runtime spec while creating container") - } + ctr.config.Spec = rSpec ctr.config.CreatedTime = time.Now() ctr.state.BindMounts = make(map[string]string) @@ -234,13 +231,6 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. } func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Container, retErr error) { - // Validate the container - if err := ctr.validate(); err != nil { - return nil, err - } - if ctr.config.IsInfra { - ctr.config.StopTimeout = 10 - } // normalize the networks to names // ocicni only knows about cni names so we have to make // sure we do not use ids internally @@ -265,11 +255,26 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai if err != nil { return nil, err } + network, err := r.network.NetworkInspect(netName) + if err != nil { + return nil, err + } + if !network.DNSEnabled { + return nil, errors.Wrapf(define.ErrInvalidArg, "cannot set network aliases for network %q because dns is disabled", netName) + } netAliases[netName] = aliases } ctr.config.NetworkAliases = netAliases } + // Validate the container + if err := ctr.validate(); err != nil { + return nil, err + } + if ctr.config.IsInfra { + ctr.config.StopTimeout = 10 + } + // Inhibit shutdown until creation succeeds shutdown.Inhibit() defer shutdown.Uninhibit() @@ -286,7 +291,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 +414,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 +701,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 +714,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 +723,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 +733,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 +752,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 +893,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..1915a5c4d 100644 --- a/libpod/runtime_img.go +++ b/libpod/runtime_img.go @@ -48,13 +48,34 @@ func (r *Runtime) RemoveContainersForImageCallback(ctx context.Context) libimage } } +// IsExternalContainerCallback returns a callback that be used in `libimage` to +// figure out whether a given container is an external one. A container is +// considered external if it is not present in libpod's database. +func (r *Runtime) IsExternalContainerCallback(_ context.Context) libimage.IsExternalContainerFunc { + // NOTE: pruning external containers is subject to race conditions + // (e.g., when a container gets removed). To address this and similar + // races, pruning had to happen inside c/storage. Containers has to be + // labelled with "podman/libpod" along with callbacks similar to + // libimage. + return func(idOrName string) (bool, error) { + _, err := r.LookupContainer(idOrName) + if err == nil { + return false, nil + } + if errors.Is(err, define.ErrNoSuchCtr) { + return true, nil + } + return false, nil + } +} + // newBuildEvent creates a new event based on completion of a built image func (r *Runtime) newImageBuildCompleteEvent(idOrName string) { e := events.NewEvent(events.Build) 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_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_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/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/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/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index a15fdb553..18005e24a 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -410,11 +410,11 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, if l.HasHealthCheck() && state.Status != "created" { state.Health = &types.Health{ - Status: inspect.State.Healthcheck.Status, - FailingStreak: inspect.State.Healthcheck.FailingStreak, + Status: inspect.State.Health.Status, + FailingStreak: inspect.State.Health.FailingStreak, } - log := inspect.State.Healthcheck.Log + log := inspect.State.Health.Log for _, item := range log { res := &types.HealthcheckResult{} 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 51157d204..1c6cc917c 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -150,7 +150,8 @@ func PruneImages(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) query := struct { - All bool `schema:"all"` + All bool `schema:"all"` + External bool `schema:"external"` }{ // override any golang type defaults } @@ -190,8 +191,9 @@ func PruneImages(w http.ResponseWriter, r *http.Request) { imageEngine := abi.ImageEngine{Libpod: runtime} pruneOptions := entities.ImagePruneOptions{ - All: query.All, - Filter: libpodFilters, + All: query.All, + External: query.External, + Filter: libpodFilters, } imagePruneReports, err := imageEngine.Prune(r.Context(), pruneOptions) if err != nil { @@ -359,7 +361,6 @@ func ExportImages(w http.ResponseWriter, r *http.Request) { 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 9f46ecc52..7bd6d3dbf 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -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/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 dce609a4e..aa573eaa6 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -176,6 +176,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - in: query // name: limit // type: integer + // default: 25 // description: maximum number of results // - in: query // name: filters @@ -186,6 +187,11 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - `is-official=(true|false)` // - `stars=<number>` Matches images that has at least 'number' stars. // - in: query + // name: tlsVerify + // type: boolean + // default: false + // description: skip TLS verification for registries + // - in: query // name: listTags // type: boolean // description: list the available tags in the repository @@ -1044,6 +1050,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: | // Remove all images not in use by containers, not just dangling ones // - in: query + // name: external + // default: false + // type: boolean + // description: | + // Remove images even when they are used by external containers (e.g, by build containers) + // - in: query // name: filters // type: string // description: | @@ -1075,6 +1087,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - in: query // name: limit // type: integer + // default: 25 // description: maximum number of results // - in: query // name: noTrunc @@ -1088,6 +1101,16 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - `is-automated=(true|false)` // - `is-official=(true|false)` // - `stars=<number>` Matches images that has at least 'number' stars. + // - in: query + // name: tlsVerify + // type: boolean + // default: false + // description: skip TLS verification for registries + // - in: query + // name: listTags + // type: boolean + // default: false + // description: list the available tags in the repository // 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/bindings/connection.go b/pkg/bindings/connection.go index 4127ad2f0..e2c46e481 100644 --- a/pkg/bindings/connection.go +++ b/pkg/bindings/connection.go @@ -112,12 +112,12 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string) return nil, errors.Errorf("unable to create connection. %q is not a supported schema", _url.Scheme) } if err != nil { - return nil, errors.Wrapf(err, "failed to create %sClient", _url.Scheme) + return nil, errors.Wrapf(err, "unable to connect to Podman. failed to create %sClient", _url.Scheme) } ctx = context.WithValue(ctx, clientKey, &connection) if err := pingNewConnection(ctx); err != nil { - return nil, errors.Wrap(err, "cannot connect to the Podman socket, please verify the connection to the Linux system, or use `podman machine` to create/start a Linux VM.") + return nil, errors.Wrap(err, "unable to connect to Podman socket") } return ctx, nil } 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..8cf4532d0 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -230,6 +230,9 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO params.Add("platform", platform) } } + if contextDir, err := filepath.EvalSymlinks(options.ContextDirectory); err == nil { + options.ContextDirectory = contextDir + } params.Set("pullpolicy", options.PullPolicy.String()) @@ -312,7 +315,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 +342,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 +374,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 +480,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 6ff9f18ec..dc6bd91c3 100644 --- a/pkg/bindings/images/types.go +++ b/pkg/bindings/images/types.go @@ -74,6 +74,8 @@ type ExportOptions struct { type PruneOptions struct { // Prune all images All *bool + // Prune images even when they're used by external containers + External *bool // Filters to apply when pruning images Filters map[string][]string } diff --git a/pkg/bindings/images/types_prune_options.go b/pkg/bindings/images/types_prune_options.go index 77bef32e3..c9772045e 100644 --- a/pkg/bindings/images/types_prune_options.go +++ b/pkg/bindings/images/types_prune_options.go @@ -32,6 +32,21 @@ func (o *PruneOptions) GetAll() bool { return *o.All } +// WithExternal set field External to given value +func (o *PruneOptions) WithExternal(value bool) *PruneOptions { + o.External = &value + return o +} + +// GetExternal returns value of field External +func (o *PruneOptions) GetExternal() bool { + if o.External == nil { + var z bool + return z + } + return *o.External +} + // WithFilters set field Filters to given value func (o *PruneOptions) WithFilters(value map[string][]string) *PruneOptions { o.Filters = value 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 edd23e662..2822b1ad7 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -251,8 +251,9 @@ type ImageListOptions struct { } type ImagePruneOptions struct { - All bool `json:"all" schema:"all"` - Filter []string `json:"filter" schema:"filter"` + All bool `json:"all" schema:"all"` + External bool `json:"external" schema:"external"` + Filter []string `json:"filter" schema:"filter"` } type ImageTagOptions struct{} @@ -305,8 +306,6 @@ type ImageSaveOptions struct { OciAcceptUncompressedLayers bool // Output - write image to the specified path. Output string - // Do not save the signature from the source image - RemoveSignatures bool // Quiet - suppress output when copying images Quiet bool } diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index affed64d1..8e7e2d411 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -169,6 +169,10 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin logrus.Debugf("Container %s is already stopped", c.ID()) case options.All && errors.Cause(err) == define.ErrCtrStateInvalid: logrus.Debugf("Container %s is not running, could not stop", c.ID()) + // container never created in OCI runtime + // docker parity: do nothing just return container id + case errors.Cause(err) == define.ErrCtrStateInvalid: + logrus.Debugf("Container %s is either not created on runtime or is in a invalid state", c.ID()) default: return err } @@ -825,7 +829,7 @@ 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()) @@ -860,7 +864,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 @@ -978,7 +982,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta 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) } } } 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 1e614ce58..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 } diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index f8ee0304d..c06059205 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -41,13 +41,21 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.Boo func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) ([]*reports.PruneReport, error) { pruneOptions := &libimage.RemoveImagesOptions{ - Filters: append(opts.Filter, "containers=false", "readonly=false"), - WithSize: true, + RemoveContainerFunc: ir.Libpod.RemoveContainersForImageCallback(ctx), + IsExternalContainerFunc: ir.Libpod.IsExternalContainerCallback(ctx), + ExternalContainers: opts.External, + Filters: append(opts.Filter, "readonly=false"), + WithSize: true, } if !opts.All { pruneOptions.Filters = append(pruneOptions.Filters, "dangling=true") } + if opts.External { + pruneOptions.Filters = append(pruneOptions.Filters, "containers=external") + } else { + pruneOptions.Filters = append(pruneOptions.Filters, "containers=false") + } var pruneReports []*reports.PruneReport @@ -368,7 +376,10 @@ func (ir *ImageEngine) Save(ctx context.Context, nameOrID string, tags []string, saveOptions := &libimage.SaveOptions{} saveOptions.DirForceCompress = options.Compress saveOptions.OciAcceptUncompressedLayers = options.OciAcceptUncompressedLayers - saveOptions.RemoveSignatures = options.RemoveSignatures + + // Force signature removal to preserve backwards compat. + // See https://github.com/containers/podman/pull/11669#issuecomment-925250264 + saveOptions.RemoveSignatures = true if !options.Quiet { saveOptions.Writer = os.Stderr @@ -573,7 +584,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..35389ec5e 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 } } @@ -435,6 +435,7 @@ func (ic *ContainerEngine) getImageAndLabelInfo(ctx context.Context, cwd string, buildOpts.Isolation = buildahDefine.IsolationChroot buildOpts.CommonBuildOpts = commonOpts buildOpts.Output = container.Image + buildOpts.ContextDirectory = filepath.Dir(buildFile) if _, _, err := ic.Libpod.Build(ctx, *buildOpts, []string{buildFile}...); err != nil { return nil, nil, err } @@ -662,21 +663,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/secrets.go b/pkg/domain/infra/abi/secrets.go index 2bf8eaae3..34c230e75 100644 --- a/pkg/domain/infra/abi/secrets.go +++ b/pkg/domain/infra/abi/secrets.go @@ -21,7 +21,7 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader // set defaults from config for the case they are not set by an upper layer // (-> i.e. tests that talk directly to the api) - cfg, err := ic.Libpod.GetConfig() + cfg, err := ic.Libpod.GetConfigNoCopy() if err != nil { return nil, err } 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 282770613..d41a20348 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -95,7 +95,7 @@ func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOption f := strings.Split(filter, "=") filters[f[0]] = f[1:] } - options := new(images.PruneOptions).WithAll(opts.All).WithFilters(filters) + options := new(images.PruneOptions).WithAll(opts.All).WithFilters(filters).WithExternal(opts.External) reports, err := images.Prune(ir.ClientCtx, options) if err != nil { return nil, err 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..0f154c524 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 @@ -241,6 +241,13 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities UTS: uts, } } + + if hc, err := ctr.HealthCheckStatus(); err == nil { + ps.Status = hc + } else { + logrus.Debug(err) + } + return ps, nil } diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 4d8443fcb..6ce4b1e29 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -212,6 +212,7 @@ can_use_shortcut () continue; if (strcmp (argv[argc], "mount") == 0 + || strcmp (argv[argc], "machine") == 0 || strcmp (argv[argc], "search") == 0 || (strcmp (argv[argc], "system") == 0 && argv[argc+1] && strcmp (argv[argc+1], "service") != 0)) { 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/container.go b/pkg/specgen/generate/container.go index ae26807a9..71b882510 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -54,7 +54,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat } } - rtc, err := r.GetConfig() + rtc, err := r.GetConfigNoCopy() if err != nil { return nil, err } diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index fefa9b4a9..6100e7a5b 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -23,7 +23,7 @@ import ( // Returns the created, container and any warnings resulting from creating the // container, or an error. func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator) (*spec.Spec, *specgen.SpecGenerator, []libpod.CtrCreateOption, error) { - rtc, err := rt.GetConfig() + rtc, err := rt.GetConfigNoCopy() if err != nil { return nil, nil, nil, err } @@ -498,6 +498,7 @@ func CreateExitCommandArgs(storageConfig types.StoreOptions, config *config.Conf "--log-level", logrus.GetLevel().String(), "--cgroup-manager", config.Engine.CgroupManager, "--tmpdir", config.Engine.TmpDir, + "--cni-config-dir", config.Network.NetworkConfigDir, } if config.Engine.OCIRuntime != "" { command = append(command, []string{"--runtime", config.Engine.OCIRuntime}...) diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index 55010f716..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 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/specgenutil/volumes.go b/pkg/specgenutil/volumes.go index 0ed08198f..3ce96164f 100644 --- a/pkg/specgenutil/volumes.go +++ b/pkg/specgenutil/volumes.go @@ -243,7 +243,7 @@ func getBindMount(args []string) (spec.Mount, error) { Type: define.TypeBind, } - var setSource, setDest, setRORW, setSuid, setDev, setExec, setRelabel bool + var setSource, setDest, setRORW, setSuid, setDev, setExec, setRelabel, setOwnership bool for _, val := range args { kv := strings.SplitN(val, "=", 2) @@ -343,6 +343,18 @@ func getBindMount(args []string) (spec.Mount, error) { default: return newMount, errors.Wrapf(util.ErrBadMntOption, "%s mount option must be 'private' or 'shared'", kv[0]) } + case "U", "chown": + if setOwnership { + return newMount, errors.Wrapf(optionArgError, "cannot pass 'U' or 'chown' option more than once") + } + ok, err := validChownFlag(val) + if err != nil { + return newMount, err + } + if ok { + newMount.Options = append(newMount.Options, "U") + } + setOwnership = true case "consistency": // Often used on MACs and mistakenly on Linux platforms. // Since Docker ignores this option so shall we. @@ -375,7 +387,7 @@ func getTmpfsMount(args []string) (spec.Mount, error) { Source: define.TypeTmpfs, } - var setDest, setRORW, setSuid, setDev, setExec, setTmpcopyup bool + var setDest, setRORW, setSuid, setDev, setExec, setTmpcopyup, setOwnership bool for _, val := range args { kv := strings.SplitN(val, "=", 2) @@ -431,6 +443,18 @@ func getTmpfsMount(args []string) (spec.Mount, error) { } newMount.Destination = filepath.Clean(kv[1]) setDest = true + case "U", "chown": + if setOwnership { + return newMount, errors.Wrapf(optionArgError, "cannot pass 'U' or 'chown' option more than once") + } + ok, err := validChownFlag(val) + if err != nil { + return newMount, err + } + if ok { + newMount.Options = append(newMount.Options, "U") + } + setOwnership = true case "consistency": // Often used on MACs and mistakenly on Linux platforms. // Since Docker ignores this option so shall we. @@ -486,7 +510,7 @@ func getDevptsMount(args []string) (spec.Mount, error) { func getNamedVolume(args []string) (*specgen.NamedVolume, error) { newVolume := new(specgen.NamedVolume) - var setSource, setDest, setRORW, setSuid, setDev, setExec bool + var setSource, setDest, setRORW, setSuid, setDev, setExec, setOwnership bool for _, val := range args { kv := strings.SplitN(val, "=", 2) @@ -532,6 +556,18 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) { } newVolume.Dest = filepath.Clean(kv[1]) setDest = true + case "U", "chown": + if setOwnership { + return newVolume, errors.Wrapf(optionArgError, "cannot pass 'U' or 'chown' option more than once") + } + ok, err := validChownFlag(val) + if err != nil { + return newVolume, err + } + if ok { + newVolume.Options = append(newVolume.Options, "U") + } + setOwnership = true case "consistency": // Often used on MACs and mistakenly on Linux platforms. // Since Docker ignores this option so shall we. @@ -628,3 +664,24 @@ func getTmpfsMounts(tmpfsFlag []string) (map[string]spec.Mount, error) { } return m, nil } + +// validChownFlag ensures that the U or chown flag is correctly used +func validChownFlag(flag string) (bool, error) { + kv := strings.SplitN(flag, "=", 2) + switch len(kv) { + case 1: + case 2: + // U=[true|false] + switch strings.ToLower(kv[1]) { + case "true": + case "false": + return false, nil + default: + return false, errors.Wrapf(optionArgError, "'U' or 'chown' must be set to true or false, instead received %q", kv[1]) + } + default: + return false, errors.Wrapf(optionArgError, "badly formatted option %q", flag) + } + + return true, nil +} 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_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py index dbad6824f..853e9da88 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_container.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py @@ -56,7 +56,7 @@ class ContainerTestCase(APITestCase): self.assertEqual(r.status_code, 200, r.text) self.assertId(r.content) out = r.json() - self.assertIsNone(out["State"].get("Health")) + self.assertIsNotNone(out["State"].get("Health")) self.assertListEqual(["CMD", "pidof", "top"], out["Config"]["Healthcheck"]["Test"]) self.assertEqual(5000000000, out["Config"]["Healthcheck"]["Interval"]) self.assertEqual(2000000000, out["Config"]["Healthcheck"]["Timeout"]) diff --git a/test/compose/test-compose b/test/compose/test-compose index 70db6dd55..beaf276fd 100755 --- a/test/compose/test-compose +++ b/test/compose/test-compose @@ -247,6 +247,7 @@ function podman() { --storage-driver=vfs \ --root $WORKDIR/root \ --runroot $WORKDIR/runroot \ + --cni-config-dir $WORKDIR/cni \ "$@") echo -n "$output" >>$WORKDIR/output.log } 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/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 1445a634b..b2666c789 100644 --- a/test/e2e/healthcheck_run_test.go +++ b/test/e2e/healthcheck_run_test.go @@ -80,6 +80,11 @@ var _ = Describe("Podman healthcheck run", func() { time.Sleep(1 * time.Second) } Expect(exitCode).To(Equal(0)) + + ps := podmanTest.Podman([]string{"ps"}) + ps.WaitWithDefaultTimeout() + Expect(ps).Should(Exit(0)) + Expect(ps.OutputToString()).To(ContainSubstring("(healthy)")) }) It("podman healthcheck that should fail", func() { @@ -117,7 +122,7 @@ var _ = Describe("Podman healthcheck run", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting")) + Expect(inspect[0].State.Health.Status).To(Equal("starting")) }) It("podman healthcheck failed checks in start-period should not change status", func() { @@ -138,7 +143,9 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(1)) inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting")) + Expect(inspect[0].State.Health.Status).To(Equal("starting")) + // test old podman compat (see #11645) + Expect(inspect[0].State.Healthcheck().Status).To(Equal("starting")) }) It("podman healthcheck failed checks must reach retries before unhealthy ", func() { @@ -151,15 +158,16 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(1)) inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting")) + Expect(inspect[0].State.Health.Status).To(Equal("starting")) hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) hc.WaitWithDefaultTimeout() Expect(hc).Should(Exit(1)) inspect = podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckUnhealthy)) - + Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckUnhealthy)) + // test old podman compat (see #11645) + Expect(inspect[0].State.Healthcheck().Status).To(Equal(define.HealthCheckUnhealthy)) }) It("podman healthcheck good check results in healthy even in start-period", func() { @@ -172,7 +180,7 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(0)) inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckHealthy)) + Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckHealthy)) }) It("podman healthcheck unhealthy but valid arguments check", func() { @@ -195,14 +203,14 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(1)) inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting")) + Expect(inspect[0].State.Health.Status).To(Equal("starting")) hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) hc.WaitWithDefaultTimeout() Expect(hc).Should(Exit(1)) inspect = podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckUnhealthy)) + Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckUnhealthy)) foo := podmanTest.Podman([]string{"exec", "hc", "touch", "/foo"}) foo.WaitWithDefaultTimeout() @@ -213,7 +221,7 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(0)) inspect = podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckHealthy)) + Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckHealthy)) // Test podman ps --filter heath is working (#11687) ps := podmanTest.Podman([]string{"ps", "--filter", "health=healthy"}) diff --git a/test/e2e/network_connect_disconnect_test.go b/test/e2e/network_connect_disconnect_test.go index 217efdeec..5f7c55d3f 100644 --- a/test/e2e/network_connect_disconnect_test.go +++ b/test/e2e/network_connect_disconnect_test.go @@ -52,7 +52,6 @@ var _ = Describe("Podman network connect and disconnect", func() { }) It("network disconnect with net mode slirp4netns should result in error", func() { - SkipIfRootless("network connect and disconnect are only rootful") netName := "slirp" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() @@ -118,7 +117,6 @@ var _ = Describe("Podman network connect and disconnect", func() { }) It("network connect with net mode slirp4netns should result in error", func() { - SkipIfRootless("network connect and disconnect are only rootful") netName := "slirp" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() @@ -146,6 +144,13 @@ var _ = Describe("Podman network connect and disconnect", func() { ctr := podmanTest.Podman([]string{"create", "--name", "test", "--network", netName, ALPINE, "top"}) ctr.WaitWithDefaultTimeout() Expect(ctr).Should(Exit(0)) + cid := ctr.OutputToString() + + // network alias container short id is always added and shown in inspect + inspect := podmanTest.Podman([]string{"container", "inspect", "test", "--format", "{{(index .NetworkSettings.Networks \"" + netName + "\").Aliases}}"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).Should(Exit(0)) + Expect(inspect.OutputToString()).To(Equal("[" + cid[0:12] + "]")) con := podmanTest.Podman([]string{"network", "connect", netName, "test"}) con.WaitWithDefaultTimeout() @@ -153,7 +158,6 @@ var _ = Describe("Podman network connect and disconnect", func() { }) It("podman network connect", func() { - SkipIfRemote("This requires a pending PR to be merged before it will work") netName := "aliasTest" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() @@ -163,6 +167,7 @@ var _ = Describe("Podman network connect and disconnect", func() { ctr := podmanTest.Podman([]string{"run", "-dt", "--name", "test", "--network", netName, ALPINE, "top"}) ctr.WaitWithDefaultTimeout() Expect(ctr).Should(Exit(0)) + cid := ctr.OutputToString() exec := podmanTest.Podman([]string{"exec", "-it", "test", "ip", "addr", "show", "eth0"}) exec.WaitWithDefaultTimeout() @@ -184,6 +189,12 @@ var _ = Describe("Podman network connect and disconnect", func() { Expect(inspect).Should(Exit(0)) Expect(inspect.OutputToString()).To(Equal("2")) + // network alias container short id is always added and shown in inspect + inspect = podmanTest.Podman([]string{"container", "inspect", "test", "--format", "{{(index .NetworkSettings.Networks \"" + newNetName + "\").Aliases}}"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).Should(Exit(0)) + Expect(inspect.OutputToString()).To(Equal("[" + cid[0:12] + "]")) + exec = podmanTest.Podman([]string{"exec", "-it", "test", "ip", "addr", "show", "eth1"}) exec.WaitWithDefaultTimeout() Expect(exec).Should(Exit(0)) @@ -193,7 +204,6 @@ var _ = Describe("Podman network connect and disconnect", func() { rm.WaitWithDefaultTimeout() Expect(rm).Should(Exit(0)) Expect(rm.ErrorToString()).To(Equal("")) - }) It("podman network connect when not running", func() { diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go index 7e56b8a25..8e47fac75 100644 --- a/test/e2e/network_test.go +++ b/test/e2e/network_test.go @@ -603,6 +603,11 @@ var _ = Describe("Podman network", func() { }) It("podman network prune --filter", func() { + // set custom cni directory to prevent flakes + podmanTest.CNIConfigDir = tempdir + if IsRemote() { + podmanTest.RestartRemoteService() + } net1 := "macvlan" + stringid.GenerateNonCryptoID() + "net1" nc := podmanTest.Podman([]string{"network", "create", net1}) @@ -613,11 +618,10 @@ var _ = Describe("Podman network", func() { list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"}) list.WaitWithDefaultTimeout() Expect(list).Should(Exit(0)) + Expect(list.OutputToStringArray()).Should(HaveLen(2)) - Expect(StringInSlice(net1, list.OutputToStringArray())).To(BeTrue()) - if !isRootless() { - Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue()) - } + Expect(list.OutputToStringArray()).Should(ContainElement(net1)) + Expect(list.OutputToStringArray()).Should(ContainElement("podman")) // -f needed only to skip y/n question prune := podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "until=50"}) @@ -627,11 +631,10 @@ var _ = Describe("Podman network", func() { listAgain := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"}) listAgain.WaitWithDefaultTimeout() Expect(listAgain).Should(Exit(0)) + Expect(listAgain.OutputToStringArray()).Should(HaveLen(2)) - Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeTrue()) - if !isRootless() { - Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue()) - } + Expect(listAgain.OutputToStringArray()).Should(ContainElement(net1)) + Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman")) // -f needed only to skip y/n question prune = podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "until=5000000000000"}) @@ -641,14 +644,18 @@ var _ = Describe("Podman network", func() { listAgain = podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"}) listAgain.WaitWithDefaultTimeout() Expect(listAgain).Should(Exit(0)) + Expect(listAgain.OutputToStringArray()).Should(HaveLen(1)) - Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeFalse()) - if !isRootless() { - Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue()) - } + Expect(listAgain.OutputToStringArray()).ShouldNot(ContainElement(net1)) + Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman")) }) It("podman network prune", func() { + // set custom cni directory to prevent flakes + podmanTest.CNIConfigDir = tempdir + if IsRemote() { + podmanTest.RestartRemoteService() + } // Create two networks // Check they are there // Run a container on one of them @@ -669,13 +676,11 @@ var _ = Describe("Podman network", func() { list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"}) list.WaitWithDefaultTimeout() - Expect(list).Should(Exit(0)) + Expect(list.OutputToStringArray()).Should(HaveLen(3)) - Expect(StringInSlice(net1, list.OutputToStringArray())).To(BeTrue()) - Expect(StringInSlice(net2, list.OutputToStringArray())).To(BeTrue()) - if !isRootless() { - Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue()) - } + Expect(list.OutputToStringArray()).Should(ContainElement(net1)) + Expect(list.OutputToStringArray()).Should(ContainElement(net2)) + Expect(list.OutputToStringArray()).Should(ContainElement("podman")) session := podmanTest.Podman([]string{"run", "-dt", "--net", net2, ALPINE, "top"}) session.WaitWithDefaultTimeout() @@ -688,13 +693,10 @@ var _ = Describe("Podman network", func() { listAgain := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"}) listAgain.WaitWithDefaultTimeout() Expect(listAgain).Should(Exit(0)) + Expect(listAgain.OutputToStringArray()).Should(HaveLen(2)) - Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeFalse()) - Expect(StringInSlice(net2, listAgain.OutputToStringArray())).To(BeTrue()) - // Make sure default network 'podman' still exists - if !isRootless() { - Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue()) - } - + Expect(listAgain.OutputToStringArray()).ShouldNot(ContainElement(net1)) + Expect(listAgain.OutputToStringArray()).Should(ContainElement(net2)) + Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman")) }) }) diff --git a/test/e2e/play_build_test.go b/test/e2e/play_build_test.go index 16f2687f3..564735e07 100644 --- a/test/e2e/play_build_test.go +++ b/test/e2e/play_build_test.go @@ -80,12 +80,17 @@ status: {} FROM quay.io/libpod/alpine_nginx:latest RUN apk update && apk add strace LABEL homer=dad +COPY copyfile /copyfile ` var prebuiltImage = ` FROM quay.io/libpod/alpine_nginx:latest RUN apk update && apk add strace LABEL marge=mom ` + + var copyFile = `just a text file +` + It("Check that image is built using Dockerfile", func() { // Setup yamlDir := filepath.Join(tempdir, RandomString(12)) @@ -97,7 +102,9 @@ LABEL marge=mom Expect(err).To(BeNil()) err = writeYaml(playBuildFile, filepath.Join(app1Dir, "Dockerfile")) Expect(err).To(BeNil()) - + // Write a file to be copied + err = writeYaml(copyFile, filepath.Join(app1Dir, "copyfile")) + Expect(err).To(BeNil()) // Switch to temp dir and restore it afterwards cwd, err := os.Getwd() Expect(err).To(BeNil()) @@ -131,7 +138,9 @@ LABEL marge=mom Expect(err).To(BeNil()) err = writeYaml(playBuildFile, filepath.Join(app1Dir, "Containerfile")) Expect(err).To(BeNil()) - + // Write a file to be copied + err = writeYaml(copyFile, filepath.Join(app1Dir, "copyfile")) + Expect(err).To(BeNil()) // Switch to temp dir and restore it afterwards cwd, err := os.Getwd() Expect(err).To(BeNil()) @@ -172,6 +181,9 @@ LABEL marge=mom Expect(err).To(BeNil()) err = writeYaml(playBuildFile, filepath.Join(app1Dir, "Containerfile")) Expect(err).To(BeNil()) + // Write a file to be copied + err = writeYaml(copyFile, filepath.Join(app1Dir, "copyfile")) + Expect(err).To(BeNil()) // Switch to temp dir and restore it afterwards cwd, err := os.Getwd() @@ -215,6 +227,9 @@ LABEL marge=mom Expect(err).To(BeNil()) err = writeYaml(playBuildFile, filepath.Join(app1Dir, "Containerfile")) Expect(err).To(BeNil()) + // Write a file to be copied + err = writeYaml(copyFile, filepath.Join(app1Dir, "copyfile")) + Expect(err).To(BeNil()) // Switch to temp dir and restore it afterwards cwd, err := os.Getwd() diff --git a/test/e2e/rename_test.go b/test/e2e/rename_test.go index 0bd1792c9..e5e69c25c 100644 --- a/test/e2e/rename_test.go +++ b/test/e2e/rename_test.go @@ -111,4 +111,29 @@ var _ = Describe("podman rename", func() { Expect(ps).Should(Exit(0)) Expect(ps.OutputToString()).To(ContainSubstring(newName)) }) + + It("Rename a container that is part of a pod", func() { + podName := "testPod" + infraName := "infra1" + pod := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--infra-name", infraName}) + pod.WaitWithDefaultTimeout() + Expect(pod).Should(Exit(0)) + + infraName2 := "infra2" + rename := podmanTest.Podman([]string{"rename", infraName, infraName2}) + rename.WaitWithDefaultTimeout() + Expect(rename).Should(Exit(0)) + + remove := podmanTest.Podman([]string{"pod", "rm", "-f", podName}) + remove.WaitWithDefaultTimeout() + Expect(remove).Should(Exit(0)) + + create := podmanTest.Podman([]string{"create", "--name", infraName2, ALPINE, "top"}) + create.WaitWithDefaultTimeout() + Expect(create).Should(Exit(0)) + + create2 := podmanTest.Podman([]string{"create", "--name", infraName, ALPINE, "top"}) + create2.WaitWithDefaultTimeout() + Expect(create2).Should(Exit(0)) + }) }) diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index 4264e1efe..f1baa7780 100644 --- a/test/e2e/run_volume_test.go +++ b/test/e2e/run_volume_test.go @@ -647,7 +647,7 @@ VOLUME /test/`, ALPINE) Expect(len(session.OutputToStringArray())).To(Equal(2)) }) - It("podman run with U volume flag", func() { + It("podman run with --volume and U flag", func() { SkipIfRemote("Overlay volumes only work locally") u, err := user.Current() @@ -698,6 +698,65 @@ VOLUME /test/`, ALPINE) Expect(found).Should(BeTrue()) }) + It("podman run with --mount and U flag", func() { + u, err := user.Current() + Expect(err).To(BeNil()) + name := u.Username + if name == "root" { + name = "containers" + } + + content, err := ioutil.ReadFile("/etc/subuid") + if err != nil { + Skip("cannot read /etc/subuid") + } + + if !strings.Contains(string(content), name) { + Skip("cannot find mappings for the current user") + } + + mountPath := filepath.Join(podmanTest.TempDir, "foo") + os.Mkdir(mountPath, 0755) + + // false bind mount + vol := "type=bind,src=" + mountPath + ",dst=" + dest + ",U=false" + session := podmanTest.Podman([]string{"run", "--rm", "--user", "888:888", "--mount", vol, ALPINE, "stat", "-c", "%u:%g", dest}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).ShouldNot(Equal("888:888")) + + // invalid bind mount + vol = "type=bind,src=" + mountPath + ",dst=" + dest + ",U=invalid" + session = podmanTest.Podman([]string{"run", "--rm", "--user", "888:888", "--mount", vol, ALPINE, "stat", "-c", "%u:%g", dest}) + session.WaitWithDefaultTimeout() + Expect(session).To(ExitWithError()) + + // true bind mount + vol = "type=bind,src=" + mountPath + ",dst=" + dest + ",U=true" + session = podmanTest.Podman([]string{"run", "--rm", "--user", "888:888", "--mount", vol, ALPINE, "stat", "-c", "%u:%g", dest}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).Should(Equal("888:888")) + + // tmpfs mount + vol = "type=tmpfs," + "dst=" + dest + ",chown" + session = podmanTest.Podman([]string{"run", "--rm", "--user", "888:888", "--mount", vol, ALPINE, "stat", "-c", "%u:%g", dest}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).Should(Equal("888:888")) + + // named volume mount + namedVolume := podmanTest.Podman([]string{"volume", "create", "foo"}) + namedVolume.WaitWithDefaultTimeout() + Expect(namedVolume).Should(Exit(0)) + + vol = "type=volume,src=foo,dst=" + dest + ",chown=true" + session = podmanTest.Podman([]string{"run", "--rm", "--user", "888:888", "--mount", vol, ALPINE, "stat", "-c", "%u:%g", dest}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).Should(Equal("888:888")) + }) + It("volume permissions after run", func() { imgName := "testimg" dockerfile := fmt.Sprintf(`FROM %s diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go index a984bf6d0..7f178d719 100644 --- a/test/e2e/stop_test.go +++ b/test/e2e/stop_test.go @@ -234,6 +234,17 @@ var _ = Describe("Podman stop", func() { Expect(strings.TrimSpace(finalCtrs.OutputToString())).To(Equal("")) }) + It("podman stop should return silent success on stopping configured containers", func() { + // following container is not created on OCI runtime + // so we return success and assume that is is stopped + session2 := podmanTest.Podman([]string{"create", "--name", "stopctr", ALPINE, "/bin/sh"}) + session2.WaitWithDefaultTimeout() + Expect(session2).Should(Exit(0)) + session3 := podmanTest.Podman([]string{"stop", "stopctr"}) + session3.WaitWithDefaultTimeout() + Expect(session3).Should(Exit(0)) + }) + It("podman stop --cidfile", func() { tmpDir, err := ioutil.TempDir("", "") diff --git a/test/system/035-logs.bats b/test/system/035-logs.bats index a04d2ac74..76ce12b81 100644 --- a/test/system/035-logs.bats +++ b/test/system/035-logs.bats @@ -135,31 +135,38 @@ function _log_test_until() { s_after="after_$(random_string)_${driver}" before=$(date --iso-8601=seconds) - sleep 5 + sleep 1 run_podman run --log-driver=$driver -d --name test $IMAGE sh -c \ "echo $s_before; trap 'echo $s_after; exit' SIGTERM; while :; do sleep 1; done" # sleep a second to make sure the date is after the first echo sleep 1 run_podman stop test - # sleep for 20 seconds to get the proper after time - sleep 20 + run_podman wait test - run_podman logs test - is "$output" \ - "$s_before + # Sigh. Stupid journald has a lag. Wait a few seconds for it to catch up. + retries=20 + s_both="$s_before $s_after" + while [[ $retries -gt 0 ]]; do + run_podman logs test + if [[ "$output" = "$s_both" ]]; then + break + fi + retries=$((retries - 1)) + sleep 0.1 + done + if [[ $retries -eq 0 ]]; then + die "Timed out waiting for before&after in podman logs: $output" + fi run_podman logs --until $before test - is "$output" \ - "" + is "$output" "" "podman logs --until before" - after=$(date --iso-8601=seconds) + after=$(date --date='+1 second' --iso-8601=seconds) run_podman logs --until $after test - is "$output" \ - "$s_before -$s_after" + is "$output" "$s_both" "podman logs --until after" run_podman rm -f test } diff --git a/test/system/040-ps.bats b/test/system/040-ps.bats index 182d75547..63f57efdc 100644 --- a/test/system/040-ps.bats +++ b/test/system/040-ps.bats @@ -90,26 +90,48 @@ load helpers is "${#lines[@]}" "1" "setup check: no storage containers at start of test" # Force a buildah timeout; this leaves a buildah container behind + local t0=$SECONDS PODMAN_TIMEOUT=5 run_podman 124 build -t thiswillneverexist - <<EOF FROM $IMAGE +RUN touch /intermediate.image.to.be.pruned RUN sleep 30 EOF + local t1=$SECONDS + local delta_t=$((t1 - t0)) + if [[ $delta_t -gt 10 ]]; then + # FIXME FIXME FIXME: when buildah issue 3544 gets fixed and vendored, + # change 'echo' to 'die' + echo "podman build did not get killed within 10 seconds (actual time: $delta_t seconds)" + fi run_podman ps -a - is "${#lines[@]}" "1" "podman ps -a does not see buildah container" + is "${#lines[@]}" "1" "podman ps -a does not see buildah containers" run_podman ps --external -a - is "${#lines[@]}" "2" "podman ps -a --external sees buildah container" + is "${#lines[@]}" "3" "podman ps -a --external sees buildah containers" is "${lines[1]}" \ "[0-9a-f]\{12\} \+$IMAGE *buildah .* seconds ago .* storage .* ${PODMAN_TEST_IMAGE_NAME}-working-container" \ "podman ps --external" - cid="${lines[1]:0:12}" - # 'rm -a' should be a NOP run_podman rm -a run_podman ps --external -a - is "${#lines[@]}" "2" "podman ps -a --external sees buildah container" + is "${#lines[@]}" "3" "podman ps -a --external sees buildah containers" + + # Cannot prune intermediate image as it's being used by a buildah + # container. + run_podman image prune -f + is "$output" "" "No image is pruned" + + # --external for removing buildah containers. + run_podman image prune -f --external + is "${#lines[@]}" "1" "Image used by build container is pruned" + + # One buildah container has been removed. + run_podman ps --external -a + is "${#lines[@]}" "2" "podman ps -a --external sees buildah containers" + + cid="${lines[1]:0:12}" # We can't rm it without -f, but podman should issue a helpful message run_podman 2 rm "$cid" diff --git a/test/system/060-mount.bats b/test/system/060-mount.bats index 63a93e13b..ba37ea5e1 100644 --- a/test/system/060-mount.bats +++ b/test/system/060-mount.bats @@ -125,6 +125,7 @@ load helpers run_podman exec $cid find /image-mount/etc/ # Clean up + run_podman stop -t 0 $cid run_podman rm -f $cid } @@ -147,6 +148,7 @@ load helpers run_podman inspect --format "{{(index .Mounts 0).RW}}" $cid is "$output" "true" "inspect data includes image mount source" + run_podman stop -t 0 $cid run_podman rm -f $cid } diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats index 39f439e7b..38c38d671 100644 --- a/test/system/065-cp.bats +++ b/test/system/065-cp.bats @@ -256,6 +256,7 @@ load helpers " # From RUNNING container + local -a destcontainers=() while read id src dest dest_fullname description; do # dest may be "''" for empty table cells if [[ $dest == "''" ]];then @@ -265,26 +266,25 @@ load helpers # To RUNNING container run_podman run -d $IMAGE sleep infinity destcontainer="$output" + destcontainers+=($destcontainer) run_podman cp cpcontainer:$src $destcontainer:"/$dest" run_podman exec $destcontainer cat "/$dest_fullname" is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)" - run_podman kill $destcontainer - run_podman rm -f $destcontainer # To CREATED container run_podman create $IMAGE sleep infinity destcontainer="$output" + destcontainers+=($destcontainer) run_podman cp cpcontainer:$src $destcontainer:"/$dest" run_podman start $destcontainer run_podman exec $destcontainer cat "/$dest_fullname" is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)" - run_podman kill $destcontainer - run_podman rm -f $destcontainer done < <(parse_table "$tests") - run_podman kill cpcontainer - run_podman rm -f cpcontainer + run_podman kill cpcontainer ${destcontainers[@]} + run_podman rm -f cpcontainer ${destcontainers[@]} # From CREATED container + destcontainers=() run_podman create --name cpcontainer --workdir=/srv $cpimage while read id src dest dest_fullname description; do # dest may be "''" for empty table cells @@ -295,23 +295,21 @@ load helpers # To RUNNING container run_podman run -d $IMAGE sleep infinity destcontainer="$output" + destcontainers+=($destcontainer) run_podman cp cpcontainer:$src $destcontainer:"/$dest" run_podman exec $destcontainer cat "/$dest_fullname" is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)" - run_podman kill $destcontainer - run_podman rm -f $destcontainer - # To CREATED container run_podman create $IMAGE sleep infinity destcontainer="$output" + destcontainers+=($destcontainer) run_podman cp cpcontainer:$src $destcontainer:"/$dest" run_podman start $destcontainer run_podman exec $destcontainer cat "/$dest_fullname" is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)" - run_podman kill $destcontainer - run_podman rm -f $destcontainer done < <(parse_table "$tests") - run_podman rm -f cpcontainer + run_podman kill ${destcontainers[@]} + run_podman rm -f cpcontainer ${destcontainers[@]} run_podman rmi -f $cpimage } @@ -496,6 +494,7 @@ load helpers " # From RUNNING container + local -a destcontainers=() while read src dest dest_fullname description; do if [[ $src == "''" ]];then unset src @@ -510,28 +509,27 @@ load helpers # To RUNNING container run_podman run -d $IMAGE sleep infinity destcontainer="$output" + destcontainers+=($destcontainer) run_podman cp cpcontainer:$src $destcontainer:"/$dest" run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1" is "$output" "${randomcontent[0]} ${randomcontent[1]}" "$description" - run_podman kill $destcontainer - run_podman rm -f $destcontainer # To CREATED container run_podman create $IMAGE sleep infinity destcontainer="$output" + destcontainers+=($destcontainer) run_podman cp cpcontainer:$src $destcontainer:"/$dest" run_podman start $destcontainer run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1" is "$output" "${randomcontent[0]} ${randomcontent[1]}" "$description" - run_podman kill $destcontainer - run_podman rm -f $destcontainer done < <(parse_table "$tests") - run_podman kill cpcontainer - run_podman rm -f cpcontainer + run_podman kill cpcontainer ${destcontainers[@]} + run_podman rm -f cpcontainer ${destcontainers[@]} # From CREATED container + destcontainers=() run_podman create --name cpcontainer --workdir=/srv $cpimage while read src dest dest_fullname description; do if [[ $src == "''" ]];then @@ -547,26 +545,25 @@ ${randomcontent[1]}" "$description" # To RUNNING container run_podman run -d $IMAGE sleep infinity destcontainer="$output" + destcontainers+=($destcontainer) run_podman cp cpcontainer:$src $destcontainer:"/$dest" run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1" is "$output" "${randomcontent[0]} ${randomcontent[1]}" "$description" - run_podman kill $destcontainer - run_podman rm -f $destcontainer # To CREATED container run_podman create $IMAGE sleep infinity destcontainer="$output" + destcontainers+=($destcontainer) run_podman start $destcontainer run_podman cp cpcontainer:$src $destcontainer:"/$dest" run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1" is "$output" "${randomcontent[0]} ${randomcontent[1]}" "$description" - run_podman kill $destcontainer - run_podman rm -f $destcontainer done < <(parse_table "$tests") - run_podman rm -f cpcontainer + run_podman kill ${destcontainers[@]} + run_podman rm -f cpcontainer ${destcontainers[@]} run_podman rmi -f $cpimage } diff --git a/test/system/070-build.bats b/test/system/070-build.bats index 0e1396fc6..4e89e299a 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -956,6 +956,15 @@ EOF run_podman build -t build_test $tmpdir } +@test "podman build build context is a symlink to a directory" { + tmpdir=$PODMAN_TMPDIR/build-test + mkdir -p $tmpdir/target + ln -s target $tmpdir/link + echo FROM $IMAGE > $tmpdir/link/Dockerfile + echo RUN echo hello >> $tmpdir/link/Dockerfile + run_podman build -t build_test $tmpdir/link +} + function teardown() { # A timeout or other error in 'build' can leave behind stale images # that podman can't even see and which will cascade into subsequent diff --git a/test/system/080-pause.bats b/test/system/080-pause.bats index 1eb47dcfb..2314324a9 100644 --- a/test/system/080-pause.bats +++ b/test/system/080-pause.bats @@ -48,6 +48,7 @@ load helpers # would imply that the container never paused. is "$max_delta" "[3456]" "delta t between paused and restarted" + run_podman stop -t 0 $cname run_podman rm -f $cname # Pause/unpause on nonexistent name or id - these should all fail @@ -73,6 +74,7 @@ load helpers is "$output" "$cid" "podman unpause output" run_podman ps --format '{{.ID}} {{.Names}} {{.Status}}' is "$output" "${cid:0:12} $cname Up.*" "podman ps on resumed container" + run_podman stop -t 0 $cname run_podman rm -f $cname run_podman rm -f notrunning } diff --git a/test/system/120-load.bats b/test/system/120-load.bats index f2f9bf4d4..8be9ed5c5 100644 --- a/test/system/120-load.bats +++ b/test/system/120-load.bats @@ -32,7 +32,7 @@ verify_iid_and_name() { echo "I am an invalid file and should cause a podman-load error" > $invalid run_podman 125 load -i $invalid # podman and podman-remote emit different messages; this is a common string - is "$output" ".*payload does not match any of the supported image formats .*" \ + is "$output" ".*payload does not match any of the supported image formats:.*" \ "load -i INVALID fails with expected diagnostic" } @@ -129,7 +129,7 @@ verify_iid_and_name() { @test "podman load - redirect corrupt payload" { run_podman 125 load <<< "Danger, Will Robinson!! This is a corrupt tarball!" is "$output" \ - ".*payload does not match any of the supported image formats .*" \ + ".*payload does not match any of the supported image formats:.*" \ "Diagnostic from 'podman load' unknown/corrupt payload" } diff --git a/test/system/220-healthcheck.bats b/test/system/220-healthcheck.bats index e416629e6..28fe8eb92 100644 --- a/test/system/220-healthcheck.bats +++ b/test/system/220-healthcheck.bats @@ -12,13 +12,13 @@ function _check_health { local testname="$1" local tests="$2" - run_podman inspect --format json healthcheck_c + run_podman inspect --format "{{json .State.Healthcheck}}" healthcheck_c parse_table "$tests" | while read field expect;do # (kludge to deal with parse_table and empty strings) if [ "$expect" = "''" ]; then expect=""; fi - actual=$(jq -r ".[0].State.Healthcheck.$field" <<<"$output") + actual=$(jq -r ".$field" <<<"$output") is "$actual" "$expect" "$testname - .State.Healthcheck.$field" done } @@ -108,6 +108,7 @@ Log[-1].Output | is "$output" "unhealthy" "output from 'podman healthcheck run'" # Clean up + run_podman stop -t 0 healthcheck_c run_podman rm -f healthcheck_c run_podman rmi healthcheck_i } diff --git a/test/system/270-socket-activation.bats b/test/system/270-socket-activation.bats index 031ba161b..dd439d3ae 100644 --- a/test/system/270-socket-activation.bats +++ b/test/system/270-socket-activation.bats @@ -69,26 +69,36 @@ function teardown() { @test "podman system service - socket activation - no container" { run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping - is "$output" "OK" "podman service responses normally" + is "$output" "OK" "podman service responds normally" } -@test "podman system service - socket activation - exist container " { - run_podman run $IMAGE sleep 90 +@test "podman system service - socket activation - existing container" { + run_podman run -d $IMAGE sleep 90 + cid="$output" + run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping - is "$output" "OK" "podman service responses normally" + is "$output" "OK" "podman service responds normally" + + run_podman stop -t 0 $cid + run_podman rm -f $cid } -@test "podman system service - socket activation - kill rootless pause " { +@test "podman system service - socket activation - kill rootless pause" { if ! is_rootless; then skip "root podman no need pause process" fi - run_podman run $IMAGE sleep 90 + run_podman run -d $IMAGE sleep 90 + cid="$output" + local pause_pid="$XDG_RUNTIME_DIR/libpod/tmp/pause.pid" if [ -f $pause_pid ]; then kill -9 $(cat $pause_pid) 2> /dev/null fi run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping - is "$output" "OK" "podman service responses normally" + is "$output" "OK" "podman service responds normally" + + run_podman stop -t 0 $cid + run_podman rm -f $cid } # vim: filetype=sh diff --git a/test/system/330-corrupt-images.bats b/test/system/330-corrupt-images.bats index eeffff3ec..86da06cb0 100644 --- a/test/system/330-corrupt-images.bats +++ b/test/system/330-corrupt-images.bats @@ -78,7 +78,7 @@ function _corrupt_image_test() { # Run the requested command. Confirm it succeeds, with suitable warnings run_podman $* - is "$output" ".*error determining parent of image.*ignoring the error" \ + is "$output" ".*Failed to determine parent of image.*ignoring the error" \ "$* with missing $what_to_rm" run_podman images -a --noheading diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index ef00d0366..548f2d764 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -415,6 +415,10 @@ load helpers run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").MacAddress}}" mac="$output" + # check network alias for container short id + run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").Aliases}}" + is "$output" "\[${cid:0:12}\]" "short container id in network aliases" + run_podman network disconnect $netname $cid # check that we cannot curl (timeout after 3 sec) @@ -443,6 +447,10 @@ load helpers # connect a second network run_podman network connect $netname2 $cid + # check network2 alias for container short id + run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname2\").Aliases}}" + is "$output" "\[${cid:0:12}\]" "short container id in network aliases" + # curl should work run curl --max-time 3 -s $SERVER/index.txt is "$output" "$random_1" "curl 127.0.0.1:/index.txt should work" diff --git a/test/system/600-completion.bats b/test/system/600-completion.bats index fbb0da231..5f4610e9e 100644 --- a/test/system/600-completion.bats +++ b/test/system/600-completion.bats @@ -110,12 +110,10 @@ function check_shell_completion() { is "$output" ".*localhost/$random_image_name:$random_image_tag${nl}" \ "$* $cmd: actual image listed in suggestions" - # check that we complete the image with and without tag after at least one char is typed + # check that we complete the image with tag after at least one char is typed run_completion "$@" $cmd "${extra_args[@]}" "${random_image_name:0:1}" is "$output" ".*$random_image_name:$random_image_tag${nl}" \ "$* $cmd: image name:tag included in suggestions" - is "$output" ".*$random_image_name${nl}" \ - "$* $cmd: image name(w/o tag) included in suggestions" # check that we complete the image id after at least two chars are typed run_completion "$@" $cmd "${extra_args[@]}" "${random_image_id:0:2}" diff --git a/test/system/700-play.bats b/test/system/700-play.bats index 2b05cdd84..0785bffdf 100644 --- a/test/system/700-play.bats +++ b/test/system/700-play.bats @@ -69,11 +69,15 @@ RELABEL="system_u:object_r:container_file_t:s0" TESTDIR=$PODMAN_TMPDIR/testdir mkdir -p $TESTDIR echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml + run_podman play kube - < $PODMAN_TMPDIR/test.yaml if [ -e /usr/sbin/selinuxenabled -a /usr/sbin/selinuxenabled ]; then run ls -Zd $TESTDIR is "$output" ${RELABEL} "selinux relabel should have happened" fi + + run_podman stop -a -t 0 + run_podman pod stop test_pod run_podman pod rm -f test_pod } @@ -86,6 +90,9 @@ RELABEL="system_u:object_r:container_file_t:s0" run ls -Zd $TESTDIR is "$output" ${RELABEL} "selinux relabel should have happened" fi + + run_podman stop -a -t 0 + run_podman pod stop test_pod run_podman pod rm -f test_pod } @@ -102,12 +109,19 @@ RELABEL="system_u:object_r:container_file_t:s0" infraID="$output" run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID is "$output" "slirp4netns" "network mode slirp4netns is set for the container" + + run_podman stop -a -t 0 + run_podman pod stop test_pod run_podman pod rm -f test_pod + run_podman play kube --network none $PODMAN_TMPDIR/test.yaml run_podman pod inspect --format {{.InfraContainerID}} "${lines[1]}" infraID="$output" run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID is "$output" "none" "network mode none is set for the container" + + run_podman stop -a -t 0 + run_podman pod stop test_pod run_podman pod rm -f test_pod } @@ -149,6 +163,9 @@ _EOF run_podman play kube --start=false $PODMAN_TMPDIR/test.yaml run_podman inspect --format "{{ .Config.User }}" test_pod-test is "$output" bin "expect container within pod to run as the bin user" + + run_podman stop -a -t 0 + run_podman pod stop test_pod run_podman pod rm -f test_pod run_podman rmi -f userimage:latest } 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/vendor/github.com/containers/common/libimage/copier.go b/vendor/github.com/containers/common/libimage/copier.go index 42d3690b9..636b97bfd 100644 --- a/vendor/github.com/containers/common/libimage/copier.go +++ b/vendor/github.com/containers/common/libimage/copier.go @@ -304,7 +304,7 @@ func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) { defaultContainerConfig, err := config.Default() if err != nil { - logrus.Warnf("failed to get container config for copy options: %v", err) + logrus.Warnf("Failed to get container config for copy options: %v", err) } else { c.imageCopyOptions.MaxParallelDownloads = defaultContainerConfig.Engine.ImageParallelCopies } diff --git a/vendor/github.com/containers/common/libimage/filters.go b/vendor/github.com/containers/common/libimage/filters.go index 0cc5cc311..833f940cc 100644 --- a/vendor/github.com/containers/common/libimage/filters.go +++ b/vendor/github.com/containers/common/libimage/filters.go @@ -47,11 +47,11 @@ func filterImages(images []*Image, filters []filterFunc) ([]*Image, error) { // compileImageFilters creates `filterFunc`s for the specified filters. The // required format is `key=value` with the following supported keys: // after, since, before, containers, dangling, id, label, readonly, reference, intermediate -func (r *Runtime) compileImageFilters(ctx context.Context, filters []string) ([]filterFunc, error) { - logrus.Tracef("Parsing image filters %s", filters) +func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOptions) ([]filterFunc, error) { + logrus.Tracef("Parsing image filters %s", options.Filters) filterFuncs := []filterFunc{} - for _, filter := range filters { + for _, filter := range options.Filters { var key, value string split := strings.SplitN(filter, "=", 2) if len(split) != 2 { @@ -77,11 +77,16 @@ func (r *Runtime) compileImageFilters(ctx context.Context, filters []string) ([] filterFuncs = append(filterFuncs, filterBefore(img.Created())) case "containers": - containers, err := strconv.ParseBool(value) - if err != nil { - return nil, errors.Wrapf(err, "non-boolean value %q for dangling filter", value) + switch value { + case "false", "true": + case "external": + if options.IsExternalContainerFunc == nil { + return nil, fmt.Errorf("libimage error: external containers filter without callback") + } + default: + return nil, fmt.Errorf("unsupported value %q for containers filter", value) } - filterFuncs = append(filterFuncs, filterContainers(containers)) + filterFuncs = append(filterFuncs, filterContainers(value, options.IsExternalContainerFunc)) case "dangling": dangling, err := strconv.ParseBool(value) @@ -190,13 +195,28 @@ func filterReadOnly(value bool) filterFunc { } // filterContainers creates a container filter for matching the specified value. -func filterContainers(value bool) filterFunc { +func filterContainers(value string, fn IsExternalContainerFunc) filterFunc { return func(img *Image) (bool, error) { ctrs, err := img.Containers() if err != nil { return false, err } - return (len(ctrs) > 0) == value, nil + if value != "external" { + boolValue := value == "true" + return (len(ctrs) > 0) == boolValue, nil + } + + // Check whether all associated containers are external ones. + for _, c := range ctrs { + isExternal, err := fn(c) + if err != nil { + return false, fmt.Errorf("checking if %s is an external container in filter: %w", c, err) + } + if !isExternal { + return isExternal, nil + } + } + return true, nil } } diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go index 8456d5280..00a2d620e 100644 --- a/vendor/github.com/containers/common/libimage/image.go +++ b/vendor/github.com/containers/common/libimage/image.go @@ -2,6 +2,7 @@ package libimage import ( "context" + "fmt" "path/filepath" "sort" "strings" @@ -51,7 +52,7 @@ func (i *Image) reload() error { logrus.Tracef("Reloading image %s", i.ID()) img, err := i.runtime.store.Image(i.ID()) if err != nil { - return errors.Wrap(err, "error reloading image") + return errors.Wrap(err, "reloading image") } i.storageImage = img i.cached.imageSource = nil @@ -232,11 +233,15 @@ func (i *Image) Containers() ([]string, error) { } // removeContainers removes all containers using the image. -func (i *Image) removeContainers(fn RemoveContainerFunc) error { - // Execute the custom removal func if specified. - if fn != nil { +func (i *Image) removeContainers(options *RemoveImagesOptions) error { + if !options.Force && !options.ExternalContainers { + // Nothing to do. + return nil + } + + if options.Force && options.RemoveContainerFunc != nil { logrus.Debugf("Removing containers of image %s with custom removal function", i.ID()) - if err := fn(i.ID()); err != nil { + if err := options.RemoveContainerFunc(i.ID()); err != nil { return err } } @@ -246,6 +251,19 @@ func (i *Image) removeContainers(fn RemoveContainerFunc) error { return err } + if !options.Force && options.ExternalContainers { + // All containers must be external ones. + for _, cID := range containers { + isExternal, err := options.IsExternalContainerFunc(cID) + if err != nil { + return fmt.Errorf("checking if %s is an external container: %w", cID, err) + } + if !isExternal { + return fmt.Errorf("cannot remove container %s: not an external container", cID) + } + } + } + logrus.Debugf("Removing containers of image %s from the local containers storage", i.ID()) var multiE error for _, cID := range containers { @@ -392,11 +410,9 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma return processedIDs, nil } - // Perform the actual removal. First, remove containers if needed. - if options.Force { - if err := i.removeContainers(options.RemoveContainerFunc); err != nil { - return processedIDs, err - } + // Perform the container removal, if needed. + if err := i.removeContainers(options); err != nil { + return processedIDs, err } // Podman/Docker compat: we only report an image as removed if it has @@ -406,7 +422,7 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma if err != nil { // We must be tolerant toward corrupted images. // See containers/podman commit fd9dd7065d44. - logrus.Warnf("error determining if an image is a parent: %v, ignoring the error", err) + logrus.Warnf("Failed to determine if an image is a parent: %v, ignoring the error", err) hasChildren = false } @@ -416,7 +432,7 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma if err != nil { // We must be tolerant toward corrupted images. // See containers/podman commit fd9dd7065d44. - logrus.Warnf("error determining parent of image: %v, ignoring the error", err) + logrus.Warnf("Failed to determine parent of image: %v, ignoring the error", err) parent = nil } @@ -440,7 +456,7 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma if err != nil { // See Podman commit fd9dd7065d44: we need to // be tolerant toward corrupted images. - logrus.Warnf("error determining if an image is a parent: %v, ignoring the error", err) + logrus.Warnf("Failed to determine if an image is a parent: %v, ignoring the error", err) danglingParent = false } if !danglingParent { @@ -462,7 +478,7 @@ func (i *Image) Tag(name string) error { ref, err := NormalizeName(name) if err != nil { - return errors.Wrapf(err, "error normalizing name %q", name) + return errors.Wrapf(err, "normalizing name %q", name) } if _, isDigested := ref.(reference.Digested); isDigested { @@ -499,7 +515,7 @@ func (i *Image) Untag(name string) error { ref, err := NormalizeName(name) if err != nil { - return errors.Wrapf(err, "error normalizing name %q", name) + return errors.Wrapf(err, "normalizing name %q", name) } // FIXME: this is breaking Podman CI but must be re-enabled once @@ -885,12 +901,12 @@ func getImageID(ctx context.Context, src types.ImageReference, sys *types.System } defer func() { if err := newImg.Close(); err != nil { - logrus.Errorf("failed to close image: %q", err) + logrus.Errorf("Failed to close image: %q", err) } }() imageDigest := newImg.ConfigInfo().Digest if err = imageDigest.Validate(); err != nil { - return "", errors.Wrapf(err, "error getting config info") + return "", errors.Wrapf(err, "getting config info") } return "@" + imageDigest.Encoded(), nil } diff --git a/vendor/github.com/containers/common/libimage/load.go b/vendor/github.com/containers/common/libimage/load.go index 33dc1a22f..f2b57c43a 100644 --- a/vendor/github.com/containers/common/libimage/load.go +++ b/vendor/github.com/containers/common/libimage/load.go @@ -2,7 +2,7 @@ package libimage import ( "context" - "errors" + "fmt" "os" "time" @@ -28,66 +28,69 @@ func (r *Runtime) Load(ctx context.Context, path string, options *LoadOptions) ( defer r.writeEvent(&Event{ID: "", Name: path, Time: time.Now(), Type: EventTypeImageLoad}) } - var ( - loadedImages []string - loadError error - ) - if options == nil { options = &LoadOptions{} } - for _, f := range []func() ([]string, error){ + var loadErrors []error + + for _, f := range []func() ([]string, string, error){ // OCI - func() ([]string, error) { + func() ([]string, string, error) { logrus.Debugf("-> Attempting to load %q as an OCI directory", path) ref, err := ociTransport.NewReference(path, "") if err != nil { - return nil, err + return nil, ociTransport.Transport.Name(), err } - return r.copyFromDefault(ctx, ref, &options.CopyOptions) + images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions) + return images, ociTransport.Transport.Name(), err }, // OCI-ARCHIVE - func() ([]string, error) { + func() ([]string, string, error) { logrus.Debugf("-> Attempting to load %q as an OCI archive", path) ref, err := ociArchiveTransport.NewReference(path, "") if err != nil { - return nil, err + return nil, ociArchiveTransport.Transport.Name(), err } - return r.copyFromDefault(ctx, ref, &options.CopyOptions) + images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions) + return images, ociArchiveTransport.Transport.Name(), err }, // DIR - func() ([]string, error) { + func() ([]string, string, error) { logrus.Debugf("-> Attempting to load %q as a Docker dir", path) ref, err := dirTransport.NewReference(path) if err != nil { - return nil, err + return nil, dirTransport.Transport.Name(), err } - return r.copyFromDefault(ctx, ref, &options.CopyOptions) + images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions) + return images, dirTransport.Transport.Name(), err }, // DOCKER-ARCHIVE - func() ([]string, error) { + func() ([]string, string, error) { logrus.Debugf("-> Attempting to load %q as a Docker archive", path) ref, err := dockerArchiveTransport.ParseReference(path) if err != nil { - return nil, err + return nil, dockerArchiveTransport.Transport.Name(), err } - return r.loadMultiImageDockerArchive(ctx, ref, &options.CopyOptions) - }, - - // Give a decent error message if nothing above worked. - func() ([]string, error) { - return nil, errors.New("payload does not match any of the supported image formats (oci, oci-archive, dir, docker-archive)") + images, err := r.loadMultiImageDockerArchive(ctx, ref, &options.CopyOptions) + return images, dockerArchiveTransport.Transport.Name(), err }, } { - loadedImages, loadError = f() - if loadError == nil { - return loadedImages, loadError + loadedImages, transportName, err := f() + if err == nil { + return loadedImages, nil } - logrus.Debugf("Error loading %s: %v", path, loadError) + logrus.Debugf("Error loading %s (%s): %v", path, transportName, err) + loadErrors = append(loadErrors, fmt.Errorf("%s: %v", transportName, err)) + } + + // Give a decent error message if nothing above worked. + loadError := fmt.Errorf("payload does not match any of the supported image formats:") + for _, err := range loadErrors { + loadError = fmt.Errorf("%v\n * %v", loadError, err) } return nil, loadError diff --git a/vendor/github.com/containers/common/libimage/manifests/manifests.go b/vendor/github.com/containers/common/libimage/manifests/manifests.go index 81b5343c0..8d1abfba9 100644 --- a/vendor/github.com/containers/common/libimage/manifests/manifests.go +++ b/vendor/github.com/containers/common/libimage/manifests/manifests.go @@ -125,19 +125,19 @@ func (l *list) SaveToImage(store storage.Store, imageID string, names []string, if err != nil { if created { if _, err2 := store.DeleteImage(img.ID, true); err2 != nil { - logrus.Errorf("error deleting image %q after failing to save manifest for it", img.ID) + logrus.Errorf("Deleting image %q after failing to save manifest for it", img.ID) } } - return "", errors.Wrapf(err, "error saving manifest list to image %q", imageID) + return "", errors.Wrapf(err, "saving manifest list to image %q", imageID) } err = store.SetImageBigData(imageID, instancesData, instancesBytes, nil) if err != nil { if created { if _, err2 := store.DeleteImage(img.ID, true); err2 != nil { - logrus.Errorf("error deleting image %q after failing to save instance locations for it", img.ID) + logrus.Errorf("Deleting image %q after failing to save instance locations for it", img.ID) } } - return "", errors.Wrapf(err, "error saving instance list to image %q", imageID) + return "", errors.Wrapf(err, "saving instance list to image %q", imageID) } return imageID, nil } @@ -200,7 +200,7 @@ func (l *list) Push(ctx context.Context, dest types.ImageReference, options Push } defer func() { if err2 := policyContext.Destroy(); err2 != nil { - logrus.Errorf("error destroying signature policy context: %v", err2) + logrus.Errorf("Destroying signature policy context: %v", err2) } }() diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go index 42461014d..dabadbec0 100644 --- a/vendor/github.com/containers/common/libimage/runtime.go +++ b/vendor/github.com/containers/common/libimage/runtime.go @@ -2,6 +2,7 @@ package libimage import ( "context" + "fmt" "os" "strings" @@ -306,7 +307,7 @@ func (r *Runtime) lookupImageInLocalStorage(name, candidate string, options *Loo if errors.Cause(err) == os.ErrNotExist { // We must be tolerant toward corrupted images. // See containers/podman commit fd9dd7065d44. - logrus.Warnf("error determining if an image is a manifest list: %v, ignoring the error", err) + logrus.Warnf("Failed to determine if an image is a manifest list: %v, ignoring the error", err) return image, nil } return nil, err @@ -484,10 +485,16 @@ func (r *Runtime) imageReferenceMatchesContext(ref types.ImageReference, options return true, nil } +// IsExternalContainerFunc allows for checking whether the specified container +// is an external one. The definition of an external container can be set by +// callers. +type IsExternalContainerFunc func(containerID string) (bool, error) + // ListImagesOptions allow for customizing listing images. type ListImagesOptions struct { // Filters to filter the listed images. Supported filters are // * after,before,since=image + // * containers=true,false,external // * dangling=true,false // * intermediate=true,false (useful for pruning images) // * id=id @@ -495,6 +502,11 @@ type ListImagesOptions struct { // * readonly=true,false // * reference=name[:tag] (wildcards allowed) Filters []string + // IsExternalContainerFunc allows for checking whether the specified + // container is an external one (when containers=external filter is + // used). The definition of an external container can be set by + // callers. + IsExternalContainerFunc IsExternalContainerFunc } // ListImages lists images in the local container storage. If names are @@ -525,7 +537,7 @@ func (r *Runtime) ListImages(ctx context.Context, names []string, options *ListI var filters []filterFunc if len(options.Filters) > 0 { - compiledFilters, err := r.compileImageFilters(ctx, options.Filters) + compiledFilters, err := r.compileImageFilters(ctx, options) if err != nil { return nil, err } @@ -550,8 +562,17 @@ type RemoveImagesOptions struct { // containers using a specific image. By default, all containers in // the local containers storage will be removed (if Force is set). RemoveContainerFunc RemoveContainerFunc + // IsExternalContainerFunc allows for checking whether the specified + // container is an external one (when containers=external filter is + // used). The definition of an external container can be set by + // callers. + IsExternalContainerFunc IsExternalContainerFunc + // Remove external containers even when Force is false. Requires + // IsExternalContainerFunc to be specified. + ExternalContainers bool // Filters to filter the removed images. Supported filters are // * after,before,since=image + // * containers=true,false,external // * dangling=true,false // * intermediate=true,false (useful for pruning images) // * id=id @@ -581,6 +602,10 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem options = &RemoveImagesOptions{} } + if options.ExternalContainers && options.IsExternalContainerFunc == nil { + return nil, []error{fmt.Errorf("libimage error: cannot remove external containers without callback")} + } + // The logic here may require some explanation. Image removal is // surprisingly complex since it is recursive (intermediate parents are // removed) and since multiple items in `names` may resolve to the @@ -635,7 +660,11 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem } default: - filteredImages, err := r.ListImages(ctx, nil, &ListImagesOptions{Filters: options.Filters}) + options := &ListImagesOptions{ + IsExternalContainerFunc: options.IsExternalContainerFunc, + Filters: options.Filters, + } + filteredImages, err := r.ListImages(ctx, nil, options) if err != nil { appendError(err) return nil, rmErrors diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go index 4f11e4ed2..735d19493 100644 --- a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go +++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go @@ -97,22 +97,22 @@ func InstallDefault(name string) error { } if err := cmd.Start(); err != nil { if pipeErr := pipe.Close(); pipeErr != nil { - logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr) + logrus.Errorf("Unable to close AppArmor pipe: %q", pipeErr) } return errors.Wrapf(err, "start %s command", apparmorParserPath) } if err := p.generateDefault(apparmorParserPath, pipe); err != nil { if pipeErr := pipe.Close(); pipeErr != nil { - logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr) + logrus.Errorf("Unable to close AppArmor pipe: %q", pipeErr) } if cmdErr := cmd.Wait(); cmdErr != nil { - logrus.Errorf("unable to wait for AppArmor command: %q", cmdErr) + logrus.Errorf("Unable to wait for AppArmor command: %q", cmdErr) } return errors.Wrap(err, "generate default profile into pipe") } if pipeErr := pipe.Close(); pipeErr != nil { - logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr) + logrus.Errorf("Unable to close AppArmor pipe: %q", pipeErr) } return errors.Wrap(cmd.Wait(), "wait for AppArmor command") @@ -252,7 +252,7 @@ func CheckProfileAndLoadDefault(name string) (string, error) { if name != "" { return "", errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name) } else { - logrus.Debug("skipping loading default AppArmor profile (rootless mode)") + logrus.Debug("Skipping loading default AppArmor profile (rootless mode)") return "", nil } } @@ -292,7 +292,7 @@ func CheckProfileAndLoadDefault(name string) (string, error) { if err != nil { return "", errors.Wrapf(err, "install profile %s", name) } - logrus.Infof("successfully loaded AppAmor profile %q", name) + logrus.Infof("Successfully loaded AppAmor profile %q", name) } else { logrus.Infof("AppAmor profile %q is already loaded", name) } diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index c1f63577a..3b4c7fa04 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -54,6 +54,8 @@ type Config struct { Containers ContainersConfig `toml:"containers"` // Engine specifies how the container engine based on Engine will run Engine EngineConfig `toml:"engine"` + // Machine specifies configurations of podman machine VMs + Machine MachineConfig `toml:"machine"` // Network section defines the configuration of CNI Plugins Network NetworkConfig `toml:"network"` // Secret section defines configurations for the secret management @@ -281,9 +283,6 @@ type EngineConfig struct { // MachineEnabled indicates if Podman is running in a podman-machine VM MachineEnabled bool `toml:"machine_enabled,omitempty"` - // MachineImage is the image used when creating a podman-machine VM - MachineImage string `toml:"machine_image,omitempty"` - // MultiImageArchive - if true, the container engine allows for storing // archives (e.g., of the docker-archive transport) with multiple // images. By default, Podman creates single-image archives. @@ -490,6 +489,18 @@ type SecretConfig struct { Opts map[string]string `toml:"opts,omitempty"` } +// MachineConfig represents the "machine" TOML config table +type MachineConfig struct { + // Number of CPU's a machine is created with. + CPUs uint64 `toml:"cpus,omitempty"` + // DiskSize is the size of the disk in GB created when init-ing a podman-machine VM + DiskSize uint64 `toml:"disk_size,omitempty"` + // MachineImage is the image used when init-ing a podman-machine VM + Image string `toml:"image,omitempty"` + // Memory in MB a machine is created with. + Memory uint64 `toml:"memory,omitempty"` +} + // Destination represents destination for remote service type Destination struct { // URI, required. Example: ssh://root@example.com:22/run/podman/podman.sock diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf index 7c72ec79f..1d3c003e3 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf +++ b/vendor/github.com/containers/common/pkg/config/containers.conf @@ -396,10 +396,6 @@ default_sysctls = [ # #machine_enabled = false -# The image used when creating a podman-machine VM. -# -#machine_image = "testing" - # MultiImageArchive - if true, the container engine allows for storing archives # (e.g., of the docker-archive transport) with multiple images. By default, # Podman creates single-image archives. @@ -559,8 +555,25 @@ default_sysctls = [ [engine.volume_plugins] #testplugin = "/run/podman/plugins/test.sock" -# The [engine.volume_plugins] table MUST be the last entry in this file. +[machine] +# Number of CPU's a machine is created with. +# +#cpus=1 + +# The size of the disk in GB created when init-ing a podman-machine VM. +# +#disk_size=10 + +# The image used when creating a podman-machine VM. +# +#image = "testing" + +# Memory in MB a machine is created with. +# +#memory=2048 + +# The [machine] table MUST be the last entry in this file. # (Unless another table is added) # TOML does not provide a way to end a table other than a further table being -# defined, so every key hereafter will be part of [volume_plugins] and not the +# defined, so every key hereafter will be part of [machine] and not the # main config. diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index 34d17d72c..e72e1b3e4 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -208,6 +208,7 @@ func DefaultConfig() (*Config, error) { }, Engine: *defaultEngineConfig, Secrets: defaultSecretConfig(), + Machine: defaultMachineConfig(), }, nil } @@ -219,6 +220,16 @@ func defaultSecretConfig() SecretConfig { } } +// defaultMachineConfig returns the default machine configuration. +func defaultMachineConfig() MachineConfig { + return MachineConfig{ + CPUs: 1, + DiskSize: 10, + Image: "testing", + Memory: 2048, + } +} + // defaultConfigFromMemory returns a default engine configuration. Note that the // config is different for root and rootless. It also parses the storage.conf. func defaultConfigFromMemory() (*EngineConfig, error) { @@ -345,8 +356,6 @@ func defaultConfigFromMemory() (*EngineConfig, error) { // constants. c.LockType = "shm" c.MachineEnabled = false - c.MachineImage = "testing" - c.ChownCopiedFiles = true return c, nil @@ -566,9 +575,3 @@ func (c *Config) MachineEnabled() bool { func (c *Config) RootlessNetworking() string { return c.Containers.RootlessNetworking } - -// MachineImage returns the image to be -// used when creating a podman-machine VM -func (c *Config) MachineImage() string { - return c.Engine.MachineImage -} diff --git a/vendor/github.com/containers/common/pkg/retry/retry.go b/vendor/github.com/containers/common/pkg/retry/retry.go index 8eb2da975..43e3a6688 100644 --- a/vendor/github.com/containers/common/pkg/retry/retry.go +++ b/vendor/github.com/containers/common/pkg/retry/retry.go @@ -30,7 +30,7 @@ func RetryIfNecessary(ctx context.Context, operation func() error, retryOptions if retryOptions.Delay != 0 { delay = retryOptions.Delay } - logrus.Warnf("failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err) + logrus.Warnf("Failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err) select { case <-time.After(delay): break diff --git a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go index 4b7253b31..6c9321e73 100644 --- a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go +++ b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go @@ -114,13 +114,13 @@ func getMounts(filePath string) []string { file, err := os.Open(filePath) if err != nil { // This is expected on most systems - logrus.Debugf("file %q not found, skipping...", filePath) + logrus.Debugf("File %q not found, skipping...", filePath) return nil } defer file.Close() scanner := bufio.NewScanner(file) if err = scanner.Err(); err != nil { - logrus.Errorf("error reading file %q, %v skipping...", filePath, err) + logrus.Errorf("Reading file %q, %v skipping...", filePath, err) return nil } var mounts []string @@ -128,7 +128,7 @@ func getMounts(filePath string) []string { if strings.HasPrefix(strings.TrimSpace(scanner.Text()), "/") { mounts = append(mounts, scanner.Text()) } else { - logrus.Debugf("skipping unrecognized mount in %v: %q", + logrus.Debugf("Skipping unrecognized mount in %v: %q", filePath, scanner.Text()) } } @@ -176,7 +176,7 @@ func MountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPoint str if _, err := os.Stat(file); err == nil { mounts, err := addSubscriptionsFromMountsFile(file, mountLabel, containerWorkingDir, uid, gid) if err != nil { - logrus.Warnf("error mounting subscriptions, skipping entry in %s: %v", file, err) + logrus.Warnf("Failed to mount subscriptions, skipping entry in %s: %v", file, err) } subscriptionMounts = mounts break @@ -192,7 +192,7 @@ func MountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPoint str switch { case err == nil: if err := addFIPSModeSubscription(&subscriptionMounts, containerWorkingDir, mountPoint, mountLabel, uid, gid); err != nil { - logrus.Errorf("error adding FIPS mode subscription to container: %v", err) + logrus.Errorf("Adding FIPS mode subscription to container: %v", err) } case os.IsNotExist(err): logrus.Debug("/etc/system-fips does not exist on host, not mounting FIPS mode subscription") diff --git a/vendor/github.com/containers/common/pkg/supplemented/supplemented.go b/vendor/github.com/containers/common/pkg/supplemented/supplemented.go index a36c3eda4..196176a1c 100644 --- a/vendor/github.com/containers/common/pkg/supplemented/supplemented.go +++ b/vendor/github.com/containers/common/pkg/supplemented/supplemented.go @@ -83,12 +83,12 @@ func (s *supplementedImageReference) NewImageSource(ctx context.Context, sys *ty if iss != nil { // The composite source has been created. Use its Close method. if err2 := iss.Close(); err2 != nil { - logrus.Errorf("error opening image: %v", err2) + logrus.Errorf("Opening image: %v", err2) } } else if top != nil { // The composite source has not been created, but the top was already opened. Close it. if err2 := top.Close(); err2 != nil { - logrus.Errorf("error opening image: %v", err2) + logrus.Errorf("Closing image: %v", err2) } } } diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go index 1935d71f1..6420ba274 100644 --- a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go +++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go @@ -237,7 +237,7 @@ func checkCgroupPids(cgMounts map[string]string, quiet bool) cgroupPids { _, ok := cgMounts["pids"] if !ok { if !quiet { - logrus.Warn("unable to find pids cgroup in mounts") + logrus.Warn("Unable to find pids cgroup in mounts") } return cgroupPids{} } diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index ba4dda5e6..b6ceabce5 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.44.1-dev" +const Version = "0.46.1-dev" diff --git a/vendor/modules.txt b/vendor/modules.txt index 661619f98..1fb03d302 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -97,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.20210921143342-f2f10e650c73 +# github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6 github.com/containers/common/libimage github.com/containers/common/libimage/manifests github.com/containers/common/pkg/apparmor |