cloud66-oss / copper

A configuration file validator for Kubernetes.
https://help.cloud66.com/copper/
Apache License 2.0
274 stars 16 forks source link

How to filter by object type #6

Closed towolf closed 6 years ago

towolf commented 6 years ago

If I have a fake concatenated manifest (in this case the output of `helm template), the I find it tricky to filter on object types.

---
apiVersion: v1
kind: ConfigMap
---
apiVersion: v1
kind: ConfigMap
---
apiVersion: v1
kind: ConfigMap
---
apiVersion: v1
kind: Service
---
apiVersion: apps/v1beta1
kind: Deployment
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy

Aside, the tool recognizes the first element as an empty doc, I think.

How do I enforce things for kind: Service only?

khash commented 6 years ago

In a multi-part yaml file like this one, each part is treated as a single yaml so the filter is applied to each part individually and can return a value or not depending on the content. For example, to fetch only kind: Service you might want to use fetch("$[?(@['kind'] == 'Service')]"). This returns [] for all parts except for the one with kind: Service.

Your condition inside of the rule then can decide to ignore this if the returned array is empty.

Having said that, I think we can improve the filtering further but this should be done in a way that doesn't compromise the best practices Copper is trying to enforce. In this case, having all resources defined in one file is not a good idea so allowing to filter by type will firstly make writing of the rules more complicated and secondly encourages not following best practices.

khash commented 6 years ago

@towolf did you manage to use the suggested filter to get around your problem?

towolf commented 6 years ago

Sorry, i haven't looked into this tool much more and have been fully occupied with other things. Feel free to close this if you like. @khash

eyalzek commented 5 years ago

How would one filter empty arrays? I tried many different ways but in most cases copper just complains for invalid syntax.

fetch("$[?(@['kind'] == 'Deployment')].apiVersion") == []

edit: I managed to get it to pass with:

rule DeploymentApiVersion ensure {
    fetch("$[?(@['kind'] == 'Deployment')].apiVersion").count == 0 or
    fetch("$[?(@['kind'] == 'Deployment')].apiVersion").first == "apps/v1"
}

though skipping would actually be better than making unmatching resources pass...