Kubernetes: patch every array element using kubectl and jq

Below is an example using ‘kubectl patch’ to update the securityContext of a single, specific container named ‘my-init-container1’ of the ‘initContainers’ list.

kubectl patch deployment my-deployment -n default --patch='{ "spec": { "template": { "spec": { "initContainers": [ { "name": "my-init-container1", "securityContext": { "runAsUser": 999 } } ] } } } }'

But ‘initContainers’ is an array of containers, and the syntax above will not allow you to generically update every container in the array (only single elements).

However, you can use the jq utility to modify the json representation of the object, then reapply it to achieve these results.  Below is an example of updating every array element in ‘initContainers’ of a deployment with a securityContext.

# install 'jq' utility
sudo apt install -y jq

# update all initContainers
kubectl get deployment my-deployment -n default -o json | jq '.spec.template.spec.initContainers[] += {"securityContext":{"runAsUser":999}}' | kubectl apply -f -

One of the benefits of this method is you can view the final representation that will be submitted to Kubernetes by simply leaving off the ‘kubectl apply’.

 

REFERENCES

kubectl apply – command reference

stackoverflow, using jq to manipulate json then reapply

github jq

NOTES

send json output to yq for pretty print

yq -o yaml -PM

using jq to prefix a string to all array items not matching

# add 'preprod-' prefix to any virtual service hosts that do not already have it
kubectl get virtualservices my-virtual-service -n default -o json | jq '.spec.hosts[] |= if (. | contains("preprod-")) then (.) else ("preprod"+.) end' | kubectl apply -f -

# remove 'preprod-' prefix from any virtual service hosts that have prefix
kubectl get virtualservices my-virtual-service -n default -o json | jq '.spec.hosts[] |= if (. | contains("preprod-")) then (.[8:]) else (.) end' | kubectl apply -f -

installing yq

# get latest release version
latest_yq_linux=$(curl -sL https://api.github.com/repos/mikefarah/yq/releases/latest | jq -r ".assets[].browser_download_url" | grep linux_amd64.tar.gz)

# download, extract, and put binary into PATH
wget $latest_yq_linux
tar xvfz yq_linux_amd64.tar.gz
sudo cp yq_linux_amd64 /usr/local/bin/yq