From 852833764c008854e5201cbe1bc94660f99f8cec Mon Sep 17 00:00:00 2001
From: Erik Brakkee <erik@brakkee.org>
Date: Fri, 3 Jan 2025 17:59:11 +0100
Subject: [PATCH] addes support for matchExpressions

---
 cmd/policygen/config.go                       | 19 +++++++++++++------
 .../templates/netpol/pod/apiserver.yaml       |  6 ++++--
 cmd/policygen/templates/netpol/pod/pod.yaml   |  4 +++-
 example/config.yaml                           |  4 ++++
 4 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/cmd/policygen/config.go b/cmd/policygen/config.go
index 9e7c8ae..398f05a 100644
--- a/cmd/policygen/config.go
+++ b/cmd/policygen/config.go
@@ -54,11 +54,18 @@ type Network struct {
 	Ports  []Port `yaml:"ports,omitempty"  validate:"dive,required"`
 }
 
+type MatchExpression struct {
+	Key      string   `json:"key" yaml:"key" validate:"required"`
+	Operator string   `json:"operator" yaml:"operator" validate:"oneof=In NotIn Exists DoesNotExist"`
+	Values   []string `json:"values" yaml:"values"`
+}
+
 type Application struct {
-	Name        string            `yaml:"name"`
-	Ports       []Port            `yaml:"ports,omitempty"`
-	MatchLabels map[string]string `yaml:"matchLabels"`
-	Namespace   *Namespace        `yaml:"-" validate:"-"`
+	Name             string            `yaml:"name"`
+	Ports            []Port            `yaml:"ports,omitempty"`
+	MatchLabels      map[string]string `yaml:"matchLabels"`
+	MatchExpressions []MatchExpression `yaml:"matchExpressions" validate:"omitempty,dive"`
+	Namespace        *Namespace        `yaml:"-" validate:"-"`
 }
 
 type Namespace struct {
@@ -138,12 +145,12 @@ func (c Config) Validate() error {
 	for _, communication := range c.Communications {
 		for _, from := range communication.From {
 			if !apps[from] {
-				errs = append(errs, fmt.Errorf("Application does not exist: %s referenced in a communication (%+v)", from, communication))
+				errs = append(errs, fmt.Errorf("Application does not exist: '%s' referenced in a communication (%+v)", from, communication))
 			}
 		}
 		for _, to := range communication.To {
 			if !apps[to] {
-				errs = append(errs, fmt.Errorf("Application does not exist: %s referenced in a communication (%+v)", to, communication))
+				errs = append(errs, fmt.Errorf("Application does not exist: '%s' referenced in a communication (%+v)", to, communication))
 			}
 		}
 	}
diff --git a/cmd/policygen/templates/netpol/pod/apiserver.yaml b/cmd/policygen/templates/netpol/pod/apiserver.yaml
index 991f3fe..4043917 100644
--- a/cmd/policygen/templates/netpol/pod/apiserver.yaml
+++ b/cmd/policygen/templates/netpol/pod/apiserver.yaml
@@ -5,9 +5,11 @@ apiVersion: cilium.io/v2
 metadata:
   name: {{.app.Name}}-apiserver
   namespace: {{.app.Namespace.Name}}
-  labels: {{ .labels | toYaml | nindent 4 }}
+  labels: {{ .labels | toJson }}
 spec:
-  endpointSelector: {{ .app.MatchLabels | toYaml | nindent 4 }}
+  endpointSelector:
+    matchLabels: {{ .app.MatchLabels | toJson }}
+    matchExpressions: {{ .app.MatchExpressions | toJson }}
   {{- if .ingress }}
   ingress:
   - fromEntities:
diff --git a/cmd/policygen/templates/netpol/pod/pod.yaml b/cmd/policygen/templates/netpol/pod/pod.yaml
index b507142..9e8d400 100644
--- a/cmd/policygen/templates/netpol/pod/pod.yaml
+++ b/cmd/policygen/templates/netpol/pod/pod.yaml
@@ -12,6 +12,7 @@
       # {{ .Application.Namespace.Name }}/{{ .Application.Name }}
       - podSelector:
           matchLabels: {{ .Application.MatchLabels | toJson }}
+          matchExpressions: {{ .Application.MatchExpressions | toJson }}
         namespaceSelector:
           matchLabels:
             kubernetes.io/metadata.name: {{ .Application.Namespace.Name }}
@@ -45,11 +46,12 @@ apiVersion: networking.k8s.io/v1
 metadata:
   name: "{{.app.Name}}"
   namespace: "{{.app.Namespace.Name }}"
-  labels: {{ .labels | toYaml | nindent 4 }}
+  labels: {{ .labels | toJson }}
 spec:
   # {{ .app.Namespace.Name }}/{{ .app.Name }}
   podSelector:
     matchLabels: {{ .app.MatchLabels | toJson }}
+    matchExpressions: {{ .app.MatchExpressions | toJson }}
   policyTypes:
     {{- if or .ingress.Applications .ingress.Networks }}
     - Ingress
diff --git a/example/config.yaml b/example/config.yaml
index 450fc97..757dc49 100644
--- a/example/config.yaml
+++ b/example/config.yaml
@@ -28,6 +28,10 @@ namespaces:
             protocol: UDP
         matchLabels:
           app: nexus-server
+        matchExpressions:
+          - key: jenkins/label
+            operator: Exists
+
 
   - name: exposure
     open: false