Skip to content

Commit

Permalink
More AIGateway rename changes (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuzisun authored Jan 16, 2025
1 parent 7fab17b commit 25d221c
Show file tree
Hide file tree
Showing 14 changed files with 46 additions and 45 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
out/
.DS_Store
.terraform
.idea
*for_tests.yaml

# Files and directories to ignore in the site directory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import (
)

const (
managedByLabel = "app.kubernetes.io/managed-by"
expProcConfigFileName = "extproc-config.yaml"
k8sClientIndexBackendToReferencingLLMRoute = "BackendToReferencingLLMRoute"
managedByLabel = "app.kubernetes.io/managed-by"
expProcConfigFileName = "extproc-config.yaml"
k8sClientIndexBackendToReferencingAIGatewayRoute = "BackendToReferencingAIGatewayRoute"
)

func aiGatewayRouteIndexFunc(o client.Object) []string {
Expand All @@ -41,7 +41,7 @@ func aiGatewayRouteIndexFunc(o client.Object) []string {

// aiGatewayRouteController implements [reconcile.TypedReconciler].
//
// This handles the LLMRoute resource and creates the necessary resources for the external process.
// This handles the AIGatewayRoute resource and creates the necessary resources for the external process.
type aiGatewayRouteController struct {
client client.Client
kube kubernetes.Interface
Expand All @@ -67,17 +67,17 @@ func NewAIGatewayRouteController(

// Reconcile implements [reconcile.TypedReconciler].
//
// This only creates the external process deployment and service for the LLMRoute as well as the extension policy.
// This only creates the external process deployment and service for the AIGatewayRoute as well as the extension policy.
// The actual HTTPRoute and the extproc configuration will be created in the config sink since we need
// not only the LLMRoute but also the AIServiceBackend and other resources to create the full configuration.
// not only the AIGatewayRoute but also the AIServiceBackend and other resources to create the full configuration.
func (c *aiGatewayRouteController) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
logger := log.FromContext(ctx)
logger.Info("Reconciling LLMRoute", "namespace", req.Namespace, "name", req.Name)
logger.Info("Reconciling AIGatewayRoute", "namespace", req.Namespace, "name", req.Name)

var aiGatewayRoute aigv1a1.AIGatewayRoute
if err := c.client.Get(ctx, req.NamespacedName, &aiGatewayRoute); err != nil {
if client.IgnoreNotFound(err) == nil {
c.logger.Info("Deleting LLMRoute",
c.logger.Info("Deleting AIGatewayRoute",
"namespace", req.Namespace, "name", req.Name)
return ctrl.Result{}, nil
}
Expand All @@ -92,7 +92,7 @@ func (c *aiGatewayRouteController) Reconcile(ctx context.Context, req reconcile.
if !unversioned && len(gvks) == 1 {
aiGatewayRoute.SetGroupVersionKind(gvks[0])
}
ownerRef := ownerReferenceForLLMRoute(&aiGatewayRoute)
ownerRef := ownerReferenceForAIGatewayRoute(&aiGatewayRoute)

if err := c.ensuresExtProcConfigMapExists(ctx, &aiGatewayRoute, ownerRef); err != nil {
logger.Error(err, "Failed to reconcile extProc config map")
Expand Down Expand Up @@ -271,7 +271,7 @@ func extProcName(route *aigv1a1.AIGatewayRoute) string {
return fmt.Sprintf("ai-gateway-ai-gateway-route-extproc-%s", route.Name)
}

func ownerReferenceForLLMRoute(aiGatewayRoute *aigv1a1.AIGatewayRoute) []metav1.OwnerReference {
func ownerReferenceForAIGatewayRoute(aiGatewayRoute *aigv1a1.AIGatewayRoute) []metav1.OwnerReference {
return []metav1.OwnerReference{{
APIVersion: aiGatewayRoute.APIVersion,
Kind: aiGatewayRoute.Kind,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func Test_extProcName(t *testing.T) {
require.Equal(t, "ai-gateway-ai-gateway-route-extproc-myroute", actual)
}

func TestLLMRouteController_ensuresExtProcConfigMapExists(t *testing.T) {
func TestAIGatewayRouteController_ensuresExtProcConfigMapExists(t *testing.T) {
c := &aiGatewayRouteController{client: fake.NewClientBuilder().WithScheme(scheme).Build()}
c.kube = fake2.NewClientset()

Expand All @@ -52,7 +52,7 @@ func TestLLMRouteController_ensuresExtProcConfigMapExists(t *testing.T) {
require.NoError(t, err)
}

func TestLLMRouteController_reconcileExtProcDeployment(t *testing.T) {
func TestAIGatewayRouteController_reconcileExtProcDeployment(t *testing.T) {
c := &aiGatewayRouteController{client: fake.NewClientBuilder().WithScheme(scheme).Build()}
c.kube = fake2.NewClientset()

Expand Down Expand Up @@ -103,7 +103,7 @@ func TestLLMRouteController_reconcileExtProcDeployment(t *testing.T) {
require.Equal(t, int32(456), *deployment.Spec.Replicas)
}

func TestLLMRouteController_reconcileExtProcExtensionPolicy(t *testing.T) {
func TestAIGatewayRouteController_reconcileExtProcExtensionPolicy(t *testing.T) {
c := &aiGatewayRouteController{client: fake.NewClientBuilder().WithScheme(scheme).Build()}
ownerRef := []metav1.OwnerReference{{APIVersion: "v1", Kind: "Kind", Name: "Name"}}
aiGatewayRoute := &aigv1a1.AIGatewayRoute{
Expand Down Expand Up @@ -189,10 +189,10 @@ func Test_aiGatewayRouteIndexFunc(t *testing.T) {

c := fake.NewClientBuilder().
WithScheme(scheme).
WithIndex(&aigv1a1.AIGatewayRoute{}, k8sClientIndexBackendToReferencingLLMRoute, aiGatewayRouteIndexFunc).
WithIndex(&aigv1a1.AIGatewayRoute{}, k8sClientIndexBackendToReferencingAIGatewayRoute, aiGatewayRouteIndexFunc).
Build()

// Create a LLMRoute.
// Create a AIGatewayRoute.
aiGatewayRoute := &aigv1a1.AIGatewayRoute{
ObjectMeta: metav1.ObjectMeta{
Name: "myroute",
Expand All @@ -218,13 +218,13 @@ func Test_aiGatewayRouteIndexFunc(t *testing.T) {

var aiGatewayRoutes aigv1a1.AIGatewayRouteList
err := c.List(context.Background(), &aiGatewayRoutes,
client.MatchingFields{k8sClientIndexBackendToReferencingLLMRoute: "backend1.default"})
client.MatchingFields{k8sClientIndexBackendToReferencingAIGatewayRoute: "backend1.default"})
require.NoError(t, err)
require.Len(t, aiGatewayRoutes.Items, 1)
require.Equal(t, aiGatewayRoute.Name, aiGatewayRoutes.Items[0].Name)

err = c.List(context.Background(), &aiGatewayRoutes,
client.MatchingFields{k8sClientIndexBackendToReferencingLLMRoute: "backend2.default"})
client.MatchingFields{k8sClientIndexBackendToReferencingAIGatewayRoute: "backend2.default"})
require.NoError(t, err)
require.Len(t, aiGatewayRoutes.Items, 1)
require.Equal(t, aiGatewayRoute.Name, aiGatewayRoutes.Items[0].Name)
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
aigv1a1 "github.com/envoyproxy/ai-gateway/api/v1alpha1"
)

func TestLlmBackendController_Reconcile(t *testing.T) {
func TestAIServiceBackendController_Reconcile(t *testing.T) {
ch := make(chan ConfigSinkEvent, 100)
cl := fake.NewClientBuilder().WithScheme(scheme).Build()
c := NewAIServiceBackendController(cl, fake2.NewClientset(), ctrl.Log, ch)
Expand Down
6 changes: 3 additions & 3 deletions internal/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func StartControllers(ctx context.Context, config *rest.Config, logger logr.Logg

sink := newConfigSink(c, kubernetes.NewForConfigOrDie(config), logger, sinkChan)

// Before starting the manager, initialize the config sink to sync all AIServiceBackend and LLMRoute objects in the cluster.
// Before starting the manager, initialize the config sink to sync all AIServiceBackend and AIGatewayRoute objects in the cluster.
logger.Info("Initializing config sink")
if err = sink.init(ctx); err != nil {
return fmt.Errorf("failed to initialize config sink: %w", err)
Expand All @@ -98,9 +98,9 @@ func StartControllers(ctx context.Context, config *rest.Config, logger logr.Logg

func applyIndexing(indexer client.FieldIndexer) error {
err := indexer.IndexField(context.Background(), &aigv1a1.AIGatewayRoute{},
k8sClientIndexBackendToReferencingLLMRoute, aiGatewayRouteIndexFunc)
k8sClientIndexBackendToReferencingAIGatewayRoute, aiGatewayRouteIndexFunc)
if err != nil {
return fmt.Errorf("failed to index field for LLMRoute: %w", err)
return fmt.Errorf("failed to index field for AIGatewayRoute: %w", err)
}
return nil
}
30 changes: 15 additions & 15 deletions internal/controller/sink.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ import (
const selectedBackendHeaderKey = "x-envoy-ai-gateway-selected-backend"

// ConfigSinkEvent is the interface for the events that the configSink can handle.
// It can be either an AIServiceBackend, an LLMRoute, or a deletion event.
// It can be either an AIServiceBackend, an AIGatewayRoute, or a deletion event.
//
// Exported for internal testing purposes.
type ConfigSinkEvent any

// configSink centralizes the LLMRoute and AIServiceBackend objects handling
// configSink centralizes the AIGatewayRoute and AIServiceBackend objects handling
// which requires to be done in a single goroutine since we need to
// consolidate the information from both objects to generate the ExtProcConfig
// and HTTPRoute objects.
Expand Down Expand Up @@ -58,7 +58,7 @@ func (c *configSink) backend(namespace, name string) (*aigv1a1.AIServiceBackend,
return backend, nil
}

// init caches all AIServiceBackend and LLMRoute objects in the cluster after the controller gets the leader election,
// init caches all AIServiceBackend and AIGatewayRoute objects in the cluster after the controller gets the leader election,
// and starts a goroutine to handle the events from the controllers.
func (c *configSink) init(ctx context.Context) error {
go func() {
Expand All @@ -81,13 +81,13 @@ func (c *configSink) handleEvent(event ConfigSinkEvent) {
case *aigv1a1.AIServiceBackend:
c.syncAIServiceBackend(e)
case *aigv1a1.AIGatewayRoute:
c.syncLLMRoute(e)
c.syncAIGatewayRoute(e)
default:
panic(fmt.Sprintf("unexpected event type: %T", e))
}
}

func (c *configSink) syncLLMRoute(aiGatewayRoute *aigv1a1.AIGatewayRoute) {
func (c *configSink) syncAIGatewayRoute(aiGatewayRoute *aigv1a1.AIGatewayRoute) {
// Check if the HTTPRoute exists.
var httpRoute gwapiv1.HTTPRoute
err := c.client.Get(context.Background(), client.ObjectKey{Name: aiGatewayRoute.Name, Namespace: aiGatewayRoute.Namespace}, &httpRoute)
Expand All @@ -97,20 +97,20 @@ func (c *configSink) syncLLMRoute(aiGatewayRoute *aigv1a1.AIGatewayRoute) {
return
}
if !existingRoute {
// This means that this LLMRoute is a new one.
// This means that this AIGatewayRoute is a new one.
httpRoute = gwapiv1.HTTPRoute{
ObjectMeta: metav1.ObjectMeta{
Name: aiGatewayRoute.Name,
Namespace: aiGatewayRoute.Namespace,
OwnerReferences: ownerReferenceForLLMRoute(aiGatewayRoute),
OwnerReferences: ownerReferenceForAIGatewayRoute(aiGatewayRoute),
},
Spec: gwapiv1.HTTPRouteSpec{},
}
}

// Update the HTTPRoute with the new LLMRoute.
// Update the HTTPRoute with the new AIGatewayRoute.
if err := c.newHTTPRoute(&httpRoute, aiGatewayRoute); err != nil {
c.logger.Error(err, "failed to update HTTPRoute with LLMRoute", "namespace", aiGatewayRoute.Namespace, "name", aiGatewayRoute.Name)
c.logger.Error(err, "failed to update HTTPRoute with AIGatewayRoute", "namespace", aiGatewayRoute.Namespace, "name", aiGatewayRoute.Name)
return
}

Expand All @@ -136,21 +136,21 @@ func (c *configSink) syncLLMRoute(aiGatewayRoute *aigv1a1.AIGatewayRoute) {
func (c *configSink) syncAIServiceBackend(aiBackend *aigv1a1.AIServiceBackend) {
key := fmt.Sprintf("%s.%s", aiBackend.Name, aiBackend.Namespace)
var aiGatewayRoutes aigv1a1.AIGatewayRouteList
err := c.client.List(context.Background(), &aiGatewayRoutes, client.MatchingFields{k8sClientIndexBackendToReferencingLLMRoute: key})
err := c.client.List(context.Background(), &aiGatewayRoutes, client.MatchingFields{k8sClientIndexBackendToReferencingAIGatewayRoute: key})
if err != nil {
c.logger.Error(err, "failed to list LLMRoutes", "backend", key)
c.logger.Error(err, "failed to list AIGatewayRoute", "backend", key)
return
}
for _, aiGatewayRoute := range aiGatewayRoutes.Items {
c.syncLLMRoute(&aiGatewayRoute)
c.syncAIGatewayRoute(&aiGatewayRoute)
}
}

// updateExtProcConfigMap updates the external process configmap with the new LLMRoute.
// updateExtProcConfigMap updates the external process configmap with the new AIGatewayRoute.
func (c *configSink) updateExtProcConfigMap(aiGatewayRoute *aigv1a1.AIGatewayRoute) error {
configMap, err := c.kube.CoreV1().ConfigMaps(aiGatewayRoute.Namespace).Get(context.Background(), extProcName(aiGatewayRoute), metav1.GetOptions{})
if err != nil {
// This is a bug since we should have created the configmap before sending the LLMRoute to the configSink.
// This is a bug since we should have created the configmap before sending the AIGatewayRoute to the configSink.
panic(fmt.Errorf("failed to get configmap %s: %w", extProcName(aiGatewayRoute), err))
}

Expand Down Expand Up @@ -197,7 +197,7 @@ func (c *configSink) updateExtProcConfigMap(aiGatewayRoute *aigv1a1.AIGatewayRou
return nil
}

// newHTTPRoute updates the HTTPRoute with the new LLMRoute.
// newHTTPRoute updates the HTTPRoute with the new AIGatewayRoute.
func (c *configSink) newHTTPRoute(dst *gwapiv1.HTTPRoute, aiGatewayRoute *aigv1a1.AIGatewayRoute) error {
var backends []*aigv1a1.AIServiceBackend
dedup := make(map[string]struct{})
Expand Down
4 changes: 2 additions & 2 deletions internal/controller/sink_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestConfigSink_init(t *testing.T) {
require.NotNil(t, s)
}

func TestConfigSink_syncLLMRoute(t *testing.T) {
func TestConfigSink_syncAIGatewayRoute(t *testing.T) {
fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()
kube := fake2.NewClientset()

Expand Down Expand Up @@ -80,7 +80,7 @@ func TestConfigSink_syncLLMRoute(t *testing.T) {
require.NoError(t, err)

// Then sync.
s.syncLLMRoute(route)
s.syncAIGatewayRoute(route)
// Referencing backends should be updated.
// Also HTTPRoute should be updated.
var updatedHTTPRoute gwapiv1.HTTPRoute
Expand Down
2 changes: 1 addition & 1 deletion tests/cel-validation/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
//go:embed testdata
var testdata embed.FS

func TestLLMRoutes(t *testing.T) {
func TestAIGatewayRoutes(t *testing.T) {
c, _, _ := tests.NewEnvTest(t)
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(30*time.Second))
defer cancel()
Expand Down
2 changes: 1 addition & 1 deletion tests/cel-validation/testdata/aigatewayroutes/basic.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: aigateway.envoyproxy.io/v1alpha1
kind: LLMRoute
kind: AIGatewayRoute
metadata:
name: apple
namespace: default
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: aigateway.envoyproxy.io/v1alpha1
kind: LLMRoute
kind: AIGatewayRoute
metadata:
name: apple
namespace: default
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: aigateway.envoyproxy.io/v1alpha1
kind: LLMRoute
kind: AIGatewayRoute
metadata:
name: apple
namespace: default
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: aigateway.envoyproxy.io/v1alpha1
kind: LLMRoute
kind: AIGatewayRoute
metadata:
name: apple
namespace: default
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/init/envoygateway/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ data:
resources:
- group: aigateway.envoyproxy.io
version: v1alpha1
kind: LLMRoute
kind: AIGatewayRoute
# Envoy Gateway will watch these resource kinds and use them as extension policies
# which can be attached to Gateway resources.
policyResources:
- group: aigateway.envoyproxy.io
version: v1alpha1
kind: LLMRoute
kind: AIGatewayRoute
hooks:
# The type of hooks that should be invoked
xdsTranslator:
Expand Down

0 comments on commit 25d221c

Please sign in to comment.