Skip to content

Commit 01ef8c1

Browse files
committed
Add service Endpoint Validate() method
This method can e.g. be used in webhooks to validate if the configuration in the CR is correct.
1 parent 09a6145 commit 01ef8c1

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed

modules/common/service/types.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@ limitations under the License.
1919
package service
2020

2121
import (
22+
"fmt"
2223
"time"
2324

25+
"golang.org/x/exp/slices"
26+
2427
corev1 "k8s.io/api/core/v1"
28+
"k8s.io/apimachinery/pkg/util/validation/field"
2529
)
2630

2731
// Endpoint - typedef to enumerate Endpoint verbs
@@ -60,6 +64,30 @@ func (e *Endpoint) String() string {
6064
return string(*e)
6165
}
6266

67+
// Validate - validates if the endpoint is an allowed one.
68+
func (e *Endpoint) Validate() error {
69+
if !slices.Contains([]Endpoint{EndpointInternal, EndpointPublic}, *e) {
70+
return fmt.Errorf("invalid endpoint type: %s", e.String())
71+
}
72+
return nil
73+
}
74+
75+
// ValidateRoutedOverrides - validates map of RoutedOverrideSpec
76+
func ValidateRoutedOverrides(basePath *field.Path, overrides map[Endpoint]RoutedOverrideSpec) field.ErrorList {
77+
allErrs := field.ErrorList{}
78+
79+
// validate the service override key is valid
80+
for k := range overrides {
81+
path := basePath.Key(k.String())
82+
83+
if err := k.Validate(); err != nil {
84+
allErrs = append(allErrs, field.Invalid(path, k.String(), err.Error()))
85+
}
86+
}
87+
88+
return allErrs
89+
}
90+
6391
func (p *Protocol) String() string {
6492
return string(*p)
6593
}

modules/common/service/types_test.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
Copyright 2024 Red Hat
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+
// +kubebuilder:object:generate:=true
18+
19+
package service
20+
21+
import (
22+
"fmt"
23+
"testing"
24+
25+
. "github.com/onsi/gomega"
26+
"k8s.io/apimachinery/pkg/util/validation/field"
27+
)
28+
29+
func TestEndpointValidate(t *testing.T) {
30+
tests := []struct {
31+
name string
32+
e Endpoint
33+
want error
34+
}{
35+
{
36+
name: "Valid endpoint",
37+
e: EndpointInternal,
38+
want: nil,
39+
},
40+
{
41+
name: "Wrong endpoint",
42+
e: Endpoint("wrooong"),
43+
want: fmt.Errorf("invalid endpoint type: wrooong"),
44+
},
45+
}
46+
47+
for _, tt := range tests {
48+
t.Run(tt.name, func(t *testing.T) {
49+
g := NewWithT(t)
50+
51+
if tt.want == nil {
52+
g.Expect(tt.e.Validate()).To(Succeed())
53+
} else {
54+
g.Expect(tt.e.Validate()).To(Equal(tt.want))
55+
}
56+
})
57+
}
58+
}
59+
60+
func TestValidateRoutedOverrides(t *testing.T) {
61+
//basePath := field.NewPath("spec")
62+
63+
tests := []struct {
64+
name string
65+
basePath *field.Path
66+
overrides map[Endpoint]RoutedOverrideSpec
67+
want field.ErrorList
68+
}{
69+
{
70+
name: "Valid override config",
71+
basePath: field.NewPath("spec").Child("override").Child("service"),
72+
overrides: map[Endpoint]RoutedOverrideSpec{
73+
EndpointInternal: {},
74+
},
75+
want: field.ErrorList{},
76+
},
77+
{
78+
name: "Wrong override endpoint",
79+
basePath: field.NewPath("spec").Child("override").Child("service"),
80+
overrides: map[Endpoint]RoutedOverrideSpec{
81+
Endpoint("wrooong"): {},
82+
},
83+
want: field.ErrorList{
84+
&field.Error{
85+
Type: field.ErrorTypeInvalid,
86+
Field: "spec.override.service[wrooong]",
87+
BadValue: "wrooong",
88+
Detail: "invalid endpoint type: wrooong",
89+
},
90+
},
91+
},
92+
{
93+
name: "Both good and wrong override endpoint configs",
94+
basePath: field.NewPath("spec").Child("foo").Child("bar"),
95+
overrides: map[Endpoint]RoutedOverrideSpec{
96+
EndpointInternal: {},
97+
Endpoint("wrooong"): {},
98+
},
99+
want: field.ErrorList{
100+
&field.Error{
101+
Type: field.ErrorTypeInvalid,
102+
Field: "spec.foo.bar[wrooong]",
103+
BadValue: "wrooong",
104+
Detail: "invalid endpoint type: wrooong",
105+
},
106+
},
107+
},
108+
{
109+
name: "Multiple wrong override endpoints",
110+
basePath: field.NewPath("spec").Child("foo"),
111+
overrides: map[Endpoint]RoutedOverrideSpec{
112+
EndpointInternal: {},
113+
Endpoint("wrooong"): {},
114+
Endpoint("wroooooong"): {},
115+
},
116+
want: field.ErrorList{
117+
&field.Error{
118+
Type: field.ErrorTypeInvalid,
119+
Field: "spec.foo[wrooong]",
120+
BadValue: "wrooong",
121+
Detail: "invalid endpoint type: wrooong",
122+
},
123+
&field.Error{
124+
Type: field.ErrorTypeInvalid,
125+
Field: "spec.foo[wroooooong]",
126+
BadValue: "wroooooong",
127+
Detail: "invalid endpoint type: wroooooong",
128+
},
129+
},
130+
},
131+
}
132+
133+
for _, tt := range tests {
134+
t.Run(tt.name, func(t *testing.T) {
135+
g := NewWithT(t)
136+
137+
g.Expect(ValidateRoutedOverrides(tt.basePath, tt.overrides)).To(Equal(tt.want))
138+
})
139+
}
140+
}

0 commit comments

Comments
 (0)