Skip to content

Commit f900468

Browse files
mathetakedaixiang0
authored andcommitted
controller: finishes reconciliation result updates (envoyproxy#436)
**Commit Message** This adds the status fields to BackendSecurityPolicy and AIServiceBackend just like we already have for AIGatewayRoute since envoyproxy#187. The output will look like ``` $ k get aiservicebackends.aigateway.envoyproxy.io NAME STATUS envoy-ai-gateway-basic-aws Accepted envoy-ai-gateway-basic-openai Accepted envoy-ai-gateway-basic-testupstream Accepted $ k get backendsecuritypolicies.aigateway.envoyproxy.io NAME STATUS envoy-ai-gateway-basic-aws-credentials Accepted envoy-ai-gateway-basic-openai-apikey Accepted $ k get aigatewayroutes.aigateway.envoyproxy.io NAME STATUS envoy-ai-gateway-basic Accepted ``` **Related Issues/PRs (if applicable)** Follow up on envoyproxy#187 and closes envoyproxy#130 --------- Signed-off-by: Takeshi Yoneda <[email protected]>
1 parent 4a5a719 commit f900468

15 files changed

+465
-113
lines changed

api/v1alpha1/api.go

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ import (
1313
gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
1414
)
1515

16-
// +kubebuilder:object:root=true
17-
// +kubebuilder:subresource:status
18-
1916
// AIGatewayRoute combines multiple AIServiceBackends and attaching them to Gateway(s) resources.
2017
//
2118
// This serves as a way to define a "unified" AI API for a Gateway which allows downstream
@@ -41,6 +38,10 @@ import (
4138
// detail subject to change. If you want to customize the default behavior of the Envoy AI Gateway, you can use these
4239
// resources as a reference and create your own resources. Alternatively, you can use EnvoyPatchPolicy API of the Envoy
4340
// Gateway to patch the generated resources. For example, you can insert a custom filter into the filter chain.
41+
//
42+
// +kubebuilder:object:root=true
43+
// +kubebuilder:subresource:status
44+
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[-1:].type`
4445
type AIGatewayRoute struct {
4546
metav1.TypeMeta `json:",inline"`
4647
metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -50,15 +51,9 @@ type AIGatewayRoute struct {
5051
Status AIGatewayRouteStatus `json:"status,omitempty"`
5152
}
5253

53-
// AIGatewayRouteStatus contains the conditions by the reconciliation result.
54-
type AIGatewayRouteStatus struct {
55-
// Conditions is the list of conditions by the reconciliation result.
56-
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
57-
}
58-
59-
// +kubebuilder:object:root=true
60-
6154
// AIGatewayRouteList contains a list of AIGatewayRoute.
55+
//
56+
// +kubebuilder:object:root=true
6257
type AIGatewayRouteList struct {
6358
metav1.TypeMeta `json:",inline"`
6459
metav1.ListMeta `json:"metadata,omitempty"`
@@ -296,8 +291,6 @@ type AIGatewayFilterConfigExternalProcessor struct {
296291
// Not sure if it is worth it as we are migrating to dynamic modules.
297292
}
298293

299-
// +kubebuilder:object:root=true
300-
301294
// AIServiceBackend is a resource that represents a single backend for AIGatewayRoute.
302295
// A backend is a service that handles traffic with a concrete API specification.
303296
//
@@ -306,16 +299,22 @@ type AIGatewayFilterConfigExternalProcessor struct {
306299
// When a backend with an attached AIServiceBackend is used as a routing target in the AIGatewayRoute (more precisely, the
307300
// HTTPRouteSpec defined in the AIGatewayRoute), the ai-gateway will generate the necessary configuration to do
308301
// the backend specific logic in the final HTTPRoute.
302+
//
303+
// +kubebuilder:object:root=true
304+
// +kubebuilder:subresource:status
305+
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[-1:].type`
309306
type AIServiceBackend struct {
310307
metav1.TypeMeta `json:",inline"`
311308
metav1.ObjectMeta `json:"metadata,omitempty"`
312309
// Spec defines the details of AIServiceBackend.
313310
Spec AIServiceBackendSpec `json:"spec,omitempty"`
311+
// Status defines the status details of the AIServiceBackend.
312+
Status AIServiceBackendStatus `json:"status,omitempty"`
314313
}
315314

316-
// +kubebuilder:object:root=true
317-
318315
// AIServiceBackendList contains a list of AIServiceBackends.
316+
//
317+
// +kubebuilder:object:root=true
319318
type AIServiceBackendList struct {
320319
metav1.TypeMeta `json:",inline"`
321320
metav1.ListMeta `json:"metadata,omitempty"`
@@ -403,14 +402,18 @@ const (
403402
BackendSecurityPolicyTypeAzureCredentials BackendSecurityPolicyType = "AzureCredentials"
404403
)
405404

406-
// +kubebuilder:object:root=true
407-
408405
// BackendSecurityPolicy specifies configuration for authentication and authorization rules on the traffic
409406
// exiting the gateway to the backend.
407+
//
408+
// +kubebuilder:object:root=true
409+
// +kubebuilder:subresource:status
410+
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[-1:].type`
410411
type BackendSecurityPolicy struct {
411412
metav1.TypeMeta `json:",inline"`
412413
metav1.ObjectMeta `json:"metadata,omitempty"`
413414
Spec BackendSecurityPolicySpec `json:"spec,omitempty"`
415+
// Status defines the status details of the BackendSecurityPolicy.
416+
Status BackendSecurityPolicyStatus `json:"status,omitempty"`
414417
}
415418

416419
// BackendSecurityPolicySpec specifies authentication rules on access the provider from the Gateway.
@@ -440,9 +443,9 @@ type BackendSecurityPolicySpec struct {
440443
AzureCredentials *BackendSecurityPolicyAzureCredentials `json:"azureCredentials,omitempty"`
441444
}
442445

443-
// +kubebuilder:object:root=true
444-
445446
// BackendSecurityPolicyList contains a list of BackendSecurityPolicy
447+
//
448+
// +kubebuilder:object:root=true
446449
type BackendSecurityPolicyList struct {
447450
metav1.TypeMeta `json:",inline"`
448451
metav1.ListMeta `json:"metadata,omitempty"`

api/v1alpha1/status.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright Envoy AI Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
6+
package v1alpha1
7+
8+
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
10+
const (
11+
// ConditionTypeAccepted is a condition type for the reconciliation result
12+
// where resources are accepted.
13+
ConditionTypeAccepted = "Accepted"
14+
// ConditionTypeNotAccepted is a condition type for the reconciliation result
15+
// where resources are not accepted.
16+
ConditionTypeNotAccepted = "NotAccepted"
17+
)
18+
19+
// AIGatewayRouteStatus contains the conditions by the reconciliation result.
20+
type AIGatewayRouteStatus struct {
21+
// Conditions is the list of conditions by the reconciliation result.
22+
// Currently, at most one condition is set.
23+
//
24+
// Known .status.conditions.type are: "Accepted", "NotAccepted".
25+
Conditions []metav1.Condition `json:"conditions,omitempty"`
26+
}
27+
28+
// AIServiceBackendStatus contains the conditions by the reconciliation result.
29+
type AIServiceBackendStatus struct {
30+
// Conditions is the list of conditions by the reconciliation result.
31+
// Currently, at most one condition is set.
32+
//
33+
// Known .status.conditions.type are: "Accepted", "NotAccepted".
34+
Conditions []metav1.Condition `json:"conditions,omitempty"`
35+
}
36+
37+
// BackendSecurityPolicyStatus contains the conditions by the reconciliation result.
38+
type BackendSecurityPolicyStatus struct {
39+
// Conditions is the list of conditions by the reconciliation result.
40+
// Currently, at most one condition is set.
41+
//
42+
// Known .status.conditions.type are: "Accepted", "NotAccepted".
43+
Conditions []metav1.Condition `json:"conditions,omitempty"`
44+
}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 55 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/controller/ai_gateway_route.go

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"context"
1010
"fmt"
1111
"path"
12-
"sort"
1312

1413
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
1514
"github.com/go-logr/logr"
@@ -94,10 +93,10 @@ func (c *AIGatewayRouteController) Reconcile(ctx context.Context, req reconcile.
9493

9594
if err := c.syncAIGatewayRoute(ctx, &aiGatewayRoute); err != nil {
9695
c.logger.Error(err, "failed to sync AIGatewayRoute")
97-
c.updateAIGatewayRouteStatus(ctx, &aiGatewayRoute, false, err.Error())
96+
c.updateAIGatewayRouteStatus(ctx, &aiGatewayRoute, aigv1a1.ConditionTypeNotAccepted, err.Error())
9897
return ctrl.Result{}, err
9998
}
100-
c.updateAIGatewayRouteStatus(ctx, &aiGatewayRoute, true, "AI Gateway Route reconciled successfully")
99+
c.updateAIGatewayRouteStatus(ctx, &aiGatewayRoute, aigv1a1.ConditionTypeAccepted, "AI Gateway Route reconciled successfully")
101100
return reconcile.Result{}, nil
102101
}
103102

@@ -670,43 +669,9 @@ func backendSecurityMountPath(backendSecurityPolicyKey string) string {
670669
return fmt.Sprintf("%s/%s", mountedExtProcSecretPath, backendSecurityPolicyKey)
671670
}
672671

673-
const (
674-
aiGatewayRouteConditionTypeAccepted = "Accepted"
675-
aiGatewayRouteConditionTypeNotAccepted = "NotAccepted"
676-
)
677-
678672
// updateAIGatewayRouteStatus updates the status of the AIGatewayRoute.
679-
func (c *AIGatewayRouteController) updateAIGatewayRouteStatus(ctx context.Context, route *aigv1a1.AIGatewayRoute, accepted bool, message string) {
680-
route = route.DeepCopy()
681-
condition := metav1.Condition{Message: message, LastTransitionTime: metav1.Now()}
682-
if accepted {
683-
condition.Type = aiGatewayRouteConditionTypeAccepted
684-
condition.Reason = "ReconciliationSucceeded"
685-
condition.Status = metav1.ConditionTrue
686-
} else {
687-
condition.Type = aiGatewayRouteConditionTypeNotAccepted
688-
condition.Reason = "ReconciliationFailed"
689-
condition.Status = metav1.ConditionFalse
690-
}
691-
692-
// Search for the same Status condition and replace it, append if not found.
693-
found := false
694-
for i, cond := range route.Status.Conditions {
695-
if cond.Type == condition.Type {
696-
found = true
697-
route.Status.Conditions[i] = condition
698-
break
699-
}
700-
}
701-
702-
if !found {
703-
route.Status.Conditions = append(route.Status.Conditions, condition)
704-
}
705-
// And sort the conditions by LastTransitionTime.
706-
sort.Slice(route.Status.Conditions, func(i, j int) bool {
707-
return route.Status.Conditions[i].LastTransitionTime.Before(&route.Status.Conditions[j].LastTransitionTime)
708-
})
709-
673+
func (c *AIGatewayRouteController) updateAIGatewayRouteStatus(ctx context.Context, route *aigv1a1.AIGatewayRoute, conditionType string, message string) {
674+
route.Status.Conditions = newConditions(conditionType, message)
710675
if err := c.client.Status().Update(ctx, route); err != nil {
711676
c.logger.Error(err, "failed to update AIGatewayRoute status")
712677
}

0 commit comments

Comments
 (0)