Skip to content

Commit

Permalink
Merge pull request kubernetes#9736 from sdminonne/bug_fix2
Browse files Browse the repository at this point in the history
To add validation for service ports when defined as string
  • Loading branch information
mbforbes committed Jun 26, 2015
2 parents 24de9af + 4b13faa commit 712f303
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 94 deletions.
8 changes: 4 additions & 4 deletions api/swagger-spec/v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -12575,7 +12575,7 @@
"properties": {
"name": {
"type": "string",
"description": "name for the port that can be referred to by services; must be a DNS_LABEL and unique without the pod"
"description": "name for the port that can be referred to by services; must be a IANA_SVC_NAME and unique within the pod"
},
"hostPort": {
"type": "integer",
Expand Down Expand Up @@ -12717,7 +12717,7 @@
},
"port": {
"type": "string",
"description": "number or name of the port to access on the container"
"description": "number or name of the port to access on the container; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"
},
"host": {
"type": "string",
Expand All @@ -12733,7 +12733,7 @@
"properties": {
"port": {
"type": "string",
"description": "number of name of the port to access on the container"
"description": "number of name of the port to access on the container; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"
}
}
},
Expand Down Expand Up @@ -13456,7 +13456,7 @@
},
"targetPort": {
"type": "string",
"description": "the port to access on the pods targeted by the service; defaults to the service port"
"description": "number or name of the port to access on the pods targeted by the service; defaults to the service port; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"
},
"nodePort": {
"type": "integer",
Expand Down
8 changes: 4 additions & 4 deletions api/swagger-spec/v1beta3.json
Original file line number Diff line number Diff line change
Expand Up @@ -12577,7 +12577,7 @@
"properties": {
"name": {
"type": "string",
"description": "name for the port that can be referred to by services; must be a DNS_LABEL and unique without the pod"
"description": "name for the port that can be referred to by services; must be a IANA_SVC_NAME and unique within the pod"
},
"hostPort": {
"type": "integer",
Expand Down Expand Up @@ -12719,7 +12719,7 @@
},
"port": {
"type": "string",
"description": "number or name of the port to access on the container"
"description": "number or name of the port to access on the container; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"
},
"host": {
"type": "string",
Expand All @@ -12735,7 +12735,7 @@
"properties": {
"port": {
"type": "string",
"description": "number of name of the port to access on the container"
"description": "number or name of the port to access on the container; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"
}
}
},
Expand Down Expand Up @@ -13462,7 +13462,7 @@
},
"targetPort": {
"type": "string",
"description": "the port to access on the pods targeted by the service; defaults to the service port"
"description": "number or name of the port to access on the pods targeted by the service; defaults to the service port; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"
},
"nodePort": {
"type": "integer",
Expand Down
2 changes: 1 addition & 1 deletion contrib/mesos/pkg/executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ func TestExecutorStaticPods(t *testing.T) {
"enabled": true,
"type": "http",
"initialDelaySeconds": 30,
"httpGet": { "path": "/", "port": "80" }
"httpGet": { "path": "/", "port": 80 }
}
}]
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/api/rest/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)

