Overview
werf has two kinds of patches, each for a different problem:
- Render patches change what is deployed, similar to Helm’s
--post-renderer. Use them to set fields a chart doesn’t expose in its values, without forking it. - Diff patches change only what werf compares with the cluster when deciding whether to update a resource. Use them to stop a resource from being updated because of fields that change on every render or are modified in the cluster.
To add patches, create patches.yaml in the root of the chart or pass a file with --patches; a patch itself is a jq program.
Changing resources without editing the chart (werf only)
To change a rendered resource without editing its template — for example, one of a dependent chart whose values don’t expose the field — add a render patch to patches.yaml in the root of the chart.
Example:
# .helm/patches.yaml:
renderPatches:
- match:
kinds: [Deployment, StatefulSet]
charts: [redis]
patch: .spec.template.spec.priorityClassName = $Values.redisPriorityClass
werf render --set redisPriorityClass=high-priority
Output:
# Source: myapp/charts/redis/templates/statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
# ...
spec:
template:
spec:
priorityClassName: high-priority
Here, every Deployment and StatefulSet of the redis chart gets the priority class from the redisPriorityClass value of the main chart: $Values holds the values of the chart that ships patches.yaml, not of redis.
Ignoring field changes that don’t need a deploy (werf only)
To stop a resource from being updated only because a field differs on every render (timestamps, random values) or is changed in the cluster by a controller, add a diff patch that removes the field.
Example:
# .helm/patches.yaml:
diffPatches:
- match:
kinds: [Deployment]
patch: del(.spec.template.metadata.annotations."example.com/deployed-at")
Here, a change of the example.com/deployed-at annotation alone no longer updates the Deployment and restarts its Pods. If other fields change too, the Deployment is updated, and the new annotation reaches the cluster along with them.
Patch sources
By default, werf takes patches from patches.yaml of every chart. To apply patches in one environment only, or to patch a chart you don’t own, pass a file of the same format with --patches (or WERF_PATCHES_*):
werf converge --patches .helm/patches-production.yaml
Patches are applied in order, each to the result of the previous one:
patches.yamlof dependent charts;patches.yamlof the main chart;--patchesfiles.
The sources differ in:
- What they apply to:
patches.yaml— only resources of its chart, including its dependent charts;--patches— all resources of the release. - Whose data they see (render patches only):
patches.yaml—$Values,$Release,$Chartand$Capabilitiesof its chart;--patches— of the main chart.
To ignore patches.yaml of all charts, pass --no-default-patches; it doesn’t affect --patches files.
werf rollback and werf dismiss apply only diff patches, and take patches.yaml from the chart stored in the release.
patches.yaml format
renderPatches:
- match:
names: [<name or /regexp/>, ...]
namespaces: [<namespace or /regexp/>, ...]
groups: [<group or /regexp/>, ...]
versions: [<version or /regexp/>, ...]
kinds: [<kind or /regexp/>, ...]
charts: [<chart name, alias, path or /regexp/>, ...]
labels: {<key>: <value>, ...}
annotations: {<key>: <value>, ...}
patch: <jq program>
diffPatches:
- <same as renderPatches>
A patch applies to every resource that matches all specified match fields:
- a value in
/.../is a regular expression that must match the whole value; other values are compared literally, case-insensitively forkinds,groupsandversions; labelsandannotationsmatch if the resource has all of them with the same values;chartsmatches the alias of the chart the resource is rendered from, or its name when no alias is set, or its path from the main chart, e.g.myapp/charts/redis.
A patch receives the whole resource and must return exactly one object, so it can’t add or remove resources.
Example:
# .helm/patches.yaml:
renderPatches:
- match:
kinds: [Deployment]
names: [/backend-.*/]
labels:
app: backend
patch: .metadata.labels.team = $Values.team
Here, only Deployments whose name starts with backend- and which carry the app: backend label get the team label.