Recently, I stumbled on a situation where I wanted to add a couple of values to an OpenShift deployment configuration. Previously I had modified or added a single attribute in a yaml file with oc patch
. So I started to wonder whether it is possible to update multiple attributes with oc patch
as well. To get right to the result: Yes, it is possible. This article will show you which features oc patch
and likewise kubectl patch
really have, beside a simple modification of one attribute.
The following deployment configuration will be used throughout the article as an example. The other example deployment configurations shown below are only abstracts and contain only the important bits to show the effect of the oc patch
command.
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
name: deployment-example
spec:
replicas: 1
selector:
app: deployment-example
strategy:
type: Rolling
template:
metadata:
labels:
app: deployment-example
spec:
containers:
- image: openshift/deployment-example
name: deployment-example
ports:
- containerPort: 8080
protocol: TCP
Let’s start with a simple example to add a label version
to the template section:
oc patch dc deployment-example -p '{"spec":{"template":{"metadata":{"labels":{"version":"v1"}}}}}'
The result will look like this:
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
name: deployment-example
spec:
replicas: 1
selector:
app: deployment-example
strategy:
type: Rolling
template:
metadata:
labels:
app: deployment-example
version: v1
spec:
containers:
- image: openshift/deployment-example
name: deployment-example
ports:
- containerPort: 8080
protocol: TCP
To change the value from v1
to version1
, execute the following command:
oc patch dc deployment-example -p '{"spec":{"template":{"metadata":{"labels":{"version":"version1"}}}}}'
And voilà the result looks like this:
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
name: deployment-example
spec:
replicas: 1
selector:
app: deployment-example
strategy:
type: Rolling
template:
metadata:
labels:
app: deployment-example
version: version1
spec:
containers:
- image: openshift/deployment-example
name: deployment-example
ports:
- containerPort: 8080
protocol: TCP
Easy, isn’t it? But let’s get rid of the label. You can do this with the following command:
oc patch dc deployment-example --type json -p '[{ "op": "remove", "path": "/spec/template/metadata/labels/version" }]'
In the next step, add multiple values to different places of yaml file. So let’s add a label to the deployment configuration itself and one label to the template.
oc patch dc deployment-example -p '{"metadata":{"labels":{"version":"version1"}},"spec":{"template":{"metadata":{"labels":{"version":"version1"}}}}}'
The result is like expected:
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
name: deployment-example
labels:
version: version1
spec:
replicas: 1
selector:
app: deployment-example
strategy:
type: Rolling
template:
metadata:
labels:
app: deployment-example
version: version1
spec:
containers:
- image: openshift/deployment-example
name: deployment-example
ports:
- containerPort: 8080
protocol: TCP
So far we were using the default merge type strategic
. Lets repeat the example above with the merge type JSON Patch:
oc patch dc deployment-example --type='json' -p='[{"op": "add", "path": "/metadata/labels/version", "value": "version1" },{"op": "add", "path": "/spec/template/metadata/labels/version", "value": "version1" }]'
Let’s have a closer look what can be achieved by using JSON Patch. Another option would be to use copy
to copy the first attribute instead of just adding it again with add
. The command looks like this now:
oc patch dc deployment-example --type='json' -p='[{"op": "add", "path": "/metadata/labels/version", "value": "version1" },{"op": "copy", "from":"/metadata/labels/version" , "path": "/spec/template/metadata/labels/version" }]'
To change the values we can use replace
. So let’s change the value of the labels version1
to version2
. This can be done with this command:
oc patch dc deployment-example --type='json' -p='[{"op": "replace", "path": "/metadata/labels/version", "value": "version2" },{"op": "replace", "path": "/spec/template/metadata/labels/version", "value": "version2" }]'
Let’s remove the new labels with this command:
oc patch dc deployment-example --type json -p '[{ "op": "remove", "path": "/spec/template/metadata/labels/version" },{ "op": "remove", "path": "/metadata/labels/version" }]'
You might have noticed that we used for the last command the parameter type
to the value json
to use JSON Patch. By default, the value of the parameter type
is strategic
. How resources are patched respectively merged for the type strategic
is defined in the source code. This can be different between a resource and its subresources. How the resources are patched respective merged can be found in the OpenShift and Kubernetes Swagger documentation in the attribute “x-kubernetes-patch-strategy” of the resource. The value merge
of the parameter type
indicated that JSON Merge patch is used. With this type, you need to provide a complete new resource that you want to modify, because the new resource will replace the existing resource.
A comprehensive description about the effect of the parameter patch can be found here: https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#alternate-forms-of-the-kubectl-patch-command
At this point, I hope you gained a good understanding about the capabilities of oc patch
. As you have seen in the last examples, it is very easy to add, change, copy and remove attributes. I haven’t described how to move attributes and verify that attributes exist with JSON Patch, however, it is still possible. I only can recommend to you at this point: Try it out for yourself and check where you can use it.