validate: Recognize Kubernetes built-in resources#197
Conversation
📝 WalkthroughWalkthroughBuilt-in Kubernetes resources are now recognized through registered Kubernetes schemes and strictly validated without CRD schemas. Tests cover valid built-in resources and invalid fields or types. ChangesBuilt-in resource validation
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
|
||
| sv, ok := schemaValidators[gvk] | ||
| if !ok { | ||
| if kubescheme.Scheme.Recognizes(gvk) { |
There was a problem hiding this comment.
Thanks for picking this up, and for the tests + validation notes in the description, much appreciated.
I think the direction needs a rethink before this lands, though. Scheme.Recognizes(gvk) is a lookup in the type registry (GVK → reflect.Type), it never touches the object. So after this change the following validates as Valid ?:
apiVersion: v1
kind: Secret
metadata:
name: foo
spec:
totally: bogus
replicas: "three"That's a behaviour change beyond silencing the message. MissingSchema is its own bucket in computeSummary and only fails the run behind --error-on-missing-schemas (see ResultError). Marking built-ins Valid means users who explicitly opted into "everything I rendered was schema-checked" silently lose that guarantee, and don't get the [!] line either. We'd be trading a noisy true statement for a quiet false one.
A few specific points:
1. Status semantics. If we keep the recognize-only approach, it needs its own status (ValidationStatusSkipped / ValidationStatusUnvalidated) that does not roll into Valid. Reading #195 again, the complaint is really that [!] could not find CRD/XRD for: v1, Kind=Secret is alarming for something that can never have a CRD. That's fixable with wording and severity alone.
2. Scheme coverage is inconsistent. k8s.io/client-go/kubernetes/scheme is pinned to whatever client-go the CLI vendors, and it doesn't include apiextensions.k8s.io/v1 CustomResourceDefinition or apiregistration.k8s.io/v1 APIService, those live in other schemes. So a composed Secret would report valid while a composed CustomResourceDefinition still reports missingSchema. Composing CRDs via provider-kubernetes is common enough that this asymmetry will generate follow-up issues.
3. There's a cheap path to actual validation. Once Recognizes returns true, the typed Go struct is available. Strict-decoding into it catches unknown fields and type mismatches, most of what people want from validate, with no OpenAPI plumbing, no cluster access, and no new dependency:
if obj, err := kubescheme.Scheme.New(gvk); err == nil {
// marshal in.Object, strict-decode into obj via
// json.NewSerializerWithOptions(..., json.SerializerOptions{Strict: true})
// strict errors → unknown/mistyped fields
}It won't cover required fields, CEL, or value constraints, but that's a limitation we can name honestly in the status and docs, rather than reporting Valid.
There was a problem hiding this comment.
Thank you — agreed on the status semantics and validation gap. I addressed this in b4e956e by replacing the recognition-only shortcut with strict typed decoding. The composed scheme now includes client-go built-ins, apiextensions/v1, and apiregistration/v1, so Secret, Deployment, CustomResourceDefinition, and APIService follow the same path. Unknown fields and basic type mismatches now produce schema errors and an invalid result; unregistered custom GVKs remain missingSchema. The tests cover all four valid scheme families plus an unknown Secret field and a mistyped Deployment replica count. The implementation also documents that strict decoding does not provide admission or semantic validation. I added the matching kube-aggregator dependency for APIService coverage and regenerated the Nix module metadata.
Signed-off-by: ihopenre-eng <247072151+ihopenre-eng@users.noreply.github.com>
Signed-off-by: ihopenre-eng <247072151+ihopenre-eng@users.noreply.github.com>
b1a3de7 to
b4e956e
Compare
Description of your changes
crossplane resource validatepreviously handled a missing custom schema by checking whether the client-go scheme recognized the GVK, then marking every recognized resource as valid without decoding it. That weakened--error-on-missing-schemasand allowed unknown fields or basic type mismatches to pass silently.This update builds a typed validation scheme from:
apiextensions.k8s.io/v1forCustomResourceDefinitionapiregistration.k8s.io/v1forAPIServiceWhen no custom schema exists, the validator now instantiates the registered type and strictly decodes the resource into it. Unknown fields and values that cannot populate typed fields produce schema errors and an
invalidresult. GVKs absent from the composed scheme continue to reportmissingSchema.Strict decoding intentionally does not attempt API-server admission or semantic validation.
Regression coverage includes valid
Secret,Deployment,CustomResourceDefinition, andAPIServiceresources, plus an unknown Secret field and a mistyped Deployment replica count.Fixes #195
Validation
go test ./pkg/validate -count=1go vet ./pkg/validategolangci-lint v2.11.4 run --new-from-rev=origin/main ./pkg/validate/...(0 issues)go mod tidygomod2nix generate --with-depswithGOOS=linux GOARCH=amd64git diff --checkCGO_ENABLED=0 go test ./...reached and passed the changed packages; the Windows run still reports unrelated path-separator and CRLF fixture failures in Linux-oriented tests outside this changeI have:
Run./nix.sh flake checkto ensure this PR is ready for review.Linked a PR or a docs tracking issue to document this change.Addedbackport release-x.ylabels to auto-backport this PR.