mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 19:13:34 +00:00
basic validation for hostname in port publishing
This commit is contained in:
+18
-5
@@ -45,12 +45,17 @@ func (p *PortSpec) Validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch p.Mode {
|
switch p.Mode {
|
||||||
case PortModeIngress:
|
case "", PortModeIngress: // Default mode is ingress if not specified.
|
||||||
if p.HostIP.IsValid() {
|
if p.HostIP.IsValid() {
|
||||||
return fmt.Errorf("host IP cannot be specified in %s mode", PortModeIngress)
|
return fmt.Errorf("host IP cannot be specified in %s mode", PortModeIngress)
|
||||||
}
|
}
|
||||||
if p.Hostname != "" && p.Protocol != ProtocolHTTP && p.Protocol != ProtocolHTTPS {
|
if p.Hostname != "" {
|
||||||
return fmt.Errorf("hostname is only valid with '%s' or '%s' protocols", ProtocolHTTP, ProtocolHTTPS)
|
if p.Protocol != ProtocolHTTP && p.Protocol != ProtocolHTTPS {
|
||||||
|
return fmt.Errorf("hostname is only valid with '%s' or '%s' protocols", ProtocolHTTP, ProtocolHTTPS)
|
||||||
|
}
|
||||||
|
if err := validateHostname(p.Hostname); err != nil {
|
||||||
|
return fmt.Errorf("invalid hostname '%s': %w", p.Hostname, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if p.Hostname == "" && (p.Protocol == ProtocolHTTP || p.Protocol == ProtocolHTTPS) {
|
if p.Hostname == "" && (p.Protocol == ProtocolHTTP || p.Protocol == ProtocolHTTPS) {
|
||||||
return fmt.Errorf("hostname is required with '%s' or '%s' protocols", ProtocolHTTP, ProtocolHTTPS)
|
return fmt.Errorf("hostname is required with '%s' or '%s' protocols", ProtocolHTTP, ProtocolHTTPS)
|
||||||
@@ -136,7 +141,6 @@ func ParsePortSpec(port string) (PortSpec, error) {
|
|||||||
if parts[0] == "" {
|
if parts[0] == "" {
|
||||||
return spec, fmt.Errorf("hostname must not be empty")
|
return spec, fmt.Errorf("hostname must not be empty")
|
||||||
}
|
}
|
||||||
// TODO: validate hostname?
|
|
||||||
spec.Hostname = parts[0]
|
spec.Hostname = parts[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +174,6 @@ func ParsePortSpec(port string) (PortSpec, error) {
|
|||||||
if parts[0] == "" {
|
if parts[0] == "" {
|
||||||
return spec, fmt.Errorf("hostname must not be empty")
|
return spec, fmt.Errorf("hostname must not be empty")
|
||||||
}
|
}
|
||||||
// TODO: validate hostname?
|
|
||||||
spec.Hostname = parts[0]
|
spec.Hostname = parts[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,3 +211,13 @@ func parsePort(s string) (uint16, error) {
|
|||||||
}
|
}
|
||||||
return uint16(port), nil
|
return uint16(port), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateHostname(hostname string) error {
|
||||||
|
if hostname == "" {
|
||||||
|
return fmt.Errorf("must not be empty")
|
||||||
|
}
|
||||||
|
if !strings.Contains(hostname, ".") {
|
||||||
|
return fmt.Errorf("must be a valid domain name containing at least one dot")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ func TestParsePortSpec(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid published port",
|
name: "invalid published port",
|
||||||
port: "test:invalid:8080",
|
port: "app.example.com:invalid:8080",
|
||||||
wantErr: "invalid published port",
|
wantErr: "invalid published port",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -232,6 +232,11 @@ func TestParsePortSpec(t *testing.T) {
|
|||||||
port: "8000:8080/https",
|
port: "8000:8080/https",
|
||||||
wantErr: "hostname is required",
|
wantErr: "hostname is required",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "invalid hostname",
|
||||||
|
port: "app:8080/http",
|
||||||
|
wantErr: "invalid hostname 'app': must be a valid domain name containing at least one dot",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "hostname with tcp protocol",
|
name: "hostname with tcp protocol",
|
||||||
port: "app.example.com:8080/tcp",
|
port: "app.example.com:8080/tcp",
|
||||||
@@ -324,13 +329,19 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
Mode: PortModeIngress,
|
Mode: PortModeIngress,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ingress mode tcp",
|
||||||
|
spec: PortSpec{
|
||||||
|
ContainerPort: 8080,
|
||||||
|
Protocol: ProtocolTCP,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "ingress mode with published tcp port",
|
name: "ingress mode with published tcp port",
|
||||||
spec: PortSpec{
|
spec: PortSpec{
|
||||||
PublishedPort: 80,
|
PublishedPort: 80,
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: ProtocolTCP,
|
Protocol: ProtocolTCP,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -338,7 +349,6 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
spec: PortSpec{
|
spec: PortSpec{
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: ProtocolUDP,
|
Protocol: ProtocolUDP,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -347,7 +357,6 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
PublishedPort: 80,
|
PublishedPort: 80,
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: ProtocolUDP,
|
Protocol: ProtocolUDP,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -356,7 +365,6 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
Hostname: "app.example.com",
|
Hostname: "app.example.com",
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: ProtocolHTTP,
|
Protocol: ProtocolHTTP,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -365,7 +373,6 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
Hostname: "app.example.com",
|
Hostname: "app.example.com",
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: ProtocolHTTPS,
|
Protocol: ProtocolHTTPS,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -375,7 +382,6 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
PublishedPort: 6443,
|
PublishedPort: 6443,
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: ProtocolHTTPS,
|
Protocol: ProtocolHTTPS,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -415,7 +421,6 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
name: "missing container port",
|
name: "missing container port",
|
||||||
spec: PortSpec{
|
spec: PortSpec{
|
||||||
Protocol: ProtocolTCP,
|
Protocol: ProtocolTCP,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
wantErr: "container port must be non-zero",
|
wantErr: "container port must be non-zero",
|
||||||
},
|
},
|
||||||
@@ -424,7 +429,6 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
spec: PortSpec{
|
spec: PortSpec{
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: "invalid",
|
Protocol: "invalid",
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
wantErr: "invalid protocol: 'invalid'",
|
wantErr: "invalid protocol: 'invalid'",
|
||||||
},
|
},
|
||||||
@@ -443,16 +447,23 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
Hostname: "app.example.com",
|
Hostname: "app.example.com",
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: ProtocolTCP,
|
Protocol: ProtocolTCP,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
wantErr: "hostname is only valid with 'http' or 'https' protocols",
|
wantErr: "hostname is only valid with 'http' or 'https' protocols",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "invalid hostname",
|
||||||
|
spec: PortSpec{
|
||||||
|
Hostname: "app",
|
||||||
|
ContainerPort: 8080,
|
||||||
|
Protocol: ProtocolHTTPS,
|
||||||
|
},
|
||||||
|
wantErr: "invalid hostname 'app': must be a valid domain name containing at least one dot",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "missing hostname with http",
|
name: "missing hostname with http",
|
||||||
spec: PortSpec{
|
spec: PortSpec{
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: ProtocolHTTP,
|
Protocol: ProtocolHTTP,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
wantErr: "hostname is required with 'http' or 'https' protocols",
|
wantErr: "hostname is required with 'http' or 'https' protocols",
|
||||||
},
|
},
|
||||||
@@ -461,7 +472,6 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
spec: PortSpec{
|
spec: PortSpec{
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: ProtocolHTTPS,
|
Protocol: ProtocolHTTPS,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
wantErr: "hostname is required with 'http' or 'https' protocols",
|
wantErr: "hostname is required with 'http' or 'https' protocols",
|
||||||
},
|
},
|
||||||
@@ -471,7 +481,6 @@ func TestPortSpec_Validate(t *testing.T) {
|
|||||||
HostIP: netip.MustParseAddr("127.0.0.1"),
|
HostIP: netip.MustParseAddr("127.0.0.1"),
|
||||||
ContainerPort: 8080,
|
ContainerPort: 8080,
|
||||||
Protocol: ProtocolTCP,
|
Protocol: ProtocolTCP,
|
||||||
Mode: PortModeIngress,
|
|
||||||
},
|
},
|
||||||
wantErr: "host IP cannot be specified in ingress mode",
|
wantErr: "host IP cannot be specified in ingress mode",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user