Skip to content

Commit

Permalink
Merge pull request #11075 from flouthoc/ps-filter-network-by-container
Browse files Browse the repository at this point in the history
ps: support the `container...` notation for `ps --filter network=...`
  • Loading branch information
openshift-ci[bot] authored Jul 30, 2021
2 parents 4429c7c + 2a484e7 commit aaf02cf
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 32 deletions.
40 changes: 40 additions & 0 deletions libpod/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,46 @@ func (c *Container) Networks() ([]string, bool, error) {
return c.networks()
}

// NetworkMode gets the configured network mode for the container.
// Get actual value from the database
func (c *Container) NetworkMode() string {
networkMode := ""
ctrSpec := c.config.Spec

switch {
case c.config.CreateNetNS:
// We actually store the network
// mode for Slirp and Bridge, so
// we can just use that
networkMode = string(c.config.NetMode)
case c.config.NetNsCtr != "":
networkMode = fmt.Sprintf("container:%s", c.config.NetNsCtr)
default:
// Find the spec's network namespace.
// If there is none, it's host networking.
// If there is one and it has a path, it's "ns:".
foundNetNS := false
for _, ns := range ctrSpec.Linux.Namespaces {
if ns.Type == spec.NetworkNamespace {
foundNetNS = true
if ns.Path != "" {
networkMode = fmt.Sprintf("ns:%s", ns.Path)
} else {
// We're making a network ns, but not
// configuring with Slirp or CNI. That
// means it's --net=none
networkMode = "none"
}
break
}
}
if !foundNetNS {
networkMode = "host"
}
}
return networkMode
}

// Unlocked accessor for networks
func (c *Container) networks() ([]string, bool, error) {
networks, err := c.runtime.state.GetNetworks(c)
Expand Down
33 changes: 1 addition & 32 deletions libpod/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -618,38 +618,7 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
hostConfig.Tmpfs = tmpfs

// Network mode parsing.
networkMode := ""
switch {
case c.config.CreateNetNS:
// We actually store the network
// mode for Slirp and Bridge, so
// we can just use that
networkMode = string(c.config.NetMode)
case c.config.NetNsCtr != "":
networkMode = fmt.Sprintf("container:%s", c.config.NetNsCtr)
default:
// Find the spec's network namespace.
// If there is none, it's host networking.
// If there is one and it has a path, it's "ns:".
foundNetNS := false
for _, ns := range ctrSpec.Linux.Namespaces {
if ns.Type == spec.NetworkNamespace {
foundNetNS = true
if ns.Path != "" {
networkMode = fmt.Sprintf("ns:%s", ns.Path)
} else {
// We're making a network ns, but not
// configuring with Slirp or CNI. That
// means it's --net=none
networkMode = "none"
}
break
}
}
if !foundNetNS {
networkMode = "host"
}
}
networkMode := c.NetworkMode()
hostConfig.NetworkMode = networkMode

// Port bindings.
Expand Down
12 changes: 12 additions & 0 deletions libpod/runtime_ctr.go
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,18 @@ func (r *Runtime) LookupContainer(idOrName string) (*Container, error) {
return r.state.LookupContainer(idOrName)
}

// LookupContainerId looks up a container id by its name or a partial ID
// If a partial ID is not unique, an error will be returned
func (r *Runtime) LookupContainerID(idOrName string) (string, error) {
r.lock.RLock()
defer r.lock.RUnlock()

if !r.valid {
return "", define.ErrRuntimeStopped
}
return r.state.LookupContainerID(idOrName)
}

// GetContainers retrieves all containers from the state
// Filters can be provided which will determine what containers are included in
// the output. Multiple filters are handled by ANDing their output, so only
Expand Down
30 changes: 30 additions & 0 deletions pkg/domain/filters/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,36 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
}, nil
case "network":
return func(c *libpod.Container) bool {
networkMode := c.NetworkMode()
// support docker like `--filter network=container:<IDorName>`
// check if networkMode is configured as `container:<ctr>`
// peform a match against filter `container:<IDorName>`
// networks is already going to be empty if `container:<ctr>` is configured as Mode
if strings.HasPrefix(networkMode, "container:") {
networkModeContainerPart := strings.SplitN(networkMode, ":", 2)
if len(networkModeContainerPart) < 2 {
return false
}
networkModeContainerID := networkModeContainerPart[1]
for _, val := range filterValues {
if strings.HasPrefix(val, "container:") {
filterNetworkModePart := strings.SplitN(val, ":", 2)
if len(filterNetworkModePart) < 2 {
return false
}
filterNetworkModeIDorName := filterNetworkModePart[1]
filterID, err := r.LookupContainerID(filterNetworkModeIDorName)
if err != nil {
return false
}
if filterID == networkModeContainerID {
return true
}
}
}
return false
}

networks, _, err := c.Networks()
// if err or no networks, quick out
if err != nil || len(networks) == 0 {
Expand Down
37 changes: 37 additions & 0 deletions test/e2e/ps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,43 @@ var _ = Describe("Podman ps", func() {
Expect(fullCid).To(Equal(result.OutputToStringArray()[0]))
})

It("podman ps --filter network=container:<name>", func() {
ctrAlpha := "alpha"
container := podmanTest.Podman([]string{"run", "-dt", "--name", ctrAlpha, ALPINE, "top"})
container.WaitWithDefaultTimeout()
Expect(container).Should(Exit(0))

ctrBravo := "bravo"
containerBravo := podmanTest.Podman([]string{"run", "-dt", "--network", "container:alpha", "--name", ctrBravo, ALPINE, "top"})
containerBravo.WaitWithDefaultTimeout()
Expect(containerBravo).Should(Exit(0))

result := podmanTest.Podman([]string{"ps", "-a", "--format", "table {{.Names}}", "--filter", "network=container:alpha"})
result.WaitWithDefaultTimeout()
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(result.OutputToString()).To(ContainSubstring("bravo"))
})

It("podman ps --filter network=container:<id>", func() {
ctrAlpha := "first"
container := podmanTest.Podman([]string{"run", "-dt", "--name", ctrAlpha, ALPINE, "top"})
container.WaitWithDefaultTimeout()
cid := container.OutputToString()
Expect(container).Should(Exit(0))

ctrBravo := "second"
containerBravo := podmanTest.Podman([]string{"run", "-dt", "--network", "container:" + cid, "--name", ctrBravo, ALPINE, "top"})
containerBravo.WaitWithDefaultTimeout()
Expect(containerBravo).Should(Exit(0))

result := podmanTest.Podman([]string{"ps", "-a", "--format", "table {{.Names}}", "--filter", "network=container:" + cid})
result.WaitWithDefaultTimeout()
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(result.OutputToString()).To(ContainSubstring("second"))
})

It("podman ps namespace flag", func() {
_, ec, _ := podmanTest.RunLsContainer("")
Expect(ec).To(Equal(0))
Expand Down

0 comments on commit aaf02cf

Please sign in to comment.