I created a custom resource definition (CRD) and its controller in my cluster, now I can create custom resources, but how do I validate update requests to the CR? e.g., only certain fields can be updated.
The Kubernetes docs on Custom Resources has a section on Advanced features and flexibility (never mind that validating requests should be considered a pretty basic feature ). For validation of CRDs, it says:
Most validation can be specified in the CRD using OpenAPI v3.0 validation. Any other validations supported by addition of a Validating Webhook.
The OpenAPI v3.0 validation won't help you accomplish what you're looking for, namely ensuring immutability of certain fields on your custom resource, it's only helpful for stateless validations where you're looking at one instance of an object and determining if it's valid or not, you can't compare it to a previous version of the resource and validate that nothing has changed.
You could use Validating Webhooks. It feels like a heavyweight solution, as you will need to implement a server that conforms to the Validating Webhook contract (responding to specific kinds of requests with specific kinds of responses), but you will have the required data at least to make the desired determination, e.g. knowing that it's an UPDATE request and knowing what the old object looked like. For more details, see here. I have not actually tried Validating Webhooks, but it feels like it could work.
An alternative approach I've used is to store the user-provided data within the Status
subresource of the custom resource the first time it's created, and then always look at the data there. Any changes to the Spec
are ignored, though your controller can notice discrepancies between what's in the Spec
and what's in the Status
, and embed a warning in the Status
telling the user that they've mutated the object in an invalid way and their specified values are being ignored. You can see an example of that approach here and here. As per the relevant README section of that linked repo, this results in the following behaviour:
The
AVAILABLE
column will show false if the UAA client for the team has not been successfully created. TheWARNING
column will display a warning if you have mutated the Team spec after initial creation. TheDIRECTOR
column displays the originally provided value forspec.director
and this is the value that this team will continue to use. If you do attempt to mutate theTeam
resource, you can see your (ignored) user-provided value with the-o wide
flag:$ kubectl get team --all-namespaces -owide NAMESPACE NAME DIRECTOR AVAILABLE WARNING USER-PROVIDED DIRECTOR test test vbox-admin true vbox-admin
If we attempt to mutate the
spec.director
property, here's what we will see:
$ kubectl get team --all-namespaces -owide NAMESPACE NAME DIRECTOR AVAILABLE WARNING USER-PROVIDED DIRECTOR test test vbox-admin true API resource has been mutated; all changes ignored bad-new-director-name