-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Proposal for extending forEach to cover generate rules
Signed-off-by: Mariam Fahmy <[email protected]>
- Loading branch information
1 parent
380a3c8
commit d2ff6cd
Showing
1 changed file
with
182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
# Support `forEach` in Generate Rules | ||
|
||
- **Authors**: [Mariam Fahmy](https://github.com/MariamFahmy98) | ||
- **Created**: Nov 11th, 2023 | ||
- **Abstract**: Supporting `forEach` in Generate Rules | ||
|
||
# Table of Contents | ||
- [Overview](#overview) | ||
- [Definitions](#definitions) | ||
- [Motivation](#motivation) | ||
- [Proposal](#proposal) | ||
- [Implementation](#implementation) | ||
- [Drawbacks](#drawbacks) | ||
- [Alternatives](#alternatives) | ||
- [Prior Art](#prior-art) | ||
- [Unresolved Questions](#unresolved-questions) | ||
|
||
# Overview | ||
[overview]: #overview | ||
Generate rules are in charge of creating new resources. The rule can either define the new resource using the `data` object or use an existing resource in the cluster with the `clone` object. Currently, only one resource can be generated. | ||
|
||
This proposal is to extend the `forEach` to cover generate rules. | ||
|
||
# Definitions | ||
[definitions]: #definitions | ||
|
||
1. Trigger: It refers to the resource responsible for triggering the generate rule as defined in a combination of `match` and `exclude` blocks. | ||
|
||
2. Downstream: It refers to the generated resource(s). | ||
|
||
3. Source: It refers to the clone source when generating new resources from existing ones in the cluster. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
There are some use cases where a single "trigger" resource should result in the creation of multiple downstream resources. | ||
|
||
Examples: | ||
1. Generating a list of new network policies based on a comma separated string in an annotation using a `forEach` and `Split()`. | ||
2. Migrating from ingress to Kubernetes Gateway API requires generating at least two resources: `Gateway` and `HTTPRoute`. | ||
|
||
# Proposal | ||
In this proposal, Kyverno generate rule can be extended to allowing the generation of multiple resources using `forEach`. | ||
This could be done by using the `list` attribute which is a JMESPath expression that defines the sub-elements it processes. | ||
|
||
Examples: | ||
1. Generate multiple network policies when a new namespace is created: | ||
```yaml | ||
spec: | ||
rules: | ||
- name: generate-network-policies | ||
match: | ||
any: | ||
- resources: | ||
kinds: | ||
- Namespace | ||
generate: | ||
synchronize: true | ||
foreach: | ||
- list: request.object.metadata.labels.networkpolicies | split(@, ',') | ||
resources: | ||
- apiVersion: v1 | ||
kind: NetworkPolicy | ||
name: '{{ element }}' | ||
namespace: "{{request.object.metadata.name}}" | ||
data: | ||
spec: | ||
podSelector: {} | ||
policyTypes: | ||
- Ingress | ||
- Egress | ||
``` | ||
2. Generate ConfigMap and Secret for each container: | ||
```yaml | ||
spec: | ||
rules: | ||
- name: generate-configmaps-and-secrets | ||
match: | ||
any: | ||
- resources: | ||
kinds: | ||
- Pod | ||
generate: | ||
synchronize: true | ||
foreach: | ||
- list: request.object.spec.containers | ||
resources: | ||
- apiVersion: v1 | ||
kind: ConfigMap | ||
name: cm | ||
namespace: "{{request.object.metadata.namespace}}" | ||
data: | ||
foo: bar | ||
- apiVersion: v1 | ||
kind: Secret | ||
name: secret | ||
namespace: "{{request.object.metadata.namespace}}" | ||
data: | ||
foo: bar | ||
``` | ||
3. Generate Gateway and HTTPRoute from Ingress: | ||
```yaml | ||
spec: | ||
rules: | ||
- name: generate-gatewayapi | ||
match: | ||
any: | ||
- resources: | ||
kinds: | ||
- Ingress | ||
generate: | ||
synchronize: false | ||
foreach: | ||
- list: request.object.spec.rules | ||
resources: | ||
- apiVersion: gateway.networking.k8s.io/v1beta1 | ||
kind: HTTPRoute | ||
# the name must be unique | ||
name: httproute | ||
namespace: "{{request.object.metadata.namespace}}" | ||
data: | ||
spec: | ||
hostnames: | ||
- '{{ element.host }}' | ||
- list: request.object.spec.ingressClassName | ||
resources: | ||
- apiVersion: gateway.networking.k8s.io/v1beta1 | ||
kind: Gateway | ||
name: gateway | ||
data: | ||
spec: | ||
gatewayClassName: '{{ element }}' | ||
``` | ||
# Implementation | ||
We will extend the generate rule as follows: | ||
```go | ||
type Generation struct { | ||
ForEachGeneration []ForEachGeneration `json:"foreach,omitempty" yaml:"foreach,omitempty"` | ||
} | ||
``` | ||
|
||
```go | ||
type ForEachGeneration struct { | ||
List string `json:"list,omitempty" yaml:"list,omitempty"` | ||
|
||
Resource []Resource `json:"resources,omitempty" yaml:"resources,omitempty"` | ||
} | ||
``` | ||
|
||
```go | ||
type Resource struct { | ||
ResourceSpec `json:",omitempty" yaml:",omitempty"` | ||
|
||
RawData *apiextv1.JSON `json:"data,omitempty" yaml:"data,omitempty"` | ||
} | ||
``` | ||
|
||
- `foreach` will only support generating Kubernetes resources that are defined as a part of the rule. | ||
|
||
- Nested `foreach` can be supported but there is no real use case for it. | ||
|
||
- At least one of the following: `data`, `clone`, or `foreach` must be declared. | ||
|
||
# Drawbacks | ||
|
||
N/A | ||
|
||
# Alternatives | ||
|
||
N/A | ||
|
||
# Prior Art | ||
|
||
N/A | ||
|
||
# Unresolved Questions | ||
|
||
N/A |