From 4857050dc8b3ee5a37ad67679f139110fca9fba9 Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Tue, 19 Dec 2023 11:46:55 +0100 Subject: [PATCH 1/2] fix: empty adresses with docker internal networks Co-authored-by: Nicolas Duchon Co-authored-by: Anton Tinyakov --- internal/context/address.go | 50 +++++++++++++++++++++++++++++++++ internal/context/context.go | 10 ------- internal/generator/generator.go | 19 +++---------- 3 files changed, 54 insertions(+), 25 deletions(-) create mode 100644 internal/context/address.go diff --git a/internal/context/address.go b/internal/context/address.go new file mode 100644 index 00000000..48368d12 --- /dev/null +++ b/internal/context/address.go @@ -0,0 +1,50 @@ +package context + +import ( + docker "github.com/fsouza/go-dockerclient" +) + +type Address struct { + IP string + IP6LinkLocal string + IP6Global string + Port string + HostPort string + Proto string + HostIP string +} + +func renderAddress(container *docker.Container, port docker.Port) Address { + return Address{ + IP: container.NetworkSettings.IPAddress, + IP6LinkLocal: container.NetworkSettings.LinkLocalIPv6Address, + IP6Global: container.NetworkSettings.GlobalIPv6Address, + Port: port.Port(), + Proto: port.Proto(), + } +} + +func GetContainerAddresses(container *docker.Container) []Address { + addresses := []Address{} + + for port, bindings := range container.NetworkSettings.Ports { + address := renderAddress(container, port) + + if len(bindings) > 0 { + address.HostPort = bindings[0].HostPort + address.HostIP = bindings[0].HostIP + } + + addresses = append(addresses, address) + } + + if len(addresses) == 0 { + // internal docker network has empty 'container.NetworkSettings.Ports' + for port := range container.Config.ExposedPorts { + address := renderAddress(container, port) + addresses = append(addresses, address) + } + } + + return addresses +} diff --git a/internal/context/context.go b/internal/context/context.go index 983721cf..2bb49275 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -52,16 +52,6 @@ func SetDockerEnv(d *docker.Env) { dockerEnv = d } -type Address struct { - IP string - IP6LinkLocal string - IP6Global string - Port string - HostPort string - Proto string - HostIP string -} - type Network struct { IP string Name string diff --git a/internal/generator/generator.go b/internal/generator/generator.go index 4ea539c9..6d5cb15e 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -420,22 +420,10 @@ func (g *generator) getContainers() ([]*context.RuntimeContainer, error) { IP6LinkLocal: container.NetworkSettings.LinkLocalIPv6Address, IP6Global: container.NetworkSettings.GlobalIPv6Address, } - for k, v := range container.NetworkSettings.Ports { - address := context.Address{ - IP: container.NetworkSettings.IPAddress, - IP6LinkLocal: container.NetworkSettings.LinkLocalIPv6Address, - IP6Global: container.NetworkSettings.GlobalIPv6Address, - Port: k.Port(), - Proto: k.Proto(), - } - if len(v) > 0 { - address.HostPort = v[0].HostPort - address.HostIP = v[0].HostIP - } - runtimeContainer.Addresses = append(runtimeContainer.Addresses, - address) - } + adresses := context.GetContainerAddresses(container) + runtimeContainer.Addresses = append(runtimeContainer.Addresses, adresses...) + for k, v := range container.NetworkSettings.Networks { network := context.Network{ IP: v.IPAddress, @@ -453,6 +441,7 @@ func (g *generator) getContainers() ([]*context.RuntimeContainer, error) { runtimeContainer.Networks = append(runtimeContainer.Networks, network) } + for k, v := range container.Volumes { runtimeContainer.Volumes[k] = context.Volume{ Path: k, From bcbfa495992bea63c6ac9611f4772942ed372ac4 Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Tue, 19 Dec 2023 11:47:30 +0100 Subject: [PATCH 2/2] test: container addresses generation --- internal/context/address_test.go | 116 +++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 internal/context/address_test.go diff --git a/internal/context/address_test.go b/internal/context/address_test.go new file mode 100644 index 00000000..bfbb76b9 --- /dev/null +++ b/internal/context/address_test.go @@ -0,0 +1,116 @@ +package context + +import ( + "testing" + + docker "github.com/fsouza/go-dockerclient" + "github.com/stretchr/testify/assert" +) + +type FakePortBinding struct{} + +var httpPort = docker.Port("80/tcp") +var httpPortBinding = docker.PortBinding{ + HostIP: "100.100.100.100", + HostPort: "8080", +} + +var httpsPort = docker.Port("443/tcp") + +var httpTestPort = docker.Port("8080/tcp") +var httpsTestPort = docker.Port("8443/tcp") + +func TestGenerateContainerAddresses(t *testing.T) { + testContainer := &docker.Container{ + Config: &docker.Config{ + ExposedPorts: map[docker.Port]struct{}{}, + }, + NetworkSettings: &docker.NetworkSettings{ + IPAddress: "10.0.0.10", + LinkLocalIPv6Address: "24", + GlobalIPv6Address: "10.0.0.1", + Ports: map[docker.Port][]docker.PortBinding{}, + }, + } + testContainer.NetworkSettings.Ports[httpPort] = []docker.PortBinding{httpPortBinding} + testContainer.NetworkSettings.Ports[httpsPort] = []docker.PortBinding{} + + addresses := GetContainerAddresses(testContainer) + assert.Len(t, addresses, len(testContainer.NetworkSettings.Ports)) + assert.Contains(t, addresses, Address{ + IP: "10.0.0.10", + IP6LinkLocal: "24", + IP6Global: "10.0.0.1", + Port: "80", + Proto: "tcp", + HostIP: "100.100.100.100", + HostPort: "8080", + }) + assert.Contains(t, addresses, Address{ + IP: "10.0.0.10", + IP6LinkLocal: "24", + IP6Global: "10.0.0.1", + Port: "443", + Proto: "tcp", + HostIP: "", + HostPort: "", + }) +} + +func TestGenerateContainerAddressesWithExposedPorts(t *testing.T) { + testContainer := &docker.Container{ + Config: &docker.Config{ + ExposedPorts: map[docker.Port]struct{}{}, + }, + NetworkSettings: &docker.NetworkSettings{ + IPAddress: "10.0.0.10", + LinkLocalIPv6Address: "24", + GlobalIPv6Address: "10.0.0.1", + Ports: map[docker.Port][]docker.PortBinding{}, + }, + } + testContainer.NetworkSettings.Ports[httpPort] = []docker.PortBinding{} + testContainer.NetworkSettings.Ports[httpsPort] = []docker.PortBinding{} + testContainer.Config.ExposedPorts[httpPort] = struct{}{} + testContainer.Config.ExposedPorts[httpsPort] = struct{}{} + testContainer.Config.ExposedPorts[httpTestPort] = struct{}{} + + assert.Len(t, GetContainerAddresses(testContainer), 2) +} + +func TestGenerateContainerAddressesWithNoPorts(t *testing.T) { + testContainer := &docker.Container{ + Config: &docker.Config{ + ExposedPorts: map[docker.Port]struct{}{}, + }, + NetworkSettings: &docker.NetworkSettings{ + IPAddress: "10.0.0.10", + LinkLocalIPv6Address: "24", + GlobalIPv6Address: "10.0.0.1", + Ports: map[docker.Port][]docker.PortBinding{}, + }, + } + testContainer.Config.ExposedPorts[httpTestPort] = FakePortBinding{} + testContainer.Config.ExposedPorts[httpsTestPort] = FakePortBinding{} + + addresses := GetContainerAddresses(testContainer) + assert.Len(t, addresses, len(testContainer.Config.ExposedPorts)) + assert.Contains(t, addresses, Address{ + IP: "10.0.0.10", + IP6LinkLocal: "24", + IP6Global: "10.0.0.1", + Port: "8080", + Proto: "tcp", + HostIP: "", + HostPort: "", + }) + assert.Contains(t, addresses, Address{ + IP: "10.0.0.10", + IP6LinkLocal: "24", + IP6Global: "10.0.0.1", + Port: "8443", + Proto: "tcp", + HostIP: "", + HostPort: "", + }) +}