Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions apis/gateway/v1beta1/targetgroupconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ type Reference struct {
Name string `json:"name"`
}

// TODO: Add a validation in the admission webhook to check if only one of HTTPCode or GRPCCode is set.
// Information to use when checking for a successful response from a target.
// +kubebuilder:validation:XValidation:rule="has(self.httpCode) != has(self.grpcCode)",message="Only one of httpCode or grpcCode must be specified"
type HealthCheckMatcher struct {
// The HTTP codes.
HTTPCode *string `json:"httpCode,omitempty"`
Expand Down Expand Up @@ -241,10 +241,11 @@ type TargetGroupAttribute struct {
Value string `json:"value"`
}

// TODO -- these can be used to set what generation the gateway is currently on to track progress on reconcile.

// TargetGroupConfigurationStatus defines the observed state of TargetGroupConfiguration
type TargetGroupConfigurationStatus struct {
// The generation of the TargetGroupConfiguration object observed by the controller.
// +optional
ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
// The generation of the Gateway Configuration attached to the Gateway object.
// +optional
ObservedGatewayConfigurationGeneration *int64 `json:"observedGatewayConfigurationGeneration,omitempty"`
Expand Down
29 changes: 26 additions & 3 deletions controllers/gateway/targetgroup_configuration_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,12 @@ func (r *targetgroupConfigurationReconciler) reconcile(ctx context.Context, req
}

func (r *targetgroupConfigurationReconciler) handleUpdate(tgConf *elbv2gw.TargetGroupConfiguration) error {
if k8s.HasFinalizer(tgConf, shared_constants.TargetGroupConfigurationFinalizer) {
return nil
if !k8s.HasFinalizer(tgConf, shared_constants.TargetGroupConfigurationFinalizer) {
if err := r.finalizerManager.AddFinalizers(context.Background(), tgConf, shared_constants.TargetGroupConfigurationFinalizer); err != nil {
return err
}
}
return r.finalizerManager.AddFinalizers(context.Background(), tgConf, shared_constants.TargetGroupConfigurationFinalizer)
return r.updateStatus(context.Background(), tgConf)
}

func (r *targetgroupConfigurationReconciler) handleDelete(tgConf *elbv2gw.TargetGroupConfiguration) error {
Expand Down Expand Up @@ -154,6 +156,27 @@ func (r *targetgroupConfigurationReconciler) handleDelete(tgConf *elbv2gw.Target
return r.finalizerManager.RemoveFinalizers(context.Background(), tgConf, shared_constants.TargetGroupConfigurationFinalizer)
}

// updateStatus updates the TargetGroupConfiguration status with the current observed generation
func (r *targetgroupConfigurationReconciler) updateStatus(ctx context.Context, tgConf *elbv2gw.TargetGroupConfiguration) error {
// Check if status actually needs updating
if tgConf.Status.ObservedGeneration != nil &&
*tgConf.Status.ObservedGeneration == tgConf.Generation {
return nil // No update needed
}

tgConfOld := tgConf.DeepCopy()

// Update status fields
tgConf.Status.ObservedGeneration = &tgConf.Generation

// Patch the status
if err := r.k8sClient.Status().Patch(ctx, tgConf, client.MergeFrom(tgConfOld)); err != nil {
return fmt.Errorf("failed to update TargetGroupConfiguration status: %w", err)
}

return nil
}

// isDefaultTGCInUse checks if any LoadBalancerConfiguration in the same namespace references
// this TGC as its defaultTargetGroupConfiguration, and if that LBC is in use by any Gateway or GatewayClass.
// Returns the namespaced names of all in-use LBCs found, or empty string if none.
Expand Down
54 changes: 54 additions & 0 deletions controllers/gateway/targetgroup_configuration_controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package gateway

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
elbv2gw "sigs.k8s.io/aws-load-balancer-controller/apis/gateway/v1beta1"
testclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func Test_targetgroupConfigurationReconciler_updateStatus(t *testing.T) {
k8sSchema := runtime.NewScheme()
_ = clientgoscheme.AddToScheme(k8sSchema)
_ = elbv2gw.AddToScheme(k8sSchema)

tgConf := &elbv2gw.TargetGroupConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "test-tgc",
Namespace: "default",
Generation: 10,
},
}

k8sClient := testclient.NewClientBuilder().
WithScheme(k8sSchema).
WithStatusSubresource(&elbv2gw.TargetGroupConfiguration{}).
WithObjects(tgConf).
Build()

r := &targetgroupConfigurationReconciler{
k8sClient: k8sClient,
}

ctx := context.Background()
// Initial update
err := r.updateStatus(ctx, tgConf)
assert.NoError(t, err)

updatedTgConf := &elbv2gw.TargetGroupConfiguration{}
err = k8sClient.Get(ctx, types.NamespacedName{Name: "test-tgc", Namespace: "default"}, updatedTgConf)
assert.NoError(t, err)

assert.NotNil(t, updatedTgConf.Status.ObservedGeneration)
assert.Equal(t, int64(10), *updatedTgConf.Status.ObservedGeneration)

// Update again with same generation - should return nil and do nothing
err = r.updateStatus(ctx, updatedTgConf)
assert.NoError(t, err)
}