Skip to content

Commit

Permalink
AV-206839 Gateway status fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
pkoshtavmware committed Sep 30, 2024
1 parent 22aaa70 commit 7986542
Show file tree
Hide file tree
Showing 11 changed files with 383 additions and 153 deletions.
144 changes: 118 additions & 26 deletions ako-gateway-api/k8s/validator.go

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions ako-gateway-api/status/gateway_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package status
import (
"context"
"encoding/json"
"errors"
"reflect"
"strings"

Expand Down Expand Up @@ -154,13 +155,12 @@ func (o *gateway) Update(key string, option status.StatusOptions) {
conditionStatus := metav1.ConditionTrue

if option.Options.Message != "" {
conditionType = string(gatewayv1.GatewayConditionAccepted)
conditionType = string(gatewayv1.GatewayConditionProgrammed)
conditionStatus = metav1.ConditionFalse
reason = string(gatewayv1.GatewayReasonInvalid)
message = option.Options.Message
} else {
conditionType = string(gatewayv1.GatewayConditionProgrammed)
conditionStatus = metav1.ConditionTrue
reason = string(gatewayv1.GatewayReasonProgrammed)
message = "Virtual service configured/updated"
}
Expand All @@ -175,9 +175,9 @@ func (o *gateway) Update(key string, option status.StatusOptions) {
for i := range status.Listeners {
listenerCondition := NewCondition()
listenerCondition.
Type(conditionType).
Type(string(gatewayv1.ListenerConditionProgrammed)).
Status(conditionStatus).
Reason(reason).
Reason(string(gatewayv1.ListenerReasonProgrammed)).
ObservedGeneration(gw.ObjectMeta.Generation).
Message(message).
SetIn(&status.Listeners[i].Conditions)
Expand Down Expand Up @@ -213,37 +213,37 @@ func (o *gateway) BulkUpdate(key string, options []status.StatusOptions) {
}
}

func (o *gateway) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) {
func (o *gateway) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) (runtime.Object, error) {
retry := 0
if len(retryNum) > 0 {
retry = retryNum[0]
if retry >= 5 {
utils.AviLog.Errorf("key: %s, msg: Patch retried 5 times, aborting", key)
return
return obj, errors.New("Patch retried 5 times, aborting")
}
}

gw := obj.(*gatewayv1.Gateway)
if o.isStatusEqual(&gw.Status, status.GatewayStatus) {
return
return obj, nil
}

patchPayload, _ := json.Marshal(map[string]interface{}{
"status": status.GatewayStatus,
})
_, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().Gateways(gw.Namespace).Patch(context.TODO(), gw.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status")
updatedGateway, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().Gateways(gw.Namespace).Patch(context.TODO(), gw.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status")
if err != nil {
utils.AviLog.Warnf("key: %s, msg: there was an error in updating the gateway status. err: %+v, retry: %d", key, err, retry)
updatedGW, err := akogatewayapilib.AKOControlConfig().GatewayApiInformers().GatewayInformer.Lister().Gateways(gw.Namespace).Get(gw.Name)
if err != nil {
utils.AviLog.Warnf("gateway not found %v", err)
return
return updatedGW, err
}
o.Patch(key, updatedGW, status, retry+1)
return
return o.Patch(key, updatedGW, status, retry+1)
}

utils.AviLog.Infof("key: %s, msg: Successfully updated the gateway %s/%s status %+v", key, gw.Namespace, gw.Name, utils.Stringify(status))
return updatedGateway, nil
}

func (o *gateway) isStatusEqual(old, new *gatewayv1.GatewayStatus) bool {
Expand Down
16 changes: 8 additions & 8 deletions ako-gateway-api/status/gatewayclass_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package status
import (
"context"
"encoding/json"
"errors"
"reflect"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -72,37 +73,36 @@ func (o *gatewayClass) BulkUpdate(key string, options []status.StatusOptions) {
// TODO: Add this code when we publish the status from the rest layer
}

func (o *gatewayClass) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) {
func (o *gatewayClass) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) (runtime.Object, error) {
retry := 0
if len(retryNum) > 0 {
retry = retryNum[0]
if retry >= 5 {
utils.AviLog.Errorf("key: %s, msg: Patch retried 5 times, aborting", key)
return
return obj, errors.New("Patch retried 5 times, aborting")
}
}

gatewayClass := obj.(*gatewayv1.GatewayClass)
if o.isStatusEqual(&gatewayClass.Status, status.GatewayClassStatus) {
return
return obj, nil
}

patchPayload, _ := json.Marshal(map[string]interface{}{
"status": status.GatewayClassStatus,
})
_, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().GatewayClasses().Patch(context.TODO(), gatewayClass.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status")
updatedObject, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().GatewayClasses().Patch(context.TODO(), gatewayClass.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status")
if err != nil {
utils.AviLog.Warnf("key: %s, msg: there was an error in updating the GatewayClass status. err: %+v, retry: %d", key, err, retry)
updatedObj, err := akogatewayapilib.AKOControlConfig().GatewayApiInformers().GatewayClassInformer.Lister().Get(gatewayClass.Name)
if err != nil {
utils.AviLog.Warnf("GatewayClass not found %v", err)
return
return updatedObj, err
}
o.Patch(key, updatedObj, status, retry+1)
return
return o.Patch(key, updatedObj, status, retry+1)
}

utils.AviLog.Infof("key: %s, msg: Successfully updated the GatewayClass %s status %+v %v", key, gatewayClass.Name, utils.Stringify(status), err)
return updatedObject, nil
}

func (o *gatewayClass) isStatusEqual(old, new *gatewayv1.GatewayClassStatus) bool {
Expand Down
15 changes: 8 additions & 7 deletions ako-gateway-api/status/httproute_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package status
import (
"context"
"encoding/json"
"errors"
"reflect"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -72,37 +73,37 @@ func (o *httproute) BulkUpdate(key string, options []status.StatusOptions) {
// TODO: Add this code when we publish the status from the rest layer
}

func (o *httproute) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) {
func (o *httproute) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) (runtime.Object, error) {
retry := 0
if len(retryNum) > 0 {
retry = retryNum[0]
if retry >= 5 {
utils.AviLog.Errorf("key: %s, msg: Patch retried 5 times, aborting", key)
return
return obj, errors.New("Patch retried 5 times, aborting")
}
}

httpRoute := obj.(*gatewayv1.HTTPRoute)
if o.isStatusEqual(&httpRoute.Status, status.HTTPRouteStatus) {
return
return obj, nil
}

patchPayload, _ := json.Marshal(map[string]interface{}{
"status": status.HTTPRouteStatus,
})
_, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().HTTPRoutes(httpRoute.Namespace).Patch(context.TODO(), httpRoute.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status")
updatedObject, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().HTTPRoutes(httpRoute.Namespace).Patch(context.TODO(), httpRoute.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status")
if err != nil {
utils.AviLog.Warnf("key: %s, msg: there was an error in updating the HTTPRoute status. err: %+v, retry: %d", key, err, retry)
updatedObj, err := akogatewayapilib.AKOControlConfig().GatewayApiInformers().HTTPRouteInformer.Lister().HTTPRoutes(httpRoute.Namespace).Get(httpRoute.Name)
if err != nil {
utils.AviLog.Warnf("HTTPRoute not found %v", err)
return
return updatedObj, err
}
o.Patch(key, updatedObj, status, retry+1)
return
return o.Patch(key, updatedObj, status, retry+1)
}

utils.AviLog.Infof("key: %s, msg: Successfully updated the HTTPRoute %s/%s status %+v", key, httpRoute.Namespace, httpRoute.Name, utils.Stringify(status))
return updatedObject, nil
}

func (o *httproute) isStatusEqual(old, new *gatewayv1.HTTPRouteStatus) bool {
Expand Down
17 changes: 13 additions & 4 deletions ako-gateway-api/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
package status

import (
"errors"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"

akogatewayapilib "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/ako-gateway-api/lib"
"github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/lib"
"github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/status"
"github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/pkg/utils"
Expand All @@ -26,7 +30,7 @@ import (
type StatusUpdater interface {
Update(key string, option status.StatusOptions)
BulkUpdate(key string, options []status.StatusOptions)
Patch(key string, obj runtime.Object, status *Status, retryNum ...int)
Patch(key string, obj runtime.Object, status *Status, retryNum ...int) (runtime.Object, error)
Delete(key string, option status.StatusOptions)
}

Expand Down Expand Up @@ -80,7 +84,7 @@ func BulkUpdate(key string, objectType string, options []status.StatusOptions) e
return nil
}

func Record(key string, obj runtime.Object, status *Status) {
func Record(key string, obj runtime.Object, status *Status) (runtime.Object, error) {
var objectType string
switch obj.(type) {
case *gatewayv1.GatewayClass:
Expand All @@ -91,8 +95,13 @@ func Record(key string, obj runtime.Object, status *Status) {
objectType = lib.HTTPRoute
default:
utils.AviLog.Warnf("key %s, msg: Unsupported object received at the status layer, %T", key, obj)
return
return obj, errors.New("Unsupported object received at the status layer")
}
o := New(objectType)
o.Patch(key, obj, status)
updatedObject, err := o.Patch(key, obj, status)
if err != nil {
akogatewayapilib.AKOControlConfig().EventRecorder().Eventf(obj, corev1.EventTypeWarning,
lib.PatchFailed, "Patch of status failed after multiple retries")
}
return updatedObject, err
}
1 change: 1 addition & 0 deletions internal/lib/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ const (
Synced = "Synced"
Attached = "Attached"
Detached = "Detached"
PatchFailed = "PatchFailed"
InvalidConfiguration = "InvalidConfiguration"
AKODeleteConfigSet = "AKODeleteConfigSet"
AKODeleteConfigUnset = "AKODeleteConfigUnset"
Expand Down
10 changes: 4 additions & 6 deletions tests/gatewayapitests/graphlayer/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,19 +427,17 @@ func TestSecretCreateDelete(t *testing.T) {
g.Eventually(func() bool {
found, _ := objects.SharedAviGraphLister().Get(modelName)
return found
}, 30*time.Second).Should(gomega.Equal(true))
}, 30*time.Second).Should(gomega.Equal(false))

_, aviModel := objects.SharedAviGraphLister().Get(modelName)
nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS()
g.Expect(nodes).To(gomega.HaveLen(1))
g.Expect(nodes[0].SSLKeyCertRefs).To(gomega.HaveLen(0))
g.Expect(aviModel).To(gomega.BeNil())

integrationtest.AddSecret(secrets[0], DEFAULT_NAMESPACE, "cert", "key")

g.Eventually(func() bool {
found, aviModel := objects.SharedAviGraphLister().Get(modelName)
if found {
nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS()
nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS()
g.Expect(nodes).To(gomega.HaveLen(1))
g.Expect(nodes[0].SSLKeyCertRefs).To(gomega.HaveLen(1))
return true
Expand All @@ -453,7 +451,7 @@ func TestSecretCreateDelete(t *testing.T) {
g.Eventually(func() bool {
found, aviModel := objects.SharedAviGraphLister().Get(modelName)
if found {
nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS()
nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS()
g.Expect(nodes).To(gomega.HaveLen(1))
g.Expect(nodes[0].SSLKeyCertRefs).To(gomega.HaveLen(0))
return true
Expand Down
1 change: 1 addition & 0 deletions tests/gatewayapitests/graphlayer/httproute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,7 @@ func TestHTTPRouteWithMultipleGateways(t *testing.T) {
integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName)
integrationtest.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName)
akogatewayapitests.TeardownGateway(t, gatewayName1, DEFAULT_NAMESPACE)
akogatewayapitests.TeardownGateway(t, gatewayName2, DEFAULT_NAMESPACE)
akogatewayapitests.TeardownGatewayClass(t, gatewayClassName)
}

Expand Down
Loading

0 comments on commit 7986542

Please sign in to comment.