opaopen-policy-agentrego

Rego function to define variables


For several rules, we need to define the same set of variables. In the example, these are "ns", "externaldns", "svc", "nssvc". How could we take these definitions away from each rule, maybe into a function, and then just call the function once in every rule?

    violation[{"msg": msg}] {
      ns := input.review.object.metadata.namespace
      externaldns := input.review.object.metadata.annotations["external-dns.alpha.kubernetes.io/hostname"]
      svc := input.review.object.metadata.name
      nssvc := sprintf("%v-%v", [ns,svc])
      not startswith(externaldns, svc)
      startswith(svc, ns)
      not endswith(ns, "-system")
      msg := "some message"
    }

Solution

  • You could just move the common variables/rules out of the rule body, like:

    ns := input.review.object.metadata.namespace
    externaldns := input.review.object.metadata.annotations["external-dns.alpha.kubernetes.io/hostname"]
    svc := input.review.object.metadata.name
    nssvc := sprintf("%v-%v", [ns,svc])
    
    violation[{"msg": msg}] {
        not startswith(externaldns, svc)
        startswith(svc, ns)
        not endswith(ns, "-system")
        msg := "some message"
    }
    

    If you'd like to move some of into functions, that would be doable too, i.e:

    annotation(key) = value {
        value = input.review.object.metadata.annotations[key]
    }
    
    violation[{"msg": msg}] {
        externaldns := annotation("external-dns.alpha.kubernetes.io/hostname")
        # ...
    }