11package route
22
33import (
4+ "context"
45 "fmt"
56
67 "slices"
78
89 routev1 "github.com/openshift/api/route/v1"
910 "github.com/rh-ecosystem-edge/eco-goinfra/pkg/clients"
10- "github.com/rh-ecosystem-edge/eco-goinfra/pkg/internal/logging"
11- "github.com/rh-ecosystem-edge/eco-goinfra/pkg/msg"
12- k8serrors "k8s.io/apimachinery/pkg/api/errors"
13- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+ "github.com/rh-ecosystem-edge/eco-goinfra/pkg/internal/common"
12+ "k8s.io/apimachinery/pkg/runtime/schema"
1413 "k8s.io/apimachinery/pkg/util/intstr"
1514 "k8s.io/klog/v2"
16-
17- goclient "sigs.k8s.io/controller-runtime/pkg/client"
1815)
1916
2017// Builder provides struct for route object containing connection to the cluster and the route definitions.
2118type Builder struct {
22- // Route definition. Used to create a route object
23- Definition * routev1.Route
24- // Created route object
25- Object * routev1.Route
26- // Used in functions that define or mutate the route definition.
27- // errorMsg is processed before the route object is created
28- errorMsg string
29- apiClient goclient.Client
19+ common.EmbeddableBuilder [routev1.Route , * routev1.Route ]
20+ common.EmbeddableCreator [routev1.Route , Builder , * routev1.Route , * Builder ]
21+ common.EmbeddableDeleteReturner [routev1.Route , Builder , * routev1.Route , * Builder ]
22+ }
23+
24+ // AttachMixins attaches the mixins to the builder. This is called automatically when the builder is initialized.
25+ func (builder * Builder ) AttachMixins () {
26+ builder .EmbeddableCreator .SetBase (builder )
27+ builder .EmbeddableDeleteReturner .SetBase (builder )
28+ }
29+
30+ // GetGVK returns the GVK for the Route resource.
31+ func (builder * Builder ) GetGVK () schema.GroupVersionKind {
32+ return routev1 .GroupVersion .WithKind ("Route" )
3033}
3134
3235// NewBuilder creates a new instance of Builder.
@@ -35,99 +38,38 @@ func NewBuilder(apiClient *clients.Settings, name, nsname, serviceName string) *
3538 "Initializing new route structure with the following params: name: %s, namespace: %s, serviceName: %s" ,
3639 name , nsname , serviceName )
3740
38- if apiClient == nil {
39- klog .V (100 ).Info ("The apiClient is nil" )
40-
41- return nil
42- }
43-
44- builder := & Builder {
45- apiClient : apiClient .Client ,
46- Definition : & routev1.Route {
47- ObjectMeta : metav1.ObjectMeta {
48- Name : name ,
49- Namespace : nsname ,
50- },
51- Spec : routev1.RouteSpec {
52- To : routev1.RouteTargetReference {
53- Kind : "Service" ,
54- Name : serviceName ,
55- },
56- },
57- },
58- }
59-
60- if name == "" {
61- klog .V (100 ).Info ("The name of the route is empty" )
62-
63- builder .errorMsg = "route 'name' cannot be empty"
64-
65- return builder
66- }
67-
68- if nsname == "" {
69- klog .V (100 ).Info ("The namespace of the route is empty" )
70-
71- builder .errorMsg = "route 'nsname' cannot be empty"
72-
41+ builder := common .NewNamespacedBuilder [routev1.Route , Builder ](apiClient , routev1 .AddToScheme , name , nsname )
42+ if builder .GetError () != nil {
7343 return builder
7444 }
7545
7646 if serviceName == "" {
7747 klog .V (100 ).Info ("The serviceName of the route is empty" )
7848
79- builder .errorMsg = "route 'serviceName' cannot be empty"
49+ builder .SetError ( fmt . Errorf ( "route 'serviceName' cannot be empty" ))
8050
8151 return builder
8252 }
8353
54+ builder .Definition .Spec .To = routev1.RouteTargetReference {
55+ Kind : "Service" ,
56+ Name : serviceName ,
57+ }
58+
8459 return builder
8560}
8661
8762// Pull loads existing route from cluster.
8863func Pull (apiClient * clients.Settings , name , nsname string ) (* Builder , error ) {
8964 klog .V (100 ).Infof ("Pulling existing route name %s under namespace %s from cluster" , name , nsname )
9065
91- if apiClient == nil {
92- klog .V (100 ).Info ("The apiClient is nil" )
93-
94- return nil , fmt .Errorf ("the apiClient cannot be nil" )
95- }
96-
97- builder := & Builder {
98- apiClient : apiClient .Client ,
99- Definition : & routev1.Route {
100- ObjectMeta : metav1.ObjectMeta {
101- Name : name ,
102- Namespace : nsname ,
103- },
104- },
105- }
106-
107- if name == "" {
108- klog .V (100 ).Info ("The name of the route is empty" )
109-
110- return nil , fmt .Errorf ("route 'name' cannot be empty" )
111- }
112-
113- if nsname == "" {
114- klog .V (100 ).Info ("The namespace of the route is empty" )
115-
116- return nil , fmt .Errorf ("route 'namespace' cannot be empty" )
117- }
118-
119- if ! builder .Exists () {
120- return nil , fmt .Errorf ("route object %s does not exist in namespace %s" , name , nsname )
121- }
122-
123- builder .Definition = builder .Object
124-
125- return builder , nil
66+ return common .PullNamespacedBuilder [routev1.Route , Builder ](
67+ context .TODO (), apiClient , routev1 .AddToScheme , name , nsname )
12668}
12769
12870// WithTargetPortNumber adds a target port to the route by number.
12971func (builder * Builder ) WithTargetPortNumber (port int32 ) * Builder {
130- if valid , _ := builder . validate ( ); ! valid {
72+ if err := common . Validate ( builder ); err != nil {
13173 return builder
13274 }
13375
@@ -145,7 +87,7 @@ func (builder *Builder) WithTargetPortNumber(port int32) *Builder {
14587
14688// WithTargetPortName adds a target port to the route by name.
14789func (builder * Builder ) WithTargetPortName (portName string ) * Builder {
148- if valid , _ := builder . validate ( ); ! valid {
90+ if err := common . Validate ( builder ); err != nil {
14991 return builder
15092 }
15193
@@ -155,10 +97,10 @@ func (builder *Builder) WithTargetPortName(portName string) *Builder {
15597 if portName == "" {
15698 klog .V (100 ).Info ("Received empty route portName" )
15799
158- builder .errorMsg = "route target port name cannot be empty string"
100+ builder .SetError ( fmt . Errorf ( "route target port name cannot be empty string" ))
159101 }
160102
161- if builder .errorMsg != "" {
103+ if builder .GetError () != nil {
162104 return builder
163105 }
164106
@@ -173,7 +115,7 @@ func (builder *Builder) WithTargetPortName(portName string) *Builder {
173115
174116// WithHostDomain adds a route host domain to the route.
175117func (builder * Builder ) WithHostDomain (hostDomain string ) * Builder {
176- if valid , _ := builder . validate ( ); ! valid {
118+ if err := common . Validate ( builder ); err != nil {
177119 return builder
178120 }
179121
@@ -183,7 +125,7 @@ func (builder *Builder) WithHostDomain(hostDomain string) *Builder {
183125 if hostDomain == "" {
184126 klog .V (100 ).Info ("Received empty route hostDomain" )
185127
186- builder .errorMsg = "route host domain cannot be empty string"
128+ builder .SetError ( fmt . Errorf ( "route host domain cannot be empty string" ))
187129
188130 return builder
189131 }
@@ -195,18 +137,17 @@ func (builder *Builder) WithHostDomain(hostDomain string) *Builder {
195137
196138// WithWildCardPolicy adds the specified wildCardPolicy to the route.
197139func (builder * Builder ) WithWildCardPolicy (wildcardPolicy string ) * Builder {
198- if valid , _ := builder . validate ( ); ! valid {
140+ if err := common . Validate ( builder ); err != nil {
199141 return builder
200142 }
201143
202144 klog .V (100 ).Infof ("Adding wildcardPolicy %s to route %s in namespace %s" ,
203145 wildcardPolicy , builder .Definition .Name , builder .Definition .Namespace )
204146
205147 if ! slices .Contains (supportedWildCardPolicies (), wildcardPolicy ) {
206- klog .V (100 ).Infof ("Received unsupported route wildcardPolicy, supported policies: %v" , supportedWildCardPolicies ())
148+ klog .V (100 ).Infof ("Received unsupported route wildcardPolicy, expected one of %v" , supportedWildCardPolicies ())
207149
208- builder .errorMsg = fmt .Sprintf ("received unsupported route wildcardPolicy: supported policies %v" ,
209- supportedWildCardPolicies ())
150+ builder .SetError (getUnsupportedWildCardPoliciesError ())
210151
211152 return builder
212153 }
@@ -216,129 +157,15 @@ func (builder *Builder) WithWildCardPolicy(wildcardPolicy string) *Builder {
216157 return builder
217158}
218159
219- // Exists checks whether the given route exists.
220- func (builder * Builder ) Exists () bool {
221- if valid , _ := builder .validate (); ! valid {
222- return false
223- }
224-
225- klog .V (100 ).Infof (
226- "Checking if route %s exists in namespace %s" ,
227- builder .Definition .Name , builder .Definition .Namespace )
228-
229- var err error
230-
231- builder .Object , err = builder .Get ()
232-
233- return err == nil || ! k8serrors .IsNotFound (err )
234- }
235-
236- // Get returns route object if found.
237- func (builder * Builder ) Get () (* routev1.Route , error ) {
238- if valid , err := builder .validate (); ! valid {
239- return nil , err
240- }
241-
242- klog .V (100 ).Infof (
243- "Getting route %s in namespace %s" ,
244- builder .Definition .Name , builder .Definition .Namespace )
245-
246- route := & routev1.Route {}
247-
248- err := builder .apiClient .Get (logging .DiscardContext (), goclient.ObjectKey {
249- Name : builder .Definition .Name ,
250- Namespace : builder .Definition .Namespace ,
251- }, route )
252- if err != nil {
253- return nil , err
254- }
255-
256- return route , nil
257- }
258-
259- // Create makes a route according to the route definition and stores the created object in the route builder.
260- func (builder * Builder ) Create () (* Builder , error ) {
261- if valid , err := builder .validate (); ! valid {
262- return builder , err
263- }
264-
265- klog .V (100 ).Infof ("Creating the route %s in namespace %s" ,
266- builder .Definition .Name , builder .Definition .Namespace )
267-
268- var err error
269- if ! builder .Exists () {
270- err = builder .apiClient .Create (logging .DiscardContext (), builder .Definition )
271- if err == nil {
272- builder .Object = builder .Definition
273- }
274- }
275-
276- return builder , err
277- }
278-
279- // Delete removes the route object and resets the builder object.
280- func (builder * Builder ) Delete () (* Builder , error ) {
281- if valid , err := builder .validate (); ! valid {
282- return builder , err
283- }
284-
285- klog .V (100 ).Infof ("Deleting the route %s in namespace %s" ,
286- builder .Definition .Name , builder .Definition .Namespace )
287-
288- if ! builder .Exists () {
289- klog .V (100 ).Infof ("Route %s does not exist in namespace %s" ,
290- builder .Definition .Name , builder .Definition .Namespace )
291-
292- builder .Object = nil
293-
294- return builder , nil
295- }
296-
297- err := builder .apiClient .Delete (logging .DiscardContext (), builder .Definition )
298- if err != nil {
299- return builder , fmt .Errorf ("cannot delete route: %w" , err )
300- }
301-
302- builder .Object = nil
303-
304- return builder , nil
305- }
306-
307- // validate will check that the builder and builder definition are properly initialized before
308- // accessing any member fields.
309- func (builder * Builder ) validate () (bool , error ) {
310- resourceCRD := "Route"
311-
312- if builder == nil {
313- klog .V (100 ).Infof ("The %s builder is uninitialized" , resourceCRD )
314-
315- return false , fmt .Errorf ("error: received nil %s builder" , resourceCRD )
316- }
317-
318- if builder .Definition == nil {
319- klog .V (100 ).Infof ("The %s is undefined" , resourceCRD )
320-
321- return false , fmt .Errorf ("%s" , msg .UndefinedCrdObjectErrString (resourceCRD ))
322- }
323-
324- if builder .apiClient == nil {
325- klog .V (100 ).Infof ("The %s builder apiclient is nil" , resourceCRD )
326-
327- return false , fmt .Errorf ("%s builder cannot have nil apiClient" , resourceCRD )
328- }
329-
330- if builder .errorMsg != "" {
331- klog .V (100 ).Infof ("The %s builder has error message: %s" , resourceCRD , builder .errorMsg )
332-
333- return false , fmt .Errorf ("%s" , builder .errorMsg )
334- }
335-
336- return true , nil
337- }
338-
339160func supportedWildCardPolicies () []string {
340161 return []string {
341162 "Subdomain" ,
342163 "None" ,
343164 }
344165}
166+
167+ func getUnsupportedWildCardPoliciesError () error {
168+ return fmt .Errorf (
169+ "received unsupported route wildcardPolicy: expected one of %v" ,
170+ supportedWildCardPolicies ())
171+ }
0 commit comments