diff --git a/core/internal/helpers/validation.go b/core/internal/helpers/validation.go index 6d1fe8aa..8e21fa7a 100644 --- a/core/internal/helpers/validation.go +++ b/core/internal/helpers/validation.go @@ -31,12 +31,20 @@ func ValidateIP(ipaddr string) bool { // * Valid characters in a segment are letters, numbers, and dashes // * Segments may not start or end with a dash // * The exception is IPv6 addresses, which are also permitted. +// * An underscore is allowed to support Docker Swarm service names. func ValidateHostname(hostname string) bool { matches, _ := regexp.MatchString(`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$`, hostname) + if !matches { - // Try as an IP address - return ValidateIP(hostname) + // Try Docker Swarm service name + matchesDocker, _ := regexp.MatchString(`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])\_([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])$`, hostname) + if !matchesDocker { + // Try as an IP address + return ValidateIP(hostname) + } + return true } + return matches } diff --git a/core/internal/helpers/validation_test.go b/core/internal/helpers/validation_test.go index 7fadd636..2f46eb22 100644 --- a/core/internal/helpers/validation_test.go +++ b/core/internal/helpers/validation_test.go @@ -11,8 +11,9 @@ package helpers import ( - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) type TestSet struct { @@ -53,6 +54,12 @@ var testHostnames = []TestSet{ {"800.hostnames.starting.with.numbers.are.valid.because.people.suck.org", true}, {"hostnames-.may.not.end.with.a.dash.com", false}, {"no spaces.com", false}, + {"docker_service.name.should.not.contain.dots", false}, + {"docker-swarmservice_name-with-one-underscore-is-valid", true}, + {"invalid-docker-_service-name", false}, + {"invalid-docker_-service-name", false}, + {"docker-service-may-not-end-with-underscore_", false}, + {"_docker-service-may-not-start-with-underscore", false}, } func TestValidateHostname(t *testing.T) {