I would like to write an mutating webhook to add a default ingress class to all ingress object, that do not explicitly provide one.
According to the examples I found I need to provide a proper json patch for the webhook to return.
I first tried my patches using kubectl:
$ kubectl patch ingress mying --type='json' -p='[{"op": "add", "path": "/metadata/annotations/key", "value":"value"}]'
The "" is invalid
Looks like this is not working when there is not already an annotations element present.
$ kubectl patch ingress mying --type='json' -p='[{"op": "add", "path": "/metadata/annotations", "value":{"key":"value"}}]'
ingress.extensions/kafka-monitoring-topics-ui patched
Creating the complete annotations element works fine, however in my case I need a key of kubernetes.io/ingress.class
which contains a slash.
kubectl patch ingress mying --type='json' -p='[{"op": "add", "path": "/metadata/annotations", "value":{"kubernetes.io/ingress.class":"value"}}]'
ingress.extensions/kafka-monitoring-topics-ui patched
This works fine when creating the annotation object. However, if there is already a some annotation present and I simply want to add one, it seems to be impossible to add one.
Simply using [{"op": "add", "path": "/metadata/annotations", "value":{"kubernetes.io/ingress.class":"value"}}]
removes all existing annotation, while something like '[{"op": "add", "path": "/metadata/annotations/kubernetes.io/ingress.class", "value": "value"}]
does not work because of the contained slash.
Long story short: What is the correct way to simply add a ingress class using a proper patch?
PS: Yes, I am aware of kubectl annotate
, but unfortunately that does not help with my webhook.
Using just:
[{"op": "add", "path": "/metadata/annotations/kubernetes.io~1ingress.class", "value":"nginx"}]
does not work when the created pod has no annotations, for example when coming from kubectl run --generator=run-pod/v1 --attach test-deploy --image=busybox ls
To detect this you need a separate parsing step into a metadata with pointer annotation so it can be detected as nil, or always send an empty annotation when it's empty:
type Metadata struct {
Annotations *map[string]string
}
type ObjectWithMeta struct {
Metadata Metadata
}
then send:
[
{"op":"add","path":"/metadata/annotations","value":{}},
{"op":"add","path":"/metadata/annotations/foo","value": "bar"}
]
Replace the forward slash (/
) in kubernetes.io/ingress.class
with ~1
.
Your command should look like this,
$ kubectl patch ingress mying --type='json' -p='[{"op": "add", "path": "/metadata/annotations/kubernetes.io~1ingress.class", "value":"nginx"}]'
Reference: RFC 6901 https://tools.ietf.org/html/rfc6901#section-3
much easier for me was to annotate
rather than patch
:
kubectl annotate ingress mying kubernetes.io/ingress.class=value
add --dry-run -o yaml
flags if you want to test it before applying the change.