2016-12-08 16:32:10 -05:00
|
|
|
package opts
|
|
|
|
|
|
|
|
import (
|
2021-02-15 10:00:07 -05:00
|
|
|
"bytes"
|
|
|
|
"os"
|
2016-12-08 16:32:10 -05:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/docker/docker/api/types/swarm"
|
2021-02-15 10:00:07 -05:00
|
|
|
"github.com/docker/go-connections/nat"
|
|
|
|
"github.com/sirupsen/logrus"
|
2020-02-22 12:12:14 -05:00
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
is "gotest.tools/v3/assert/cmp"
|
2016-12-08 16:32:10 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestPortOptValidSimpleSyntax(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
value string
|
|
|
|
expected []swarm.PortConfig
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
value: "80",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
2016-12-09 15:17:57 -05:00
|
|
|
Protocol: "tcp",
|
|
|
|
TargetPort: 80,
|
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "80:8080",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
Protocol: "tcp",
|
|
|
|
TargetPort: 8080,
|
|
|
|
PublishedPort: 80,
|
2016-12-09 15:17:57 -05:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "8080:80/tcp",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
Protocol: "tcp",
|
|
|
|
TargetPort: 80,
|
|
|
|
PublishedPort: 8080,
|
2016-12-09 15:17:57 -05:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "80:8080/udp",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
Protocol: "udp",
|
|
|
|
TargetPort: 8080,
|
|
|
|
PublishedPort: 80,
|
2016-12-09 15:17:57 -05:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "80-81:8080-8081/tcp",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
Protocol: "tcp",
|
|
|
|
TargetPort: 8080,
|
|
|
|
PublishedPort: 80,
|
2016-12-09 15:17:57 -05:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Protocol: "tcp",
|
|
|
|
TargetPort: 8081,
|
|
|
|
PublishedPort: 81,
|
2016-12-09 15:17:57 -05:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "80-82:8080-8082/udp",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
Protocol: "udp",
|
|
|
|
TargetPort: 8080,
|
|
|
|
PublishedPort: 80,
|
2016-12-09 15:17:57 -05:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Protocol: "udp",
|
|
|
|
TargetPort: 8081,
|
|
|
|
PublishedPort: 81,
|
2016-12-09 15:17:57 -05:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Protocol: "udp",
|
|
|
|
TargetPort: 8082,
|
|
|
|
PublishedPort: 82,
|
2016-12-09 15:17:57 -05:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2018-05-31 19:41:22 -04:00
|
|
|
{
|
|
|
|
value: "80-82:8080/udp",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
Protocol: "udp",
|
|
|
|
TargetPort: 8080,
|
|
|
|
PublishedPort: 80,
|
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Protocol: "udp",
|
|
|
|
TargetPort: 8080,
|
|
|
|
PublishedPort: 81,
|
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Protocol: "udp",
|
|
|
|
TargetPort: 8080,
|
|
|
|
PublishedPort: 82,
|
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "80-80:8080/tcp",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
Protocol: "tcp",
|
|
|
|
TargetPort: 8080,
|
|
|
|
PublishedPort: 80,
|
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-12-08 16:32:10 -05:00
|
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
|
|
var port PortOpt
|
2018-03-06 15:13:00 -05:00
|
|
|
assert.NilError(t, port.Set(tc.value))
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Len(port.Value(), len(tc.expected)))
|
2016-12-08 16:32:10 -05:00
|
|
|
for _, expectedPortConfig := range tc.expected {
|
|
|
|
assertContains(t, port.Value(), expectedPortConfig)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPortOptValidComplexSyntax(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
value string
|
|
|
|
expected []swarm.PortConfig
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
value: "target=80",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
2016-12-09 15:17:57 -05:00
|
|
|
TargetPort: 80,
|
|
|
|
Protocol: "tcp",
|
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "target=80,protocol=tcp",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
2016-12-09 15:17:57 -05:00
|
|
|
Protocol: "tcp",
|
|
|
|
TargetPort: 80,
|
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "target=80,published=8080,protocol=tcp",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
Protocol: "tcp",
|
|
|
|
TargetPort: 80,
|
|
|
|
PublishedPort: 8080,
|
2016-12-09 15:17:57 -05:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "published=80,target=8080,protocol=tcp",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
Protocol: "tcp",
|
|
|
|
TargetPort: 8080,
|
|
|
|
PublishedPort: 80,
|
2016-12-09 15:17:57 -05:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "target=80,published=8080,protocol=tcp,mode=host",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
Protocol: "tcp",
|
|
|
|
TargetPort: 80,
|
|
|
|
PublishedPort: 8080,
|
|
|
|
PublishMode: "host",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "target=80,published=8080,mode=host",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
TargetPort: 80,
|
|
|
|
PublishedPort: 8080,
|
|
|
|
PublishMode: "host",
|
2016-12-09 15:17:57 -05:00
|
|
|
Protocol: "tcp",
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "target=80,published=8080,mode=ingress",
|
|
|
|
expected: []swarm.PortConfig{
|
|
|
|
{
|
|
|
|
TargetPort: 80,
|
|
|
|
PublishedPort: 8080,
|
|
|
|
PublishMode: "ingress",
|
2016-12-09 15:17:57 -05:00
|
|
|
Protocol: "tcp",
|
2016-12-08 16:32:10 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
|
|
var port PortOpt
|
2018-03-06 15:13:00 -05:00
|
|
|
assert.NilError(t, port.Set(tc.value))
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Len(port.Value(), len(tc.expected)))
|
2016-12-08 16:32:10 -05:00
|
|
|
for _, expectedPortConfig := range tc.expected {
|
|
|
|
assertContains(t, port.Value(), expectedPortConfig)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPortOptInvalidComplexSyntax(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
value string
|
|
|
|
expectedError string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
value: "invalid,target=80",
|
|
|
|
expectedError: "invalid field",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "invalid=field",
|
|
|
|
expectedError: "invalid field",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "protocol=invalid",
|
|
|
|
expectedError: "invalid protocol value",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "target=invalid",
|
|
|
|
expectedError: "invalid syntax",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "published=invalid",
|
|
|
|
expectedError: "invalid syntax",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "mode=invalid",
|
|
|
|
expectedError: "invalid publish mode value",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "published=8080,protocol=tcp,mode=ingress",
|
|
|
|
expectedError: "missing mandatory field",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: `target=80,protocol="tcp,mode=ingress"`,
|
|
|
|
expectedError: "non-quoted-field",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: `target=80,"protocol=tcp,mode=ingress"`,
|
|
|
|
expectedError: "invalid protocol value",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
|
|
var port PortOpt
|
2018-03-06 14:03:47 -05:00
|
|
|
assert.ErrorContains(t, port.Set(tc.value), tc.expectedError)
|
2016-12-08 16:32:10 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-06 08:16:03 -05:00
|
|
|
func TestPortOptInvalidSimpleSyntax(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
value string
|
|
|
|
expectedError string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
value: "9999999",
|
2023-11-10 16:32:30 -05:00
|
|
|
expectedError: "invalid containerPort: 9999999",
|
2017-02-06 08:16:03 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "80/xyz",
|
2023-11-10 16:32:30 -05:00
|
|
|
expectedError: "invalid proto: xyz",
|
2017-02-06 08:16:03 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "tcp",
|
2023-11-10 16:32:30 -05:00
|
|
|
expectedError: "invalid containerPort: tcp",
|
2017-02-06 08:16:03 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "udp",
|
2023-11-10 16:32:30 -05:00
|
|
|
expectedError: "invalid containerPort: udp",
|
2017-02-06 08:16:03 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "",
|
2023-11-10 16:32:30 -05:00
|
|
|
expectedError: "no port specified: <empty>",
|
2017-02-06 08:16:03 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "1.1.1.1:80:80",
|
2017-05-15 08:45:19 -04:00
|
|
|
expectedError: "hostip is not supported",
|
2017-02-06 08:16:03 -05:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
|
|
var port PortOpt
|
2018-03-06 15:54:24 -05:00
|
|
|
assert.Error(t, port.Set(tc.value), tc.expectedError)
|
2017-02-06 08:16:03 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-15 10:00:07 -05:00
|
|
|
func TestConvertPortToPortConfigWithIP(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
value string
|
|
|
|
expectedWarning string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
value: "0.0.0.0",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "::",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "192.168.1.5",
|
|
|
|
expectedWarning: `ignoring IP-address (192.168.1.5:2345:80/tcp) service will listen on '0.0.0.0'`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "::2",
|
|
|
|
expectedWarning: `ignoring IP-address ([::2]:2345:80/tcp) service will listen on '0.0.0.0'`,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var b bytes.Buffer
|
|
|
|
logrus.SetOutput(&b)
|
|
|
|
for _, tc := range testCases {
|
|
|
|
tc := tc
|
|
|
|
t.Run(tc.value, func(t *testing.T) {
|
|
|
|
_, err := ConvertPortToPortConfig("80/tcp", map[nat.Port][]nat.PortBinding{
|
|
|
|
"80/tcp": {{HostIP: tc.value, HostPort: "2345"}},
|
|
|
|
})
|
|
|
|
assert.NilError(t, err)
|
|
|
|
if tc.expectedWarning == "" {
|
|
|
|
assert.Equal(t, b.String(), "")
|
|
|
|
} else {
|
|
|
|
assert.Assert(t, is.Contains(b.String(), tc.expectedWarning))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
logrus.SetOutput(os.Stderr)
|
|
|
|
}
|
|
|
|
|
2016-12-08 16:32:10 -05:00
|
|
|
func assertContains(t *testing.T, portConfigs []swarm.PortConfig, expected swarm.PortConfig) {
|
2022-09-29 11:21:51 -04:00
|
|
|
contains := false
|
2016-12-08 16:32:10 -05:00
|
|
|
for _, portConfig := range portConfigs {
|
|
|
|
if portConfig == expected {
|
|
|
|
contains = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !contains {
|
|
|
|
t.Errorf("expected %v to contain %v, did not", portConfigs, expected)
|
|
|
|
}
|
|
|
|
}
|