Create a patch to add a kubernetes annotation

4/8/2019

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.

-- michas
go
kubernetes
patch
webhooks

3 Answers

4/30/2020

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"}
]
-- grosser
Source: StackOverflow

4/8/2019

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

-- abvarun226
Source: StackOverflow

2/25/2020

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.

-- Efrat Levitan
Source: StackOverflow