<p>I would like to check that every Service in a rendered Helm chart has <em>exactly</em> one matching Pod.</p>
<p>A Pod to service association exists when every entry specified in a Services <code>spec.selector</code> object is reflected in a Pods <code>metadata.labels</code> object (which can have additional keys).</p>
<p>The following policy is tested using Conftest by running <code>conftest test --combine {YAML_FILE}</code> and checks that every Service has <em>at least</em> one matching Pod. I'm completely unsure how to transform this so that it checks for <em>exactly</em> one matching Pod.</p>
<pre><code>package main

import future.keywords.every

in_set(e, s) { s[e] }

get_pod(resource) := pod {
  in_set(resource.kind, {&quot;Deployment&quot;, &quot;StatefulSet&quot;, &quot;Job&quot;})
  pod := resource.spec.template
}

# ensure that every service has at least one matching pod
# TODO: ensure that every service has exactly one matching pod
deny_service_without_matching_pod[msg] {
  service := input[_].contents
  service.kind == &quot;Service&quot;
  selector := object.get(service, [&quot;spec&quot;, &quot;selector&quot;], {})
  pods := { p | p := get_pod(input[_].contents) }
  every pod in pods {
    labels := object.get(pod, [&quot;metadata&quot;, &quot;labels&quot;], {})
    matches := { key | some key; labels[key] == selector[key] }
    count(matches) != count(selector)
  }
  msg := sprintf(&quot;service %s has no matching pod&quot;, [service.metadata.name])
}
</code></pre>
<p>Marginal note: The <code>get_pod</code> function doesn't retrieve all PodTemplates that can possibly occur in a Helm chart. Other checks are in place to keep the Kubernetes API-surface of the Helm chart small - so in this case, Pods can only occur in Deployment, StatefulSet and Job.</p>
<p>Maybe there are rego experts here that can chime in and help. That would be very appreciated! 😀</p>

Codepunkt
<p>Since there's no sample data provided, this is untested code. It <em>should</em> work though :)</p>
<pre><code>package main

import future.keywords.in

pods := { pod | 
  resource := input[_].contents
  resource.kind in {&quot;Deployment&quot;, &quot;StatefulSet&quot;, &quot;Job&quot;}
  pod := resource.spec.template
}

services := { service |
  service := input[_].contents
  service.kind == &quot;Service&quot;
}

pods_matching_selector(selector) := { pod |
  selector != {}
  some pod in pods
  labels := pod.metadata.labels
  some key
  labels[key] == selector[key]
}

deny_service_without_one_matching_pod[msg] {
  some service in services
  selector := object.get(service, [&quot;spec&quot;, &quot;selector&quot;], {})
  matching_pods := count(pods_matching_selector(selector))
  matching_pods != 1
  msg := sprintf(
    &quot;service %s has %d matching pods, must have exactly one&quot;,
    [service.metadata.name, matching_pods]
  )
}
</code></pre>
