Skip to content

Commit

Permalink
tests: enable SupportgatewayStaticAddresses tests
Browse files Browse the repository at this point in the history
  • Loading branch information
shaneutt committed Sep 27, 2023
1 parent e442cd2 commit 558113e
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 50 deletions.
40 changes: 19 additions & 21 deletions controllers/gateway_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func (r *GatewayReconciler) gatewayHasMatchingGatewayClass(obj client.Object) bo
}

// Reconcile provisions (and de-provisions) resources relevant to this controller.
// TODO: this whole thing needs a rewrite
func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)

Expand All @@ -102,12 +103,25 @@ func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, nil
}

gatewayReadyStatus, gatewayReadyStatusIsSet := isGatewayProgrammed(gw)
// determine if the Gateway has been accepted, and if it has not then
// determine whether we will accept it, and if not drop it until it has
// been corrected.
oldGateway := gw.DeepCopy()
initGatewayStatus(gw)
factorizeStatus(gw, oldGateway)
if !gatewayReadyStatusIsSet {
return ctrl.Result{}, r.Status().Patch(ctx, gw, client.MergeFrom(oldGateway))
isAccepted := isGatewayAccepted(gw)
if !isAccepted {
initGatewayStatus(gw)
setGatewayAcceptance(gw)
factorizeStatus(gw, oldGateway)

oldAccepted := getAcceptedConditionForGateway(oldGateway)
accepted := getAcceptedConditionForGateway(gw)

if !sameConditions(oldAccepted, accepted) {
return ctrl.Result{}, r.Status().Patch(ctx, gw, client.MergeFrom(oldGateway))
}

log.Info("gateway %s/%s is not accepted and will not be provisioned", gw.Namespace, gw.Name)
return ctrl.Result{}, nil
}

log.Info("checking for Service for Gateway")
Expand All @@ -116,10 +130,6 @@ func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, err
}
if svc == nil {
// if the ready status is not set, or the gateway is marked as ready, mark it as not ready
if gatewayReadyStatus {
return ctrl.Result{}, r.Status().Patch(ctx, gw, client.MergeFrom(oldGateway)) // status patch will requeue gateway
}
log.Info("creating Service for Gateway")
return ctrl.Result{}, r.createServiceForGateway(ctx, gw) // service creation will requeue gateway
}
Expand All @@ -133,29 +143,17 @@ func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, err
}
if needsUpdate {
// if the ready status is not set, or the gateway is marked as ready, mark it as not ready
if gatewayReadyStatus {
return ctrl.Result{}, r.Status().Patch(ctx, gw, client.MergeFrom(oldGateway)) // status patch will requeue gateway
}
return ctrl.Result{}, r.Client.Update(ctx, svc)
}

log.Info("checking Service status", "namespace", svc.Namespace, "name", svc.Name)
switch t := svc.Spec.Type; t {
case corev1.ServiceTypeLoadBalancer:
if svc.Spec.ClusterIP == "" || len(svc.Status.LoadBalancer.Ingress) < 1 {
// if the ready status is not set, or the gateway is marked as ready, mark it as not ready
if gatewayReadyStatus {
return ctrl.Result{}, r.Status().Patch(ctx, gw, client.MergeFrom(oldGateway)) // status patch will requeue gateway
}
log.Info("waiting for Service to be ready")
return ctrl.Result{Requeue: true}, nil
}
default:
// if the ready status is not set, or the gateway is marked as ready, mark it as not ready
if gatewayReadyStatus {
return ctrl.Result{}, r.Status().Patch(ctx, gw, client.MergeFrom(oldGateway)) // status patch will requeue gateway
}
return ctrl.Result{}, fmt.Errorf("found unsupported Service type: %s (only LoadBalancer type is currently supported)", t)
}

Expand Down
61 changes: 33 additions & 28 deletions controllers/gateway_controller_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package controllers

