Modified the generation rules for Crossplane GCP Buckets to omit the version in resource type definitions, allowing the use of the API server's preferred version (currently v1beta2). Updated documentation to reflect this change and clarify version pinning for schema stability. Changes include: - Updated YAML generation rules to remove explicit versioning. - Revised documentation to explain the implications of omitting versioning and the preferred version usage. This enhances resilience across CRD upgrades and simplifies the configuration for users.
5.3 KiB
04 — Generation rule walkthrough
What you'll do
Read the generation rule at codebundles/gcp-bucket-crossplane-health/.runwhen/generation-rules/gcp-bucket-crossplane-health.yaml
line by line and understand each block.
The full file
apiVersion: runwhen.com/v1
kind: GenerationRules
spec:
platform: kubernetes
generationRules:
- resourceTypes:
- buckets.storage.gcp.upbound.io
matchRules:
- type: pattern
pattern: ".+"
properties: [name]
mode: substring
slxs:
- baseName: xp-bkt-hlth
qualifiers: ["resource", "cluster"]
baseTemplateName: gcp-bucket-crossplane-health
levelOfDetail: detailed
outputItems:
- type: slx
- type: sli
- type: runbook
templateName: gcp-bucket-crossplane-health-taskset.yaml
Block-by-block
Envelope
apiVersion: runwhen.com/v1
kind: GenerationRules # note the plural — the loader rejects "GenerationRule"
spec:
platform: kubernetes # per-file default; can be overridden per rule
generationRules: [ ... ] # one or more rules
kindmust be exactlyGenerationRules. RunWhen Local's loader compares this to a schema constant.spec.platformsets the default platform for every rule in the file.spec.generationRulesis a list — you can define many rules per file.
resourceTypes
resourceTypes:
- buckets.storage.gcp.upbound.io
Omitting /v1beta2 (or /v1beta1) tells the indexer to use the API
server's preferred version, which survives CRD schema upgrades. Pin the
version only when you rely on a specific schema shape.
This is the selective discovery signal. Because this string appears in a loaded rule, the Kubernetes indexer knows to enumerate that CRD. Without any rule mentioning a CRD, it would not be listed.
You can list multiple types in one rule if you want the same SLX shape for each. Splitting into separate rules is usually cleaner though.
matchRules
matchRules:
- type: pattern
pattern: ".+"
properties: [name]
mode: substring
Match predicates are ANDed together. The pattern predicate here says
"the resource's name property must match the regex .+ (i.e. non-empty)
as a substring". Since every Bucket has a name, every Bucket matches.
You can filter more aggressively if you want. Examples:
# Only buckets whose name starts with "prod-"
- type: pattern
pattern: "^prod-"
properties: [name]
mode: substring
# Only buckets that carry the label env=production
- type: exists
path: "resource/metadata/labels/env"
# Combine — buckets in the prod GCP project label AND with a Ready condition entry
- type: and
matches:
- type: pattern
pattern: "^runwhen-prod-.*"
properties: [name]
mode: substring
- type: exists
path: "resource/status/conditions"
slxs
slxs:
- baseName: xp-bkt-hlth
qualifiers: ["resource", "cluster"]
baseTemplateName: gcp-bucket-crossplane-health
levelOfDetail: detailed
outputItems:
- type: slx
- type: sli
- type: runbook
templateName: gcp-bucket-crossplane-health-taskset.yaml
baseName— short identifier appended to the qualifier prefix to form the finalslx_name. Keep it under 15 characters (xp-bkt-hlthis 11).qualifiers— determines both the generated SLX name and how many SLXs are produced.- Including
resourcemeans "one SLX per matching Bucket". - Including
clusterprefixes the name with the cluster name so it is stable across multi-cluster workspaces. - Not including
namespace— Crossplane managed resources are cluster-scoped; they have no namespace.
- Including
baseTemplateName— the file-name stem for the templates. The output items resolve to<baseTemplateName>-<type>.yamlunless overridden. Sotype: slxlooks upgcp-bucket-crossplane-health-slx.yaml,type: sli→-sli.yaml, etc.levelOfDetail— one ofnone | basic | detailed(or0|1|2). This gates whether the SLX is emitted based on the platform's LOD filter. Since our airgapdefaultLODisdetailed, we set the SLX todetailedso it always renders.outputItems— one entry per artifact we want.type: runbookspecifies an explicittemplateNamebecause we want to point at a file named-taskset.yaml, not-runbook.yaml, purely for convention matching what other RunWhen bundles do.
What resource identity ends up in the SLX
Given a Bucket named runwhen-nonprod-shared-litellm-logging on cluster
shared-cluster, the rule will produce an SLX whose name is roughly:
shared-cluster-runwhen-nonprod-shared-litellm-logging-xp-bkt-hlth
RunWhen Local will also shorten and hash-suffix pieces as needed for
length. The exact rendering happens in
generation_rules.py::make_slx_name.
Screenshot placeholders
images/04-generation-rule-annotated.png— the YAML above with arrows pointing to the resource type, match rule, and output items.
Next
Continue to 05 — SLX and templates.