func makeValidService() api.Service {
Expand All @@ -36,7 +37,7 @@ func makeValidService() api.Service {
Selector: map[string]string{"key": "val"},
SessionAffinity: "None",
Type: api.ServiceTypeClusterIP,
Ports: []api.ServicePort{{Name: "p", Protocol: "TCP", Port: 8675}},
Ports: []api.ServicePort{{Name: "p", Protocol: "TCP", Port: 8675, TargetPort: util.NewIntOrStringFromInt(8675)}},
},
}
}
Expand Down
8 changes: 7 additions & 1 deletion pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ import (
// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*
// or more simply:
// DNS_LABEL(\.DNS_LABEL)*
//
// IANA_SVC_NAME: This is a string, no more than 15 characters long, that
// conforms to the definition of IANA service name in RFC 6335.
// It must contains at least one letter [a-z] and it must contains only [a-z0-9-].
// Hypens ('-') cannot be leading or trailing character of the string
// and cannot be adjacent to other hyphens.

// TypeMeta describes an individual object in an API response or request
// with strings representing the type of the object and its API schema version.
Expand Down Expand Up @@ -545,7 +551,7 @@ type RBDVolumeSource struct {

// ContainerPort represents a network port in a single container
type ContainerPort struct {
// Optional: If specified, this must be a DNS_LABEL. Each named port
// Optional: If specified, this must be a IANA_SVC_NAME Each named port
// in a pod must have a unique name.
Name string `json:"name,omitempty"`
// Optional: If specified, this must be a valid port number, 0 < x < 65536.
Expand Down
16 changes: 11 additions & 5 deletions pkg/api/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ import (
// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*
// or more simply:
// DNS_LABEL(\.DNS_LABEL)*
//
// IANA_SVC_NAME: This is a string, no more than 15 characters long, that
// conforms to the definition of IANA service name in RFC 6335.
// It must contains at least one letter [a-z] and it must contains only [a-z0-9-].
// Hypens ('-') cannot be leading or trailing character of the string
// and cannot be adjacent to other hyphens.

// TypeMeta describes an individual object in an API response or request
// with strings representing the type of the object and its API schema version.
Expand Down Expand Up @@ -523,9 +529,9 @@ type ISCSIVolumeSource struct {

// ContainerPort represents a network port in a single container.
type ContainerPort struct {
// Optional: If specified, this must be a DNS_LABEL. Each named port
// Optional: If specified, this must be a IANA_SVC_NAME Each named port
// in a pod must have a unique name.
Name string `json:"name,omitempty" description:"name for the port that can be referred to by services; must be a DNS_LABEL and unique without the pod"`
Name string `json:"name,omitempty" description:"name for the port that can be referred to by services; must be a IANA_SVC_NAME and unique within the pod"`
// Optional: If specified, this must be a valid port number, 0 < x < 65536.
// If HostNetwork is specified, this must match ContainerPort.
HostPort int `json:"hostPort,omitempty" description:"number of port to expose on the host; most containers do not need this"`
Expand Down Expand Up @@ -583,15 +589,15 @@ type HTTPGetAction struct {
// Optional: Path to access on the HTTP server.
Path string `json:"path,omitempty" description:"path to access on the HTTP server"`
// Required: Name or number of the port to access on the container.
Port util.IntOrString `json:"port" description:"number or name of the port to access on the container"`
Port util.IntOrString `json:"port" description:"number or name of the port to access on the container; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"`
// Optional: Host name to connect to, defaults to the pod IP.
Host string `json:"host,omitempty" description:"hostname to connect to; defaults to pod IP"`
}

// TCPSocketAction describes an action based on opening a socket
type TCPSocketAction struct {
// Required: Port to connect to.
Port util.IntOrString `json:"port" description:"number of name of the port to access on the container"`
Port util.IntOrString `json:"port" description:"number of name of the port to access on the container; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"`
}

// ExecAction describes a "run in container" action.
Expand Down Expand Up @@ -1102,7 +1108,7 @@ type ServicePort struct {
// If this is a string, it will be looked up as a named port in the
// target Pod's container ports. If this is not specified, the value
// of Port is used (an identity map).
TargetPort util.IntOrString `json:"targetPort,omitempty" description:"the port to access on the pods targeted by the service; defaults to the service port"`
TargetPort util.IntOrString `json:"targetPort,omitempty" description:"number or name of the port to access on the pods targeted by the service; defaults to the service port; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"`

// The port on each node on which this service is exposed.
// Default is to auto-allocate a port if the ServiceType of this Service requires one.
Expand Down
16 changes: 11 additions & 5 deletions pkg/api/v1beta3/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ import (
// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*
// or more simply:
// DNS_LABEL(\.DNS_LABEL)*
//
// IANA_SVC_NAME: This is a string, no more than 15 characters long, that
// conforms to the definition of IANA service name in RFC 6335.
// It must contains at least one letter [a-z] and it must contains only [a-z0-9-].
// Hypens ('-') cannot be leading or trailing character of the string
// and cannot be adjacent to other hyphens.

// TypeMeta describes an individual object in an API response or request
// with strings representing the type of the object and its API schema version.
Expand Down Expand Up @@ -523,9 +529,9 @@ type ISCSIVolumeSource struct {

// ContainerPort represents a network port in a single container.
type ContainerPort struct {
// Optional: If specified, this must be a DNS_LABEL. Each named port
// Optional: If specified, this must be a IANA_SVC_NAME. Each named port
// in a pod must have a unique name.
Name string `json:"name,omitempty" description:"name for the port that can be referred to by services; must be a DNS_LABEL and unique without the pod"`
Name string `json:"name,omitempty" description:"name for the port that can be referred to by services; must be a IANA_SVC_NAME and unique within the pod"`
// Optional: If specified, this must be a valid port number, 0 < x < 65536.
// If HostNetwork is specified, this must match ContainerPort.
HostPort int `json:"hostPort,omitempty" description:"number of port to expose on the host; most containers do not need this"`
Expand Down Expand Up @@ -583,15 +589,15 @@ type HTTPGetAction struct {
// Optional: Path to access on the HTTP server.
Path string `json:"path,omitempty" description:"path to access on the HTTP server"`
// Required: Name or number of the port to access on the container.
Port util.IntOrString `json:"port" description:"number or name of the port to access on the container"`
Port util.IntOrString `json:"port" description:"number or name of the port to access on the container; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"`
// Optional: Host name to connect to, defaults to the pod IP.
Host string `json:"host,omitempty" description:"hostname to connect to; defaults to pod IP"`
}

// TCPSocketAction describes an action based on opening a socket
type TCPSocketAction struct {
// Required: Port to connect to.
Port util.IntOrString `json:"port" description:"number of name of the port to access on the container"`
Port util.IntOrString `json:"port" description:"number or name of the port to access on the container; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"`
}

// ExecAction describes a "run in container" action.
Expand Down Expand Up @@ -1108,7 +1114,7 @@ type ServicePort struct {
// If this is a string, it will be looked up as a named port in the
// target Pod's container ports. If this is not specified, the value
// of Port is used (an identity map).
TargetPort util.IntOrString `json:"targetPort,omitempty" description:"the port to access on the pods targeted by the service; defaults to the service port"`
TargetPort util.IntOrString `json:"targetPort,omitempty" description:"number or name of the port to access on the pods targeted by the service; defaults to the service port; number must be in the range 1 to 65535; name must be a IANA_SVC_NAME"`

// The port on each node on which this service is exposed.
// Default is to auto-allocate a port if the ServiceType of this Service requires one.
Expand Down
22 changes: 12 additions & 10 deletions pkg/api/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ var dns1123LabelErrorMsg string = fmt.Sprintf(`must be a DNS label (at most %d c
var dns952LabelErrorMsg string = fmt.Sprintf(`must be a DNS 952 label (at most %d characters, matching regex %s): e.g. "my-name"`, util.DNS952LabelMaxLength, util.DNS952LabelFmt)
var pdPartitionErrorMsg string = intervalErrorMsg(0, 255)
var portRangeErrorMsg string = intervalErrorMsg(0, 65536)
var portNameErrorMsg string = fmt.Sprintf(`must be a IANA_SVC_NAME (at most 15 characters, matching regex %s and it must containts at least one letter [a-z], hypens cannot be adjacent to other hyphens): e.g. "http"`, util.IdentifierNoHyphensBeginEndFmt)

const totalAnnotationSizeLimitB int = 64 * (1 << 10) // 64 kB

Expand Down Expand Up @@ -594,8 +595,8 @@ func validatePorts(ports []api.ContainerPort) errs.ValidationErrorList {
for i, port := range ports {
pErrs := errs.ValidationErrorList{}
if len(port.Name) > 0 {
if len(port.Name) > util.DNS1123LabelMaxLength || !util.IsDNS1123Label(port.Name) {
pErrs = append(pErrs, errs.NewFieldInvalid("name", port.Name, dns1123LabelErrorMsg))
if !util.IsValidPortName(port.Name) {
pErrs = append(pErrs, errs.NewFieldInvalid("name", port.Name, portNameErrorMsg))
} else if allNames.Has(port.Name) {
pErrs = append(pErrs, errs.NewFieldDuplicate("name", port.Name))
} else {
Expand Down Expand Up @@ -759,8 +760,8 @@ func validateHTTPGetAction(http *api.HTTPGetAction) errs.ValidationErrorList {
}
if http.Port.Kind == util.IntstrInt && !util.IsValidPortNum(http.Port.IntVal) {
allErrors = append(allErrors, errs.NewFieldInvalid("port", http.Port, portRangeErrorMsg))
} else if http.Port.Kind == util.IntstrString && len(http.Port.StrVal) == 0 {
allErrors = append(allErrors, errs.NewFieldRequired("port"))
} else if http.Port.Kind == util.IntstrString && !util.IsValidPortName(http.Port.StrVal) {
allErrors = append(allErrors, errs.NewFieldInvalid("port", http.Port.StrVal, portNameErrorMsg))
}
return allErrors
}
Expand All @@ -769,8 +770,8 @@ func validateTCPSocketAction(tcp *api.TCPSocketAction) errs.ValidationErrorList
allErrors := errs.ValidationErrorList{}
if tcp.Port.Kind == util.IntstrInt && !util.IsValidPortNum(tcp.Port.IntVal) {
allErrors = append(allErrors, errs.NewFieldInvalid("port", tcp.Port, portRangeErrorMsg))
} else if tcp.Port.Kind == util.IntstrString && len(tcp.Port.StrVal) == 0 {
allErrors = append(allErrors, errs.NewFieldRequired("port"))
} else if tcp.Port.Kind == util.IntstrString && !util.IsValidPortName(tcp.Port.StrVal) {
allErrors = append(allErrors, errs.NewFieldInvalid("port", tcp.Port.StrVal, portNameErrorMsg))
}
return allErrors
}
Expand Down Expand Up @@ -1127,10 +1128,11 @@ func validateServicePort(sp *api.ServicePort, requireName bool, allNames *util.S
allErrs = append(allErrs, errs.NewFieldNotSupported("protocol", sp.Protocol))
}

if sp.TargetPort != util.NewIntOrStringFromInt(0) && sp.TargetPort != util.NewIntOrStringFromString("") {
if sp.TargetPort.Kind == util.IntstrInt && !util.IsValidPortNum(sp.TargetPort.IntVal) {
allErrs = append(allErrs, errs.NewFieldInvalid("targetPort", sp.TargetPort, portRangeErrorMsg))
}
if sp.TargetPort.Kind == util.IntstrInt && !util.IsValidPortNum(sp.TargetPort.IntVal) {
allErrs = append(allErrs, errs.NewFieldInvalid("targetPort", sp.TargetPort, portRangeErrorMsg))
}
if sp.TargetPort.Kind == util.IntstrString && !util.IsValidPortName(sp.TargetPort.StrVal) {
allErrs = append(allErrs, errs.NewFieldInvalid("targetPort", sp.TargetPort, portNameErrorMsg))
}

return allErrs
Expand Down
Loading

0 comments on commit 712f303

Please sign in to comment.