import (
"context"
"fmt"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -91,28 +90,16 @@ func updateGatewayStatus(_ context.Context, gateway *gatewayv1beta1.Gateway, svc
// initGatewayStatus initializes the GatewayStatus, setting the ready condition to
// not ready and all the listeners ready status to not ready as well.
func initGatewayStatus(gateway *gatewayv1beta1.Gateway) {
accepted := metav1.Condition{
Type: string(gatewayv1beta1.GatewayConditionAccepted),
Status: metav1.ConditionTrue,
Reason: string(gatewayv1beta1.GatewayReasonAccepted),
ObservedGeneration: gateway.Generation,
LastTransitionTime: metav1.Now(),
Message: "blixt controlplane accepts responsibility for the Gateway",
}
if unsupportedAddr, addrType := gatewayHasUnsupportedAddresses(gateway); unsupportedAddr {
accepted = metav1.Condition{
Type: string(gatewayv1beta1.GatewayConditionAccepted),
Status: metav1.ConditionFalse,
Reason: string(gatewayv1beta1.GatewayReasonUnsupportedAddress),
ObservedGeneration: gateway.Generation,
LastTransitionTime: metav1.Now(),
Message: fmt.Sprintf("blixt only supports Gateway addresses of type IPAddress, %s is not supported", addrType),
}
}

gateway.Status = gatewayv1beta1.GatewayStatus{
Conditions: []metav1.Condition{
accepted,
{
Type: string(gatewayv1beta1.GatewayConditionAccepted),
Status: metav1.ConditionTrue,
Reason: string(gatewayv1beta1.GatewayReasonAccepted),
ObservedGeneration: gateway.Generation,
LastTransitionTime: metav1.Now(),
Message: "blixt controlplane accepts responsibility for the Gateway",
},
{
Type: string(gatewayv1beta1.GatewayConditionProgrammed),
Status: metav1.ConditionFalse,
Expand Down Expand Up @@ -214,6 +201,10 @@ func factorizeStatus(gateway, oldGateway *gatewayv1beta1.Gateway) {
}
}

for i := 0; i < len(gateway.Status.Conditions); i++ {
gateway.Status.Conditions[0].ObservedGeneration = gateway.Generation
}

for i, l := range gateway.Status.Listeners {
for j, lc := range l.Conditions {
for _, ol := range oldGateway.Status.Listeners {
Expand All @@ -232,6 +223,23 @@ func factorizeStatus(gateway, oldGateway *gatewayv1beta1.Gateway) {
}
}

func isGatewayAccepted(gateway *gatewayv1beta1.Gateway) bool {
accepted := getAcceptedConditionForGateway(gateway)
if accepted == nil {
return false
}
return accepted.Status == metav1.ConditionTrue
}

func getAcceptedConditionForGateway(gateway *gatewayv1beta1.Gateway) *metav1.Condition {
for _, c := range gateway.Status.Conditions {
if c.Type == string(gatewayv1beta1.GatewayConditionAccepted) {
return &c
}
}
return nil
}

// isGatewayProgrammed returns two boolean values:
// - the status of the programmed condition
// - a boolean flag to check if the condition exists
Expand All @@ -244,11 +252,8 @@ func isGatewayProgrammed(gateway *gatewayv1beta1.Gateway) (status bool, isSet bo
return false, false
}

func gatewayHasUnsupportedAddresses(gateway *gatewayv1beta1.Gateway) (bool, string) {
for _, addr := range gateway.Spec.Addresses {
if addr.Type != nil && *addr.Type != gatewayv1beta1.IPAddressType {
return false, string(*addr.Type)
}
}
return true, ""
// sameConditions returns true if the type, status and reason match for
// the two provided metav1.Conditions.
func sameConditions(cond1, cond2 *metav1.Condition) bool {
return cond1.Type == cond2.Type && cond1.Status == cond2.Status && cond1.Reason == cond2.Reason && cond1.Message == cond2.Message && cond1.ObservedGeneration == cond2.ObservedGeneration
}
39 changes: 39 additions & 0 deletions controllers/gateway_controller_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,45 @@ func mapServiceToGateway(_ context.Context, obj client.Object) (reqs []reconcile
return
}

func setGatewayAcceptance(gateway *gatewayv1beta1.Gateway) {
var conditions []metav1.Condition
for _, cond := range gateway.Status.Conditions {
if cond.Type != string(gatewayv1beta1.GatewayConditionAccepted) {
conditions = append(conditions, cond)
}
}

accepted := determineGatewayAcceptance(gateway)
gateway.Status.Conditions = append(
[]metav1.Condition{accepted},
conditions...,
)
}

func determineGatewayAcceptance(gateway *gatewayv1beta1.Gateway) metav1.Condition {
// this is the default accepted condition, it may get overidden if there are
// unsupported values in the specification.
accepted := metav1.Condition{
Type: string(gatewayv1beta1.GatewayConditionAccepted),
Status: metav1.ConditionTrue,
Reason: string(gatewayv1beta1.GatewayReasonAccepted),
ObservedGeneration: gateway.Generation,
LastTransitionTime: metav1.Now(),
Message: "blixt controlplane accepts responsibility for the Gateway",
}

// verify that all addresses are supported
for _, addr := range gateway.Spec.Addresses {
if addr.Type != nil && *addr.Type != gatewayv1beta1.IPAddressType {
accepted.Status = metav1.ConditionFalse
accepted.Reason = string(gatewayv1beta1.GatewayReasonUnsupportedAddress)
accepted.Message = fmt.Sprintf("found an address of type %s, only IPAddress is supported", *addr.Type)
}
}

return accepted
}

type portAndProtocol struct {
port int32
protocol corev1.Protocol
Expand Down
6 changes: 5 additions & 1 deletion test/conformance/gateway_conformance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ func TestGatewayConformance(t *testing.T) {
t.Cleanup(func() { assert.NoError(t, c.Delete(ctx, gatewayClass)) })

t.Log("configuring the gateway conformance test suite")
supportedFeatures := suite.GatewayCoreFeatures.Clone()
supportedFeatures.Insert(suite.SupportGatewayStaticAddresses)
cSuite, err := suite.NewExperimentalConformanceTestSuite(
suite.ExperimentalConformanceOptions{
Options: suite.Options{
Expand All @@ -69,7 +71,7 @@ func TestGatewayConformance(t *testing.T) {
Debug: showDebug,
CleanupBaseResources: shouldCleanup,
BaseManifests: conformanceTestsBaseManifests,
SupportedFeatures: suite.GatewayCoreFeatures,
SupportedFeatures: supportedFeatures,
SkipTests: []string{
// TODO: these tests are broken because they incorrectly require HTTP support
// see https://github.com/kubernetes-sigs/gateway-api/issues/2403
Expand All @@ -81,6 +83,8 @@ func TestGatewayConformance(t *testing.T) {
"GatewayClassObservedGenerationBump",
"GatewayWithAttachedRoutes",
},
UsableNetworkAddresses: []gatewayv1beta1.GatewayAddress{{Value: "172.18.0.242"}},
UnusableNetworkAddresses: []gatewayv1beta1.GatewayAddress{{Value: "1.1.1.1"}},
},
Implementation: v1alpha1.Implementation{
Organization: "kong",
Expand Down

0 comments on commit 558113e

Please sign in to comment.