agent: include ip in container port if not 0.0.0.0 or ::

This commit is contained in:
henrygd
2026-03-15 14:57:55 -04:00
parent 380d2b1091
commit 5bfe4f6970
3 changed files with 36 additions and 40 deletions

View File

@@ -368,6 +368,12 @@ func convertContainerPortsToString(ctr *container.ApiInfo) string {
if builder.Len() > 0 { if builder.Len() > 0 {
builder.WriteString(", ") builder.WriteString(", ")
} }
switch p.IP {
case "0.0.0.0", "::":
default:
builder.WriteString(p.IP)
builder.WriteByte(':')
}
builder.WriteString(strconv.Itoa(int(p.PublicPort))) builder.WriteString(strconv.Itoa(int(p.PublicPort)))
} }
// clear ports slice so it doesn't get reused and blend into next response // clear ports slice so it doesn't get reused and blend into next response

View File

@@ -1458,9 +1458,8 @@ func TestAnsiEscapePattern(t *testing.T) {
func TestConvertContainerPortsToString(t *testing.T) { func TestConvertContainerPortsToString(t *testing.T) {
type port = struct { type port = struct {
PrivatePort uint16 PublicPort uint16
PublicPort uint16 IP string
Type string
} }
tests := []struct { tests := []struct {
name string name string
@@ -1473,72 +1472,64 @@ func TestConvertContainerPortsToString(t *testing.T) {
expected: "", expected: "",
}, },
{ {
name: "single port public==private", name: "single port",
ports: []port{ ports: []port{
{PublicPort: 80, PrivatePort: 80}, {PublicPort: 80, IP: "0.0.0.0"},
}, },
expected: "80", expected: "80",
}, },
{ {
name: "single port public!=private", name: "single port with non-default IP",
ports: []port{ ports: []port{
{PublicPort: 443, PrivatePort: 2019}, {PublicPort: 80, IP: "1.2.3.4"},
}, },
// expected: "443:2019", expected: "1.2.3.4:80",
expected: "443", },
{
name: "ipv6 default ip",
ports: []port{
{PublicPort: 80, IP: "::"},
},
expected: "80",
}, },
{ {
name: "zero PublicPort is skipped", name: "zero PublicPort is skipped",
ports: []port{ ports: []port{
{PublicPort: 0, PrivatePort: 8080}, {PublicPort: 0, IP: "0.0.0.0"},
{PublicPort: 80, PrivatePort: 80}, {PublicPort: 80, IP: "0.0.0.0"},
}, },
expected: "80", expected: "80",
}, },
{ {
name: "ports sorted ascending by PublicPort", name: "ports sorted ascending by PublicPort",
ports: []port{ ports: []port{
{PublicPort: 443, PrivatePort: 443}, {PublicPort: 443, IP: "0.0.0.0"},
{PublicPort: 80, PrivatePort: 80}, {PublicPort: 80, IP: "0.0.0.0"},
{PublicPort: 8080, PrivatePort: 8080}, {PublicPort: 8080, IP: "0.0.0.0"},
}, },
expected: "80, 443, 8080", expected: "80, 443, 8080",
}, },
{
name: "same PublicPort sorted by PrivatePort",
ports: []port{
{PublicPort: 443, PrivatePort: 9000},
{PublicPort: 443, PrivatePort: 2019},
},
// expected: "443:2019,443:9000",
expected: "443",
},
{ {
name: "duplicates are deduplicated", name: "duplicates are deduplicated",
ports: []port{ ports: []port{
{PublicPort: 80, PrivatePort: 80}, {PublicPort: 80, IP: "0.0.0.0"},
{PublicPort: 80, PrivatePort: 80}, {PublicPort: 80, IP: "0.0.0.0"},
{PublicPort: 443, PrivatePort: 2019}, {PublicPort: 443, IP: "0.0.0.0"},
{PublicPort: 443, PrivatePort: 2019},
}, },
// expected: "80,443:2019",
expected: "80, 443", expected: "80, 443",
}, },
{ {
name: "mixed zero and non-zero ports", name: "multiple ports with different IPs",
ports: []port{ ports: []port{
{PublicPort: 0, PrivatePort: 5432}, {PublicPort: 80, IP: "0.0.0.0"},
{PublicPort: 443, PrivatePort: 2019}, {PublicPort: 443, IP: "1.2.3.4"},
{PublicPort: 80, PrivatePort: 80},
{PublicPort: 0, PrivatePort: 9000},
}, },
// expected: "80,443:2019", expected: "80, 1.2.3.4:443",
expected: "80, 443",
}, },
{ {
name: "ports slice is nilled after call", name: "ports slice is nilled after call",
ports: []port{ ports: []port{
{PublicPort: 8080, PrivatePort: 8080}, {PublicPort: 8080, IP: "0.0.0.0"},
}, },
expected: "8080", expected: "8080",
}, },
@@ -1549,10 +1540,9 @@ func TestConvertContainerPortsToString(t *testing.T) {
ctr := &container.ApiInfo{} ctr := &container.ApiInfo{}
for _, p := range tt.ports { for _, p := range tt.ports {
ctr.Ports = append(ctr.Ports, struct { ctr.Ports = append(ctr.Ports, struct {
// PrivatePort uint16
PublicPort uint16 PublicPort uint16
// Type string IP string
}{PublicPort: p.PublicPort}) }{PublicPort: p.PublicPort, IP: p.IP})
} }
result := convertContainerPortsToString(ctr) result := convertContainerPortsToString(ctr)
assert.Equal(t, tt.expected, result) assert.Equal(t, tt.expected, result)

View File

@@ -17,7 +17,7 @@ type ApiInfo struct {
Ports []struct { Ports []struct {
// PrivatePort uint16 // PrivatePort uint16
PublicPort uint16 PublicPort uint16
// IP string IP string
// Type string // Type string
} }
// ImageID string // ImageID string