@@ -3,9 +3,11 @@ package gateway
33import (
44"context"
55"fmt"
6+ elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
67"github.com/go-logr/logr"
78"github.com/pkg/errors"
89corev1 "k8s.io/api/core/v1"
10+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
911"k8s.io/apimachinery/pkg/types"
1012"k8s.io/apimachinery/pkg/util/sets"
1113"k8s.io/client-go/tools/record"
@@ -35,6 +37,12 @@ import (
3537"sigs.k8s.io/controller-runtime/pkg/source"
3638gwv1 "sigs.k8s.io/gateway-api/apis/v1"
3739gwalpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
40+ "time"
41+ )
42+
43+ const (
44+ requeueMessage = "Monitoring provisioning state"
45+ statusUpdateRequeueTime = 2 * time .Minute
3846)
3947
4048var _ Reconciler = & gatewayReconciler {}
@@ -86,6 +94,7 @@ func newGatewayReconciler(controllerName string, lbType elbv2model.LoadBalancerT
8694reconcileTracker : reconcileTracker ,
8795cfgResolver : cfgResolver ,
8896routeReconciler : routeReconciler ,
97+ gatewayConditionUpdater : prepareGatewayConditionUpdate ,
8998}
9099}
91100
@@ -107,6 +116,7 @@ type gatewayReconciler struct {
107116logger logr.Logger
108117metricsCollector lbcmetrics.MetricCollector
109118reconcileTracker func (namespaceName types.NamespacedName )
119+ gatewayConditionUpdater func (gw * gwv1.Gateway , targetConditionType string , newStatus metav1.ConditionStatus , reason string , message string ) bool
110120
111121cfgResolver gatewayConfigResolver
112122routeReconciler routeutils.RouteReconciler
@@ -186,12 +196,23 @@ func (r *gatewayReconciler) reconcileHelper(ctx context.Context, req reconcile.R
186196mergedLbConfig , err := r .cfgResolver .getLoadBalancerConfigForGateway (ctx , r .k8sClient , gw , gwClass )
187197
188198if err != nil {
199+ statusErr := r .updateGatewayStatusFailure (ctx , gw , gwv1 .GatewayReasonInvalid , err )
200+ if statusErr != nil {
201+ r .logger .Error (statusErr , "Unable to update gateway status on failure to retrieve attached config" )
202+ }
189203return err
190204}
191205
192206allRoutes , err := r .gatewayLoader .LoadRoutesForGateway (ctx , * gw , r .routeFilter , r .routeReconciler )
193207
194208if err != nil {
209+ var loaderErr routeutils.LoaderError
210+ if errors .As (err , & loaderErr ) {
211+ statusErr := r .updateGatewayStatusFailure (ctx , gw , loaderErr .GetGatewayReason (), loaderErr )
212+ if statusErr != nil {
213+ r .logger .Error (statusErr , "Unable to update gateway status on failure to build routes" )
214+ }
215+ }
195216return err
196217}
197218
@@ -248,18 +269,14 @@ func (r *gatewayReconciler) reconcileUpdate(ctx context.Context, gw *gwv1.Gatewa
248269if err != nil {
249270return err
250271}
251- lbDNS , err := lb .DNSName ().Resolve (ctx )
252- if err != nil {
253- return err
254- }
255272
256273if ! backendSGRequired {
257274if err := r .backendSGProvider .Release (ctx , networking .ResourceTypeGateway , []types.NamespacedName {k8s .NamespacedName (gw )}); err != nil {
258275return err
259276}
260277}
261278
262- if err = r .updateGatewayStatus (ctx , lbDNS , gw ); err != nil {
279+ if err = r .updateGatewayStatusSuccess (ctx , lb . Status , gw ); err != nil {
263280r .eventRecorder .Event (gw , corev1 .EventTypeWarning , k8s .GatewayEventReasonFailedUpdateStatus , fmt .Sprintf ("Failed update status due to %v" , err ))
264281return err
265282}
@@ -295,28 +312,59 @@ func (r *gatewayReconciler) buildModel(ctx context.Context, gw *gwv1.Gateway, cf
295312return stack , lb , backendSGRequired , nil
296313}
297314
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 = r .gatewayConditionUpdater (gw , string (gwv1 .GatewayConditionProgrammed ), metav1 .ConditionTrue , string (gwv1 .GatewayConditionProgrammed ), lbStatus .LoadBalancerARN )
327+ } else {
328+ requeueNeeded = true
329+ }
300330
301- // Gateway Address Status
331+ needPatch = r . gatewayConditionUpdater ( gw , string ( gwv1 . GatewayConditionAccepted ), metav1 . ConditionTrue , string ( gwv1 . GatewayConditionAccepted ), "" ) || needPatch
302332if len (gw .Status .Addresses ) != 1 ||
303333gw .Status .Addresses [0 ].Value != "" ||
304- gw .Status .Addresses [0 ].Value != lbDNS {
305- gwOld := gw .DeepCopy ()
334+ gw .Status .Addresses [0 ].Value != lbStatus .DNSName {
306335ipAddressType := gwv1 .HostnameAddressType
307336gw .Status .Addresses = []gwv1.GatewayStatusAddress {
308337{
309338Type : & ipAddressType ,
310- Value : lbDNS ,
339+ Value : lbStatus . DNSName ,
311340},
312341}
342+ needPatch = true
343+ }
344+
345+ if needPatch {
313346if err := r .k8sClient .Status ().Patch (ctx , gw , client .MergeFrom (gwOld )); err != nil {
314347return errors .Wrapf (err , "failed to update gw status: %v" , k8s .NamespacedName (gw ))
315348}
316349}
317350
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 := r .gatewayConditionUpdater (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+ }
320368
321369return nil
322370}
@@ -475,3 +523,12 @@ func (r *gatewayReconciler) setupNLBGatewayControllerWatches(ctrl controller.Con
475523return nil
476524
477525}
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