diff options
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | cmd/podman/volumes/prune.go | 52 | ||||
-rw-r--r-- | libpod/options.go | 29 | ||||
-rw-r--r-- | libpod/pod.go | 1 | ||||
-rw-r--r-- | libpod/runtime_pod_infra_linux.go | 14 | ||||
-rw-r--r-- | pkg/specgen/generate/pod_create.go | 3 | ||||
-rw-r--r-- | test/e2e/pod_create_test.go | 20 | ||||
-rw-r--r-- | test/system/160-volumes.bats | 15 |
8 files changed, 122 insertions, 20 deletions
@@ -303,13 +303,17 @@ localunit: test/goecho/goecho .PHONY: test test: localunit localintegration remoteintegration localsystem remotesystem ## Run unit, integration, and system tests. +.PHONY: ginkgo-run +ginkgo-run: + $(GOBIN)/ginkgo -v $(TESTFLAGS) -tags "$(TAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -nodes 3 -debug test/e2e/. $(HACK) + .PHONY: ginkgo ginkgo: - $(GOBIN)/ginkgo -v $(TESTFLAGS) -tags "$(BUILDTAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -nodes 3 -debug test/e2e/. hack/. + $(MAKE) ginkgo-run TAGS="$(BUILDTAGS)" HACK=hack/. .PHONY: ginkgo-remote ginkgo-remote: - $(GOBIN)/ginkgo -v $(TESTFLAGS) -tags "$(REMOTETAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor test/e2e/. + $(MAKE) ginkgo-run TAGS="$(REMOTETAGS)" HACK= .PHONY: localintegration localintegration: test-binaries ginkgo diff --git a/cmd/podman/volumes/prune.go b/cmd/podman/volumes/prune.go index 0f3ba9ef6..39ad2735b 100644 --- a/cmd/podman/volumes/prune.go +++ b/cmd/podman/volumes/prune.go @@ -49,16 +49,46 @@ func init() { func prune(cmd *cobra.Command, args []string) error { var ( - pruneOptions = entities.VolumePruneOptions{} + pruneOptions = entities.VolumePruneOptions{} + listOptions = entities.VolumeListOptions{} + unusedOptions = entities.VolumeListOptions{} ) // Prompt for confirmation if --force is not set force, err := cmd.Flags().GetBool("force") if err != nil { return err } + pruneOptions.Filters, err = filters.ParseFilterArgumentsIntoFilters(filter) if !force { reader := bufio.NewReader(os.Stdin) - fmt.Println("WARNING! This will remove all volumes not used by at least one container.") + fmt.Println("WARNING! This will remove all volumes not used by at least one container. The following volumes will be removed:") + if err != nil { + return err + } + listOptions.Filter, err = filters.ParseFilterArgumentsIntoFilters(filter) + if err != nil { + return err + } + // filter all the dangling volumes + unusedOptions.Filter = make(map[string][]string, 1) + unusedOptions.Filter["dangling"] = []string{"true"} + unusedVolumes, err := registry.ContainerEngine().VolumeList(context.Background(), unusedOptions) + if err != nil { + return err + } + // filter volumes based on user input + filteredVolumes, err := registry.ContainerEngine().VolumeList(context.Background(), listOptions) + if err != nil { + return err + } + finalVolumes := getIntersection(unusedVolumes, filteredVolumes) + if len(finalVolumes) < 1 { + fmt.Println("No dangling volumes found") + return nil + } + for _, fv := range finalVolumes { + fmt.Println(fv.Name) + } fmt.Print("Are you sure you want to continue? [y/N] ") answer, err := reader.ReadString('\n') if err != nil { @@ -68,13 +98,23 @@ func prune(cmd *cobra.Command, args []string) error { return nil } } - pruneOptions.Filters, err = filters.ParseFilterArgumentsIntoFilters(filter) - if err != nil { - return err - } responses, err := registry.ContainerEngine().VolumePrune(context.Background(), pruneOptions) if err != nil { return err } return utils.PrintVolumePruneResults(responses, false) } + +func getIntersection(a, b []*entities.VolumeListReport) []*entities.VolumeListReport { + var intersection []*entities.VolumeListReport + hash := make(map[string]bool, len(a)) + for _, aa := range a { + hash[aa.Name] = true + } + for _, bb := range b { + if hash[bb.Name] { + intersection = append(intersection, bb) + } + } + return intersection +} diff --git a/libpod/options.go b/libpod/options.go index c7bac7e1f..20f62ee37 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -2190,13 +2190,37 @@ func WithPodNetworks(networks []string) PodCreateOption { } } +// WithPodNoNetwork tells the pod to disable external networking. +func WithPodNoNetwork() PodCreateOption { + return func(pod *Pod) error { + if pod.valid { + return define.ErrPodFinalized + } + + if !pod.config.InfraContainer.HasInfraContainer { + return errors.Wrapf(define.ErrInvalidArg, "cannot disable pod networking as no infra container is being created") + } + + if len(pod.config.InfraContainer.PortBindings) > 0 || + pod.config.InfraContainer.StaticIP != nil || + pod.config.InfraContainer.StaticMAC != nil || + len(pod.config.InfraContainer.Networks) > 0 || + pod.config.InfraContainer.HostNetwork { + return errors.Wrapf(define.ErrInvalidArg, "cannot disable pod network if network-related configuration is specified") + } + + pod.config.InfraContainer.NoNetwork = true + + return nil + } +} + // WithPodHostNetwork tells the pod to use the host's network namespace. func WithPodHostNetwork() PodCreateOption { return func(pod *Pod) error { if pod.valid { return define.ErrPodFinalized } - if !pod.config.InfraContainer.HasInfraContainer { return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod host networking as no infra container is being created") } @@ -2204,7 +2228,8 @@ func WithPodHostNetwork() PodCreateOption { if len(pod.config.InfraContainer.PortBindings) > 0 || pod.config.InfraContainer.StaticIP != nil || pod.config.InfraContainer.StaticMAC != nil || - len(pod.config.InfraContainer.Networks) > 0 { + len(pod.config.InfraContainer.Networks) > 0 || + pod.config.InfraContainer.NoNetwork { return errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified") } diff --git a/libpod/pod.go b/libpod/pod.go index c8f62ca18..784c2cf5e 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -93,6 +93,7 @@ type podState struct { type InfraContainerConfig struct { ConmonPidFile string `json:"conmonPidFile"` HasInfraContainer bool `json:"makeInfraContainer"` + NoNetwork bool `json:"noNetwork,omitempty"` HostNetwork bool `json:"infraHostNetwork,omitempty"` PortBindings []ocicni.PortMapping `json:"infraPortBindings"` StaticIP net.IP `json:"staticIP,omitempty"` diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go index dd957527d..564851f4e 100644 --- a/libpod/runtime_pod_infra_linux.go +++ b/libpod/runtime_pod_infra_linux.go @@ -94,8 +94,16 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm } } - // Since user namespace sharing is not implemented, we only need to check if it's rootless - if !p.config.InfraContainer.HostNetwork { + switch { + case p.config.InfraContainer.HostNetwork: + if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil { + return nil, errors.Wrapf(err, "error removing network namespace from pod %s infra container", p.ID()) + } + case p.config.InfraContainer.NoNetwork: + // Do nothing - we have a network namespace by default, + // but should not configure slirp. + default: + // Since user namespace sharing is not implemented, we only need to check if it's rootless netmode := "bridge" if isRootless || p.config.InfraContainer.Slirp4netns { netmode = "slirp4netns" @@ -106,8 +114,6 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm // PostConfigureNetNS should not be set since user namespace sharing is not implemented // and rootless networking no longer supports post configuration setup options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, false, netmode, p.config.InfraContainer.Networks)) - } else if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil { - return nil, errors.Wrapf(err, "error removing network namespace from pod %s infra container", p.ID()) } // For each option in InfraContainerConfig - if set, pass into diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index 43caf0fe9..645bf7a47 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -102,6 +102,9 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod case specgen.Slirp: logrus.Debugf("Pod will use slirp4netns") options = append(options, libpod.WithPodSlirp4netns(p.NetworkOptions)) + case specgen.NoNetwork: + logrus.Debugf("Pod will not use networking") + options = append(options, libpod.WithPodNoNetwork()) default: return nil, errors.Errorf("pods presently do not support network mode %s", p.NetNS.NSMode) } diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index 575f9df68..9818c4f65 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -478,12 +478,7 @@ entrypoint ["/fromimage"] }) It("podman create with unsupported network options", func() { - podCreate := podmanTest.Podman([]string{"pod", "create", "--network", "none"}) - podCreate.WaitWithDefaultTimeout() - Expect(podCreate.ExitCode()).To(Equal(125)) - Expect(podCreate.ErrorToString()).To(ContainSubstring("pods presently do not support network mode none")) - - podCreate = podmanTest.Podman([]string{"pod", "create", "--network", "container:doesnotmatter"}) + podCreate := podmanTest.Podman([]string{"pod", "create", "--network", "container:doesnotmatter"}) podCreate.WaitWithDefaultTimeout() Expect(podCreate.ExitCode()).To(Equal(125)) Expect(podCreate.ErrorToString()).To(ContainSubstring("pods presently do not support network mode container")) @@ -493,4 +488,17 @@ entrypoint ["/fromimage"] Expect(podCreate.ExitCode()).To(Equal(125)) Expect(podCreate.ErrorToString()).To(ContainSubstring("pods presently do not support network mode path")) }) + + It("podman pod create with --net=none", func() { + podName := "testPod" + podCreate := podmanTest.Podman([]string{"pod", "create", "--network", "none", "--name", podName}) + podCreate.WaitWithDefaultTimeout() + Expect(podCreate.ExitCode()).To(Equal(0)) + + session := podmanTest.Podman([]string{"run", "--pod", podName, ALPINE, "ip", "-o", "-4", "addr"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("inet 127.0.0.1/8 scope host lo")) + Expect(len(session.OutputToStringArray())).To(Equal(1)) + }) }) diff --git a/test/system/160-volumes.bats b/test/system/160-volumes.bats index 0b7aab2fb..4952eafc2 100644 --- a/test/system/160-volumes.bats +++ b/test/system/160-volumes.bats @@ -214,6 +214,13 @@ EOF run_podman volume create $vol done + # Create two additional labeled volumes + for i in 5 6; do + vol=myvol${i}$(random_string) + v[$i]=$vol + run_podman volume create $vol --label "mylabel" + done + # (Assert that output is formatted, not a one-line blob: #8011) run_podman volume inspect ${v[1]} if [[ "${#lines[*]}" -lt 10 ]]; then @@ -225,6 +232,14 @@ EOF run_podman run --name c2 --volume ${v[2]}:/vol2 -v ${v[3]}:/vol3 \ $IMAGE date + # List available volumes for pruning after using 1,2,3 + run_podman volume prune <<< N + is "$(echo $(sort <<<${lines[@]:1:3}))" "${v[4]} ${v[5]} ${v[6]}" "volume prune, with 1,2,3 in use, lists 4,5,6" + + # List available volumes for pruning after using 1,2,3 and filtering; see #8913 + run_podman volume prune --filter label=mylabel <<< N + is "$(echo $(sort <<<${lines[@]:1:2}))" "${v[5]} ${v[6]}" "volume prune, with 1,2,3 in use and 4 filtered out, lists 5,6" + # prune should remove v4 run_podman volume prune --force is "$output" "${v[4]}" "volume prune, with 1, 2, 3 in use, deletes only 4" |