Skip to content

Repository files navigation

k8s-overlay-patch

Kubernetes overlay patches

Disclaimer

This codebase was mostly plucked from https://github.com/istio/istio

Purpose

Users often need to customize the resources generated from a kubernetes operator/Custom Resource. Though, for every new configuration option that needs to be added, new fields need to be added to the Custom Resource. This is time-consuming and can lead to a bloated Custom Resource.

This library implements logic so that these overlays are a first-class citizen in a CRD. This allows users to customize the output of a kubernetes operator by overlaying patches on top of the generated output, without having to modify the CRD.

Command-line usage

Usage:
k8s-overlay-patch [flags]
Flags:
-h, --help help for k8s-overlay-patch
-m, --manifest-file string File containing the rendered manifests to patch
-n, --namespace string Namespace to use when patching the manifests
-o, --out string File to write the patched manifests to
-p, --patch-file string File containing the patch to apply

Usage as helm post-renderer

Example

helm template test pkg/testdata/chart --debug --dry-run --post-renderer pkg/testdata/postrender.sh
# build the binary and place it in your path
go build
# Create a postrender.sh file. Helm doesn't allow passing
# arguments to postrenderers.
#!/bin/bash
k8s-overlay-patch -n default -p patch.yaml
# Make the file executable
chmod +x postrender.sh
# Call helm with the postrender.sh file
helm template [NAME] [CHART] --post-renderer postrender.sh

Example usage with CRD

Adding the overlay patch to the CRD

package v1alpha1
typeMySpecstruct {
// Overlays is the list of overlay patches to apply to resource.//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Patches",order=4Overlays []K8sObjectOverlay`json:"overlays,omitempty"`
}
typeK8sObjectOverlaystruct {
// Resource API version.//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="API Version",order=1ApiVersionstring`json:"apiVersion,omitempty"`// Resource kind.//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Kind",order=2Kindstring`json:"kind,omitempty"`// Name of resource.//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Name",order=3Namestring`json:"name,omitempty"`// List of patches to apply to resource.//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Patches",order=4Patches []*K8sObjectOverlayPatch`json:"patches,omitempty"`
}
typeK8sObjectOverlayPatchstruct {
// Path of the form a.[key1:value1].b.[:value2]// Where [key1:value1] is a selector for a key-value pair to identify a list element and [:value] is a value// selector to identify a list element in a leaf list.// All path intermediate nodes must exist.//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Path",order=1Pathstring`json:"path,omitempty"`// Value to add, delete or replace.// For add, the path should be a new leaf.// For delete, value should be unset.// For replace, path should reference an existing node.// All values are strings but are converted into appropriate type based on schema.//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Value",order=2Valuestring`json:"value,omitempty"`// Verbatim value to add, delete or replace.// Same as Value, however the content is not interpreted as YAML, but treated as literal string instead.// At least one of Value and Verbatim must be empty.//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Verbatim",order=3Verbatimstring`json:"verbatim,omitempty"`
}

Using the overlay patch in the reconciler

package reconciler
import (
"github.com/stackrox/k8s-overlay-patch/pkg/patch""github.com/stackrox/k8s-overlay-patch/pkg/types"
)
func (rreconciler) Reconcile(obj v1alpha1.MyObject){
manifests:=renderManifests(obj)
patched:=patch.YAMLManifestPatch(manifests, obj.Namespace, mapOverlays(obj.Spec.Overlays))
// ...
}
funcmapOverlays(overlays []*v1alpha1.K8sObjectOverlay) []*types.K8sObjectOverlay {
out:=make([]*types.K8sObjectOverlay, len(overlays))
fori, o:=rangeoverlays {
out[i] =&types.K8sObjectOverlay{
ApiVersion: o.ApiVersion,
Kind: o.Kind,
Name: o.Name,
Patches: mapOverlayPatches(o.Patches),
}
}
returnout
}
funcmapOverlayPatches(patches []*v1alpha1.K8sObjectOverlayPatch) []*types.K8sObjectOverlayPatch {
out:=make([]*types.K8sObjectOverlayPatch, len(patches))
fori, p:=rangepatches {
out[i] =&types.K8sObjectOverlayPatch{
Path: p.Path,
Value: p.Value,
Verbatim: p.Verbatim,
}
}
returnout
}

Example CRD

apiVersion: blah.com/v1alpha1kind: MyObjectmetadata:
name: my-objectspec:
resources:
requests:
cpu: 100mmemory: 128Milimits:
cpu: 200mmemory: 256Mi overlays:
- apiVersion: v1kind: ConfigMapname: my-config-mappatches:
- path: data.foovalue: bar
- path: data.bazverbatim: | qux separate lines

About

Kubernetes overlay patches

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages