---
# System prepended metadata

title: 'Mutating Webhooks: Does Kyverno have a bright future?'

---

# Mutating Webhooks: Does Kyverno have a bright future?

The motivation behind mutating webhooks is as old as Kubernetes itself -
Some objects should have default values when they are applied.

I have been working on the topic through many iterations of our product and at Giant Swarm we have used multiple different solutions over the years. And those solutions are plentiful:
If you have control over the Custom Resource Definition then you can default through the `openAPIV3Schema`. If you are running [Gatekeeper](https://github.com/open-policy-agent/gatekeeper) then you can write relatively simple mutation rules. If you want to write your own webhooks in `go` - [you can](https://docs.giantswarm.io/advanced/custom-admission-controller/)!

But what if it gets a bit more complicated than just statically defaulting something?

## The advanced usecase

When mutating and especially dealing with defaulting values you might very quickly run into the following scenario:
The value you want to set as a default changes depending on another object.

A brief example:
You want all pods in a namespace to inherit an annotation set on the namespace.

[[Potential diagram?!]]

Sounds pretty simple right? But it implies that you are able to get this information from the namespace at the time a new pod is created.
This furthermore implies that during the mutating webhook makes a different API call to the Kubernetes API to retrieve this information.

Achieving this in different solutions for mutating webhooks ranges drastically in complexity from impossible to pretty straight forward.

## The Kyverno way

I initially learned about Kyverno from @Zach and I have to admit that I was very sceptical at first. My personal experience with Gatekeeper was not positive as I struggled to express the advanced usecase we aim to cover here in REGO. So why would a different policy agent be any better?

I started to look into Kyverno nonetheless and what I saw convinced me pretty quickly:
Kyverno does not try to use or implement a general purpose policy engine. This allows Kyverno to focus on Kubernetes much more and allows it to fit into the Kubernetes ecosystem a lot more cleanly in my opinion.
The use of JMESPath (even though it has its flaws) also felt much more natural to me compared to REGO - so in no time I was playing around with Kyverno and enjoying myself.

_Disclaimer: If you are looking for a more in depth comparison between Kyverno and Gatekeeper, check out [this blog post by Chip Zoller](https://neonmirrors.net/post/2021-02/kubernetes-policy-comparison-opa-gatekeeper-vs-kyverno/)._

So let's get right into it with the example from above:
```yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: "pod-defaulting"
spec:
  rules:
  - name: "copy-annotation"
    match:
      resources:
        kinds:
          - Pod
    context:
    - name: namespaceAnnotation
      apiCall:
        urlPath: "/api/v1/namespaces/{{ request.object.metadata.namespace }}"
        jmesPath: "metadata.annotations.\"my.key/copy-me\""
    mutate:
      patchStrategicMerge:
        metadata:
          annotations:
            +(my.key/special-value): "{{ namespaceAnnotation }}"
```
These contexts allow us to fetch information from a different object in the same kubernetes cluster.
The context name is then usable later on as variable which 


## Conclusion

I THINK SO - BUT?!