Skip to content

Commit 5952486

Browse files
committed
podman network inspect: include running containers
Like docker podman network inspect should output the information of running container with their ip/mac address on this network. However the output format is not docker compatible as this cannot include all the info we have and the previous output was already not compatible so this is not new. New example output: ``` [ { ... "containers": { "7c0d295779cee4a6db7adc07a99e635909413a390eeab9f951edbc4aac406bf1": { "name": "c2", "interfaces": { "eth0": { "subnets": [ { "ipnet": "10.89.0.4/24", "gateway": "10.89.0.1" }, { "ipnet": "fda3:b4da:da1e:7e9d::4/64", "gateway": "fda3:b4da:da1e:7e9d::1" } ], "mac_address": "1a:bd:ca:ea:4b:3a" } } }, "b17c6651ae6d9cc7d5825968e01d6b1e67f44460bb0c140bcc32bd9d436ac11d": { "name": "c1", "interfaces": { "eth0": { "subnets": [ { "ipnet": "10.89.0.3/24", "gateway": "10.89.0.1" }, { "ipnet": "fda3:b4da:da1e:7e9d::3/64", "gateway": "fda3:b4da:da1e:7e9d::1" } ], "mac_address": "f6:50:e6:22:d9:55" } } } } } ] ``` Fixes #14126 Fixes https://issues.redhat.com/browse/RHEL-3153 Signed-off-by: Paul Holzinger <[email protected]>
1 parent 031e7a1 commit 5952486

File tree

15 files changed

+155
-65
lines changed

15 files changed

+155
-65
lines changed

cmd/podman/common/completion.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,7 @@ func getEntityType(cmd *cobra.Command, args []string, o interface{}) interface{}
12981298
}
12991299
// network logic
13001300
if networks, _ := getNetworks(cmd, args[0], completeDefault); len(networks) > 0 {
1301-
return &types.Network{}
1301+
return &entities.NetworkInspectReport{}
13021302
}
13031303
return o
13041304
}

cmd/podman/networks/inspect.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package network
22

33
import (
4-
"github.com/containers/common/libnetwork/types"
54
"github.com/containers/podman/v5/cmd/podman/common"
65
"github.com/containers/podman/v5/cmd/podman/inspect"
76
"github.com/containers/podman/v5/cmd/podman/registry"
@@ -33,7 +32,7 @@ func init() {
3332

3433
formatFlagName := "format"
3534
flags.StringVarP(&inspectOpts.Format, formatFlagName, "f", "", "Pretty-print network to JSON or using a Go template")
36-
_ = networkinspectCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&types.Network{}))
35+
_ = networkinspectCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.NetworkInspectReport{}))
3736
}
3837

