2

I want to add an initContainer to all of my pods (with a specific annotation) in my kustomize base. The newly added init container should be the first init container. My patch looks like this.

patches:
  - target:
      kind: Pod
      annotationSelector: "database_init=True"
    patch: |-
      - op: add
        path: /spec/initContainers/0
        value:
          name: database-init
          ...

This works fine for all pods that already have an init container. Unfortunately, I have pods without init containers and there the patch fails with the error add operation does not apply: doc is missing path: \"/spec/initContainers/0\". How do I write a patch that works for all my pods?

Complete example:

.
├── base
│   ├── kustomization.yaml
│   ├── pod-1.yaml
│   └── pod-2.yaml
└── overlay
    └── kustomization.yaml
# cat base/pod-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod-1
  annotations:
    database_init: True
spec:
  initContainers:
    - name: something
      image: alpine:latest
      command: ["sleep", "10" ]
  containers:
    - name: main
      image: alpine:latest
      command: [ "sleep", "60" ]
# cat base/pod-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod-2
  annotations:
    database_init: True
spec:
#   initContainers:
#     - name: something
#       image: alpine:latest
#       command: ["sleep", "10" ]
  containers:
    - name: main
      image: alpine:latest
      command: [ "sleep", "60" ]
# cat base/kustomization.yaml
resources:
  - pod-1.yaml
  - pod-2.yaml
# cat overlay/kustomization.yaml
resources:
  - ../base

patches:

  - target:
      kind: Pod
      annotationSelector: "database_init=True"
    patch: |-
      - op: add
        path: /spec/initContainers/0
        value:
          name: database-init
          image: alpine:latest
          command: [ "sleep", 10 ]

Result:

$ kubectl kustomize overlay
error: add operation does not apply: doc is missing path: "/spec/initContainers/0": missing value

After uncommenting the init container of pod-2, everything works.

Edit: Added the annotationSelector.

Edit: Added the complete example code.

briconaut
  • 322
  • 1
  • 3
  • 12

1 Answers1

3

JSONPatch patches in general are fundamentally unable to handle the "append to existing list or create new list" situation. See e.g. this question.

Fortunately, with Kustomize 5.0.1 it appears to be possible to achieve your goal using a strategic merge patch. Given your example configuration, if I place the following in overlay/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base/

patches:
  - target:
      kind: Pod
      annotationSelector: database_init=True
    patch: |-
      apiVersion: v1
      kind: Pod
      metadata:
        name: __ignored__
      spec:
        initContainers:
          - name: database-init
            image: alpine:latest
            command:
              - init
              - the
              - database

Then running kustomize build overlay produces the following output:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    database_init: "True"
  name: mypod-1
spec:
  containers:
  - command:
    - sleep
    - "60"
    image: alpine:latest
    name: main
  initContainers:
  - command:
    - init
    - the
    - database
    image: alpine:latest
    name: database-init
  - command:
    - sleep
    - "10"
    image: alpine:latest
    name: something
---
apiVersion: v1
kind: Pod
metadata:
  annotations:
    database_init: "True"
  name: mypod-2
spec:
  containers:
  - command:
    - sleep
    - "60"
    image: alpine:latest
    name: main
  initContainers:
  - command:
    - init
    - the
    - database
    image: alpine:latest
    name: database-init
larsks
  • 277,717
  • 41
  • 399
  • 399
  • Maaaaany thanks! Works perfectly now. Nevertheless, it's surprising that such a simple thing cannot be done with the JSONpatches. – briconaut Apr 13 '23 at 16:02