Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions internal/tester/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"io"
"log/slog"
"math"
"os"

"github.com/yannh/kubeconform/pkg/resource"
Expand Down Expand Up @@ -142,6 +143,8 @@ func (r *ResourceLoader) LoadResources(paths []string) {
slog.Warn("failed to decode resource", "error", err)
continue
}
// ensure numbers to be int if possible
normalizeObject(obj)
unstructuredObj := &unstructured.Unstructured{Object: obj}

// if resource manifest validation is enabled, check whether the resource manifest follows a schema.
Expand Down Expand Up @@ -193,3 +196,34 @@ func defaultingMAPPolicy(p *v1alpha1.MutatingAdmissionPolicy) {
p.Spec.MatchConstraints.ObjectSelector = &metav1.LabelSelector{}
}
}

// normalizeObject ensures int-able values to be int.
func normalizeObject(obj map[string]any) {
for k, v := range obj {
obj[k] = normalizeValue(v)
}
}

func normalizeArray(arr []any) {
for i := range arr {
arr[i] = normalizeValue(arr[i])
}
}

func normalizeValue(v any) any {
switch val := v.(type) {
case map[string]any:
normalizeObject(val)
return val
case []any:
normalizeArray(val)
return val
case float64:
if math.Trunc(val) == float64(int64(val)) {
return int64(val)
}
return val
default:
return v
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
policies:
- ../vap-custom-resources.yaml
resources:
- resources.yaml
schemaLocations:
- "https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json"
vapTestSuites:
- policy: httpproxy-auth
tests:
- object:
kind: HTTPProxy
name: not-exist
expect: admit
16 changes: 16 additions & 0 deletions internal/tester/testdata/map-custom-resources.test/kaptest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
policies:
- ../map-custom-resources.yaml
resources:
- resources.yaml
schemaLocations:
- "https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json"
mapTestSuites:
- policy: httpproxy-update
tests:
- object:
kind: HTTPProxy
name: base
expect: mutate
expectObject:
kind: HTTPProxy
name: updated
27 changes: 27 additions & 0 deletions internal/tester/testdata/map-custom-resources.test/resources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: base
spec:
virtualhost:
fqdn: foo-basic.bar.com
routes:
- conditions:
- prefix: /
services:
- name: s1
port: 80
---
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: updated
spec:
virtualhost:
fqdn: mutated.foo-basic.bar.com
routes:
- conditions:
- prefix: /
services:
- name: s1
port: 8080
38 changes: 38 additions & 0 deletions internal/tester/testdata/map-custom-resources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: MutatingAdmissionPolicy
metadata:
name: httpproxy-update
spec:
matchConstraints:
matchPolicy: "Equivalent"
namespaceSelector: {}
objectSelector: {}
resourceRules:
- apiGroups: ["projectcontour.io"]
apiVersions: ["*"]
operations: ["CREATE", "UPDATE"]
resources: ["httpproxies"]
failurePolicy: Fail
reinvocationPolicy: IfNeeded
mutations:
- patchType: ApplyConfiguration
applyConfiguration:
expression: >-
Object{
spec: Object.spec{
virtualhost: Object.spec.virtualhost{
fqdn: "mutated.foo-basic.bar.com",
},
routes: object.spec.routes.map(
x, Object.spec.routes{
conditions: x.conditions,
services: x.services.map(
y, Object.spec.routes.services{
name: y.name,
port: 8080,
}
),
}
),
}
}
25 changes: 25 additions & 0 deletions internal/tester/testdata/map-with-crd-params.test/kaptest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
policies:
- ../map-with-crd-params.yaml
resources:
- resources.yaml
mapTestSuites:
- policy: deployment-replicas
tests:
- object:
kind: Deployment
name: small
namespace: foo
param:
name: my-config
expect: mutate
expectObject:
kind: Deployment
name: ok
namespace: foo
- object:
kind: Deployment
name: ok
namespace: foo
param:
name: my-config
expect: skip
49 changes: 49 additions & 0 deletions internal/tester/testdata/map-with-crd-params.test/resources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ok
namespace: foo
labels:
app: ok-deployment
spec:
replicas: 5
selector:
matchLabels:
app: ok-deployment
template:
metadata:
labels:
app: ok-deployment
spec:
containers:
- name: nginx
image: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: small
namespace: foo
labels:
app: ok-deployment
spec:
replicas: 1
selector:
matchLabels:
app: ok-deployment
template:
metadata:
labels:
app: ok-deployment
spec:
containers:
- name: nginx
image: nginx
---
apiVersion: example.com/v1
kind: MyCustomResource
metadata:
name: my-config
namespace: hoge
spec:
maxReplicas: 5
34 changes: 34 additions & 0 deletions internal/tester/testdata/map-with-crd-params.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: MutatingAdmissionPolicy
metadata:
name: deployment-replicas
spec:
matchConstraints:
matchPolicy: "Equivalent"
namespaceSelector: {}
objectSelector: {}
resourceRules:
- apiGroups: ["*"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
failurePolicy: Fail
reinvocationPolicy: IfNeeded
paramKind:
apiVersion: example.com/v1
kind: MyCustomResource
variables:
- name: maxReplicas
expression: int(params.spec.maxReplicas)
matchConditions:
- name: replicas-increase
expression: "object.spec.replicas < int(params.spec.maxReplicas)"
mutations:
- patchType: ApplyConfiguration
applyConfiguration:
expression: >-
Object{
spec: Object.spec {
replicas: variables.maxReplicas
}
}
20 changes: 20 additions & 0 deletions internal/tester/testdata/vap-with-crd-params.test/kaptest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
policies:
- ../vap-with-crd-params.yaml
resources:
- resources.yaml
vapTestSuites:
- policy: deployment-replicas
tests:
- object:
kind: Deployment
name: ok
param:
name: my-config
expect: admit
- object:
kind: Deployment
name: bad
param:
name: my-config
expect: deny
deniedMessage: "replicas must be equal or less than 5"
47 changes: 47 additions & 0 deletions internal/tester/testdata/vap-with-crd-params.test/resources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ok
labels:
app: ok-deployment
spec:
replicas: 5
selector:
matchLabels:
app: ok-deployment
template:
metadata:
labels:
app: ok-deployment
spec:
containers:
- name: nginx
image: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: bad
labels:
app: bad-deployment
spec:
replicas: 6
selector:
matchLabels:
app: bad-deployment
template:
metadata:
labels:
app: bad-deployment
spec:
containers:
- name: nginx
image: nginx
---
apiVersion: example.com/v1
kind: MyCustomResource
metadata:
name: my-config
namespace: hoge
spec:
maxReplicas: 5
24 changes: 24 additions & 0 deletions internal/tester/testdata/vap-with-crd-params.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: deployment-replicas
spec:
failurePolicy: Fail
matchConstraints:
matchPolicy: "Equivalent"
namespaceSelector: {}
objectSelector: {}
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
paramKind:
apiVersion: example.com/v1
kind: MyCustomResource
variables:
- expression: "has(object.spec.replicas) ? object.spec.replicas : 1"
name: replicas
validations:
- expression: variables.replicas <= int(params.spec.maxReplicas)
messageExpression: "'replicas must be equal or less than ' + string(params.spec.maxReplicas)"
Loading