3938
func networkInspect(_ *cobra.Command, args []string) error {

docs/source/markdown/podman-network-inspect.1.md

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Pretty-print networks to JSON or using a Go template.
1616

1717
| **Placeholder** | **Description** |
1818
|--------------------|-------------------------------------------|
19+
| .Containers ... | Running containers on this network. |
1920
| .Created ... | Timestamp when the network was created |
2021
| .DNSEnabled | Network has dns enabled (boolean) |
2122
| .Driver | Network driver |
@@ -25,6 +26,7 @@ Pretty-print networks to JSON or using a Go template.
2526
| .IPv6Enabled | Network has ipv6 subnet (boolean) |
2627
| .Labels ... | Network labels |
2728
| .Name | Network name |
29+
| .Network ... | Nested Network type |
2830
| .NetworkDNSServers | Array of DNS servers used in this network |
2931
| .NetworkInterface | Name of the network interface on the host |
3032
| .Options ... | Network options |

pkg/api/handlers/compat/networks.go

+7-36
Original file line numberDiff line numberDiff line change
@@ -22,36 +22,6 @@ import (
2222
"github.com/sirupsen/logrus"
2323
)
2424

25-
type containerNetStatus struct {
26-
name string
27-
id string
28-
status map[string]nettypes.StatusBlock
29-
}
30-
31-
func getContainerNetStatuses(rt *libpod.Runtime) ([]containerNetStatus, error) {
32-
cons, err := rt.GetAllContainers()
33-
if err != nil {
34-
return nil, err
35-
}
36-
statuses := make([]containerNetStatus, 0, len(cons))
37-
for _, con := range cons {
38-
status, err := con.GetNetworkStatus()
39-
if err != nil {
40-
if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrRemoved) {
41-
continue
42-
}
43-
return nil, err
44-
}
45-
46-
statuses = append(statuses, containerNetStatus{
47-
id: con.ID(),
48-
name: con.Name(),
49-
status: status,
50-
})
51-
}
52-
return statuses, nil
53-
}
54-
5525
func normalizeNetworkName(rt *libpod.Runtime, name string) (string, bool) {
5626
if name == nettypes.BridgeNetworkDriver {
5727
return rt.Network().DefaultNetworkName(), true
@@ -86,7 +56,8 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
8656
utils.NetworkNotFound(w, name, err)
8757
return
8858
}
89-
statuses, err := getContainerNetStatuses(runtime)
59+
ic := abi.ContainerEngine{Libpod: runtime}
60+
statuses, err := ic.GetContainerNetStatuses()
9061
if err != nil {
9162
utils.InternalServerError(w, err)
9263
return
@@ -95,10 +66,10 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
9566
utils.WriteResponse(w, http.StatusOK, report)
9667
}
9768

98-
func convertLibpodNetworktoDockerNetwork(runtime *libpod.Runtime, statuses []containerNetStatus, network *nettypes.Network, changeDefaultName bool) *types.NetworkResource {
69+
func convertLibpodNetworktoDockerNetwork(runtime *libpod.Runtime, statuses []abi.ContainerNetStatus, network *nettypes.Network, changeDefaultName bool) *types.NetworkResource {
9970
containerEndpoints := make(map[string]types.EndpointResource, len(statuses))
10071
for _, st := range statuses {
101-
if netData, ok := st.status[network.Name]; ok {
72+
if netData, ok := st.Status[network.Name]; ok {
10273
ipv4Address := ""
10374
ipv6Address := ""
10475
macAddr := ""
@@ -116,12 +87,12 @@ func convertLibpodNetworktoDockerNetwork(runtime *libpod.Runtime, statuses []con
11687
break
11788
}
11889
containerEndpoint := types.EndpointResource{
119-
Name: st.name,
90+
Name: st.Name,
12091
MacAddress: macAddr,
12192
IPv4Address: ipv4Address,
12293
IPv6Address: ipv6Address,
12394
}
124-
containerEndpoints[st.id] = containerEndpoint
95+
containerEndpoints[st.ID] = containerEndpoint
12596
}
12697
}
12798
ipamConfigs := make([]dockerNetwork.IPAMConfig, 0, len(network.Subnets))
@@ -192,7 +163,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
192163
utils.InternalServerError(w, err)
193164
return
194165
}
195-
statuses, err := getContainerNetStatuses(runtime)
166+
statuses, err := ic.GetContainerNetStatuses()
196167
if err != nil {
197168
utils.InternalServerError(w, err)
198169
return

pkg/api/handlers/swagger/responses.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ type networkRmResponse struct {
434434
// swagger:response
435435
type networkInspectResponse struct {
436436
// in:body
437-
Body types.Network
437+
Body entities.NetworkInspectReport
438438
}
439439

440440
// Network list

pkg/bindings/network/network.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ func Update(ctx context.Context, netNameOrID string, options *UpdateOptions) err
7070
}
7171

7272
// Inspect returns information about a network configuration
73-
func Inspect(ctx context.Context, nameOrID string, _ *InspectOptions) (types.Network, error) {
74-
var net types.Network
73+
func Inspect(ctx context.Context, nameOrID string, _ *InspectOptions) (entitiesTypes.NetworkInspectReport, error) {
74+
var net entitiesTypes.NetworkInspectReport
7575
conn, err := bindings.GetClient(ctx)
7676
if err != nil {
7777
return net, err

pkg/domain/entities/engine_container.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ type ContainerEngine interface { //nolint:interfacebloat
7070
NetworkUpdate(ctx context.Context, networkname string, options NetworkUpdateOptions) error
7171
NetworkDisconnect(ctx context.Context, networkname string, options NetworkDisconnectOptions) error
7272
NetworkExists(ctx context.Context, networkname string) (*BoolReport, error)
73-
NetworkInspect(ctx context.Context, namesOrIds []string, options InspectOptions) ([]netTypes.Network, []error, error)
73+
NetworkInspect(ctx context.Context, namesOrIds []string, options InspectOptions) ([]NetworkInspectReport, []error, error)
7474
NetworkList(ctx context.Context, options NetworkListOptions) ([]netTypes.Network, error)
7575
NetworkPrune(ctx context.Context, options NetworkPruneOptions) ([]*NetworkPruneReport, error)
7676
NetworkReload(ctx context.Context, names []string, options NetworkReloadOptions) ([]*NetworkReloadReport, error)

pkg/domain/entities/network.go

+3
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,6 @@ type NetworkPruneReport = entitiesTypes.NetworkPruneReport
8282
type NetworkPruneOptions struct {
8383
Filters map[string][]string
8484
}
85+
86+
type NetworkInspectReport = entitiesTypes.NetworkInspectReport
87+
type NetworkContainerInfo = entitiesTypes.NetworkContainerInfo

pkg/domain/entities/types/network.go

+14
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,17 @@ type NetworkRmReport struct {
3535
type NetworkCreateReport struct {
3636
Name string
3737
}
38+
39+
type NetworkInspectReport struct {
40+
commonTypes.Network
41+
42+
Containers map[string]NetworkContainerInfo `json:"containers"`
43+
}
44+
45+
type NetworkContainerInfo struct {
46+
// Name of the container
47+
Name string `json:"name"`
48+
49+
// Interfaces configured for this container with their addresses
50+
Interfaces map[string]commonTypes.NetInterface `json:"interfaces,omitempty"`
51+
}

pkg/domain/infra/abi/network.go

+55-3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,13 @@ func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.Net
6464
return nets, err
6565
}
6666

67-
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]types.Network, []error, error) {
67+
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]entities.NetworkInspectReport, []error, error) {
6868
var errs []error
69-
networks := make([]types.Network, 0, len(namesOrIds))
69+
statuses, err := ic.GetContainerNetStatuses()
70+
if err != nil {
71+
return nil, nil, fmt.Errorf("failed to get network status for containers: %w", err)
72+
}
73+
networks := make([]entities.NetworkInspectReport, 0, len(namesOrIds))
7074
for _, name := range namesOrIds {
7175
net, err := ic.Libpod.Network().NetworkInspect(name)
7276
if err != nil {
@@ -77,7 +81,22 @@ func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []stri
7781
return nil, nil, fmt.Errorf("inspecting network %s: %w", name, err)
7882
}
7983
}
80-
networks = append(networks, net)
84+
containerMap := make(map[string]entities.NetworkContainerInfo)
85+
for _, st := range statuses {
86+
// Make sure to only show the info for the correct network
87+
if sb, ok := st.Status[net.Name]; ok {
88+
containerMap[st.ID] = entities.NetworkContainerInfo{
89+
Name: st.Name,
90+
Interfaces: sb.Interfaces,
91+
}
92+
}
93+
}
94+
95+
netReport := entities.NetworkInspectReport{
96+
Network: net,
97+
Containers: containerMap,
98+
}
99+
networks = append(networks, netReport)
81100
}
82101
return networks, errs, nil
83102
}
@@ -243,3 +262,36 @@ func (ic *ContainerEngine) createDanglingFilterFunc(wantDangling bool) (types.Fi
243262
return wantDangling
244263
}, nil
245264
}
265+
266+
type ContainerNetStatus struct {
267+
// Name of the container
268+
Name string
269+
// ID of the container
270+
ID string
271+
// Status contains the net status, the key is the network name
272+
Status map[string]types.StatusBlock
273+
}
274+
275+
func (ic *ContainerEngine) GetContainerNetStatuses() ([]ContainerNetStatus, error) {
276+
cons, err := ic.Libpod.GetAllContainers()
277+
if err != nil {
278+
return nil, err
279+
}
280+
statuses := make([]ContainerNetStatus, 0, len(cons))
281+
for _, con := range cons {
282+
status, err := con.GetNetworkStatus()
283+
if err != nil {
284+
if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrRemoved) {
285+
continue
286+
}
287+
return nil, err
288+
}
289+
290+
statuses = append(statuses, ContainerNetStatus{
291+
ID: con.ID(),
292+
Name: con.Name(),
293+
Status: status,
294+
})
295+
}
296+
return statuses, nil
297+
}

pkg/domain/infra/tunnel/network.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ func (ic *ContainerEngine) NetworkList(ctx context.Context, opts entities.Networ
2222
return network.List(ic.ClientCtx, options)
2323
}
2424

25-
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, opts entities.InspectOptions) ([]types.Network, []error, error) {
25+
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, opts entities.InspectOptions) ([]entities.NetworkInspectReport, []error, error) {
2626
var (
27-
reports = make([]types.Network, 0, len(namesOrIds))
27+
reports = make([]entities.NetworkInspectReport, 0, len(namesOrIds))
2828
errs = []error{}
2929
)
3030
options := new(network.InspectOptions)

test/e2e/network_create_test.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"net"
66

77
"github.com/containers/common/libnetwork/types"
8+
"github.com/containers/podman/v5/pkg/domain/entities"
89
. "github.com/containers/podman/v5/test/utils"
910
"github.com/containers/storage/pkg/stringid"
1011
. "github.com/onsi/ginkgo/v2"
@@ -32,7 +33,7 @@ var _ = Describe("Podman network create", func() {
3233
Expect(inspect).Should(ExitCleanly())
3334

3435
// JSON the network configuration into something usable
35-
var results []types.Network
36+
var results []entities.NetworkInspectReport
3637
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
3738
Expect(err).ToNot(HaveOccurred())
3839
Expect(results).To(HaveLen(1))
@@ -84,7 +85,7 @@ var _ = Describe("Podman network create", func() {
8485
Expect(inspect).Should(ExitCleanly())
8586

8687
// JSON the network configuration into something usable
87-
var results []types.Network
88+
var results []entities.NetworkInspectReport
8889
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
8990
Expect(err).ToNot(HaveOccurred())
9091
Expect(results).To(HaveLen(1))
@@ -125,7 +126,7 @@ var _ = Describe("Podman network create", func() {
125126
Expect(inspect).Should(ExitCleanly())
126127

127128
// JSON the network configuration into something usable
128-
var results []types.Network
129+
var results []entities.NetworkInspectReport
129130
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
130131
Expect(err).ToNot(HaveOccurred())
131132
Expect(results).To(HaveLen(1))
@@ -168,7 +169,7 @@ var _ = Describe("Podman network create", func() {
168169
Expect(inspect).Should(ExitCleanly())
169170

170171
// JSON the network configuration into something usable
171-
var results []types.Network
172+
var results []entities.NetworkInspectReport
172173
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
173174
Expect(err).ToNot(HaveOccurred())
174175
Expect(results).To(HaveLen(1))
@@ -213,7 +214,7 @@ var _ = Describe("Podman network create", func() {
213214
Expect(inspect).Should(ExitCleanly())
214215

215216
// JSON the network configuration into something usable
216-
var results []types.Network
217+
var results []entities.NetworkInspectReport
217218
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
218219
Expect(err).ToNot(HaveOccurred())
219220
Expect(results).To(HaveLen(1))
@@ -254,7 +255,7 @@ var _ = Describe("Podman network create", func() {
254255
Expect(inspect).Should(ExitCleanly())
255256

256257
// JSON the network configuration into something usable
257-
var results []types.Network
258+
var results []entities.NetworkInspectReport
258259
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
259260
Expect(err).ToNot(HaveOccurred())
260261
Expect(results).To(HaveLen(1))
@@ -284,7 +285,7 @@ var _ = Describe("Podman network create", func() {
284285
Expect(inspect).Should(ExitCleanly())
285286

286287
// JSON the network configuration into something usable
287-
var results []types.Network
288+
var results []entities.NetworkInspectReport
288289
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
289290
Expect(err).ToNot(HaveOccurred())
290291
Expect(results).To(HaveLen(1))
@@ -323,7 +324,7 @@ var _ = Describe("Podman network create", func() {
323324
Expect(inspect).Should(ExitCleanly())
324325

325326
// JSON the network configuration into something usable
326-
var results []types.Network
327+
var results []entities.NetworkInspectReport
327328
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
328329
Expect(err).ToNot(HaveOccurred())
329330
Expect(results).To(HaveLen(1))
@@ -711,7 +712,7 @@ var _ = Describe("Podman network create", func() {
711712
Expect(inspect).Should(ExitCleanly())
712713

713714
// JSON the network configuration into something usable
714-
var results []types.Network
715+
var results []entities.NetworkInspectReport
715716
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
716717
Expect(err).ToNot(HaveOccurred())
717718
Expect(results).To(HaveLen(1))

0 commit comments

Comments
 (0)