@@ -3,9 +3,11 @@ package gateway
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
6
7
"github.com/go-logr/logr"
7
8
"github.com/pkg/errors"
8
9
corev1 "k8s.io/api/core/v1"
10
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9
11
"k8s.io/apimachinery/pkg/types"
10
12
"k8s.io/apimachinery/pkg/util/sets"
11
13
"k8s.io/client-go/tools/record"
@@ -35,6 +37,12 @@ import (
35
37
"sigs.k8s.io/controller-runtime/pkg/source"
36
38
gwv1 "sigs.k8s.io/gateway-api/apis/v1"
37
39
gwalpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
40
+ "time"
41
+ )
42
+
43
+ const (
44
+ requeueMessage = "Monitoring provisioning state"
45
+ statusUpdateRequeueTime = 2 * time .Minute
38
46
)
39
47
40
48
var _ Reconciler = & gatewayReconciler {}
@@ -86,6 +94,7 @@ func newGatewayReconciler(controllerName string, lbType elbv2model.LoadBalancerT
86
94
reconcileTracker : reconcileTracker ,
87
95
cfgResolver : cfgResolver ,
88
96
routeReconciler : routeReconciler ,
97
+ gatewayConditionUpdater : prepareGatewayConditionUpdate ,
89
98
}
90
99
}
91
100
@@ -107,6 +116,7 @@ type gatewayReconciler struct {
107
116
logger logr.Logger
108
117
metricsCollector lbcmetrics.MetricCollector
109
118
reconcileTracker func (namespaceName types.NamespacedName )
119
+ gatewayConditionUpdater func (gw * gwv1.Gateway , targetConditionType string , newStatus metav1.ConditionStatus , reason string , message string ) bool
110
120
111
121
cfgResolver gatewayConfigResolver
112
122
routeReconciler routeutils.RouteReconciler
@@ -186,12 +196,23 @@ func (r *gatewayReconciler) reconcileHelper(ctx context.Context, req reconcile.R
186
196
mergedLbConfig , err := r .cfgResolver .getLoadBalancerConfigForGateway (ctx , r .k8sClient , gw , gwClass )
187
197
188
198
if err != nil {
199
+ statusErr := r .updateGatewayStatusFailure (ctx , gw , gwv1 .GatewayReasonInvalid , err )
200
+ if statusErr != nil {
201
+ r .logger .Error (err , "Unable to update gateway status on failure to retrieve attached config" )
202
+ }
189
203
return err
190
204
}
191
205
192
206
allRoutes , err := r .gatewayLoader .LoadRoutesForGateway (ctx , * gw , r .routeFilter , r .routeReconciler )
193
207
194
208
if err != nil {
209
+ var loaderErr routeutils.LoaderError
210
+ if errors .As (err , & loaderErr ) {
211
+ statusErr := r .updateGatewayStatusFailure (ctx , gw , loaderErr .GetReason (), loaderErr )
212
+ if statusErr != nil {
213
+ r .logger .Error (statusErr , "Unable to update gateway status on failure to build routes" )
214
+ }
215
+ }
195
216
return err
196
217
}
197
218
@@ -248,18 +269,14 @@ func (r *gatewayReconciler) reconcileUpdate(ctx context.Context, gw *gwv1.Gatewa
248
269
if err != nil {
249
270
return err
250
271
}
251
- lbDNS , err := lb .DNSName ().Resolve (ctx )
252
- if err != nil {
253
- return err
254
- }
255
272
256
273
if ! backendSGRequired {
257
274
if err := r .backendSGProvider .Release (ctx , networking .ResourceTypeGateway , []types.NamespacedName {k8s .NamespacedName (gw )}); err != nil {
258
275
return err
259
276
}
260
277
}
261
278
262
- if err = r .updateGatewayStatus (ctx , lbDNS , gw ); err != nil {
279
+ if err = r .updateGatewayStatusSuccess (ctx , lb . Status , gw ); err != nil {
263
280
r .eventRecorder .Event (gw , corev1 .EventTypeWarning , k8s .GatewayEventReasonFailedUpdateStatus , fmt .Sprintf ("Failed update status due to %v" , err ))
264
281
return err
265
282
}
@@ -295,28 +312,59 @@ func (r *gatewayReconciler) buildModel(ctx context.Context, gw *gwv1.Gateway, cf
295
312
return stack , lb , backendSGRequired , nil
296
313
}
297
314
298
- func (r * gatewayReconciler ) updateGatewayStatus (ctx context.Context , lbDNS string , gw * gwv1.Gateway ) error {
299
- // TODO Consider LB ARN.
315
+ func (r * gatewayReconciler ) updateGatewayStatusSuccess (ctx context.Context , lbStatus * elbv2model.LoadBalancerStatus , gw * gwv1.Gateway ) error {
316
+ // LB Status should always be set, if it's not, we need to prevent NPE
317
+ if lbStatus == nil {
318
+ r .logger .Info ("Unable to update Gateway Status due to null LB status" )
319
+ return nil
320
+ }
321
+ gwOld := gw .DeepCopy ()
322
+
323
+ var needPatch bool
324
+ var requeueNeeded bool
325
+ if isGatewayProgrammed (* lbStatus ) {
326
+ needPatch = prepareGatewayConditionUpdate (gw , string (gwv1 .GatewayConditionProgrammed ), metav1 .ConditionTrue , string (gwv1 .GatewayConditionProgrammed ), lbStatus .LoadBalancerARN )
327
+ } else {
328
+ requeueNeeded = true
329
+ }
300
330
301
- // Gateway Address Status
331
+ needPatch = prepareGatewayConditionUpdate ( gw , string ( gwv1 . GatewayConditionAccepted ), metav1 . ConditionTrue , string ( gwv1 . GatewayConditionAccepted ), "" ) || needPatch
302
332
if len (gw .Status .Addresses ) != 1 ||
303
333
gw .Status .Addresses [0 ].Value != "" ||
304
- gw .Status .Addresses [0 ].Value != lbDNS {
305
- gwOld := gw .DeepCopy ()
334
+ gw .Status .Addresses [0 ].Value != lbStatus .DNSName {
306
335
ipAddressType := gwv1 .HostnameAddressType
307
336
gw .Status .Addresses = []gwv1.GatewayStatusAddress {
308
337
{
309
338
Type : & ipAddressType ,
310
- Value : lbDNS ,
339
+ Value : lbStatus . DNSName ,
311
340
},
312
341
}
342
+ needPatch = true
343
+ }
344
+
345
+ if needPatch {
313
346
if err := r .k8sClient .Status ().Patch (ctx , gw , client .MergeFrom (gwOld )); err != nil {
314
347
return errors .Wrapf (err , "failed to update gw status: %v" , k8s .NamespacedName (gw ))
315
348
}
316
349
}
317
350
318
- // TODO: Listener status ListenerStatus
319
- // https://github.com/aws/aws-application-networking-k8s/blob/main/pkg/controllers/gateway_controller.go#L350
351
+ if requeueNeeded {
352
+ return runtime .NewRequeueNeededAfter (requeueMessage , statusUpdateRequeueTime )
353
+ }
354
+
355
+ return nil
356
+ }
357
+
358
+ func (r * gatewayReconciler ) updateGatewayStatusFailure (ctx context.Context , gw * gwv1.Gateway , reason gwv1.GatewayConditionReason , err error ) error {
359
+ gwOld := gw .DeepCopy ()
360
+
361
+ needPatch := prepareGatewayConditionUpdate (gw , string (gwv1 .GatewayConditionAccepted ), metav1 .ConditionFalse , string (reason ), err .Error ())
362
+
363
+ if needPatch {
364
+ if err := r .k8sClient .Status ().Patch (ctx , gw , client .MergeFrom (gwOld )); err != nil {
365
+ return errors .Wrapf (err , "failed to update gw status: %v" , k8s .NamespacedName (gw ))
366
+ }
367
+ }
320
368
321
369
return nil
322
370
}
@@ -475,3 +523,12 @@ func (r *gatewayReconciler) setupNLBGatewayControllerWatches(ctrl controller.Con
475
523
return nil
476
524
477
525
}
526
+
527
+ func isGatewayProgrammed (lbStatus elbv2model.LoadBalancerStatus ) bool {
528
+ if lbStatus .ProvisioningState == nil {
529
+ return false
530
+ }
531
+
532
+ return lbStatus .ProvisioningState .Code == elbv2types .LoadBalancerStateEnumActive || lbStatus .ProvisioningState .Code == elbv2types .LoadBalancerStateEnumActiveImpaired
533
+
534
+ }
0 commit comments