Skip to content

Commit 6972b37

Browse files
committed
Allow duplicate endpoint targetPorts if they are in same container
Allow multiple endpoints to have the same target point if and only if they are attached to the same container. Otherwise, target ports must be unique unless dedicatedPod is set to true. Allowing multiple endpoints to use the same port is required for some applications which require two routes to the same endpoint, in order to create isolation between components within the browser. Signed-off-by: Angel Misevski <[email protected]>
1 parent 882fa9a commit 6972b37

File tree

6 files changed

+26
-16
lines changed

6 files changed

+26
-16
lines changed

pkg/apis/workspaces/v1alpha2/endpoint.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ type Endpoint struct {
5050
// +kubebuilder:validation:MaxLength=63
5151
Name string `json:"name"`
5252

53-
// The port number should be unique.
53+
// Port number to be used within the container component. The same port cannot
54+
// be used by two different container components.
5455
TargetPort int `json:"targetPort"`
5556

5657
// Describes how the endpoint should be exposed on the network.

pkg/validation/components_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ func TestValidateComponents(t *testing.T) {
244244
reservedEnvErr := "env variable .* is reserved and cannot be customized in component.*"
245245
invalidSizeErr := "size .* for volume component is invalid"
246246
sameEndpointNameErr := "devfile contains multiple endpoint entries with same name.*"
247-
sameTargetPortErr := "devfile contains multiple endpoint entries with same TargetPort.*"
247+
sameTargetPortErr := "devfile contains multiple containers with same endpoint targetPort.*"
248248
invalidURIErr := ".*invalid URI for request"
249249
imageCompTwoRemoteErr := "component .* should have one remote only"
250250
imageCompNoRemoteErr := "component .* should have at least one remote"
@@ -533,9 +533,10 @@ func TestValidateComponents(t *testing.T) {
533533
err := ValidateComponents(tt.components)
534534

535535
if merr, ok := err.(*multierror.Error); ok && tt.wantErr != nil {
536-
assert.Equal(t, len(tt.wantErr), len(merr.Errors), "Error list length should match")
537-
for i := 0; i < len(merr.Errors); i++ {
538-
assert.Regexp(t, tt.wantErr[i], merr.Errors[i].Error(), "Error message should match")
536+
if assert.Equal(t, len(tt.wantErr), len(merr.Errors), "Error list length should match") {
537+
for i := 0; i < len(merr.Errors); i++ {
538+
assert.Regexp(t, tt.wantErr[i], merr.Errors[i].Error(), "Error message should match")
539+
}
539540
}
540541
} else {
541542
assert.Equal(t, nil, err, "Error should be nil")

pkg/validation/endpoints.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,24 @@ import "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
55
// validateEndpoints checks if
66
// 1. all the endpoint names are unique across components
77
// 2. endpoint port are unique across component containers
8+
// ie; two component containers cannot have the same target port but two endpoints
9+
// in a single component container can have the same target port
810
func validateEndpoints(endpoints []v1alpha2.Endpoint, processedEndPointPort map[int]bool, processedEndPointName map[string]bool) (errList []error) {
11+
currentComponentEndPointPort := make(map[int]bool)
912

1013
for _, endPoint := range endpoints {
1114
if _, ok := processedEndPointName[endPoint.Name]; ok {
1215
errList = append(errList, &InvalidEndpointError{name: endPoint.Name})
1316
}
14-
if _, ok := processedEndPointPort[endPoint.TargetPort]; ok {
15-
errList = append(errList, &InvalidEndpointError{port: endPoint.TargetPort})
16-
}
1717
processedEndPointName[endPoint.Name] = true
18-
processedEndPointPort[endPoint.TargetPort] = true
18+
currentComponentEndPointPort[endPoint.TargetPort] = true
19+
}
20+
21+
for targetPort := range currentComponentEndPointPort {
22+
if _, ok := processedEndPointPort[targetPort]; ok {
23+
errList = append(errList, &InvalidEndpointError{port: targetPort})
24+
}
25+
processedEndPointPort[targetPort] = true
1926
}
2027

2128
return errList

pkg/validation/endpoints_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
func TestValidateEndpoints(t *testing.T) {
1111

1212
duplicateNameErr := "multiple endpoint entries with same name"
13-
duplicatePortErr := "devfile contains multiple endpoint entries with same TargetPort"
13+
duplicatePortErr := "devfile contains multiple containers with same endpoint targetPort"
1414

1515
tests := []struct {
1616
name string
@@ -48,7 +48,6 @@ func TestValidateEndpoints(t *testing.T) {
4848
},
4949
processedEndpointName: map[string]bool{},
5050
processedEndpointPort: map[int]bool{},
51-
wantErr: []string{duplicatePortErr},
5251
},
5352
{
5453
name: "Duplicate endpoint port across components",
@@ -83,9 +82,10 @@ func TestValidateEndpoints(t *testing.T) {
8382
err := validateEndpoints(tt.endpoints, tt.processedEndpointPort, tt.processedEndpointName)
8483

8584
if tt.wantErr != nil {
86-
assert.Equal(t, len(tt.wantErr), len(err), "Error list length should match")
87-
for i := 0; i < len(err); i++ {
88-
assert.Regexp(t, tt.wantErr[i], err[i].Error(), "Error message should match")
85+
if assert.Equal(t, len(tt.wantErr), len(err), "Error list length should match") {
86+
for i := 0; i < len(err); i++ {
87+
assert.Regexp(t, tt.wantErr[i], err[i].Error(), "Error message should match")
88+
}
8989
}
9090
} else {
9191
assert.Equal(t, 0, len(err), "Error list should be empty")

pkg/validation/errors.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func (e *InvalidEndpointError) Error() string {
9696
if e.name != "" {
9797
errMsg = fmt.Sprintf("devfile contains multiple endpoint entries with same name: %v", e.name)
9898
} else if fmt.Sprint(e.port) != "" {
99-
errMsg = fmt.Sprintf("devfile contains multiple endpoint entries with same TargetPort: %v", e.port)
99+
errMsg = fmt.Sprintf("devfile contains multiple containers with same endpoint targetPort: %v", e.port)
100100
}
101101

102102
return errMsg

pkg/validation/validation-rule.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ The validation will be done as part of schema validation, the rule will be intro
1414

1515
### Endpoints:
1616
- all the endpoint names are unique across components
17-
- all the endpoint ports are unique across components. Only exception: container component with `dedicatedpod=true`
17+
- endpoint ports must be unique across components -- two components cannot have the same target port, but one component may have two endpoints with the same target port. This restriction does not apply to container components with `dedicatedPod` set to `true`.
18+
1819

1920
### Commands:
2021
1. id must be unique

0 commit comments

Comments
 (0)