diff options
125 files changed, 809 insertions, 208 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 621430670..1a7153848 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -12,6 +12,9 @@ documented on the top of Podman's [README.md](../README.md). If they differ, pl update your version of Podman to the latest possible and retry your command before creating an issue. +Also, there is a running list of known issues in the [Podman Troubleshooting Guide](https://github.com/containers/podman/blob/master/troubleshooting.md), +please reference that page before opening a new issue. + If you are filing a bug against `podman build`, please instead file a bug against Buildah (https://github.com/containers/buildah/issues). Podman build executes Buildah to perform container builds, and as such the Buildah @@ -64,4 +67,8 @@ Briefly describe the problem you are having in a few paragraphs. (paste your output here) ``` +**Have you tested with the latest version of Podman and have you checked the Podman Troubleshooting Guide?** + +Yes/No + **Additional environment details (AWS, VirtualBox, physical, etc.):** @@ -305,7 +305,7 @@ testunit: libpodimage ## Run unittest on the built image localunit: test/goecho/goecho varlink_generate hack/check_root.sh make localunit rm -rf ${COVERAGE_PATH} && mkdir -p ${COVERAGE_PATH} - ginkgo \ + $(GOBIN)/ginkgo \ -r \ $(TESTFLAGS) \ --skipPackage test/e2e,pkg/apparmor,test/endpoint,pkg/bindings,hack \ @@ -321,16 +321,16 @@ localunit: test/goecho/goecho varlink_generate .PHONY: ginkgo ginkgo: - ginkgo -v $(TESTFLAGS) -tags "$(BUILDTAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -nodes 3 -debug test/e2e/. hack/. + $(GOBIN)/ginkgo -v $(TESTFLAGS) -tags "$(BUILDTAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -nodes 3 -debug test/e2e/. hack/. .PHONY: ginkgo-remote ginkgo-remote: - ginkgo -v $(TESTFLAGS) -tags "$(REMOTETAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor test/e2e/. + $(GOBIN)/ginkgo -v $(TESTFLAGS) -tags "$(REMOTETAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor test/e2e/. .PHONY: endpoint ifneq (,$(findstring varlink,$(BUILDTAGS))) endpoint: - ginkgo -v $(TESTFLAGS) -tags "$(BUILDTAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -debug test/endpoint/. + $(GOBIN)/ginkgo -v $(TESTFLAGS) -tags "$(BUILDTAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -debug test/endpoint/. endpoint: endif diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 5c6c47e8d..bf50bb56b 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -511,6 +511,8 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string } switch con[0] { + case "proc-opts": + s.ProcOpts = strings.Split(con[1], ",") case "label": // TODO selinux opts and label opts are the same thing s.ContainerSecurityConfig.SelinuxOpts = append(s.ContainerSecurityConfig.SelinuxOpts, con[1]) diff --git a/cmd/podman/images/save.go b/cmd/podman/images/save.go index 024045b9d..82a3513f5 100644 --- a/cmd/podman/images/save.go +++ b/cmd/podman/images/save.go @@ -5,10 +5,9 @@ import ( "os" "strings" - "github.com/containers/podman/v2/libpod/define" - "github.com/containers/podman/v2/cmd/podman/parse" "github.com/containers/podman/v2/cmd/podman/registry" + "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/pkg/domain/entities" "github.com/containers/podman/v2/pkg/util" "github.com/pkg/errors" @@ -83,9 +82,10 @@ func saveFlags(flags *pflag.FlagSet) { } -func save(cmd *cobra.Command, args []string) error { +func save(cmd *cobra.Command, args []string) (finalErr error) { var ( - tags []string + tags []string + succeeded = false ) if cmd.Flag("compress").Changed && (saveOpts.Format != define.OCIManifestDir && saveOpts.Format != define.V2s2ManifestDir && saveOpts.Format == "") { return errors.Errorf("--compress can only be set when --format is either 'oci-dir' or 'docker-dir'") @@ -95,7 +95,22 @@ func save(cmd *cobra.Command, args []string) error { if terminal.IsTerminal(int(fi.Fd())) { return errors.Errorf("refusing to save to terminal. Use -o flag or redirect") } - saveOpts.Output = "/dev/stdout" + pipePath, cleanup, err := setupPipe() + if err != nil { + return err + } + if cleanup != nil { + defer func() { + errc := cleanup() + if succeeded { + writeErr := <-errc + if writeErr != nil && finalErr == nil { + finalErr = writeErr + } + } + }() + } + saveOpts.Output = pipePath } if err := parse.ValidateFileName(saveOpts.Output); err != nil { return err @@ -103,5 +118,9 @@ func save(cmd *cobra.Command, args []string) error { if len(args) > 1 { tags = args[1:] } - return registry.ImageEngine().Save(context.Background(), args[0], tags, saveOpts) + err := registry.ImageEngine().Save(context.Background(), args[0], tags, saveOpts) + if err == nil { + succeeded = true + } + return err } diff --git a/cmd/podman/images/utils_linux.go b/cmd/podman/images/utils_linux.go new file mode 100644 index 000000000..5521abab4 --- /dev/null +++ b/cmd/podman/images/utils_linux.go @@ -0,0 +1,47 @@ +package images + +import ( + "io" + "io/ioutil" + "os" + "path/filepath" + + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "golang.org/x/sys/unix" +) + +// setupPipe for fixing https://github.com/containers/podman/issues/7017 +// uses named pipe since containers/image EvalSymlinks fails with /dev/stdout +// the caller should use the returned function to clean up the pipeDir +func setupPipe() (string, func() <-chan error, error) { + errc := make(chan error) + pipeDir, err := ioutil.TempDir(os.TempDir(), "pipeDir") + if err != nil { + return "", nil, err + } + pipePath := filepath.Join(pipeDir, "saveio") + err = unix.Mkfifo(pipePath, 0600) + if err != nil { + if e := os.RemoveAll(pipeDir); e != nil { + logrus.Errorf("error removing named pipe: %q", e) + } + return "", nil, errors.Wrapf(err, "error creating named pipe") + } + go func() { + fpipe, err := os.Open(pipePath) + if err != nil { + errc <- err + return + } + _, err = io.Copy(os.Stdout, fpipe) + fpipe.Close() + errc <- err + }() + return pipePath, func() <-chan error { + if e := os.RemoveAll(pipeDir); e != nil { + logrus.Errorf("error removing named pipe: %q", e) + } + return errc + }, nil +} diff --git a/cmd/podman/images/utils_unsupported.go b/cmd/podman/images/utils_unsupported.go new file mode 100644 index 000000000..69d1df786 --- /dev/null +++ b/cmd/podman/images/utils_unsupported.go @@ -0,0 +1,7 @@ +// +build !linux + +package images + +func setupPipe() (string, func() <-chan error, error) { + return "/dev/stdout", nil, nil +} diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 2aa7267c2..dd9c75ece 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -290,6 +290,7 @@ func resolveDestination() (string, string) { cfg, err := config.ReadCustomConfig() if err != nil { + logrus.Warning(errors.Wrap(err, "unable to read local containers.conf")) return registry.DefaultAPIAddress(), "" } diff --git a/cmd/podman/system/connection/add.go b/cmd/podman/system/connection/add.go index 89cea10ca..af13b970c 100644 --- a/cmd/podman/system/connection/add.go +++ b/cmd/podman/system/connection/add.go @@ -124,6 +124,7 @@ func add(cmd *cobra.Command, args []string) error { cfg.Engine.ServiceDestinations = map[string]config.Destination{ args[0]: dst, } + cfg.Engine.ActiveService = args[0] } else { cfg.Engine.ServiceDestinations[args[0]] = dst } @@ -181,12 +182,20 @@ func getUDS(cmd *cobra.Command, uri *url.URL) (string, error) { authMethods = append(authMethods, ssh.PublicKeysCallback(a.Signers)) } - config := &ssh.ClientConfig{ + if len(authMethods) == 0 { + pass, err := terminal.ReadPassword(fmt.Sprintf("%s's login password:", uri.User.Username())) + if err != nil { + return "", err + } + authMethods = append(authMethods, ssh.Password(string(pass))) + } + + cfg := &ssh.ClientConfig{ User: uri.User.Username(), Auth: authMethods, HostKeyCallback: ssh.InsecureIgnoreHostKey(), } - dial, err := ssh.Dial("tcp", uri.Host, config) + dial, err := ssh.Dial("tcp", uri.Host, cfg) if err != nil { return "", errors.Wrapf(err, "failed to connect to %q", uri.Host) } diff --git a/contrib/build_rpm.sh b/contrib/build_rpm.sh index a4f1817b9..6a82b131f 100755 --- a/contrib/build_rpm.sh +++ b/contrib/build_rpm.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euxo pipefail # returned path can vary: /usr/bin/dnf /bin/dnf ... diff --git a/contrib/cirrus/add_second_partition.sh b/contrib/cirrus/add_second_partition.sh index 73db192c5..3c2f9f056 100644 --- a/contrib/cirrus/add_second_partition.sh +++ b/contrib/cirrus/add_second_partition.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # N/B: This script could mega f*!@up your disks if run by mistake. # it is left without the execute-bit on purpose! diff --git a/contrib/cirrus/apiv2_test.sh b/contrib/cirrus/apiv2_test.sh index 546fe8e30..dbee078b6 100755 --- a/contrib/cirrus/apiv2_test.sh +++ b/contrib/cirrus/apiv2_test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/build_release.sh b/contrib/cirrus/build_release.sh index 45634f368..46fe9781f 100755 --- a/contrib/cirrus/build_release.sh +++ b/contrib/cirrus/build_release.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/build_swagger.sh b/contrib/cirrus/build_swagger.sh index 0471f0c10..eb9288dcd 100755 --- a/contrib/cirrus/build_swagger.sh +++ b/contrib/cirrus/build_swagger.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/build_vm_images.sh b/contrib/cirrus/build_vm_images.sh index 543f83a14..be1c82185 100755 --- a/contrib/cirrus/build_vm_images.sh +++ b/contrib/cirrus/build_vm_images.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e source $(dirname $0)/lib.sh diff --git a/contrib/cirrus/check_image.sh b/contrib/cirrus/check_image.sh index 13172fe1c..04867ca64 100755 --- a/contrib/cirrus/check_image.sh +++ b/contrib/cirrus/check_image.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eo pipefail diff --git a/contrib/cirrus/container_test.sh b/contrib/cirrus/container_test.sh index b56a12232..8ea66e63c 100644 --- a/contrib/cirrus/container_test.sh +++ b/contrib/cirrus/container_test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -xeo pipefail export GOPATH=/var/tmp/go diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh index c65f5e25f..636d67411 100755 --- a/contrib/cirrus/integration_test.sh +++ b/contrib/cirrus/integration_test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh index 968b2de39..3292e9d14 100644 --- a/contrib/cirrus/lib.sh +++ b/contrib/cirrus/lib.sh @@ -376,7 +376,7 @@ install_scl_git() { echo "Installing SoftwareCollections updated 'git' version." ooe.sh $SUDO yum -y install rh-git29 cat << "EOF" | $SUDO tee /usr/bin/git -#!/bin/bash +#!/usr/bin/env bash scl enable rh-git29 -- git $@ EOF diff --git a/contrib/cirrus/lib.sh.t b/contrib/cirrus/lib.sh.t index 8f4080dd5..204af1245 100755 --- a/contrib/cirrus/lib.sh.t +++ b/contrib/cirrus/lib.sh.t @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Unit tests for some functions in lib.sh # diff --git a/contrib/cirrus/logcollector.sh b/contrib/cirrus/logcollector.sh index 859da2966..fd5017b44 100755 --- a/contrib/cirrus/logcollector.sh +++ b/contrib/cirrus/logcollector.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/networking.sh b/contrib/cirrus/networking.sh index 2546fab71..824d03e44 100755 --- a/contrib/cirrus/networking.sh +++ b/contrib/cirrus/networking.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script attempts basic confirmation of functional networking # by connecting to a set of essential external servers and failing diff --git a/contrib/cirrus/notice_branch_failure.sh b/contrib/cirrus/notice_branch_failure.sh index f030c12e5..b810bd266 100755 --- a/contrib/cirrus/notice_branch_failure.sh +++ b/contrib/cirrus/notice_branch_failure.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/ooe.sh b/contrib/cirrus/ooe.sh index 3c8a0409d..0966b5ce8 100755 --- a/contrib/cirrus/ooe.sh +++ b/contrib/cirrus/ooe.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script executes a command while logging all output to a temporary # file. If the command exits non-zero, then all output is sent to the console, diff --git a/contrib/cirrus/packer/fedora_base-setup.sh b/contrib/cirrus/packer/fedora_base-setup.sh index f271abee0..bf29a1aec 100644 --- a/contrib/cirrus/packer/fedora_base-setup.sh +++ b/contrib/cirrus/packer/fedora_base-setup.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # N/B: This script is not intended to be run by humans. It is used to configure the # fedora base image for importing, so that it will boot in GCE diff --git a/contrib/cirrus/packer/fedora_packaging.sh b/contrib/cirrus/packer/fedora_packaging.sh index 4a8f62e45..fcf9eb93f 100644 --- a/contrib/cirrus/packer/fedora_packaging.sh +++ b/contrib/cirrus/packer/fedora_packaging.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is called from fedora_setup.sh and various Dockerfiles. # It's not intended to be used outside of those contexts. It assumes the lib.sh diff --git a/contrib/cirrus/packer/fedora_setup.sh b/contrib/cirrus/packer/fedora_setup.sh index 25b568e8a..16ae87d8a 100644 --- a/contrib/cirrus/packer/fedora_setup.sh +++ b/contrib/cirrus/packer/fedora_setup.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is called by packer on the subject fedora VM, to setup the podman # build/test environment. It's not intended to be used outside of this context. diff --git a/contrib/cirrus/packer/image-builder-image_base-setup.sh b/contrib/cirrus/packer/image-builder-image_base-setup.sh index 78772da09..26fbe2903 100644 --- a/contrib/cirrus/packer/image-builder-image_base-setup.sh +++ b/contrib/cirrus/packer/image-builder-image_base-setup.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is called by packer on a vanilla CentOS VM, to setup the image # used for building images FROM base images. It's not intended to be used diff --git a/contrib/cirrus/packer/make-user-data.sh b/contrib/cirrus/packer/make-user-data.sh index 7f7fa1c1a..676a50f5c 100644 --- a/contrib/cirrus/packer/make-user-data.sh +++ b/contrib/cirrus/packer/make-user-data.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is utilized by Makefile, it's not intended to be run by humans diff --git a/contrib/cirrus/packer/prior-fedora_base-setup.sh b/contrib/cirrus/packer/prior-fedora_base-setup.sh index f271abee0..bf29a1aec 100644 --- a/contrib/cirrus/packer/prior-fedora_base-setup.sh +++ b/contrib/cirrus/packer/prior-fedora_base-setup.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # N/B: This script is not intended to be run by humans. It is used to configure the # fedora base image for importing, so that it will boot in GCE diff --git a/contrib/cirrus/packer/systemd_banish.sh b/contrib/cirrus/packer/systemd_banish.sh index 6e2dd9c3e..2219f2a4f 100755 --- a/contrib/cirrus/packer/systemd_banish.sh +++ b/contrib/cirrus/packer/systemd_banish.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set +e # Not all of these exist on every platform diff --git a/contrib/cirrus/packer/ubuntu_packaging.sh b/contrib/cirrus/packer/ubuntu_packaging.sh index 935e81147..c478028b5 100644 --- a/contrib/cirrus/packer/ubuntu_packaging.sh +++ b/contrib/cirrus/packer/ubuntu_packaging.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is called from ubuntu_setup.sh and various Dockerfiles. # It's not intended to be used outside of those contexts. It assumes the lib.sh diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh index 2febbd265..d650e6c76 100644 --- a/contrib/cirrus/packer/ubuntu_setup.sh +++ b/contrib/cirrus/packer/ubuntu_setup.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is called by packer on the subject Ubuntu VM, to setup the podman # build/test environment. It's not intended to be used outside of this context. diff --git a/contrib/cirrus/packer/xfedora_setup.sh b/contrib/cirrus/packer/xfedora_setup.sh index 25b568e8a..16ae87d8a 100644 --- a/contrib/cirrus/packer/xfedora_setup.sh +++ b/contrib/cirrus/packer/xfedora_setup.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is called by packer on the subject fedora VM, to setup the podman # build/test environment. It's not intended to be used outside of this context. diff --git a/contrib/cirrus/rootless_test.sh b/contrib/cirrus/rootless_test.sh index 63cbec69b..31db18302 100755 --- a/contrib/cirrus/rootless_test.sh +++ b/contrib/cirrus/rootless_test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/setup_container_environment.sh b/contrib/cirrus/setup_container_environment.sh index c268c162e..72542df17 100755 --- a/contrib/cirrus/setup_container_environment.sh +++ b/contrib/cirrus/setup_container_environment.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e source $(dirname $0)/lib.sh diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 0b9d686d3..eeae96469 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/success.sh b/contrib/cirrus/success.sh index 3b171757f..8783f6b81 100755 --- a/contrib/cirrus/success.sh +++ b/contrib/cirrus/success.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/system_test.sh b/contrib/cirrus/system_test.sh index 546fe8e30..dbee078b6 100755 --- a/contrib/cirrus/system_test.sh +++ b/contrib/cirrus/system_test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/unit_test.sh b/contrib/cirrus/unit_test.sh index 2852c31ae..17a618a1c 100755 --- a/contrib/cirrus/unit_test.sh +++ b/contrib/cirrus/unit_test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/cirrus/update_meta.sh b/contrib/cirrus/update_meta.sh index 618cd670c..6e4a473e9 100755 --- a/contrib/cirrus/update_meta.sh +++ b/contrib/cirrus/update_meta.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash source $(dirname $0)/lib.sh diff --git a/contrib/cirrus/upload_release_archive.sh b/contrib/cirrus/upload_release_archive.sh index e1b8937b7..2e2f4ddde 100755 --- a/contrib/cirrus/upload_release_archive.sh +++ b/contrib/cirrus/upload_release_archive.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eo pipefail diff --git a/contrib/gate/entrypoint.sh b/contrib/gate/entrypoint.sh index ab6528e00..102d012e5 100755 --- a/contrib/gate/entrypoint.sh +++ b/contrib/gate/entrypoint.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/imgprune/entrypoint.sh b/contrib/imgprune/entrypoint.sh index b0f006332..fd80d9b26 100755 --- a/contrib/imgprune/entrypoint.sh +++ b/contrib/imgprune/entrypoint.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/imgts/entrypoint.sh b/contrib/imgts/entrypoint.sh index 9c653eda0..b089e1e9b 100755 --- a/contrib/imgts/entrypoint.sh +++ b/contrib/imgts/entrypoint.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/imgts/lib_entrypoint.sh b/contrib/imgts/lib_entrypoint.sh index 3f6b11128..6eb5cdc2f 100644 --- a/contrib/imgts/lib_entrypoint.sh +++ b/contrib/imgts/lib_entrypoint.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/contrib/msi/podman.wxs b/contrib/msi/podman.wxs index c2c2cea4f..ff8160a53 100644 --- a/contrib/msi/podman.wxs +++ b/contrib/msi/podman.wxs @@ -24,8 +24,7 @@ <CreateFolder/> </Component> <Component Id="MainExecutable" Guid="73752F94-6589-4C7B-ABED-39D655A19714"> - <File Id="520C6E17-77A2-4F41-9611-30FA763A0702" Name="podman-remote-windows.exe" Source="bin/podman-remote-windows.exe"/> - <File Id="A14218A0-4180-44AC-B109-7C63B3099DCA" Name="podman.bat" Source="podman.bat" KeyPath="yes"/> + <File Id="520C6E17-77A2-4F41-9611-30FA763A0702" Name="podman.exe" Source="bin/podman-remote-windows.exe" KeyPath="yes"/> </Component> </Directory> </Directory> @@ -33,7 +32,7 @@ </Directory> <Property Id="setx" Value="setx.exe"/> - <CustomAction Id="ChangePath" ExeCommand="PATH "%PATH%;[INSTALLDIR] "" Property="setx" Execute="deferred" Impersonate="yes" Return="check"/> + <CustomAction Id="ChangePath" ExeCommand="PATH "%PATH%;[INSTALLDIR]"" Property="setx" Execute="deferred" Impersonate="yes" Return="check"/> <Feature Id="Complete" Level="1"> <ComponentRef Id="INSTALLDIR_Component"/> diff --git a/contrib/podmanimage/README.md b/contrib/podmanimage/README.md index 9d841cdba..d6abb8ae6 100644 --- a/contrib/podmanimage/README.md +++ b/contrib/podmanimage/README.md @@ -4,12 +4,19 @@ ## Overview -This directory contains the Dockerfiles necessary to create the three podmanimage container -images that are housed on quay.io under the Podman account. All three repositories where +This directory contains the Dockerfiles necessary to create the podmanimage container +images that are housed on quay.io under the Podman account. All repositories where the images live are public and can be pulled without credentials. These container images are secured and the -resulting containers can run safely with privileges within the container. The container images are built -using the latest Fedora and then Podman is installed into them: +resulting containers can run safely with privileges within the container. +The container images are built using the latest Fedora and then Podman is installed into them. +The PATH in the container images is set to the default PATH provided by Fedora. Also, the +ENTRYPOINT and the WORKDIR variables are not set within these container images, as such they +default to `/`. + +The container images are: + + * quay.io/containers/podman - This image is built using the latest stable version of Podman in a Fedora based container. Built with [podmanimage/stable/Dockerfile](stable/Dockerfile). * quay.io/podman/stable - This image is built using the latest stable version of Podman in a Fedora based container. Built with [podmanimage/stable/Dockerfile](stable/Dockerfile). * quay.io/podman/upstream - This image is built using the latest code found in this GitHub repository. When someone creates a commit and pushes it, the image is created. Due to that the image changes frequently and is not guaranteed to be stable. Built with [podmanimage/upstream/Dockerfile](upstream/Dockerfile). * quay.io/podman/testing - This image is built using the latest version of Podman that is or was in updates testing for Fedora. At times this may be the same as the stable image. This container image will primarily be used by the development teams for verification testing when a new package is created. Built with [podmanimage/testing/Dockerfile](testing/Dockerfile). diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in index 2411eaabc..363aa60d7 100644 --- a/contrib/spec/podman.spec.in +++ b/contrib/spec/podman.spec.in @@ -91,6 +91,7 @@ Recommends: container-selinux Recommends: slirp4netns Recommends: fuse-overlayfs %endif +Recommends: xz # vendored libraries # awk '{print "Provides: bundled(golang("$1")) = "$2}' vendor.conf | sort diff --git a/contrib/systemd/system/podman.service b/contrib/systemd/system/podman.service index c8751168d..e14bbe078 100644 --- a/contrib/systemd/system/podman.service +++ b/contrib/systemd/system/podman.service @@ -6,5 +6,6 @@ Documentation=man:podman-system-service(1) StartLimitIntervalSec=0 [Service] -Type=simple +Type=notify +KillMode=process ExecStart=/usr/bin/podman system service diff --git a/contrib/upldrel/entrypoint.sh b/contrib/upldrel/entrypoint.sh index dc0e69676..6eb1b8f94 100755 --- a/contrib/upldrel/entrypoint.sh +++ b/contrib/upldrel/entrypoint.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/docs/remote-docs.sh b/docs/remote-docs.sh index 4774b94a3..6d520fae6 100755 --- a/docs/remote-docs.sh +++ b/docs/remote-docs.sh @@ -1,5 +1,6 @@ -#!/bin/bash -e +#!/usr/bin/env bash # Assemble remote man pages for darwin or windows from markdown files +set -e PLATFORM=$1 ## linux, windows or darwin TARGET=${2} ## where to output files diff --git a/docs/source/Commands.rst b/docs/source/Commands.rst index a3ff24e89..096bdbedf 100644 --- a/docs/source/Commands.rst +++ b/docs/source/Commands.rst @@ -98,7 +98,7 @@ Commands :doc:`top <markdown/podman-top.1>` Display the running processes of a container -:doc:`umount <markdown/podman-umount.1>` Unmounts working container's root filesystem +:doc:`unmount <markdown/podman-unmount.1>` Unmounts working container's root filesystem :doc:`unpause <markdown/podman-unpause.1>` Unpause the processes in one or more containers diff --git a/docs/source/image.rst b/docs/source/image.rst index fe3a7aa3b..2b0ef3d43 100644 --- a/docs/source/image.rst +++ b/docs/source/image.rst @@ -18,7 +18,7 @@ Image :doc:`load <markdown/podman-load.1>` Load an image from container archive -:doc:`mount <markdown/podman-images-mount.1>` Mount an image's root filesystem. +:doc:`mount <markdown/podman-image-mount.1>` Mount an image's root filesystem. :doc:`prune <markdown/podman-image-prune.1>` Remove unused images @@ -40,6 +40,6 @@ Image :doc:`trust <markdown/podman-image-trust.1>` Manage container image trust policy -:doc:`untag <markdown/podman-untag.1>` Removes one or more names from a locally-stored image - :doc:`unmount <markdown/podman-unmount.1>` Unmount an image's root filesystem + +:doc:`untag <markdown/podman-untag.1>` Removes one or more names from a locally-stored image diff --git a/docs/source/managecontainers.rst b/docs/source/managecontainers.rst index 2e787c9e9..849fd1d25 100644 --- a/docs/source/managecontainers.rst +++ b/docs/source/managecontainers.rst @@ -37,10 +37,10 @@ Manage Containers :doc:`port <markdown/podman-port.1>` List port mappings or a specific mapping for the container -:doc:`restart <markdown/podman-restart.1>` Restart one or more containers - :doc:`prune <markdown/podman-container-prune.1>` Remove all stopped containers +:doc:`restart <markdown/podman-restart.1>` Restart one or more containers + :doc:`restore <markdown/podman-container-restore.1>` Restores one or more containers from a checkpoint :doc:`rm <markdown/podman-rm.1>` Remove one or more containers diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 5c58d59fc..05aea53b6 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -563,6 +563,7 @@ Valid values are: - `private`: create a new namespace for the container (default) - `slirp4netns[:OPTIONS,...]`: use slirp4netns to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options: - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`). Default is false. + - **cidr=CIDR**: Specify ip range to use for this network. (Default is `10.0.2.0/24`). - **enable_ipv6=true|false**: Enable IPv6. Default is false. (Required for `outbound_addr6`). - **outbound_addr=INTERFACE**: Specify the outbound interface slirp should bind to (ipv4 traffic only). - **outbound_addr=IPv4**: Specify the outbound ipv4 address slirp should bind to. @@ -755,6 +756,9 @@ Security Options - `seccomp=unconfined` : Turn off seccomp confinement for the container - `seccomp=profile.json` : White listed syscalls seccomp Json file to be used as a seccomp filter +- `proc-opts=OPTIONS` : Comma separated list of options to use for the /proc mount. More details for the + possible mount options are specified at **proc(5)** man page. + Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file. **--shm-size**=*size* @@ -801,8 +805,8 @@ Run container in systemd mode. The default is *true*. The value *always* enforces the systemd mode is enforced without looking at the executable name. Otherwise, if set to true and the -command you are running inside the container is systemd, /usr/sbin/init -or /sbin/init. +command you are running inside the container is systemd, /usr/sbin/init, +/sbin/init or /usr/local/sbin/init. If the command you are running inside of the container is systemd, Podman will setup tmpfs mount points in the following directories: @@ -1167,7 +1171,7 @@ b NOTE: Use the environment variable `TMPDIR` to change the temporary storage location of downloaded container images. Podman defaults to use `/var/tmp`. ## SEE ALSO -**subgid**(5), **subuid**(5), **containers.conf**(5), **systemd.unit**(5), **setsebool**(8), **slirp4netns**(1), **fuse-overlayfs**(1). +**subgid**(5), **subuid**(5), **containers.conf**(5), **systemd.unit**(5), **setsebool**(8), **slirp4netns**(1), **fuse-overlayfs**(1), **proc**(5)**. ## HISTORY October 2017, converted from Docker documentation to Podman by Dan Walsh for Podman <dwalsh@redhat.com> diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index db742e429..ef78e15e3 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -570,9 +570,15 @@ Valid _mode_ values are: - **ns:**_path_: path to a network namespace to join; - `private`: create a new namespace for the container (default) - **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options: - **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default. - **port_handler=slirp4netns**: Use the slirp4netns port forwarding. - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`). Default to false. + - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`). Default is false. + - **cidr=CIDR**: Specify ip range to use for this network. (Default is `10.0.2.0/24`). + - **enable_ipv6=true|false**: Enable IPv6. Default is false. (Required for `outbound_addr6`). + - **outbound_addr=INTERFACE**: Specify the outbound interface slirp should bind to (ipv4 traffic only). + - **outbound_addr=IPv4**: Specify the outbound ipv4 address slirp should bind to. + - **outbound_addr6=INTERFACE**: Specify the outbound interface slirp should bind to (ipv6 traffic only). + - **outbound_addr6=IPv6**: Specify the outbound ipv6 address slirp should bind to. + - **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default. + - **port_handler=slirp4netns**: Use the slirp4netns port forwarding. **--network-alias**=*alias* @@ -768,6 +774,8 @@ Security Options - **no-new-privileges**: Disable container processes from gaining additional privileges - **seccomp=unconfined**: Turn off seccomp confinement for the container - **seccomp**=_profile.json_: Allowed syscall list seccomp JSON file to be used as a seccomp filter +- **proc-opts**=_OPTIONS_ : Comma separated list of options to use for the /proc mount. More details + for the possible mount options are specified at **proc(5)** man page. Note: Labeling can be disabled for all containers by setting **label=false** in the **containers.conf**(5) file. @@ -831,8 +839,8 @@ Run container in systemd mode. The default is **true**. The value *always* enforces the systemd mode is enforced without looking at the executable name. Otherwise, if set to **true** and the -command you are running inside the container is systemd, _/usr/sbin/init_ -or _/sbin/init_. +command you are running inside the container is systemd, _/usr/sbin/init_, +_/sbin/init_ or _/usr/local/sbin/init_. If the command you are running inside of the container is systemd Podman will setup tmpfs mount points in the following directories: @@ -1443,7 +1451,7 @@ b NOTE: Use the environment variable `TMPDIR` to change the temporary storage location of downloaded container images. Podman defaults to use `/var/tmp`. ## SEE ALSO -**subgid**(5), **subuid**(5), **containers.conf**(5), **systemd.unit**(5), **setsebool**(8), **slirp4netns**(1), **fuse-overlayfs**(1). +**subgid**(5), **subuid**(5), **containers.conf**(5), **systemd.unit**(5), **setsebool**(8), **slirp4netns**(1), **fuse-overlayfs**(1), **proc**(5)**. ## HISTORY September 2018, updated by Kunal Kushwaha <kushwaha_kunal_v7@lab.ntt.co.jp> diff --git a/docs/source/system.rst b/docs/source/system.rst index e3dfa9d01..566fd1a95 100644 --- a/docs/source/system.rst +++ b/docs/source/system.rst @@ -1,7 +1,7 @@ System ====== -:doc:`connection <markdown/podman-system-conection.1>` Manage the destination(s) for Podman service(s) +:doc:`connection <connection>` Manage the destination(s) for Podman service(s) :doc:`df <markdown/podman-system-df.1>` Show podman disk usage @@ -15,7 +15,7 @@ require ( github.com/containers/conmon v2.0.19+incompatible github.com/containers/image/v5 v5.5.1 github.com/containers/psgo v1.5.1 - github.com/containers/storage v1.21.2 + github.com/containers/storage v1.23.0 github.com/coreos/go-systemd/v22 v22.1.0 github.com/cri-o/ocicni v0.2.0 github.com/cyphar/filepath-securejoin v0.2.2 @@ -62,7 +62,7 @@ require ( golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 - k8s.io/api v0.18.6 - k8s.io/apimachinery v0.18.6 + k8s.io/api v0.18.8 + k8s.io/apimachinery v0.18.8 k8s.io/client-go v0.0.0-20190620085101-78d2af792bab ) @@ -81,7 +81,6 @@ github.com/containers/image/v5 v5.5.1 h1:h1FCOXH6Ux9/p/E4rndsQOC4yAdRU0msRTfLVeQ github.com/containers/image/v5 v5.5.1/go.mod h1:4PyNYR0nwlGq/ybVJD9hWlhmIsNra4Q8uOQX2s6E2uM= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= -github.com/containers/ocicrypt v1.0.2 h1:Q0/IPs8ohfbXNxEfyJ2pFVmvJu5BhqJUAmc6ES9NKbo= github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNjsqWarIUce4M= github.com/containers/ocicrypt v1.0.3 h1:vYgl+RZ9Q3DPMuTfxmN+qp0X2Bj52uuY2vnt6GzVe1c= github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g= @@ -90,6 +89,8 @@ github.com/containers/psgo v1.5.1/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzP github.com/containers/storage v1.20.2/go.mod h1:oOB9Ie8OVPojvoaKWEGSEtHbXUAs+tSyr7RO7ZGteMc= github.com/containers/storage v1.21.2 h1:bf9IqA+g6ClBviqVG5lVCp5tTH9lvWwjYws7mVYSti0= github.com/containers/storage v1.21.2/go.mod h1:I1EIAA7B4OwWRSA0b4yq2AW1wjvvfcY0zLWQuwTa4zw= +github.com/containers/storage v1.23.0 h1:gYyNkBiihC2FvGiHOjOjpnfojYwgxpLVooTUlmD6pxs= +github.com/containers/storage v1.23.0/go.mod h1:I1EIAA7B4OwWRSA0b4yq2AW1wjvvfcY0zLWQuwTa4zw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38= @@ -145,13 +146,12 @@ github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsouza/go-dockerclient v1.6.5 h1:vuFDnPcds3LvTWGYb9h0Rty14FLgkjHZdwLDROCdgsw= github.com/fsouza/go-dockerclient v1.6.5/go.mod h1:GOdftxWLWIbIWKbIMDroKFJzPdg6Iw7r+jX1DDZdVsA= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= @@ -244,6 +244,7 @@ github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07 h1:rw3IAne6CDuVF github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jamescun/tuntap v0.0.0-20190712092105-cb1fb277045c/go.mod h1:zzwpsgcYhzzIP5WyF8g9ivCv38cY9uAV9Gu0m3lThhE= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -639,11 +640,11 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A= -k8s.io/api v0.18.6 h1:osqrAXbOQjkKIWDTjrqxWQ3w0GkKb1KA1XkUGHHYpeE= -k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI= +k8s.io/api v0.18.8 h1:aIKUzJPb96f3fKec2lxtY7acZC9gQNDLVhfSGpxBAC4= +k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY= k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= -k8s.io/apimachinery v0.18.6 h1:RtFHnfGNfd1N0LeSrKCUznz5xtUP1elRGvHJbL3Ntag= -k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= +k8s.io/apimachinery v0.18.8 h1:jimPrycCqgx2QPearX3to1JePz7wSbVLq+7PdBTTwQ0= +k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig= k8s.io/client-go v0.0.0-20190620085101-78d2af792bab h1:E8Fecph0qbNsAbijJJQryKu4Oi9QTp5cVpjTE+nqg6g= k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= diff --git a/hack/apparmor_tag.sh b/hack/apparmor_tag.sh index 0fd222210..794370e79 100755 --- a/hack/apparmor_tag.sh +++ b/hack/apparmor_tag.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash if pkg-config libapparmor 2> /dev/null ; then echo apparmor fi diff --git a/hack/btrfs_installed_tag.sh b/hack/btrfs_installed_tag.sh index 357f33b8b..c4d99f377 100755 --- a/hack/btrfs_installed_tag.sh +++ b/hack/btrfs_installed_tag.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash cc -E - > /dev/null 2> /dev/null << EOF #include <btrfs/ioctl.h> EOF diff --git a/hack/btrfs_tag.sh b/hack/btrfs_tag.sh index cc48504ab..59cb969ad 100755 --- a/hack/btrfs_tag.sh +++ b/hack/btrfs_tag.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash cc -E - > /dev/null 2> /dev/null << EOF #include <btrfs/version.h> EOF diff --git a/hack/check_root.sh b/hack/check_root.sh index 203eae9d3..1f53887ff 100755 --- a/hack/check_root.sh +++ b/hack/check_root.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash if ! [ $(id -u) = 0 ]; then echo "Please run as root! '$@' requires root privileges." exit 1 diff --git a/hack/get_ci_vm.sh b/hack/get_ci_vm.sh index 05b7a4a6d..b37dba508 100755 --- a/hack/get_ci_vm.sh +++ b/hack/get_ci_vm.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/hack/get_release_info.sh b/hack/get_release_info.sh index c1c694a44..69cf8cd57 100755 --- a/hack/get_release_info.sh +++ b/hack/get_release_info.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script produces various bits of metadata needed by Makefile. Using # a script allows uniform behavior across multiple environments and diff --git a/hack/golangci-lint.sh b/hack/golangci-lint.sh index 8c81a3743..03c29c89a 100755 --- a/hack/golangci-lint.sh +++ b/hack/golangci-lint.sh @@ -1,6 +1,7 @@ -#!/bin/bash -e +#!/usr/bin/env bash # Need to run linter twice to cover all the build tags code paths +set -e declare -A BUILD_TAGS # TODO: add systemd tag diff --git a/hack/install_bats.sh b/hack/install_bats.sh index 00ded07a9..d30e3daf8 100755 --- a/hack/install_bats.sh +++ b/hack/install_bats.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/hack/install_catatonit.sh b/hack/install_catatonit.sh index 7fd7592a9..8837db3a8 100755 --- a/hack/install_catatonit.sh +++ b/hack/install_catatonit.sh @@ -1,7 +1,8 @@ -#!/bin/bash -e +#!/usr/bin/env bash BASE_PATH="/usr/libexec/podman" CATATONIT_PATH="${BASE_PATH}/catatonit" CATATONIT_VERSION="v0.1.4" +set -e if [ -f $CATATONIT_PATH ]; then echo "skipping ... catatonit is already installed" diff --git a/hack/install_golangci.sh b/hack/install_golangci.sh index 6ef8ce823..57cdd2e4d 100755 --- a/hack/install_golangci.sh +++ b/hack/install_golangci.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/hack/libdm_tag.sh b/hack/libdm_tag.sh index d1f83ba10..d3668aab1 100755 --- a/hack/libdm_tag.sh +++ b/hack/libdm_tag.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash tmpdir="$PWD/tmp.$RANDOM" mkdir -p "$tmpdir" trap 'rm -fr "$tmpdir"' EXIT diff --git a/hack/man-page-checker b/hack/man-page-checker index d2cc6c6e1..45f9edbd1 100755 --- a/hack/man-page-checker +++ b/hack/man-page-checker @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # man-page-checker - validate and cross-reference man page names # diff --git a/hack/podman-commands.sh b/hack/podman-commands.sh index da4d446aa..587cac782 100755 --- a/hack/podman-commands.sh +++ b/hack/podman-commands.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Compare commands listed by 'podman help' against those in 'man podman'. # Recurse into subcommands as well. diff --git a/hack/podmanv2-retry b/hack/podmanv2-retry index ea77486ff..1f3be0731 100755 --- a/hack/podmanv2-retry +++ b/hack/podmanv2-retry @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # podman-try - try running a command via PODMAN1; use PODMAN2 as fallback # diff --git a/hack/selinux_tag.sh b/hack/selinux_tag.sh index ff80fda04..993630ad6 100755 --- a/hack/selinux_tag.sh +++ b/hack/selinux_tag.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash if pkg-config libselinux 2> /dev/null ; then echo selinux fi diff --git a/hack/tree_status.sh b/hack/tree_status.sh index ac874a347..2f56cdcd3 100755 --- a/hack/tree_status.sh +++ b/hack/tree_status.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e SUGGESTION="${SUGGESTION:-sync the vendor.conf and commit all changes.}" diff --git a/hack/xref-helpmsgs-manpages b/hack/xref-helpmsgs-manpages index 16b596589..7b617eed7 100755 --- a/hack/xref-helpmsgs-manpages +++ b/hack/xref-helpmsgs-manpages @@ -26,8 +26,14 @@ $| = 1; my $Default_Podman = './bin/podman'; my $PODMAN = $ENV{PODMAN} || $Default_Podman; +# Path to all doc files, including .rst and (down one level) markdown +my $Docs_Path = 'docs/source'; + # Path to podman markdown source files (of the form podman-*.1.md) -my $Markdown_Path = 'docs/source/markdown'; +my $Markdown_Path = "$Docs_Path/markdown"; + +# Global error count +my $Errs = 0; # END user-customizable section ############################################################################### @@ -96,35 +102,38 @@ sub main { my $help = podman_help(); my $man = podman_man('podman'); + my $rst = podman_rst(); + + xref_by_help($help, $man); + xref_by_man($help, $man); - my $retval = xref_by_help($help, $man) - + xref_by_man($help, $man); + xref_rst($help, $rst); - exit !!$retval; + exit !!$Errs; } +############################################################################### +# BEGIN cross-referencing + ################## # xref_by_help # Find keys in '--help' but not in man ################## sub xref_by_help { my ($help, $man, @subcommand) = @_; - my $errs = 0; for my $k (sort keys %$help) { if (exists $man->{$k}) { if (ref $help->{$k}) { - $errs += xref_by_help($help->{$k}, $man->{$k}, @subcommand, $k); + xref_by_help($help->{$k}, $man->{$k}, @subcommand, $k); } # Otherwise, non-ref is leaf node such as a --option } else { my $man = $man->{_path} || 'man'; warn "$ME: podman @subcommand --help lists $k, but $k not in $man\n"; - ++$errs; + ++$Errs; } } - - return $errs; } ################# @@ -137,13 +146,11 @@ sub xref_by_help { sub xref_by_man { my ($help, $man, @subcommand) = @_; - my $errs = 0; - # FIXME: this generates way too much output for my $k (grep { $_ ne '_path' } sort keys %$man) { if (exists $help->{$k}) { if (ref $man->{$k}) { - $errs += xref_by_man($help->{$k}, $man->{$k}, @subcommand, $k); + xref_by_man($help->{$k}, $man->{$k}, @subcommand, $k); } } elsif ($k ne '--help' && $k ne '-h') { @@ -175,13 +182,38 @@ sub xref_by_man { next if "@subcommand" eq 'system' && $k eq 'service'; warn "$ME: podman @subcommand: $k in $man, but not --help\n"; - ++$errs; + ++$Errs; } } +} - return $errs; +############## +# xref_rst # Cross-check *.rst files against help +############## +sub xref_rst { + my ($help, $rst, @subcommand) = @_; + + # Cross-check against rst (but only subcommands, not options). + # We key on $help because that is Absolute Truth: anything in podman --help + # must be referenced in an rst (the converse is not true). + for my $k (sort grep { $_ !~ /^-/ } keys %$help) { + # Check for subcommands, if any (eg podman system -> connection -> add) + if (ref $help->{$k}) { + xref_rst($help->{$k}, $rst->{$k}, @subcommand, $k); + } + + # Check that command is mentioned in at least one .rst file + if (! exists $rst->{$k}{_desc}) { + my @podman = ("podman", @subcommand, $k); + warn "$ME: no link in *.rst for @podman\n"; + ++$Errs; + } + } } +# END cross-referencing +############################################################################### +# BEGIN data gathering ################# # podman_help # Parse output of 'podman [subcommand] --help' @@ -249,6 +281,7 @@ sub podman_man { or die "$ME: Cannot read $manpath: $!\n"; my $section = ''; my @most_recent_flags; + my $previous_subcmd = ''; while (my $line = <$fh>) { chomp $line; next unless $line; # skip empty lines @@ -278,6 +311,11 @@ sub podman_man { elsif ($line =~ /^\|\s+(\S+)\s+\|\s+\[\S+\]\((\S+)\.1\.md\)/) { # $1 will be changed by recursion _*BEFORE*_ left-hand assignment my $subcmd = $1; + if ($previous_subcmd gt $subcmd) { + warn "$ME: $subpath: '$previous_subcmd' and '$subcmd' are out of order\n"; + ++$Errs; + } + $previous_subcmd = $subcmd; $man{$subcmd} = podman_man($2); } } @@ -315,4 +353,76 @@ sub podman_man { } +################ +# podman_rst # Parse contents of docs/source/*.rst +################ +sub podman_rst { + my %rst; + + # Read all .rst files, looking for ":doc:`subcmd <target>` description" + for my $rst (glob "$Docs_Path/*.rst") { + open my $fh, '<', $rst + or die "$ME: Cannot read $rst: $!\n"; + + # The basename of foo.rst is usually, but not always, the name of + # a podman subcommand. There are a few special cases: + (my $command = $rst) =~ s!^.*/(.*)\.rst!$1!; + + my $subcommand_href = \%rst; + if ($command eq 'Commands') { + ; + } + elsif ($command eq 'managecontainers') { + $subcommand_href = $rst{container} //= { }; + } + elsif ($command eq 'connection') { + $subcommand_href = $rst{system}{connection} //= { }; + } + else { + $subcommand_href = $rst{$command} //= { }; + } + + my $previous_subcommand = ''; + while (my $line = <$fh>) { + if ($line =~ /^:doc:`(\S+)\s+<(.*?)>`\s+(.*)/) { + my ($subcommand, $target, $desc) = ($1, $2, $3); + + # Check that entries are in alphabetical order + if ($subcommand lt $previous_subcommand) { + warn "$ME: $rst:$.: '$previous_subcommand' and '$subcommand' are out of order\n"; + ++$Errs; + } + $previous_subcommand = $subcommand; + + # Mark this subcommand as documented. + $subcommand_href->{$subcommand}{_desc} = $desc; + + # Check for invalid links. These will be one of two forms: + # <markdown/foo.1> -> markdown/foo.1.md + # <foo> -> foo.rst + if ($target =~ m!^markdown/!) { + if (! -e "$Docs_Path/$target.md") { + warn "$ME: $rst:$.: '$subcommand' links to nonexistent $target\n"; + ++$Errs; + } + } + else { + if (! -e "$Docs_Path/$target.rst") { + warn "$ME: $rst:$.: '$subcommand' links to nonexistent $target.rst\n"; + } + } + } + } + close $fh; + } + + # Special case: 'image trust set/show' are documented in image-trust.1 + $rst{image}{trust}{$_} = { _desc => 'ok' } for (qw(set show)); + + return \%rst; +} + +# END data gathering +############################################################################### + 1; diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 9fb9738dc..fdee3877c 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -626,7 +626,7 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro Destination: "/sys/fs/cgroup/systemd", Type: "bind", Source: "/sys/fs/cgroup/systemd", - Options: []string{"bind", "nodev", "noexec", "nosuid"}, + Options: []string{"bind", "nodev", "noexec", "nosuid", "rprivate"}, } g.AddMount(systemdMnt) g.AddLinuxMaskedPaths("/sys/fs/cgroup/systemd/release_agent") diff --git a/libpod/events/config.go b/libpod/events/config.go index c34408e63..bb35c03c0 100644 --- a/libpod/events/config.go +++ b/libpod/events/config.go @@ -101,6 +101,8 @@ const ( Attach Status = "attach" // AutoUpdate ... AutoUpdate Status = "auto-update" + // Build ... + Build Status = "build" // Checkpoint ... Checkpoint Status = "checkpoint" // Cleanup ... diff --git a/libpod/events/events.go b/libpod/events/events.go index 0253b1ee5..722c9595e 100644 --- a/libpod/events/events.go +++ b/libpod/events/events.go @@ -127,6 +127,8 @@ func StringToStatus(name string) (Status, error) { switch name { case Attach.String(): return Attach, nil + case Build.String(): + return Build, nil case Checkpoint.String(): return Checkpoint, nil case Cleanup.String(): diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index ed8f82c46..6f266e5d6 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -171,6 +171,7 @@ type slirpFeatures struct { HasMTU bool HasEnableSandbox bool HasEnableSeccomp bool + HasCIDR bool HasOutboundAddr bool HasIPv6 bool } @@ -199,6 +200,7 @@ func checkSlirpFlags(path string) (*slirpFeatures, error) { HasMTU: strings.Contains(string(out), "--mtu"), HasEnableSandbox: strings.Contains(string(out), "--enable-sandbox"), HasEnableSeccomp: strings.Contains(string(out), "--enable-seccomp"), + HasCIDR: strings.Contains(string(out), "--cidr"), HasOutboundAddr: strings.Contains(string(out), "--outbound-addr"), HasIPv6: strings.Contains(string(out), "--enable-ipv6"), }, nil @@ -227,6 +229,7 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error { havePortMapping := len(ctr.Config().PortMappings) > 0 logPath := filepath.Join(ctr.runtime.config.Engine.TmpDir, fmt.Sprintf("slirp4netns-%s.log", ctr.config.ID)) + cidr := "" isSlirpHostForward := false disableHostLoopback := true enableIPv6 := false @@ -240,6 +243,12 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error { option, value := parts[0], parts[1] switch option { + case "cidr": + ipv4, _, err := net.ParseCIDR(value) + if err != nil || ipv4.To4() == nil { + return errors.Errorf("invalid cidr %q", value) + } + cidr = value case "port_handler": switch value { case "slirp4netns": @@ -309,6 +318,13 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error { cmdArgs = append(cmdArgs, "--enable-seccomp") } + if cidr != "" { + if !slirpFeatures.HasCIDR { + return errors.Errorf("cidr not supported") + } + cmdArgs = append(cmdArgs, fmt.Sprintf("--cidr=%s", cidr)) + } + if enableIPv6 { if !slirpFeatures.HasIPv6 { return errors.Errorf("enable_ipv6 not supported") diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go index 4b5129f44..a95cd1d7a 100644 --- a/libpod/runtime_img.go +++ b/libpod/runtime_img.go @@ -17,6 +17,7 @@ import ( "github.com/containers/image/v5/oci/layout" "github.com/containers/image/v5/types" "github.com/containers/podman/v2/libpod/define" + "github.com/containers/podman/v2/libpod/events" "github.com/containers/podman/v2/libpod/image" "github.com/containers/podman/v2/pkg/util" "github.com/containers/storage" @@ -150,9 +151,21 @@ func removeStorageContainers(ctrIDs []string, store storage.Store) error { return 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) + } +} + // Build adds the runtime to the imagebuildah call func (r *Runtime) Build(ctx context.Context, options imagebuildah.BuildOptions, dockerfiles ...string) (string, reference.Canonical, error) { id, ref, err := imagebuildah.BuildDockerfiles(ctx, r.store, options, dockerfiles...) + // Write event for build completion + r.newImageBuildCompleteEvent(id) return id, ref, err } diff --git a/nix/default.nix b/nix/default.nix index 4fe818b39..cc8786ce0 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -7,6 +7,15 @@ let libassuan = (static pkg.libassuan); libgpgerror = (static pkg.libgpgerror); libseccomp = (static pkg.libseccomp); + glib = (static pkg.glib).overrideAttrs(x: { + outputs = [ "bin" "out" "dev" ]; + mesonFlags = [ + "-Ddefault_library=static" + "-Ddevbindir=${placeholder ''dev''}/bin" + "-Dgtk_doc=false" + "-Dnls=disabled" + ]; + }); }; }; }); diff --git a/nix/nixpkgs.json b/nix/nixpkgs.json index 8eeb4f470..976284ed4 100644 --- a/nix/nixpkgs.json +++ b/nix/nixpkgs.json @@ -1,7 +1,7 @@ { "url": "https://github.com/nixos/nixpkgs", - "rev": "b49e7987632e4c7ab3a093fdfc433e1826c4b9d7", - "date": "2020-07-26T09:18:52+02:00", - "sha256": "1mj6fy0p24izmasl653s5z4f2ka9v3b6mys45kjrqmkv889yk2r6", + "rev": "d6a445fe821052861b379d9b6c02d21623c25464", + "date": "2020-08-11T04:28:16+01:00", + "sha256": "064scwaxg8qg4xbmq07hag57saa4bhsb4pgg5h5vfs4nhhwvchg9", "fetchSubmodules": false } diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go index 18b48a3f6..e7c031234 100644 --- a/pkg/api/server/server.go +++ b/pkg/api/server/server.go @@ -2,6 +2,7 @@ package server import ( "context" + "fmt" "log" "net" "net/http" @@ -17,6 +18,7 @@ import ( "github.com/containers/podman/v2/pkg/api/handlers" "github.com/containers/podman/v2/pkg/api/server/idletracker" "github.com/coreos/go-systemd/v22/activation" + "github.com/coreos/go-systemd/v22/daemon" "github.com/gorilla/mux" "github.com/gorilla/schema" "github.com/pkg/errors" @@ -147,8 +149,31 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li return &server, nil } -// Serve starts responding to HTTP requests +// If the NOTIFY_SOCKET is set, communicate the PID and readiness, and +// further unset NOTIFY_SOCKET to prevent containers from sending +// messages and unset INVOCATION_ID so conmon and containers are in +// the correct cgroup. +func setupSystemd() { + if len(os.Getenv("NOTIFY_SOCKET")) == 0 { + return + } + payload := fmt.Sprintf("MAINPID=%d", os.Getpid()) + payload += "\n" + payload += daemon.SdNotifyReady + if sent, err := daemon.SdNotify(true, payload); err != nil { + logrus.Errorf("Error notifying systemd of Conmon PID: %s", err.Error()) + } else if sent { + logrus.Debugf("Notify sent successfully") + } + + if err := os.Unsetenv("INVOCATION_ID"); err != nil { + logrus.Errorf("Error unsetting INVOCATION_ID: %s", err.Error()) + } +} + +// Serve starts responding to HTTP requests. func (s *APIServer) Serve() error { + setupSystemd() sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) errChan := make(chan error, 1) diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go index e820e1c8b..ef9644de8 100644 --- a/pkg/bindings/connection.go +++ b/pkg/bindings/connection.go @@ -180,8 +180,9 @@ func pingNewConnection(ctx context.Context) error { } func sshClient(_url *url.URL, secure bool, passPhrase string, identity string) (Connection, error) { + // if you modify the authmethods or their conditionals, you will also need to make similar + // changes in the client (currently cmd/podman/system/connection/add getUDS). authMethods := []ssh.AuthMethod{} - if len(identity) > 0 { auth, err := terminal.PublicKey(identity, []byte(passPhrase)) if err != nil { @@ -205,6 +206,13 @@ func sshClient(_url *url.URL, secure bool, passPhrase string, identity string) ( if pw, found := _url.User.Password(); found { authMethods = append(authMethods, ssh.Password(pw)) } + if len(authMethods) == 0 { + pass, err := terminal.ReadPassword("Login password:") + if err != nil { + return Connection{}, err + } + authMethods = append(authMethods, ssh.Password(string(pass))) + } callback := ssh.InsecureIgnoreHostKey() if secure { diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go index 0183a90d8..c06714cbb 100644 --- a/pkg/domain/infra/abi/network.go +++ b/pkg/domain/infra/abi/network.go @@ -191,7 +191,7 @@ func createBridge(r *libpod.Runtime, name string, options entities.NetworkCreate var plugins []network.CNIPlugins var routes []network.IPAMRoute - defaultRoute, err := network.NewIPAMDefaultRoute() + defaultRoute, err := network.NewIPAMDefaultRoute(network.IsIPv6(subnet.IP)) if err != nil { return "", err } diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index c7bfdcd2b..b255c5da4 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -9,6 +9,7 @@ import ( "os" "path/filepath" "strings" + "time" "github.com/containers/common/pkg/config" "github.com/containers/image/v5/docker/reference" @@ -73,8 +74,16 @@ func (ir *ImageEngine) History(ctx context.Context, nameOrID string, opts entiti } for i, layer := range results { - hold := entities.ImageHistoryLayer{} - _ = utils.DeepCopy(&hold, layer) + // Created time comes over as an int64 so needs conversion to time.time + t := time.Unix(layer.Created, 0) + hold := entities.ImageHistoryLayer{ + ID: layer.ID, + Created: t.UTC(), + CreatedBy: layer.CreatedBy, + Tags: layer.Tags, + Size: layer.Size, + Comment: layer.Comment, + } history.Layers[i] = hold } return &history, nil diff --git a/pkg/network/ip.go b/pkg/network/ip.go index 1798cd939..ba93a0d05 100644 --- a/pkg/network/ip.go +++ b/pkg/network/ip.go @@ -12,3 +12,8 @@ func CalcGatewayIP(ipn *net.IPNet) net.IP { nid := ipn.IP.Mask(ipn.Mask) return ip.NextIP(nid) } + +// IsIPv6 returns if netIP is IPv6. +func IsIPv6(netIP net.IP) bool { + return netIP != nil && netIP.To4() == nil +} diff --git a/pkg/network/netconflist.go b/pkg/network/netconflist.go index 4271d3f54..8187fdb39 100644 --- a/pkg/network/netconflist.go +++ b/pkg/network/netconflist.go @@ -6,6 +6,11 @@ import ( "path/filepath" ) +const ( + defaultIPv4Route = "0.0.0.0/0" + defaultIPv6Route = "::/0" +) + // NcList describes a generic map type NcList map[string]interface{} @@ -86,9 +91,13 @@ func NewIPAMRoute(r *net.IPNet) IPAMRoute { //nolint:interfacer } // NewIPAMDefaultRoute creates a new IPAMDefault route of -// 0.0.0.0/0 -func NewIPAMDefaultRoute() (IPAMRoute, error) { - _, n, err := net.ParseCIDR("0.0.0.0/0") +// 0.0.0.0/0 for IPv4 or ::/0 for IPv6 +func NewIPAMDefaultRoute(isIPv6 bool) (IPAMRoute, error) { + route := defaultIPv4Route + if isIPv6 { + route = defaultIPv6Route + } + _, n, err := net.ParseCIDR(route) if err != nil { return IPAMRoute{}, err } diff --git a/pkg/network/netconflist_test.go b/pkg/network/netconflist_test.go new file mode 100644 index 000000000..a82a0140a --- /dev/null +++ b/pkg/network/netconflist_test.go @@ -0,0 +1,38 @@ +package network + +import ( + "reflect" + "testing" +) + +func TestNewIPAMDefaultRoute(t *testing.T) { + + tests := []struct { + name string + isIPv6 bool + want IPAMRoute + }{ + { + name: "IPv4 default route", + isIPv6: false, + want: IPAMRoute{defaultIPv4Route}, + }, + { + name: "IPv6 default route", + isIPv6: true, + want: IPAMRoute{defaultIPv6Route}, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + got, err := NewIPAMDefaultRoute(tt.isIPv6) + if err != nil { + t.Errorf("no errorr expected: %v", err) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewIPAMDefaultRoute() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/network/network.go b/pkg/network/network.go index b24c72f5f..db625da56 100644 --- a/pkg/network/network.go +++ b/pkg/network/network.go @@ -137,6 +137,15 @@ func networkIntersect(n1, n2 *net.IPNet) bool { // ValidateUserNetworkIsAvailable returns via an error if a network is available // to be used func ValidateUserNetworkIsAvailable(config *config.Config, userNet *net.IPNet) error { + if len(userNet.IP) == 0 || len(userNet.Mask) == 0 { + return errors.Errorf("network %s's ip or mask cannot be empty", userNet.String()) + } + + ones, bit := userNet.Mask.Size() + if ones == 0 || bit == 0 { + return errors.Errorf("network %s's mask is invalid", userNet.String()) + } + networks, err := GetNetworksFromFilesystem(config) if err != nil { return err diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index c3f1fc7fa..ecd309d36 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -389,14 +389,12 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st lastErr = nil break } else { - fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_DGRAM, 0) + r, w, err := os.Pipe() if err != nil { lastErr = err continue } - r, w := os.NewFile(uintptr(fds[0]), "read file"), os.NewFile(uintptr(fds[1]), "write file") - defer errorhandling.CloseQuiet(r) if _, _, err := becomeRootInUserNS("", path, w); err != nil { diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 40f9bc029..c49d51fc5 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -125,6 +125,7 @@ type SecurityConfig struct { ReadOnlyRootfs bool //read-only ReadOnlyTmpfs bool //read-only-tmpfs Sysctl map[string]string //sysctl + ProcOpts []string } // CreateConfig is a pre OCI spec structure. It represents user input from varlink or the CLI diff --git a/pkg/spec/security.go b/pkg/spec/security.go index fc908b49d..e152e3495 100644 --- a/pkg/spec/security.go +++ b/pkg/spec/security.go @@ -76,6 +76,8 @@ func (c *SecurityConfig) SetSecurityOpts(runtime *libpod.Runtime, securityOpts [ } switch con[0] { + case "proc-opts": + c.ProcOpts = strings.Split(con[1], ",") case "label": c.LabelOpts = append(c.LabelOpts, con[1]) case "apparmor": diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index 4635b755b..fda4c098c 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -164,13 +164,19 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen. } if len(command) > 0 { - if command[0] == "/usr/sbin/init" || command[0] == "/sbin/init" || (filepath.Base(command[0]) == "systemd") { + useSystemdCommands := map[string]bool{ + "/sbin/init": true, + "/usr/sbin/init": true, + "/usr/local/sbin/init": true, + } + if useSystemdCommands[command[0]] || (filepath.Base(command[0]) == "systemd") { useSystemd = true } } default: return nil, errors.Wrapf(err, "invalid value %q systemd option requires 'true, false, always'", s.Systemd) } + logrus.Debugf("using systemd mode: %t", useSystemd) if useSystemd { // is StopSignal was not set by the user then set it to systemd // expected StopSigal diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index ee9f63680..fd324c6e1 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -18,6 +18,18 @@ import ( "golang.org/x/sys/unix" ) +func setProcOpts(s *specgen.SpecGenerator, g *generate.Generator) { + if s.ProcOpts == nil { + return + } + for i := range g.Config.Mounts { + if g.Config.Mounts[i].Destination == "/proc" { + g.Config.Mounts[i].Options = s.ProcOpts + return + } + } +} + func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) error { var ( isRootless = rootless.IsRootless() @@ -341,6 +353,8 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt configSpec.Annotations[define.InspectAnnotationInit] = define.InspectResponseFalse } + setProcOpts(s, &g) + return configSpec, nil } diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index 84a6c36a0..a9161071b 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -289,6 +289,8 @@ type ContainerSecurityConfig struct { ReadOnlyFilesystem bool `json:"read_only_filesystem,omittempty"` // Umask is the umask the init process of the container will be run with. Umask string `json:"umask,omitempty"` + // ProcOpts are the options used for the proc mount. + ProcOpts []string `json:"procfs_opts,omitempty"` } // ContainerCgroupConfig contains configuration information about a container's diff --git a/pkg/varlinkapi/create.go b/pkg/varlinkapi/create.go index 2d3e20f67..e9309a2d4 100644 --- a/pkg/varlinkapi/create.go +++ b/pkg/varlinkapi/create.go @@ -704,7 +704,12 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. if err != nil { return nil, errors.Wrapf(err, "cannot parse bool %s", c.String("systemd")) } - if x && (command[0] == "/usr/sbin/init" || command[0] == "/sbin/init" || (filepath.Base(command[0]) == "systemd")) { + useSystemdCommands := map[string]bool{ + "/sbin/init": true, + "/usr/sbin/init": true, + "/usr/local/sbin/init": true, + } + if x && (useSystemdCommands[command[0]] || (filepath.Base(command[0]) == "systemd")) { systemd = true } } diff --git a/test/apiv2/35-networks.at b/test/apiv2/35-networks.at index fff3f3b1f..4c032c072 100644 --- a/test/apiv2/35-networks.at +++ b/test/apiv2/35-networks.at @@ -3,6 +3,32 @@ # network-related tests # -t GET /networks/non-existing-network 404 +t GET networks/non-existing-network 404 \ + .cause='network not found' + +if root; then + t POST libpod/networks/create?name=network1 '' 200 \ + .Filename~.*/network1\\.conflist + + # --data '{"Subnet":{"IP":"10.10.254.0","Mask":[255,255,255,0]}}' + t POST libpod/networks/create?name=network2 '"Subnet":{"IP":"10.10.254.0","Mask":[255,255,255,0]}' 200 \ + .Filename~.*/network2\\.conflist + + # test for empty mask + t POST libpod/networks/create '"Subnet":{"IP":"10.10.1.0","Mask":[]}' 500 \ + .cause~'.*cannot be empty' + # test for invalid mask + t POST libpod/networks/create '"Subnet":{"IP":"10.10.1.0","Mask":[0,255,255,0]}' 500 \ + .cause~'.*mask is invalid' + + # clean the network + t DELETE libpod/networks/network1 200 \ + .[0].Name~network1 \ + .[0].Err=null + t DELETE libpod/networks/network2 200 \ + .[0].Name~network2 \ + .[0].Err=null + +fi # vim: filetype=sh diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2 index d0bf28b9a..2f01783ff 100755 --- a/test/apiv2/test-apiv2 +++ b/test/apiv2/test-apiv2 @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Usage: test-apiv2 [PORT] # diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go index fcd324cd1..f97e6c1f1 100644 --- a/test/e2e/network_create_test.go +++ b/test/e2e/network_create_test.go @@ -178,6 +178,47 @@ var _ = Describe("Podman network create", func() { Expect(subnet.Contains(containerIP)).To(BeTrue()) }) + It("podman network create with name and IPv6 subnet", func() { + SkipIfRemote() + var ( + results []network.NcList + ) + nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", "newIPv6network"}) + nc.WaitWithDefaultTimeout() + Expect(nc.ExitCode()).To(BeZero()) + + defer podmanTest.removeCNINetwork("newIPv6network") + + // Inspect the network configuration + inspect := podmanTest.Podman([]string{"network", "inspect", "newIPv6network"}) + inspect.WaitWithDefaultTimeout() + + // JSON the network configuration into something usable + err := json.Unmarshal([]byte(inspect.OutputToString()), &results) + Expect(err).To(BeNil()) + result := results[0] + Expect(result["name"]).To(Equal("newIPv6network")) + + // JSON the bridge info + bridgePlugin, err := genericPluginsToBridge(result["plugins"], "bridge") + Expect(err).To(BeNil()) + Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("::/0")) + + // Once a container executes a new network, the nic will be created. We should clean those up + // best we can + defer removeNetworkDevice(bridgePlugin.BrName) + + try := podmanTest.Podman([]string{"run", "-it", "--rm", "--network", "newIPv6network", ALPINE, "sh", "-c", "ip addr show eth0 | grep global | awk ' /inet6 / {print $2}'"}) + try.WaitWithDefaultTimeout() + + _, subnet, err := net.ParseCIDR("fd00:1:2:3:4::/64") + Expect(err).To(BeNil()) + containerIP, _, err := net.ParseCIDR(try.OutputToString()) + Expect(err).To(BeNil()) + // Ensure that the IP the container got is within the subnet the user asked for + Expect(subnet.Contains(containerIP)).To(BeTrue()) + }) + It("podman network create with invalid subnet", func() { nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/17000", "fail"}) nc.WaitWithDefaultTimeout() diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index d735217d6..83befe730 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -293,6 +293,22 @@ var _ = Describe("Podman run networking", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman run slirp4netns network with different cidr", func() { + slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"}) + Expect(slirp4netnsHelp.ExitCode()).To(Equal(0)) + + networkConfiguration := "slirp4netns:cidr=192.168.0.0/24,allow_host_loopback=true" + session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, ALPINE, "ping", "-c1", "192.168.0.2"}) + session.Wait(30) + + if strings.Contains(slirp4netnsHelp.OutputToString(), "cidr") { + Expect(session.ExitCode()).To(Equal(0)) + } else { + Expect(session.ExitCode()).ToNot(Equal(0)) + Expect(session.ErrorToString()).To(ContainSubstring("cidr not supported")) + } + }) + It("podman run network bind to 127.0.0.1", func() { slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"}) Expect(slirp4netnsHelp.ExitCode()).To(Equal(0)) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 30e565894..6c65a23e8 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -827,6 +827,15 @@ USER mail` Expect(isSharedOnly).Should(BeTrue()) }) + It("podman run --security-opts proc-opts=", func() { + session := podmanTest.Podman([]string{"run", "--security-opt", "proc-opts=nosuid,exec", fedoraMinimal, "findmnt", "-noOPTIONS", "/proc"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + output := session.OutputToString() + Expect(output).To(ContainSubstring("nosuid")) + Expect(output).To(Not(ContainSubstring("exec"))) + }) + It("podman run --mount type=bind,bind-nonrecursive", func() { SkipIfRootless() session := podmanTest.Podman([]string{"run", "--mount", "type=bind,bind-nonrecursive,slave,src=/,target=/host", fedoraMinimal, "findmnt", "-nR", "/host"}) diff --git a/test/system/110-history.bats b/test/system/110-history.bats index b83e90fe4..5dc221d61 100644 --- a/test/system/110-history.bats +++ b/test/system/110-history.bats @@ -3,8 +3,6 @@ load helpers @test "podman history - basic tests" { - skip_if_remote "FIXME: pending #7122" - tests=" | .*[0-9a-f]\\\{12\\\} .* CMD .* LABEL --format '{{.ID}} {{.Created}}' | .*[0-9a-f]\\\{12\\\} .* ago diff --git a/test/system/120-load.bats b/test/system/120-load.bats index 2fcabcd8a..14dae4c8a 100644 --- a/test/system/120-load.bats +++ b/test/system/120-load.bats @@ -26,6 +26,16 @@ verify_iid_and_name() { is "$new_img_name" "$1" "Name & tag of restored image" } +@test "podman save to pipe and load" { + # We can't use run_podman because that uses the BATS 'run' function + # which redirects stdout and stderr. Here we need to guarantee + # that podman's stdout is a pipe, not any other form of redirection + $PODMAN save --format oci-archive $IMAGE | cat >$PODMAN_TMPDIR/test.tar + [ $status -eq 0 ] + + run_podman load -i $PODMAN_TMPDIR/test.tar +} + @test "podman load - by image ID" { # FIXME: how to build a simple archive instead? diff --git a/test/system/260-sdnotify.bats b/test/system/260-sdnotify.bats index c37eea15a..6bc9fc02e 100644 --- a/test/system/260-sdnotify.bats +++ b/test/system/260-sdnotify.bats @@ -12,8 +12,15 @@ _SOCAT_LOG= function setup() { skip_if_remote - # TODO: remove this once CI systems have newer crun and container-selinux - skip "TEMPORARY SKIP - until CI systems get new crun, container-selinux" + # Skip if systemd is not running + systemctl list-units &>/dev/null || skip "systemd not available" + + # sdnotify fails with runc 1.0.0-3-dev2 on Ubuntu. Let's just + # assume that we work only with crun, nothing else. + run_podman info --format '{{ .Host.OCIRuntime.Name }}' + if [[ "$output" != "crun" ]]; then + skip "this test only works with crun, not '$output'" + fi basic_setup } @@ -107,7 +114,7 @@ function _assert_mainpid_is_conmon() { @test "sdnotify : container" { # Sigh... we need to pull a humongous image because it has systemd-notify. # FIXME: is there a smaller image we could use? - _FEDORA=registry.fedoraproject.org/fedora:latest + _FEDORA=registry.fedoraproject.org/fedora:31 # Pull that image. Retry in case of flakes. run_podman pull $_FEDORA || \ diff --git a/test/system/400-unprivileged-access.bats b/test/system/400-unprivileged-access.bats index 1b2d14554..142d7dcd9 100644 --- a/test/system/400-unprivileged-access.bats +++ b/test/system/400-unprivileged-access.bats @@ -23,7 +23,7 @@ load helpers # as a user, the parent directory must be world-readable. test_script=$PODMAN_TMPDIR/fail-if-writable cat >$test_script <<"EOF" -#!/bin/bash +#!/usr/bin/env bash path="$1" diff --git a/test/system/helpers.t b/test/system/helpers.t index bee09505c..7a331174b 100755 --- a/test/system/helpers.t +++ b/test/system/helpers.t @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # regression tests for helpers.bash # diff --git a/test/test_podman_baseline.sh b/test/test_podman_baseline.sh index d205f544a..3624d24c2 100755 --- a/test/test_podman_baseline.sh +++ b/test/test_podman_baseline.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # test_podman_baseline.sh # A script to be run at the command line with Podman installed. # This should be run against a new kit to provide base level testing @@ -215,7 +215,7 @@ podman run $image ls / ######## FILE=./runecho.sh /bin/cat <<EOM >$FILE -#!/bin/bash +#!/usr/bin/env bash for i in {1..9}; do echo "This is a new container pull ipbabble [" \$i "]" diff --git a/test/test_podman_build.sh b/test/test_podman_build.sh index e3e53cae6..29b7354b1 100644 --- a/test/test_podman_build.sh +++ b/test/test_podman_build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # test_podman_build.sh # diff --git a/test/test_podman_pods.sh b/test/test_podman_pods.sh index f2f47f510..c19f4fcab 100755 --- a/test/test_podman_pods.sh +++ b/test/test_podman_pods.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # test_podman_pods.sh # A script to be run at the command line with Podman installed. # This should be run against a new kit to provide base level testing diff --git a/vendor/github.com/containers/storage/.cirrus.yml b/vendor/github.com/containers/storage/.cirrus.yml index ce99cb0a5..fe611f085 100644 --- a/vendor/github.com/containers/storage/.cirrus.yml +++ b/vendor/github.com/containers/storage/.cirrus.yml @@ -62,8 +62,10 @@ testing_task: - lint # Not all $TEST_DRIVER combinations are valid for all OS types. - # Note: Nested-variable resolution happens at runtime, not eval. time. - # Use verbose logic for ease of reading/maintaining. + # N/B: As of the addition of this note, nested-variable resolution + # does not happen for boolean `only_if` expressions. Since $VM_IMAGE + # contains nested variables, we must filter based on that and not the + # actual distro/version value. only_if: >- ( $VM_IMAGE =~ '.*UBUNTU.*' && $TEST_DRIVER == "vfs" ) || ( $VM_IMAGE =~ '.*UBUNTU.*' && $TEST_DRIVER == "aufs" ) || @@ -146,3 +148,15 @@ vendor_task: folder: $GOPATH/pkg/mod build_script: make vendor test_script: hack/tree_status.sh + +# Represent overall pass/fail status from required dependent tasks +success_task: + depends_on: + - lint + - testing + - meta + - vendor + container: + image: golang:1.14 + clone_script: 'mkdir -p "$CIRRUS_WORKING_DIR"' # Source code not needed + script: /bin/true diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index 0369d0b1e..4d1e5d262 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.21.2 +1.23.1-dev diff --git a/vendor/github.com/containers/storage/images.go b/vendor/github.com/containers/storage/images.go index ef95598b8..2808f579f 100644 --- a/vendor/github.com/containers/storage/images.go +++ b/vendor/github.com/containers/storage/images.go @@ -10,6 +10,7 @@ import ( "github.com/containers/storage/pkg/ioutils" "github.com/containers/storage/pkg/stringid" + "github.com/containers/storage/pkg/stringutils" "github.com/containers/storage/pkg/truncindex" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" @@ -465,6 +466,19 @@ func (r *imageStore) addMappedTopLayer(id, layer string) error { return errors.Wrapf(ErrImageUnknown, "error locating image with ID %q", id) } +func (r *imageStore) removeMappedTopLayer(id, layer string) error { + if image, ok := r.lookup(id); ok { + initialLen := len(image.MappedTopLayers) + image.MappedTopLayers = stringutils.RemoveFromSlice(image.MappedTopLayers, layer) + // No layer was removed. No need to save. + if initialLen == len(image.MappedTopLayers) { + return nil + } + return r.Save() + } + return errors.Wrapf(ErrImageUnknown, "error locating image with ID %q", id) +} + func (r *imageStore) Metadata(id string) (string, error) { if image, ok := r.lookup(id); ok { return image.Metadata, nil diff --git a/vendor/github.com/containers/storage/pkg/archive/archive.go b/vendor/github.com/containers/storage/pkg/archive/archive.go index 78744e0f3..ac0f5f336 100644 --- a/vendor/github.com/containers/storage/pkg/archive/archive.go +++ b/vendor/github.com/containers/storage/pkg/archive/archive.go @@ -602,7 +602,7 @@ func (ta *tarAppender) addTarFile(path, name string) error { return nil } -func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *idtools.IDPair, inUserns, ignoreChownErrors bool) error { +func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *idtools.IDPair, inUserns, ignoreChownErrors bool, buffer []byte) error { // hdr.Mode is in linux format, which we can use for sycalls, // but for os.Foo() calls we need the mode converted to os.FileMode, // so use hdrInfo.Mode() (they differ for e.g. setuid bits) @@ -626,7 +626,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L if err != nil { return err } - if _, err := io.Copy(file, reader); err != nil { + if _, err := io.CopyBuffer(file, reader, buffer); err != nil { file.Close() return err } @@ -942,6 +942,7 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) rootIDs := idMappings.RootPair() whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat, options.WhiteoutData) + buffer := make([]byte, 1<<20) // Iterate through the files in the archive. loop: @@ -1038,7 +1039,7 @@ loop: chownOpts = &idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid} } - if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, chownOpts, options.InUserNS, options.IgnoreChownErrors); err != nil { + if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, chownOpts, options.InUserNS, options.IgnoreChownErrors, buffer); err != nil { return err } diff --git a/vendor/github.com/containers/storage/pkg/archive/changes_unix.go b/vendor/github.com/containers/storage/pkg/archive/changes_unix.go index 805fb960a..1cc1910f8 100644 --- a/vendor/github.com/containers/storage/pkg/archive/changes_unix.go +++ b/vendor/github.com/containers/storage/pkg/archive/changes_unix.go @@ -18,9 +18,11 @@ func statDifferent(oldStat *system.StatT, oldInfo *FileInfo, newStat *system.Sta if cuid, cgid, err := newInfo.idMappings.ToContainer(idtools.IDPair{UID: int(uid), GID: int(gid)}); err == nil { uid = uint32(cuid) gid = uint32(cgid) - if oldcuid, oldcgid, err := oldInfo.idMappings.ToContainer(idtools.IDPair{UID: int(oldUID), GID: int(oldGID)}); err == nil { - oldUID = uint32(oldcuid) - oldGID = uint32(oldcgid) + if oldInfo != nil { + if oldcuid, oldcgid, err := oldInfo.idMappings.ToContainer(idtools.IDPair{UID: int(oldUID), GID: int(oldGID)}); err == nil { + oldUID = uint32(oldcuid) + oldGID = uint32(oldcgid) + } } } ownerChanged := uid != oldUID || gid != oldGID diff --git a/vendor/github.com/containers/storage/pkg/archive/diff.go b/vendor/github.com/containers/storage/pkg/archive/diff.go index 78e3d9102..a12dd4202 100644 --- a/vendor/github.com/containers/storage/pkg/archive/diff.go +++ b/vendor/github.com/containers/storage/pkg/archive/diff.go @@ -37,6 +37,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, aufsTempdir := "" aufsHardlinks := make(map[string]*tar.Header) + buffer := make([]byte, 1<<20) // Iterate through the files in the archive. for { @@ -105,7 +106,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, } defer os.RemoveAll(aufsTempdir) } - if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil, options.InUserNS, options.IgnoreChownErrors); err != nil { + if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil, options.InUserNS, options.IgnoreChownErrors, buffer); err != nil { return 0, err } } @@ -196,7 +197,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, return 0, err } - if err := createTarFile(path, dest, srcHdr, srcData, true, nil, options.InUserNS, options.IgnoreChownErrors); err != nil { + if err := createTarFile(path, dest, srcHdr, srcData, true, nil, options.InUserNS, options.IgnoreChownErrors, buffer); err != nil { return 0, err } diff --git a/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go b/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go index 90f196371..e5faf9aad 100644 --- a/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go +++ b/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go @@ -262,7 +262,7 @@ func (p *Pattern) compile() error { } } - regStr += "(/.*)?$" + regStr += "(" + escSL + ".*)?$" re, err := regexp.Compile(regStr) if err != nil { diff --git a/vendor/github.com/containers/storage/pkg/stringutils/stringutils.go b/vendor/github.com/containers/storage/pkg/stringutils/stringutils.go index 8c4c39875..66a59c85d 100644 --- a/vendor/github.com/containers/storage/pkg/stringutils/stringutils.go +++ b/vendor/github.com/containers/storage/pkg/stringutils/stringutils.go @@ -56,13 +56,24 @@ func Truncate(s string, maxlen int) string { // Comparison is case insensitive func InSlice(slice []string, s string) bool { for _, ss := range slice { - if strings.ToLower(s) == strings.ToLower(ss) { + if strings.EqualFold(s, ss) { return true } } return false } +// RemoveFromSlice removes a string from a slice. The string can be present +// multiple times. The entire slice is iterated. +func RemoveFromSlice(slice []string, s string) (ret []string) { + for _, ss := range slice { + if !strings.EqualFold(s, ss) { + ret = append(ret, ss) + } + } + return ret +} + func quote(word string, buf *bytes.Buffer) { // Bail out early for "simple" strings if word != "" && !strings.ContainsAny(word, "\\'\"`${[|&;<>()~*?! \t\n") { diff --git a/vendor/github.com/containers/storage/pkg/unshare/unshare.c b/vendor/github.com/containers/storage/pkg/unshare/unshare.c index dc7b9d570..c0e359b27 100644 --- a/vendor/github.com/containers/storage/pkg/unshare/unshare.c +++ b/vendor/github.com/containers/storage/pkg/unshare/unshare.c @@ -292,6 +292,7 @@ static int containers_reexec(int flags) { fprintf(stderr, "Error during reexec(...): %m\n"); return -1; } + close(fd); return 0; } diff --git a/vendor/github.com/containers/storage/storage_test.conf b/vendor/github.com/containers/storage/storage_test.conf new file mode 100644 index 000000000..9b682fe15 --- /dev/null +++ b/vendor/github.com/containers/storage/storage_test.conf @@ -0,0 +1,35 @@ +# This file is is a TEST configuration file for all tools +# that use the containers/storage library. +# See man 5 containers-storage.conf for more information +# The "container storage" table contains all of the server options. +[storage] + +# Default Storage Driver +driver = "" + +# Temporary storage location +runroot = "$HOME/$UID/containers/storage" + +# Primary Read/Write location of container storage +graphroot = "$HOME/$UID/containers/storage" + +# Storage path for rootless users +# +rootless_storage_path = "$HOME/$UID/containers/storage" + +[storage.options] +# Storage options to be passed to underlying storage drivers + +# AdditionalImageStores is used to pass paths to additional Read/Only image stores +# Must be comma separated list. +additionalimagestores = [ +] + +[storage.options.overlay] + +# mountopt specifies comma separated list of extra mount options +mountopt = "nodev" + + +[storage.options.thinpool] +# Storage Options for thinpool diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go index 56e1e545b..937bf8c3a 100644 --- a/vendor/github.com/containers/storage/store.go +++ b/vendor/github.com/containers/storage/store.go @@ -2223,16 +2223,23 @@ func (s *store) DeleteLayer(id string) error { } for _, layer := range layers { if layer.Parent == id { - return ErrLayerHasChildren + return errors.Wrapf(ErrLayerHasChildren, "used by layer %v", layer.ID) } } images, err := ristore.Images() if err != nil { return err } + for _, image := range images { - if image.TopLayer == id || stringutils.InSlice(image.MappedTopLayers, id) { - return errors.Wrapf(ErrLayerUsedByImage, "Layer %v used by image %v", id, image.ID) + if image.TopLayer == id { + return errors.Wrapf(ErrLayerUsedByImage, "layer %v used by image %v", id, image.ID) + } + if stringutils.InSlice(image.MappedTopLayers, id) { + // No write access to the image store, fail before the layer is deleted + if _, ok := ristore.(*imageStore); !ok { + return errors.Wrapf(ErrLayerUsedByImage, "layer %v used by image %v", id, image.ID) + } } } containers, err := rcstore.Containers() @@ -2241,10 +2248,25 @@ func (s *store) DeleteLayer(id string) error { } for _, container := range containers { if container.LayerID == id { - return errors.Wrapf(ErrLayerUsedByContainer, "Layer %v used by container %v", id, container.ID) + return errors.Wrapf(ErrLayerUsedByContainer, "layer %v used by container %v", id, container.ID) } } - return rlstore.Delete(id) + if err := rlstore.Delete(id); err != nil { + return errors.Wrapf(err, "delete layer %v", id) + } + + // The check here is used to avoid iterating the images if we don't need to. + // There is already a check above for the imageStore to be writeable when the layer is part of MappedTopLayers. + if istore, ok := ristore.(*imageStore); ok { + for _, image := range images { + if stringutils.InSlice(image.MappedTopLayers, id) { + if err = istore.removeMappedTopLayer(image.ID, id); err != nil { + return errors.Wrapf(err, "remove mapped top layer %v from image %v", id, image.ID) + } + } + } + } + return nil } return ErrNotALayer } diff --git a/vendor/github.com/containers/storage/userns.go b/vendor/github.com/containers/storage/userns.go index e2b56da2f..5ba8cc418 100644 --- a/vendor/github.com/containers/storage/userns.go +++ b/vendor/github.com/containers/storage/userns.go @@ -252,7 +252,7 @@ func subtractHostIDs(avail idtools.IDMap, used idtools.IDMap) []idtools.IDMap { } r2 := idtools.IDMap{ ContainerID: used.ContainerID + used.Size, - HostID: used.HostID + used.Size, + HostID: avail.HostID + (used.HostID - avail.HostID), Size: avail.HostID + avail.Size - used.HostID - used.Size, } return []idtools.IDMap{r1, r2} @@ -297,7 +297,7 @@ func subtractContainerIDs(avail idtools.IDMap, used idtools.IDMap) []idtools.IDM } r2 := idtools.IDMap{ ContainerID: used.ContainerID + used.Size, - HostID: avail.HostID + used.Size, + HostID: avail.HostID + (used.ContainerID - avail.ContainerID), Size: avail.ContainerID + avail.Size - used.ContainerID - used.Size, } return []idtools.IDMap{r1, r2} @@ -314,22 +314,17 @@ func subtractContainerIDs(avail idtools.IDMap, used idtools.IDMap) []idtools.IDM // subtractAll subtracts all usedIDs from the available IDs. func subtractAll(availableIDs, usedIDs []idtools.IDMap, host bool) []idtools.IDMap { for _, u := range usedIDs { - for i := 0; i < len(availableIDs); { - var prev []idtools.IDMap - if i > 0 { - prev = availableIDs[:i-1] - } - next := availableIDs[i+1:] - cur := availableIDs[i] + var newAvailableIDs []idtools.IDMap + for _, cur := range availableIDs { var newRanges []idtools.IDMap if host { newRanges = subtractHostIDs(cur, u) } else { newRanges = subtractContainerIDs(cur, u) } - availableIDs = append(append(prev, newRanges...), next...) - i += len(newRanges) + newAvailableIDs = append(newAvailableIDs, newRanges...) } + availableIDs = newAvailableIDs } return availableIDs } @@ -361,6 +356,7 @@ func findAvailableIDRange(size uint32, availableIDs, usedIDs []idtools.IDMap) ([ return avail[:i+1], nil } remaining -= uint32(avail[i].Size) + currentID += avail[i].Size } return nil, errors.New("could not find enough available IDs") @@ -452,6 +448,5 @@ func (s *store) getAutoUserNS(id string, options *AutoUserNsOptions, image *Imag if len(options.AdditionalGIDMappings) > 0 { availableGIDs = subtractAll(availableGIDs, options.AdditionalGIDMappings, false) } - return append(availableUIDs, options.AdditionalUIDMappings...), append(availableGIDs, options.AdditionalGIDMappings...), nil } diff --git a/vendor/github.com/containers/storage/utils.go b/vendor/github.com/containers/storage/utils.go index 101f5cc7a..d65d52718 100644 --- a/vendor/github.com/containers/storage/utils.go +++ b/vendor/github.com/containers/storage/utils.go @@ -5,9 +5,7 @@ import ( "io/ioutil" "os" "os/exec" - "os/user" "path/filepath" - "regexp" "strconv" "strings" @@ -234,8 +232,9 @@ func DefaultStoreOptionsAutoDetectUID() (StoreOptions, error) { return DefaultStoreOptions(uid != 0, uid) } -// DefaultStoreOptions returns the default storage ops for containers -func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) { +// defaultStoreOptionsIsolated is an internal implementation detail of DefaultStoreOptions to allow testing. +// Everyone but the tests this is intended for should only call DefaultStoreOptions, never this function. +func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf string) (StoreOptions, error) { var ( defaultRootlessRunRoot string defaultRootlessGraphRoot string @@ -248,11 +247,6 @@ func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) { return storageOpts, err } } - - storageConf, err := DefaultConfigFile(rootless && rootlessUID != 0) - if err != nil { - return storageOpts, err - } _, err = os.Stat(storageConf) if err != nil && !os.IsNotExist(err) { return storageOpts, errors.Wrapf(err, "cannot stat %s", storageConf) @@ -263,6 +257,20 @@ func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) { storageOpts = StoreOptions{} reloadConfigurationFileIfNeeded(storageConf, &storageOpts) } + if storageOpts.RunRoot != "" { + runRoot, err := expandEnvPath(storageOpts.RunRoot, rootlessUID) + if err != nil { + return storageOpts, err + } + storageOpts.RunRoot = runRoot + } + if storageOpts.GraphRoot != "" { + graphRoot, err := expandEnvPath(storageOpts.GraphRoot, rootlessUID) + if err != nil { + return storageOpts, err + } + storageOpts.GraphRoot = graphRoot + } if rootless && rootlessUID != 0 { if err == nil { @@ -276,16 +284,10 @@ func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) { storageOpts.GraphRoot = defaultRootlessGraphRoot } if storageOpts.RootlessStoragePath != "" { - if err = validRootlessStoragePathFormat(storageOpts.RootlessStoragePath); err != nil { - return storageOpts, err - } - rootlessStoragePath := strings.Replace(storageOpts.RootlessStoragePath, "$HOME", homedir.Get(), -1) - rootlessStoragePath = strings.Replace(rootlessStoragePath, "$UID", strconv.Itoa(rootlessUID), -1) - usr, err := user.LookupId(strconv.Itoa(rootlessUID)) + rootlessStoragePath, err := expandEnvPath(storageOpts.RootlessStoragePath, rootlessUID) if err != nil { return storageOpts, err } - rootlessStoragePath = strings.Replace(rootlessStoragePath, "$USER", usr.Username, -1) storageOpts.GraphRoot = rootlessStoragePath } } @@ -293,22 +295,19 @@ func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) { return storageOpts, nil } -// validRootlessStoragePathFormat checks if the environments contained in the path are accepted -func validRootlessStoragePathFormat(path string) error { - if !strings.Contains(path, "$") { - return nil +// DefaultStoreOptions returns the default storage ops for containers +func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) { + storageConf, err := DefaultConfigFile(rootless && rootlessUID != 0) + if err != nil { + return defaultStoreOptions, err } + return defaultStoreOptionsIsolated(rootless, rootlessUID, storageConf) +} - splitPaths := strings.SplitAfter(path, "$") - validEnv := regexp.MustCompile(`^(HOME|USER|UID)([^a-zA-Z]|$)`).MatchString - if len(splitPaths) > 1 { - for _, p := range splitPaths[1:] { - if !validEnv(p) { - return errors.Errorf("Unrecognized environment variable") - } - } - } - return nil +func expandEnvPath(path string, rootlessUID int) (string, error) { + path = strings.Replace(path, "$UID", strconv.Itoa(rootlessUID), -1) + path = os.ExpandEnv(path) + return path, nil } func validateMountOptions(mountOptions []string) error { diff --git a/vendor/modules.txt b/vendor/modules.txt index 3f490616a..0ab37e30c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -156,7 +156,7 @@ github.com/containers/psgo/internal/dev github.com/containers/psgo/internal/host github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/process -# github.com/containers/storage v1.21.2 +# github.com/containers/storage v1.23.0 github.com/containers/storage github.com/containers/storage/drivers github.com/containers/storage/drivers/aufs @@ -693,10 +693,10 @@ gopkg.in/tomb.v1 gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c gopkg.in/yaml.v3 -# k8s.io/api v0.18.6 +# k8s.io/api v0.18.8 k8s.io/api/apps/v1 k8s.io/api/core/v1 -# k8s.io/apimachinery v0.18.6 +# k8s.io/apimachinery v0.18.8 k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/apis/meta/v1 |