diff options
28 files changed, 419 insertions, 63 deletions
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index 6270bad16..fbc8fb8ab 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -5,6 +5,7 @@ import ( "github.com/containers/common/pkg/auth" "github.com/containers/common/pkg/completion" + commonFlag "github.com/containers/common/pkg/flag" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/domain/entities" @@ -589,12 +590,9 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(timeoutFlagName, completion.AutocompleteNone) - // Flag for TLS verification, so that `run` and `create` commands can make use of it. - // Make sure to use `=` while using this flag i.e `--tls-verify=false/true` - tlsVerifyFlagName := "tls-verify" - createFlags.BoolVar( + commonFlag.OptionalBoolFlag(createFlags, &cf.TLSVerify, - tlsVerifyFlagName, true, + "tls-verify", "Require HTTPS and verify certificates when contacting registries for pulling images", ) diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 3be426ae2..d35c1a192 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -303,6 +303,11 @@ func PullImage(imageName string, cliVals entities.ContainerCreateOptions) (strin } } + skipTLSVerify := types.OptionalBoolUndefined + if cliVals.TLSVerify.Present() { + skipTLSVerify = types.NewOptionalBool(!cliVals.TLSVerify.Value()) + } + pullReport, pullErr := registry.ImageEngine().Pull(registry.GetContext(), imageName, entities.ImagePullOptions{ Authfile: cliVals.Authfile, Quiet: cliVals.Quiet, @@ -311,7 +316,7 @@ func PullImage(imageName string, cliVals entities.ContainerCreateOptions) (strin Variant: cliVals.Variant, SignaturePolicy: cliVals.SignaturePolicy, PullPolicy: pullPolicy, - SkipTLSVerify: types.NewOptionalBool(!cliVals.TLSVerify), // If Flag changed for TLS Verification + SkipTLSVerify: skipTLSVerify, }) if pullErr != nil { return "", pullErr diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index ea9042861..3ff736adb 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -638,6 +638,16 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container. + Options specific to devpts: + + · uid: UID of the file owner (default 0). + + · gid: GID of the file owner (default 0). + + · mode: permission mask for the file (default 600). + + · max: maximum number of PTYs (default 1048576). + #### **--name**=*name* Assign a name to the container diff --git a/docs/source/markdown/podman-pause.1.md b/docs/source/markdown/podman-pause.1.md index 123362822..90ea1e32e 100644 --- a/docs/source/markdown/podman-pause.1.md +++ b/docs/source/markdown/podman-pause.1.md @@ -31,7 +31,7 @@ podman pause 860a4b23 Pause all **running** containers. ``` -podman stop -a +podman pause -a ``` ## SEE ALSO diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index b5f3130fe..a1170253f 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -665,6 +665,16 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container. + Options specific to devpts: + + · uid: UID of the file owner (default 0). + + · gid: GID of the file owner (default 0). + + · mode: permission mask for the file (default 600). + + · max: maximum number of PTYs (default 1048576). + #### **--name**=*name* Assign a name to the container. @@ -12,7 +12,7 @@ require ( github.com/containernetworking/cni v1.0.1 github.com/containernetworking/plugins v1.0.1 github.com/containers/buildah v1.23.1 - github.com/containers/common v0.46.1-0.20211008123044-d846f5aaec0e + github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f github.com/containers/conmon v2.0.20+incompatible github.com/containers/image/v5 v5.16.1 github.com/containers/ocicrypt v1.1.2 @@ -258,8 +258,8 @@ github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNB github.com/containers/buildah v1.23.1 h1:Tpc9DsRuU+0Oofewpxb6OJVNQjCu7yloN/obUqzfDTY= github.com/containers/buildah v1.23.1/go.mod h1:4WnrN0yrA7ab0ppgunixu2WM1rlD2rG8QLJAKbEkZlQ= github.com/containers/common v0.44.2/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo= -github.com/containers/common v0.46.1-0.20211008123044-d846f5aaec0e h1:lYazDued7KBcMq5IJzRIbX47SSLRg/yYxvM/P9LaVhE= -github.com/containers/common v0.46.1-0.20211008123044-d846f5aaec0e/go.mod h1:ggZks97KCmjBcHvNTCyLc17SqdjSYoeexW7rnRt9H9Y= +github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f h1:jFFIV8QvsPgwkJHh3tjfREFRwSeMq5M8lt8vklkZaOk= +github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f/go.mod h1:pVvmLTLCOZE300e4rex/QDmpnRmEM/5aZ/YfCkkjgZo= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/image/v5 v5.16.0/go.mod h1:XgTpfAPLRGOd1XYyCU5cISFr777bLmOerCSpt/v7+Q4= @@ -336,7 +336,6 @@ github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BU github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.10+incompatible h1:GKkP0T7U4ks6X3lmmHKC2QDprnpRJor2Z5a8m62R9ZM= github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index d3151f7e0..2fd519990 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1546,6 +1546,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti logrus.Debugf("Restored container %s", c.ID()) c.state.State = define.ContainerStateRunning + c.state.Checkpointed = false if !options.Keep { // Delete all checkpoint related files. At this point, in theory, all files diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 1719b2dfa..db906fabb 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -1016,7 +1016,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co } if ctr.config.CgroupsMode == cgroupSplit { - if err := utils.MoveUnderCgroupSubtree("supervisor"); err != nil { + if err := utils.MoveUnderCgroupSubtree("runtime"); err != nil { return err } } diff --git a/libpod/runtime.go b/libpod/runtime.go index 855f3a9f9..b01f8dd13 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -543,6 +543,8 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { return err } if became { + // Check if the pause process was created. If it was created, then + // move it to its own systemd scope. utils.MovePauseProcessToScope(pausePid) os.Exit(ret) } diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go index 3ba39b860..ffdb30551 100644 --- a/pkg/api/handlers/libpod/volumes.go +++ b/pkg/api/handlers/libpod/volumes.go @@ -29,12 +29,13 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { }{ // override any golang type defaults } - input := entities.VolumeCreateOptions{} if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return } + + input := entities.VolumeCreateOptions{} // decode params from body if err := json.NewDecoder(r.Body).Decode(&input); err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()")) @@ -47,9 +48,19 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { if len(input.Driver) > 0 { volumeOptions = append(volumeOptions, libpod.WithVolumeDriver(input.Driver)) } - if len(input.Label) > 0 { - volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(input.Label)) + + // Label provided for compatibility. + labels := make(map[string]string, len(input.Label)+len(input.Labels)) + for k, v := range input.Label { + labels[k] = v } + for k, v := range input.Labels { + labels[k] = v + } + if len(labels) > 0 { + volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(labels)) + } + if len(input.Options) > 0 { parsedOptions, err := parse.VolumeOptions(input.Options) if err != nil { diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index a2f36eaa6..3d8579acf 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -5,6 +5,7 @@ import ( "strings" "time" + commonFlag "github.com/containers/common/pkg/flag" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/specgen" "github.com/containers/podman/v3/pkg/util" @@ -241,7 +242,7 @@ type ContainerCreateOptions struct { Sysctl []string Systemd string Timeout uint - TLSVerify bool + TLSVerify commonFlag.OptionalBool TmpFS []string TTY bool Timezone string diff --git a/pkg/domain/entities/volumes.go b/pkg/domain/entities/volumes.go index 2ecfb4446..9b2a170e2 100644 --- a/pkg/domain/entities/volumes.go +++ b/pkg/domain/entities/volumes.go @@ -78,8 +78,10 @@ type VolumeCreateOptions struct { Name string `schema:"name"` // Volume driver to use Driver string `schema:"driver"` - // User-defined key/value metadata. + // User-defined key/value metadata. Provided for compatibility Label map[string]string `schema:"label"` + // User-defined key/value metadata. Preferred field, will override Label + Labels map[string]string `schema:"labels"` // Mapping of driver options and values. Options map[string]string `schema:"opts"` } diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go index e211f5ea6..42d729458 100644 --- a/pkg/machine/ignition.go +++ b/pkg/machine/ignition.go @@ -304,6 +304,24 @@ machine_enabled=true }, }) + setDockerHost := `export DOCKER_HOST="unix://$(podman info -f "{{.Host.RemoteSocket.Path}}")" +` + + files = append(files, File{ + Node: Node{ + Group: getNodeGrp("root"), + Path: "/etc/profile.d/docker-host.sh", + User: getNodeUsr("root"), + }, + FileEmbedded1: FileEmbedded1{ + Append: nil, + Contents: Resource{ + Source: encodeDataURLPtr(setDockerHost), + }, + Mode: intToPtr(0644), + }, + }) + return files } diff --git a/pkg/specgenutil/volumes.go b/pkg/specgenutil/volumes.go index 3ce96164f..184bfadf8 100644 --- a/pkg/specgenutil/volumes.go +++ b/pkg/specgenutil/volumes.go @@ -360,7 +360,7 @@ func getBindMount(args []string) (spec.Mount, error) { // Since Docker ignores this option so shall we. continue default: - return newMount, errors.Wrapf(util.ErrBadMntOption, kv[0]) + return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) } } @@ -460,7 +460,7 @@ func getTmpfsMount(args []string) (spec.Mount, error) { // Since Docker ignores this option so shall we. continue default: - return newMount, errors.Wrapf(util.ErrBadMntOption, kv[0]) + return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) } } @@ -483,6 +483,8 @@ func getDevptsMount(args []string) (spec.Mount, error) { for _, val := range args { kv := strings.SplitN(val, "=", 2) switch kv[0] { + case "uid", "gid", "mode", "ptxmode", "newinstance", "max": + newMount.Options = append(newMount.Options, val) case "target", "dst", "destination": if len(kv) == 1 { return newMount, errors.Wrapf(optionArgError, kv[0]) @@ -493,7 +495,7 @@ func getDevptsMount(args []string) (spec.Mount, error) { newMount.Destination = filepath.Clean(kv[1]) setDest = true default: - return newMount, errors.Wrapf(util.ErrBadMntOption, kv[0]) + return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) } } @@ -573,7 +575,7 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) { // Since Docker ignores this option so shall we. continue default: - return nil, errors.Wrapf(util.ErrBadMntOption, kv[0]) + return nil, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) } } @@ -624,7 +626,7 @@ func getImageVolume(args []string) (*specgen.ImageVolume, error) { // Since Docker ignores this option so shall we. continue default: - return nil, errors.Wrapf(util.ErrBadMntOption, kv[0]) + return nil, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) } } diff --git a/test/apiv2/python/rest_api/test_v2_0_0_volume.py b/test/apiv2/python/rest_api/test_v2_0_0_volume.py index f5231e17c..2156318b0 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_volume.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_volume.py @@ -7,7 +7,7 @@ from .fixtures import APITestCase class VolumeTestCase(APITestCase): - def test_volume(self): + def test_volume_crud(self): name = f"Volume_{random.getrandbits(160):x}" ls = requests.get(self.podman_url + "/v1.40/volumes") @@ -70,6 +70,71 @@ class VolumeTestCase(APITestCase): self.assertIn(name, payload["VolumesDeleted"]) self.assertGreater(payload["SpaceReclaimed"], 0) + def test_volume_label(self): + name = f"Volume_{random.getrandbits(160):x}" + expected = { + "Production": "False", + "Database": "Foxbase", + } + + create = requests.post( + self.podman_url + "/v4.0.0/libpod/volumes/create", + json={"name": name, "label": expected}, + ) + self.assertEqual(create.status_code, 201, create.text) + + inspect = requests.get(self.podman_url + f"/v4.0.0/libpod/volumes/{name}/json") + self.assertEqual(inspect.status_code, 200, inspect.text) + + volume = inspect.json() + self.assertIn("Labels", volume) + self.assertNotIn("Label", volume) + self.assertDictEqual(expected, volume["Labels"]) + + def test_volume_labels(self): + name = f"Volume_{random.getrandbits(160):x}" + expected = { + "Production": "False", + "Database": "Foxbase", + } + + create = requests.post( + self.podman_url + "/v4.0.0/libpod/volumes/create", + json={"name": name, "labels": expected}, + ) + self.assertEqual(create.status_code, 201, create.text) + + inspect = requests.get(self.podman_url + f"/v4.0.0/libpod/volumes/{name}/json") + self.assertEqual(inspect.status_code, 200, inspect.text) + + volume = inspect.json() + self.assertIn("Labels", volume) + self.assertDictEqual(expected, volume["Labels"]) + + def test_volume_label_override(self): + name = f"Volume_{random.getrandbits(160):x}" + create = requests.post( + self.podman_url + "/v4.0.0/libpod/volumes/create", + json={ + "Name": name, + "Label": { + "Database": "dbase", + }, + "Labels": { + "Database": "sqlserver", + }, + }, + ) + self.assertEqual(create.status_code, 201, create.text) + + inspect = requests.get(self.podman_url + f"/v4.0.0/libpod/volumes/{name}/json") + self.assertEqual(inspect.status_code, 200, inspect.text) + + volume = inspect.json() + self.assertIn("Labels", volume) + self.assertNotIn("Label", volume) + self.assertDictEqual({"Database": "sqlserver"}, volume["Labels"]) + if __name__ == "__main__": unittest.main() diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go index b7e8309fb..7b35acd35 100644 --- a/test/e2e/push_test.go +++ b/test/e2e/push_test.go @@ -146,7 +146,7 @@ var _ = Describe("Podman push", func() { session = podmanTest.Podman([]string{"logs", "registry"}) session.WaitWithDefaultTimeout() - push := podmanTest.Podman([]string{"push", "--format=v2s2", "--creds=podmantest:test", ALPINE, "localhost:5000/tlstest"}) + push := podmanTest.Podman([]string{"push", "--tls-verify=true", "--format=v2s2", "--creds=podmantest:test", ALPINE, "localhost:5000/tlstest"}) push.WaitWithDefaultTimeout() Expect(push).To(ExitWithError()) @@ -163,7 +163,7 @@ var _ = Describe("Podman push", func() { if !IsRemote() { // remote does not support --cert-dir - push = podmanTest.Podman([]string{"push", "--creds=podmantest:test", "--cert-dir=fakedir", ALPINE, "localhost:5000/certdirtest"}) + push = podmanTest.Podman([]string{"push", "--tls-verify=true", "--creds=podmantest:test", "--cert-dir=fakedir", ALPINE, "localhost:5000/certdirtest"}) push.WaitWithDefaultTimeout() Expect(push).To(ExitWithError()) } diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 8502879ff..95660bfc9 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -188,6 +188,12 @@ var _ = Describe("Podman run", func() { run.WaitWithDefaultTimeout() Expect(run).Should(Exit(0)) Expect(podmanTest.NumberOfContainers()).To(Equal(3)) + + // Now registries.conf will be consulted where localhost:5000 + // is set to be insecure. + run = podmanTest.Podman([]string{"run", ALPINE}) + run.WaitWithDefaultTimeout() + Expect(run).Should(Exit(0)) }) It("podman run a container with a --rootfs", func() { @@ -1192,6 +1198,14 @@ USER mail`, BB) Expect(session.OutputToString()).To(ContainSubstring("devpts")) }) + It("podman run --mount type=devpts,target=/dev/pts with uid, gid and mode", func() { + // runc doesn't seem to honor uid= so avoid testing it + session := podmanTest.Podman([]string{"run", "-t", "--mount", "type=devpts,target=/dev/pts,uid=1000,gid=1001,mode=123", fedoraMinimal, "stat", "-c%g-%a", "/dev/pts/0"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("1001-123")) + }) + It("podman run --pod automatically", func() { session := podmanTest.Podman([]string{"run", "-d", "--pod", "new:foobar", ALPINE, "nc", "-l", "-p", "8686"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/system_reset_test.go b/test/e2e/system_reset_test.go index 102526a46..93ab166cd 100644 --- a/test/e2e/system_reset_test.go +++ b/test/e2e/system_reset_test.go @@ -60,6 +60,8 @@ var _ = Describe("podman system reset", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + Expect(session.ErrorToString()).To(Not(ContainSubstring("Failed to add pause process"))) + // If remote then the API service should have exited // On local tests this is a noop podmanTest.StartRemoteService() diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index a1b25b723..98def3d8f 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -4,7 +4,6 @@ import ( "io/ioutil" "os" "strings" - "time" . "github.com/containers/podman/v3/test/utils" . "github.com/onsi/ginkgo" @@ -82,27 +81,13 @@ WantedBy=multi-user.target run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", ubi_init, "/sbin/init"}) run.WaitWithDefaultTimeout() Expect(run).Should(Exit(0)) - ctrID := run.OutputToString() logs := podmanTest.Podman([]string{"logs", ctrName}) logs.WaitWithDefaultTimeout() Expect(logs).Should(Exit(0)) // Give container 10 seconds to start - started := false - for i := 0; i < 10; i++ { - runningCtrs := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"}) - runningCtrs.WaitWithDefaultTimeout() - Expect(runningCtrs).Should(Exit(0)) - - if strings.Contains(runningCtrs.OutputToString(), ctrID) { - started = true - break - } - - time.Sleep(1 * time.Second) - } - + started := podmanTest.WaitContainerReady(ctrName, "Reached target Multi-User System.", 30, 1) Expect(started).To(BeTrue()) systemctl := podmanTest.Podman([]string{"exec", "-t", "-i", ctrName, "systemctl", "status", "--no-pager"}) diff --git a/test/registries.conf b/test/registries.conf index 0559c9e52..8e4671760 100644 --- a/test/registries.conf +++ b/test/registries.conf @@ -15,3 +15,9 @@ location="mirror.gcr.io" [[registry]] prefix="docker.io/library" location="quay.io/libpod" + +# For testing #11933 to make sure that registries.conf is consulted unless +# --tls-verify is used during container creation. +[[registry]] +location="localhost:5000" +insecure=true diff --git a/utils/utils.go b/utils/utils.go index b08630d2f..109ae088b 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -14,6 +14,7 @@ import ( "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/cgroups" "github.com/containers/storage/pkg/archive" + "github.com/godbus/dbus/v5" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -177,13 +178,26 @@ func RunsOnSystemd() bool { func moveProcessToScope(pidPath, slice, scope string) error { data, err := ioutil.ReadFile(pidPath) if err != nil { + // do not raise an error if the file doesn't exist + if os.IsNotExist(err) { + return nil + } return errors.Wrapf(err, "cannot read pid file %s", pidPath) } pid, err := strconv.ParseUint(string(data), 10, 0) if err != nil { return errors.Wrapf(err, "cannot parse pid file %s", pidPath) } - return RunUnderSystemdScope(int(pid), slice, scope) + err = RunUnderSystemdScope(int(pid), slice, scope) + + // If the PID is not valid anymore, do not return an error. + if dbusErr, ok := err.(dbus.Error); ok { + if dbusErr.Name == "org.freedesktop.DBus.Error.UnixProcessIdUnknown" { + return nil + } + } + + return err } // MovePauseProcessToScope moves the pause process used for rootless mode to keep the namespaces alive to @@ -191,8 +205,8 @@ func moveProcessToScope(pidPath, slice, scope string) error { func MovePauseProcessToScope(pausePidPath string) { err := moveProcessToScope(pausePidPath, "user.slice", "podman-pause.scope") if err != nil { - unified, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { + unified, err2 := cgroups.IsCgroup2UnifiedMode() + if err2 != nil { logrus.Warnf("Failed to detect if running with cgroup unified: %v", err) } if RunsOnSystemd() && unified { diff --git a/vendor/github.com/containers/common/libimage/filters.go b/vendor/github.com/containers/common/libimage/filters.go index 833f940cc..521af5d06 100644 --- a/vendor/github.com/containers/common/libimage/filters.go +++ b/vendor/github.com/containers/common/libimage/filters.go @@ -50,6 +50,18 @@ func filterImages(images []*Image, filters []filterFunc) ([]*Image, error) { func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOptions) ([]filterFunc, error) { logrus.Tracef("Parsing image filters %s", options.Filters) + var tree *layerTree + getTree := func() (*layerTree, error) { + if tree == nil { + t, err := r.layerTree() + if err != nil { + return nil, err + } + tree = t + } + return tree, nil + } + filterFuncs := []filterFunc{} for _, filter := range options.Filters { var key, value string @@ -93,7 +105,11 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp if err != nil { return nil, errors.Wrapf(err, "non-boolean value %q for dangling filter", value) } - filterFuncs = append(filterFuncs, filterDangling(ctx, dangling)) + t, err := getTree() + if err != nil { + return nil, err + } + filterFuncs = append(filterFuncs, filterDangling(ctx, dangling, t)) case "id": filterFuncs = append(filterFuncs, filterID(value)) @@ -103,7 +119,11 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp if err != nil { return nil, errors.Wrapf(err, "non-boolean value %q for intermediate filter", value) } - filterFuncs = append(filterFuncs, filterIntermediate(ctx, intermediate)) + t, err := getTree() + if err != nil { + return nil, err + } + filterFuncs = append(filterFuncs, filterIntermediate(ctx, intermediate, t)) case "label": filterFuncs = append(filterFuncs, filterLabel(ctx, value)) @@ -221,9 +241,9 @@ func filterContainers(value string, fn IsExternalContainerFunc) filterFunc { } // filterDangling creates a dangling filter for matching the specified value. -func filterDangling(ctx context.Context, value bool) filterFunc { +func filterDangling(ctx context.Context, value bool, tree *layerTree) filterFunc { return func(img *Image) (bool, error) { - isDangling, err := img.IsDangling(ctx) + isDangling, err := img.isDangling(ctx, tree) if err != nil { return false, err } @@ -241,9 +261,9 @@ func filterID(value string) filterFunc { // filterIntermediate creates an intermediate filter for images. An image is // considered to be an intermediate image if it is dangling (i.e., no tags) and // has no children (i.e., no other image depends on it). -func filterIntermediate(ctx context.Context, value bool) filterFunc { +func filterIntermediate(ctx context.Context, value bool, tree *layerTree) filterFunc { return func(img *Image) (bool, error) { - isIntermediate, err := img.IsIntermediate(ctx) + isIntermediate, err := img.isIntermediate(ctx, tree) if err != nil { return false, err } diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go index 00a2d620e..bf3310da2 100644 --- a/vendor/github.com/containers/common/libimage/image.go +++ b/vendor/github.com/containers/common/libimage/image.go @@ -128,10 +128,16 @@ func (i *Image) IsReadOnly() bool { // IsDangling returns true if the image is dangling, that is an untagged image // without children. func (i *Image) IsDangling(ctx context.Context) (bool, error) { + return i.isDangling(ctx, nil) +} + +// isDangling returns true if the image is dangling, that is an untagged image +// without children. If tree is nil, it will created for this invocation only. +func (i *Image) isDangling(ctx context.Context, tree *layerTree) (bool, error) { if len(i.Names()) > 0 { return false, nil } - children, err := i.getChildren(ctx, false) + children, err := i.getChildren(ctx, false, tree) if err != nil { return false, err } @@ -141,10 +147,17 @@ func (i *Image) IsDangling(ctx context.Context) (bool, error) { // IsIntermediate returns true if the image is an intermediate image, that is // an untagged image with children. func (i *Image) IsIntermediate(ctx context.Context) (bool, error) { + return i.isIntermediate(ctx, nil) +} + +// isIntermediate returns true if the image is an intermediate image, that is +// an untagged image with children. If tree is nil, it will created for this +// invocation only. +func (i *Image) isIntermediate(ctx context.Context, tree *layerTree) (bool, error) { if len(i.Names()) > 0 { return false, nil } - children, err := i.getChildren(ctx, false) + children, err := i.getChildren(ctx, false, tree) if err != nil { return false, err } @@ -189,7 +202,7 @@ func (i *Image) Parent(ctx context.Context) (*Image, error) { // HasChildren returns indicates if the image has children. func (i *Image) HasChildren(ctx context.Context) (bool, error) { - children, err := i.getChildren(ctx, false) + children, err := i.getChildren(ctx, false, nil) if err != nil { return false, err } @@ -198,7 +211,7 @@ func (i *Image) HasChildren(ctx context.Context) (bool, error) { // Children returns the image's children. func (i *Image) Children(ctx context.Context) ([]*Image, error) { - children, err := i.getChildren(ctx, true) + children, err := i.getChildren(ctx, true, nil) if err != nil { return nil, err } @@ -206,13 +219,16 @@ func (i *Image) Children(ctx context.Context) ([]*Image, error) { } // getChildren returns a list of imageIDs that depend on the image. If all is -// false, only the first child image is returned. -func (i *Image) getChildren(ctx context.Context, all bool) ([]*Image, error) { - tree, err := i.runtime.layerTree() - if err != nil { - return nil, err +// false, only the first child image is returned. If tree is nil, it will be +// created for this invocation only. +func (i *Image) getChildren(ctx context.Context, all bool, tree *layerTree) ([]*Image, error) { + if tree == nil { + t, err := i.runtime.layerTree() + if err != nil { + return nil, err + } + tree = t } - return tree.children(ctx, i, all) } diff --git a/vendor/github.com/containers/common/libimage/search.go b/vendor/github.com/containers/common/libimage/search.go index 7e20e4331..ece81531a 100644 --- a/vendor/github.com/containers/common/libimage/search.go +++ b/vendor/github.com/containers/common/libimage/search.go @@ -244,7 +244,7 @@ func (r *Runtime) searchImageInRegistry(ctx context.Context, term, registry stri name = index + "/library/" + results[i].Name } params := SearchResult{ - Index: index, + Index: registry, Name: name, Description: description, Official: official, diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index d5be77edd..45230703d 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -574,7 +574,7 @@ func readConfigFromFile(path string, config *Config) error { } keys := meta.Undecoded() if len(keys) > 0 { - logrus.Warningf("Failed to decode the keys %q from %q.", keys, path) + logrus.Debugf("Failed to decode the keys %q from %q.", keys, path) } return nil diff --git a/vendor/github.com/containers/common/pkg/flag/flag.go b/vendor/github.com/containers/common/pkg/flag/flag.go new file mode 100644 index 000000000..52eb50da0 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/flag/flag.go @@ -0,0 +1,174 @@ +package flag + +import ( + "strconv" + + "github.com/spf13/pflag" +) + +// OptionalBool is a boolean with a separate presence flag and value. +type OptionalBool struct { + present bool + value bool +} + +// Present returns the bool's presence flag. +func (ob *OptionalBool) Present() bool { + return ob.present +} + +// Present returns the bool's value. Should only be used if Present() is true. +func (ob *OptionalBool) Value() bool { + return ob.value +} + +// optionalBool is a cli.Generic == flag.Value implementation equivalent to +// the one underlying flag.Bool, except that it records whether the flag has been set. +// This is distinct from optionalBool to (pretend to) force callers to use +// optionalBoolFlag +type optionalBoolValue OptionalBool + +// OptionalBoolFlag creates new flag for an optional in the specified flag with +// the specified name and usage. +func OptionalBoolFlag(fs *pflag.FlagSet, p *OptionalBool, name, usage string) *pflag.Flag { + flag := fs.VarPF(internalNewOptionalBoolValue(p), name, "", usage) + flag.NoOptDefVal = "true" + flag.DefValue = "false" + return flag +} + +// WARNING: Do not directly use this method to define optionalBool flag. +// Caller should use optionalBoolFlag +func internalNewOptionalBoolValue(p *OptionalBool) pflag.Value { + p.present = false + return (*optionalBoolValue)(p) +} + +// Set parses the string to a bool and sets it. +func (ob *optionalBoolValue) Set(s string) error { + v, err := strconv.ParseBool(s) + if err != nil { + return err + } + ob.value = v + ob.present = true + return nil +} + +// String returns the string representation of the string. +func (ob *optionalBoolValue) String() string { + if !ob.present { + return "" // This is, sadly, not round-trip safe: --flag is interpreted as --flag=true + } + return strconv.FormatBool(ob.value) +} + +// Type returns the type. +func (ob *optionalBoolValue) Type() string { + return "bool" +} + +// IsBoolFlag indicates that it's a bool flag. +func (ob *optionalBoolValue) IsBoolFlag() bool { + return true +} + +// OptionalString is a string with a separate presence flag. +type OptionalString struct { + present bool + value string +} + +// Present returns the strings's presence flag. +func (os *OptionalString) Present() bool { + return os.present +} + +// Present returns the string's value. Should only be used if Present() is true. +func (os *OptionalString) Value() string { + return os.value +} + +// optionalString is a cli.Generic == flag.Value implementation equivalent to +// the one underlying flag.String, except that it records whether the flag has been set. +// This is distinct from optionalString to (pretend to) force callers to use +// newoptionalString +type optionalStringValue OptionalString + +// NewOptionalStringValue returns a pflag.Value fo the string. +func NewOptionalStringValue(p *OptionalString) pflag.Value { + p.present = false + return (*optionalStringValue)(p) +} + +// Set sets the string. +func (ob *optionalStringValue) Set(s string) error { + ob.value = s + ob.present = true + return nil +} + +// String returns the string if present. +func (ob *optionalStringValue) String() string { + if !ob.present { + return "" // This is, sadly, not round-trip safe: --flag= is interpreted as {present:true, value:""} + } + return ob.value +} + +// Type returns the string type. +func (ob *optionalStringValue) Type() string { + return "string" +} + +// OptionalInt is a int with a separate presence flag. +type OptionalInt struct { + present bool + value int +} + +// Present returns the int's presence flag. +func (oi *OptionalInt) Present() bool { + return oi.present +} + +// Present returns the int's value. Should only be used if Present() is true. +func (oi *OptionalInt) Value() int { + return oi.value +} + +// optionalInt is a cli.Generic == flag.Value implementation equivalent to +// the one underlying flag.Int, except that it records whether the flag has been set. +// This is distinct from optionalInt to (pretend to) force callers to use +// newoptionalIntValue +type optionalIntValue OptionalInt + +// NewOptionalIntValue returns the pflag.Value of the int. +func NewOptionalIntValue(p *OptionalInt) pflag.Value { + p.present = false + return (*optionalIntValue)(p) +} + +// Set parses the string to an int and sets it. +func (ob *optionalIntValue) Set(s string) error { + v, err := strconv.ParseInt(s, 0, strconv.IntSize) + if err != nil { + return err + } + ob.value = int(v) + ob.present = true + return nil +} + +// String returns the string representation of the int. +func (ob *optionalIntValue) String() string { + if !ob.present { + return "" // If the value is not present, just return an empty string, any other value wouldn't make sense. + } + return strconv.Itoa(int(ob.value)) +} + +// Type returns the int's type. +func (ob *optionalIntValue) Type() string { + return "int" +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 6891f6ab1..8ea5dc5ee 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -95,7 +95,7 @@ github.com/containers/buildah/pkg/rusage github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/util -# github.com/containers/common v0.46.1-0.20211008123044-d846f5aaec0e +# github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f github.com/containers/common/libimage github.com/containers/common/libimage/manifests github.com/containers/common/pkg/apparmor @@ -108,6 +108,7 @@ github.com/containers/common/pkg/completion github.com/containers/common/pkg/config github.com/containers/common/pkg/defaultnet github.com/containers/common/pkg/filters +github.com/containers/common/pkg/flag github.com/containers/common/pkg/manifests github.com/containers/common/pkg/parse github.com/containers/common/pkg/report |