mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 19:13:34 +00:00
feat: detect conflicing service port on a container
This commit is contained in:
@@ -3,6 +3,8 @@ package api
|
||||
import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"net/netip"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -90,3 +92,178 @@ func TestContainer_Healthy(t *testing.T) {
|
||||
assert.False(t, c.Healthy())
|
||||
})
|
||||
}
|
||||
|
||||
func TestContainer_ConflictingServicePorts(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
containerPorts string
|
||||
checkPorts []PortSpec
|
||||
want []PortSpec
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "no conflicts when container has no ports",
|
||||
containerPorts: "",
|
||||
checkPorts: []PortSpec{
|
||||
{Mode: PortModeHost, PublishedPort: 8080, ContainerPort: 80, Protocol: ProtocolTCP},
|
||||
},
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "host mode ports with same published port and protocol conflict",
|
||||
containerPorts: "8080:80/tcp@host",
|
||||
checkPorts: []PortSpec{
|
||||
{Mode: PortModeHost, PublishedPort: 8080, ContainerPort: 80, Protocol: ProtocolTCP},
|
||||
},
|
||||
want: []PortSpec{
|
||||
{Mode: PortModeHost, PublishedPort: 8080, ContainerPort: 80, Protocol: ProtocolTCP},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "host mode ports with same port but different protocols don't conflict",
|
||||
containerPorts: "8080:80/tcp@host",
|
||||
checkPorts: []PortSpec{
|
||||
{Mode: PortModeHost, PublishedPort: 8080, ContainerPort: 80, Protocol: ProtocolUDP},
|
||||
},
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "multiple protocols on same port don't conflict",
|
||||
containerPorts: "8080:80/tcp@host,8080:80/udp@host",
|
||||
checkPorts: []PortSpec{
|
||||
{Mode: PortModeHost, PublishedPort: 8080, ContainerPort: 80, Protocol: ProtocolUDP},
|
||||
},
|
||||
want: []PortSpec{
|
||||
{Mode: PortModeHost, PublishedPort: 8080, ContainerPort: 80, Protocol: ProtocolUDP},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "host mode ports with different published ports don't conflict",
|
||||
containerPorts: "8080:80/tcp@host",
|
||||
checkPorts: []PortSpec{
|
||||
{Mode: PortModeHost, PublishedPort: 8081, ContainerPort: 80, Protocol: ProtocolTCP},
|
||||
},
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "host mode ports with same published port but different host IPs don't conflict",
|
||||
containerPorts: "127.0.0.1:8080:80/tcp@host",
|
||||
checkPorts: []PortSpec{
|
||||
{
|
||||
Mode: PortModeHost,
|
||||
HostIP: netip.MustParseAddr("127.0.0.2"),
|
||||
PublishedPort: 8080,
|
||||
ContainerPort: 80,
|
||||
Protocol: ProtocolTCP,
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "host mode ports with same published port, protocol, and host IP conflict",
|
||||
containerPorts: "127.0.0.1:8080:80/tcp@host",
|
||||
checkPorts: []PortSpec{
|
||||
{
|
||||
Mode: PortModeHost,
|
||||
HostIP: netip.MustParseAddr("127.0.0.1"),
|
||||
PublishedPort: 8080,
|
||||
ContainerPort: 80,
|
||||
Protocol: ProtocolTCP,
|
||||
},
|
||||
},
|
||||
want: []PortSpec{
|
||||
{
|
||||
Mode: PortModeHost,
|
||||
HostIP: netip.MustParseAddr("127.0.0.1"),
|
||||
PublishedPort: 8080,
|
||||
ContainerPort: 80,
|
||||
Protocol: ProtocolTCP,
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "host mode port with no host IP conflicts with specific host IP on same port and protocol",
|
||||
containerPorts: "8080:80/tcp@host",
|
||||
checkPorts: []PortSpec{
|
||||
{
|
||||
Mode: PortModeHost,
|
||||
HostIP: netip.MustParseAddr("127.0.0.1"),
|
||||
PublishedPort: 8080,
|
||||
ContainerPort: 80,
|
||||
Protocol: ProtocolTCP,
|
||||
},
|
||||
},
|
||||
want: []PortSpec{
|
||||
{
|
||||
Mode: PortModeHost,
|
||||
HostIP: netip.MustParseAddr("127.0.0.1"),
|
||||
PublishedPort: 8080,
|
||||
ContainerPort: 80,
|
||||
Protocol: ProtocolTCP,
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "host mode port with no host IP doesn't conflict with different protocol",
|
||||
containerPorts: "8080:80/tcp@host",
|
||||
checkPorts: []PortSpec{
|
||||
{
|
||||
Mode: PortModeHost,
|
||||
HostIP: netip.MustParseAddr("127.0.0.1"),
|
||||
PublishedPort: 8080,
|
||||
ContainerPort: 80,
|
||||
Protocol: ProtocolUDP,
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "ingress mode ports don't conflict with host mode ports",
|
||||
containerPorts: "8080:80/tcp",
|
||||
checkPorts: []PortSpec{
|
||||
{Mode: PortModeHost, PublishedPort: 8080, ContainerPort: 80, Protocol: ProtocolTCP},
|
||||
},
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "container with invalid port spec returns error",
|
||||
containerPorts: "invalid:port:spec",
|
||||
checkPorts: []PortSpec{
|
||||
{Mode: PortModeHost, PublishedPort: 8080, ContainerPort: 80, Protocol: ProtocolTCP},
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
container := &Container{
|
||||
Container: types.Container{
|
||||
Labels: map[string]string{
|
||||
LabelServicePorts: tt.containerPorts,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
got, err := container.ConflictingServicePorts(tt.checkPorts)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user