WIP use structured type

Still failing when joining;

    docker container ls --format 'table {{.ID}}\t{{join .IPAddresses ", "}}'
    CONTAINER ID   IP ADDRESSES
    245bd1d81375   bridge/172.17.0.2, foo/172.19.0.2

    docker container ls --format '{{json .IPAddresses}}'
    [{"Network":"bridge","IP":"172.17.0.2"},{"Network":"foo","IP":"172.19.0.2"}]

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2020-09-22 16:03:21 +02:00
parent 9c9fcec6d4
commit 0e8f85c5bf
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
3 changed files with 57 additions and 15 deletions

View File

@ -4,8 +4,10 @@
package formatter package formatter
import ( import (
"cmp"
"fmt" "fmt"
"net" "net"
"slices"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -40,6 +42,16 @@ func (p Platform) String() string {
return platforms.FormatAll(p.Platform) return platforms.FormatAll(p.Platform)
} }
// NetworkIP describes an IP-address and the network it's associated with.
type NetworkIP struct {
Network string `json:"Network,omitempty"`
IP string `json:"IP"`
}
func (p NetworkIP) String() string {
return p.Network + "/" + p.IP
}
// NewContainerFormat returns a Format for rendering using a Context // NewContainerFormat returns a Format for rendering using a Context
func NewContainerFormat(source string, quiet bool, size bool) Format { func NewContainerFormat(source string, quiet bool, size bool) Format {
switch source { switch source {
@ -340,19 +352,30 @@ func (c *ContainerContext) Networks() string {
// IPAddresses returns the list of IP-addresses assigned to the container // IPAddresses returns the list of IP-addresses assigned to the container
// IP-addresses are prefixed with the name of the network, separated with a colon. // IP-addresses are prefixed with the name of the network, separated with a colon.
// For example: "bridge:192.168.1.10" // For example: "bridge:192.168.1.10"
func (c *ContainerContext) IPAddresses() []string { func (c *ContainerContext) IPAddresses() []NetworkIP {
ipAddresses := []string{} if c.c.NetworkSettings == nil || len(c.c.NetworkSettings.Networks) == 0 {
if c.c.NetworkSettings == nil { return []NetworkIP{}
return ipAddresses
} }
ipAddresses := make([]NetworkIP, 0, len(c.c.NetworkSettings.Networks))
for name, nw := range c.c.NetworkSettings.Networks { for name, nw := range c.c.NetworkSettings.Networks {
if nw.IPAddress != "" { if nw.IPAddress != "" {
ipAddresses = append(ipAddresses, name+":"+nw.IPAddress) ipAddresses = append(ipAddresses, NetworkIP{
Network: name,
IP: nw.IPAddress,
})
} }
if nw.GlobalIPv6Address != "" { if nw.GlobalIPv6Address != "" {
ipAddresses = append(ipAddresses, name+":"+nw.GlobalIPv6Address) ipAddresses = append(ipAddresses, NetworkIP{
Network: name,
IP: nw.GlobalIPv6Address,
})
} }
} }
slices.SortFunc(ipAddresses, func(a, b NetworkIP) int {
return cmp.Compare(a.String(), b.String())
})
return ipAddresses return ipAddresses
} }

View File

@ -439,7 +439,18 @@ func TestContainerContextWriteJSON(t *testing.T) {
Image: "ubuntu", Image: "ubuntu",
Created: unix, Created: unix,
State: container.StateRunning, State: container.StateRunning,
NetworkSettings: &container.NetworkSettingsSummary{
Networks: map[string]*network.EndpointSettings{
"bridge": {
IPAddress: "172.17.0.1",
GlobalIPv6Address: "ff02::1",
},
"my-net": {
IPAddress: "172.18.0.1",
GlobalIPv6Address: "ff02::2",
},
},
},
ImageManifestDescriptor: &ocispec.Descriptor{Platform: &ocispec.Platform{Architecture: "amd64", OS: "linux"}}, ImageManifestDescriptor: &ocispec.Descriptor{Platform: &ocispec.Platform{Architecture: "amd64", OS: "linux"}},
}, },
{ {
@ -458,6 +469,7 @@ func TestContainerContextWriteJSON(t *testing.T) {
"Command": `""`, "Command": `""`,
"CreatedAt": expectedCreated, "CreatedAt": expectedCreated,
"ID": "containerID1", "ID": "containerID1",
"IPAddresses": []any{},
"Image": "ubuntu", "Image": "ubuntu",
"Labels": "", "Labels": "",
"LocalVolumes": "0", "LocalVolumes": "0",
@ -472,15 +484,21 @@ func TestContainerContextWriteJSON(t *testing.T) {
"Status": "", "Status": "",
}, },
{ {
"Command": `""`, "Command": `""`,
"CreatedAt": expectedCreated, "CreatedAt": expectedCreated,
"ID": "containerID2", "ID": "containerID2",
"IPAddresses": []any{
map[string]any{"IP": "172.17.0.1", "Network": "bridge"},
map[string]any{"IP": "ff02::1", "Network": "bridge"},
map[string]any{"IP": "172.18.0.1", "Network": "my-net"},
map[string]any{"IP": "ff02::2", "Network": "my-net"},
},
"Image": "ubuntu", "Image": "ubuntu",
"Labels": "", "Labels": "",
"LocalVolumes": "0", "LocalVolumes": "0",
"Mounts": "", "Mounts": "",
"Names": "foobar_bar", "Names": "foobar_bar",
"Networks": "", "Networks": "bridge,my-net",
"Platform": map[string]any{"architecture": "amd64", "os": "linux"}, "Platform": map[string]any{"architecture": "amd64", "os": "linux"},
"Ports": "", "Ports": "",
"RunningFor": "About a minute ago", "RunningFor": "About a minute ago",
@ -492,6 +510,7 @@ func TestContainerContextWriteJSON(t *testing.T) {
"Command": `""`, "Command": `""`,
"CreatedAt": expectedCreated, "CreatedAt": expectedCreated,
"ID": "containerID3", "ID": "containerID3",
"IPAddresses": []any{},
"Image": "ubuntu", "Image": "ubuntu",
"Labels": "", "Labels": "",
"LocalVolumes": "0", "LocalVolumes": "0",
@ -564,8 +583,8 @@ func TestContainerContextIPAddresses(t *testing.T) {
out := bytes.NewBufferString("") out := bytes.NewBufferString("")
err := ContainerWrite(Context{Format: "{{.IPAddresses}}", Output: out}, containers) err := ContainerWrite(Context{Format: "{{.IPAddresses}}", Output: out}, containers)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.String(), `[one:192.168.1.2 two:192.168.178.2] assert.Equal(t, out.String(), `[one/192.168.1.2 two/192.168.178.2]
[one:192.168.1.3 two:192.168.178.3] [one/192.168.1.3 two/192.168.178.3]
`) `)
} }

View File

@ -455,6 +455,6 @@ Show the IP-addresses that containers have:
$ docker ps --format "table {{.ID}}\\t{{join .IPAddresses \", \"}}" $ docker ps --format "table {{.ID}}\\t{{join .IPAddresses \", \"}}"
CONTAINER ID IP ADDRESSES CONTAINER ID IP ADDRESSES
c0cf2877da71 bridge:172.17.0.3 c0cf2877da71 bridge/172.17.0.3
17e7d1910fc0 bridge:172.17.0.2, mynetwork:172.19.0.2 17e7d1910fc0 bridge/172.17.0.2, mynetwork/172.19.0.2
``` ```