@@ -38,14 +38,38 @@ higher-level abstraction to our existing policies.
3838# Guide-level explanation
3939[ guide-level-explanation ] : #guide-level-explanation
4040
41+ While this proposal does enable the work on ` Metapolicy ` ies as they are mostly understood today, it actually abstracts
42+ the very essence of what the Kuadrant controller already is, i.e. a metacontroller that knows about the so-called
43+ "State-of-the-World" (or SotW), the directed acyclic graph (or DAG) we use to represent the state of the different
44+ Gateway API network objects and how policies attach to them.
45+
46+ Aside that particularity of the SotW knowledge, certainly as far as the data-plane is concerned, the Kuadrant controller
47+ ingests ` Auth- ` and ` RateLimit- ` ` Policy ` ies and outputs ` AuthConfig ` and ` Limit ` CR respectively, while configuring the
48+ ` Gateway ` (s) as required, by configuring the wasm-shim they are running.
49+
4150## What's a * Metapolicy* ?
4251
43- A * Metapolicy* is a policy just like any other [ Gateway API Policy] [ 2 ] , other than it only produces one or more "core
52+ A * Metapolicy* is a policy just like any other [ Gateway API Policy] [ 2 ] , other than it only affects one or more "core
4453Kuadrant policies". A * Metapolicy* is managed by a ` MetapolicyController ` that will interact with the
4554` KuadrantController ` to integrate seamlessly in the ecosystem.
4655
4756Think of a ` MetapolicyController ` being a pure function that takes the custom * Metapolicy* and the Gateway API network
48- objects it targets as input, and outputs one or more Kuadrant Policies as a result.
57+ objects it targets as input, and alters one or more Kuadrant Policies as a result.
58+
59+ The simplest form will be a one-to-one match and their lifecycle will be the same. When creating the metapolicy, the
60+ resulting output ` Policy ` gets created; on updates, it is updated; and, finally, when the metapolicy is deleted, the
61+ matching core ` Policy ` also gets deleted.
62+
63+ In other cases tho, a metapolicy might depend directly or indirectly on the existence of another core ` Policy ` . Further
64+ more it may need to alter that policy in one way or another.
65+
66+ > [ !NOTE]
67+ > An example of such a policy, would be the ` PlanPolicy ` . That policy points indirectly to an ` AuthConfig ` , that it'll use
68+ > as the source of data to match a request to a "plan". In abstract terms, it would need to alter the ` AuthConfig ` so that
69+ > it enriches the metadata available to the wasm-shim (and as such to other services it calls into), with the "plan"
70+ > identifier, so that limitador can apply the proper limits (and look up the proper counters). So while the ` PlanPolicy `
71+ > would match straight to a ` RateLimitPolicy ` , it also would need to add, modify and remove that mapping function from,
72+ > ultimately, the ` AuthConfig ` .
4973
5074## Implementing a custom * Metapolicy*
5175
@@ -56,10 +80,6 @@ Controller](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/
5680it also needs to reconcile when changes to properties of the Gateway API it uses are observed. For that reason, the
5781controller for a custom * Metapolicy* registers itself with the ` KuadrantController ` .
5882
59- > [ !TODO]
60- > Some initial SDK usage example
61-
62-
6383The example below is a modified example from the
6484[ controller-runtime's own example] ( https://github.com/kubernetes-sigs/controller-runtime/blob/main/examples/builtins/controller.go#L39 ) .
6585
@@ -83,7 +103,7 @@ func (r *reconcileMetapolicy) Reconcile(ctx context.Context, request reconcile.R
83103 }
84104
85105 // resolve the CEL expression using the `KuadrantContext`
86- label := kuadrant.evaluateExpression (" kuadrant.gatewaysFor(self )[0].metadata.name" )
106+ label := kuadrant.evaluateExpression (" self.findGateways( )[0].metadata.name" )
87107
88108 if rs.Labels [" gateway" ] == label {
89109 return reconcile.Result {}, nil
@@ -103,8 +123,9 @@ It on differs in three ways from the original example:
103123
1041241 . The ` Reconcile ` signature takes an additional parameter, the ` kuadrant *KuadrantContext ` ;
1051251 . It acts upon an hypothetical ` user.MetaPolicy ` ;
106- 1 . It uses the ` evaluateExpression ` to resolve the CEL expression ` kuadrant.gatewaysFor(self)[0].metadata.name ` instead
107- of using a fixed string for the label's value.
126+ 1 . It uses the ` evaluateExpression ` to resolve the CEL expression ` self.findGateways(self)[0].metadata.name ` instead
127+ of using a fixed string for the label's value. Where ` self ` is the * Metapolicy* being reconciled.
128+ 1 . The Kuadrant CEL Library is the one providing the additional functionality needed to support the different use cases.
108129
109130Because that expression is evaluated upon creation, the ` KuadrantRuntime ` will make sure to reconcile whenever that cel
110131expression's evaluated result would change; in this particular example whenever the name of the first ` Gateway ` changes.
@@ -113,52 +134,43 @@ expression's evaluated result would change; in this particular example whenever
113134> Below is the proposed inital integration point for ` MetapolicyController ` s. The idea is to keep the deployment model
114135> fairly open moving forward. As of now, this would be the deployment model for _ our own_ * Metapolicies*
115136
116- To deploy our custom reconciler, we need to let the Kuadrant operator know about it, by adding it to the ` Kuadrant ` CR:
117-
118- ``` yaml
119- apiVersion : kuadrant.io/v1beta2
120- kind : Kuadrant
121- metadata :
122- name : kuadrant-sample
123- spec :
124- plugins :
125- userMetaPolicy :
126- deployment : embedded
127- ` ` `
128137
129138The ` UserMetaPolicy ` will need to be packaged with a custom Docker image containing the plugin. It'll be automatically
130- registered with the Kuadrant Controller from its own config file.
131-
132- > [!TODO]
133- > Support out-of-image deployments of plugins, i.e. ones running as their own container. Which then also means we need
134- > to deal with failures et al, so probably adding the necessity for more configuration options for these plugins
139+ registered with the Kuadrant Controller when present.
135140
136141# Reference-level explanation
137142[ reference-level-explanation ] : #reference-level-explanation
138143
139144## Plugin architecture
140145
141- # ## gRPC to controller
146+ ### Kuadrant's ` MetapolicyControllerRuntime `
147+
148+ - [ ] Provides the layer around the standard [ Kubernetes' Controller Runtime] ( https://github.com/kubernetes-sigs/controller-runtime )
149+ - [ ] Provides a logger to ` stderr ` for log forwarding, according to tbd formart
150+ - [ ] Provides a golang API that interfaces with the controller through gRPC (including streams for eventing)
151+ - [ ] Provides eventing for the changes triggered by the SotW DAG
152+ - [ ] Handles the lifecycling of the extension, ` SIGTEM ` handler
153+ - [ ] * Optional* : Readiness probe, tho looks like we don't need it
154+ - [ ] * Optional* : More advanced liveliness probe, tho again there probably is no reason
155+
156+ ### Kuadrant Controller extension mechanism
142157
143158- [ ] Unix socket for "in-pod/embedded" plugins
159+ - [ ] Monitors child processes and restarts them when needed
160+ - [ ] Forwards ` stderr ` to a per-extension logger at the appropriate log level
144161- [ ] Declarative way to load plugins
145- - [ ] Provide a decorated [Controller Runtime](https://github.com/kubernetes-sigs/controller-runtime) Golang that
146- provides the changes triggered by the DAG
147-
148- # ## gRPC streams for eventing on the DAG
149162
150- - [ ] Subscriptions infered from CEL and the current CR being reconcilied
163+ ### Extension services
151164
152- # ## Typed DSL in CEL
165+ - [ ] API to query the SotW DAG, with subscriptions
166+ - [ ] API to add/modify/delete transformer functions to the DAG
167+ - [ ] metadata enrichment ("per action" ?)
168+ - [ ] others?
153169
154- > [!IMPORTANT]
155- > Provide both the `MetapolicyCR` & the `GwAPIContext` instances relative to a reconciliation
156- > The `GwAPIContext` would not only be responsible for resolving the [CEL expressions][3] but also deriving the
157- > necessary subscriptions needed to inform the controller when a reconciliation is needed because of changes to the
158- > Gateway API objects queried
170+ ### CEL Kuadrant Library
159171
160- - [ ] Support existing `context`s in the CEL interpreter's `Env`
161- - [ ] Find a way to express the `context`s present/set for each CEL
172+ - [ ] Support for all Gateway API types through protobuf
173+ - [ ] Add utility methods to ` Policy ` type for DAG navigation
162174
163175
164176### Deployment
0 commit comments