Skip to content

Commit 25dc9ca

Browse files
author
Huang Xin
committed
Refactor codes
Signed-off-by: Huang Xin <[email protected]>
1 parent 8ca0b7d commit 25dc9ca

File tree

3 files changed

+105
-11
lines changed

3 files changed

+105
-11
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
Copyright 2022 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package validation
18+
19+
import gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1"
20+
21+
// ContainsInProtocolSlice checks whether the provided Protocol
22+
// is in the target Protocol slice.
23+
func ContainsInProtocolSlice(items []gatewayv1b1.ProtocolType, item *gatewayv1b1.ProtocolType) bool {
24+
for _, eachItem := range items {
25+
if eachItem == *item {
26+
return true
27+
}
28+
}
29+
return false
30+
}
31+
32+
// ContainsInPortSlice checks whether the provided Port
33+
// is in the target Port slice.
34+
func ContainsInPortSlice(items []gatewayv1b1.PortNumber, item *gatewayv1b1.PortNumber) bool {
35+
for _, eachItem := range items {
36+
if eachItem == *item {
37+
return true
38+
}
39+
}
40+
return false
41+
}

apis/v1beta1/validation/gateway.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"k8s.io/apimachinery/pkg/util/validation/field"
2323

2424
gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1"
25+
utils "sigs.k8s.io/gateway-api/apis/v1beta1/util/validation"
2526
)
2627

2728
var (
@@ -62,6 +63,8 @@ func validateGatewayListeners(listeners []gatewayv1b1.Listener, path *field.Path
6263
var errs field.ErrorList
6364
errs = append(errs, validateListenerTLSConfig(listeners, path)...)
6465
errs = append(errs, validateListenerHostname(listeners, path)...)
66+
errs = append(errs, ValidateTLSCertificateRefs(listeners, path)...)
67+
errs = append(errs, ValidateHostnameProtocolPort(listeners, path)...)
6568
return errs
6669
}
6770

@@ -91,3 +94,56 @@ func validateListenerHostname(listeners []gatewayv1b1.Listener, path *field.Path
9194
}
9295
return errs
9396
}
97+
98+
// ValidateTLSCertificateRefs validates the certificateRefs
99+
// must be set and not empty when tls config is set and
100+
// TLSModeType is terminate
101+
func ValidateTLSCertificateRefs(listeners []gatewayv1b1.Listener, path *field.Path) field.ErrorList {
102+
var errs field.ErrorList
103+
for i, c := range listeners {
104+
if isProtocolInSubset(c.Protocol, protocolsTLSRequired) && c.TLS != nil {
105+
if *c.TLS.Mode == gatewayv1b1.TLSModeTerminate && len(c.TLS.CertificateRefs) == 0 {
106+
errs = append(errs, field.Forbidden(path.Index(i).Child("tls").Child("certificateRefs"), fmt.Sprintln("should be set and not empty when TLSModeType is Terminate")))
107+
}
108+
}
109+
}
110+
return errs
111+
}
112+
113+
114+
// validateHostnameProtocolPort validates listener protocols or ports
115+
// must be different for the same hostname
116+
func ValidateHostnameProtocolPort(listeners []gatewayv1b1.Listener, path *field.Path) field.ErrorList {
117+
var errs field.ErrorList
118+
hostnameProtocolMap := make(map[gatewayv1b1.Hostname][]gatewayv1b1.ProtocolType)
119+
hostnamePortMap := make(map[gatewayv1b1.Hostname][]gatewayv1b1.PortNumber)
120+
for i, listener := range listeners {
121+
targetHostname := *new(gatewayv1b1.Hostname)
122+
if listener.Hostname != nil {
123+
targetHostname = *listener.Hostname
124+
}
125+
if len(listener.Protocol) == 0 && listener.Port == 0 {
126+
errs = append(errs, field.Forbidden(path.Index(i).Child("hostname"), fmt.Sprintf("Protocol and Port should not all be empty for the same Hostname: %s", targetHostname)))
127+
return errs
128+
}
129+
if len(listener.Protocol) != 0 {
130+
if protocolSlice, ok := hostnameProtocolMap[targetHostname]; ok {
131+
if utils.ContainsInProtocolSlice(protocolSlice, &listener.Protocol) {
132+
errs = append(errs, field.Forbidden(path.Index(i).Child("protocol"), fmt.Sprintf("must be different for the same Hostname: %s", targetHostname)))
133+
return errs
134+
}
135+
}
136+
hostnameProtocolMap[targetHostname] = append(hostnameProtocolMap[targetHostname], listener.Protocol)
137+
}
138+
if listener.Port != 0 {
139+
if portSlice, ok := hostnamePortMap[targetHostname]; ok {
140+
if utils.ContainsInPortSlice(portSlice, &listener.Port) {
141+
errs = append(errs, field.Forbidden(path.Index(i).Child("port"), fmt.Sprintf("must be different for the same Hostname: %s", targetHostname)))
142+
return errs
143+
}
144+
}
145+
hostnamePortMap[targetHostname] = append(hostnamePortMap[targetHostname], listener.Port)
146+
}
147+
}
148+
return errs
149+
}

apis/v1beta1/validation/gateway_test.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ func TestValidateGateway(t *testing.T) {
2929
{
3030
Hostname: nil,
3131
},
32-
{
33-
Hostname: nil,
34-
},
3532
}
3633
addresses := []gatewayv1b1.GatewayAddress{
3734
{
@@ -159,16 +156,16 @@ func TestValidateGateway(t *testing.T) {
159156
expectErrsOnFields: []string{"spec.listeners[1].protocol"},
160157
},
161158
"port is not unique in hostname": {
159+
"ports are not different for the same hostname": {
162160
mutate: func(gw *gatewayv1b1.Gateway) {
163-
hostname := gatewayv1b1.Hostname("foo.bar.com")
164-
gw.Spec.Listeners[0].Hostname = &hostname
165-
gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPProtocolType
166-
gw.Spec.Listeners[0].Port = gatewayv1b1.PortNumber(80)
167-
gw.Spec.Listeners[1].Hostname = &hostname
168-
gw.Spec.Listeners[1].Protocol = gatewayv1b1.HTTPSProtocolType
169-
gw.Spec.Listeners[1].Port = gatewayv1b1.PortNumber(80)
161+
moreListeners := []gatewayv1b1.Listener {
162+
{
163+
Hostname: nil,
164+
},
165+
}
166+
gw.Spec.Listeners = append(gw.Spec.Listeners, moreListeners...)
170167
},
171-
expectErrsOnFields: []string{"spec.listeners[1].port"},
168+
expectErrsOnFields: []string{"spec.listeners[0].hostname"},
172169
},
173170
}
174171

0 commit comments

Comments
 (0)