Initial scaffold: generation-rule-only Crossplane Bucket example
Educational RunWhen CodeCollection that discovers Crossplane GCP Bucket CRDs (storage.gcp.upbound.io/v1beta1) and generates one SLX per bucket. Ships only generation rules and Jinja templates; the runtime lives in rw-generic-codecollection/k8s-kubectl-cmd (already loaded by the airgap runner). Includes: - codebundles/gcp-bucket-crossplane-health with generation rule + 3 templates - docs/01..07 numbered training chapters with screenshot placeholders - README, .gitignore Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
# gcp-bucket-crossplane-health
|
||||
|
||||
A **generation-rule-only** codebundle. It has no `sli.robot`, no
|
||||
`runbook.robot`, and no `meta.yaml`. It ships:
|
||||
|
||||
| File | Role |
|
||||
| --- | --- |
|
||||
| [`.runwhen/generation-rules/gcp-bucket-crossplane-health.yaml`](.runwhen/generation-rules/gcp-bucket-crossplane-health.yaml) | Tells workspace-builder to discover every Crossplane `Bucket` (`storage.gcp.upbound.io/v1beta1`) in the cluster and generate one SLX per bucket. |
|
||||
| [`.runwhen/templates/gcp-bucket-crossplane-health-slx.yaml`](.runwhen/templates/gcp-bucket-crossplane-health-slx.yaml) | Jinja template for the `ServiceLevelX` resource. |
|
||||
| [`.runwhen/templates/gcp-bucket-crossplane-health-sli.yaml`](.runwhen/templates/gcp-bucket-crossplane-health-sli.yaml) | Jinja template for the `ServiceLevelIndicator`. Points at `rw-generic-codecollection/k8s-kubectl-cmd/sli.robot`. |
|
||||
| [`.runwhen/templates/gcp-bucket-crossplane-health-taskset.yaml`](.runwhen/templates/gcp-bucket-crossplane-health-taskset.yaml) | Jinja template for the `Runbook` (TaskSet). Points at `rw-generic-codecollection/k8s-kubectl-cmd/runbook.robot` in JSON-issue mode. |
|
||||
|
||||
## How it works
|
||||
|
||||
1. `workspace-builder` loads this codecollection and reads the generation rule.
|
||||
2. The rule declares `resourceTypes: [buckets.storage.gcp.upbound.io/v1beta1]`.
|
||||
RunWhen Local's Kubernetes indexer expands that spec into
|
||||
`plural=buckets, group=storage.gcp.upbound.io, version=v1beta1`, calls
|
||||
`list_cluster_custom_object`, and stores each Bucket in the registry.
|
||||
3. The `matchRules` predicate matches every Bucket by name (regex `.+`).
|
||||
4. For each match, the rule emits an SLX with three output items (`slx`,
|
||||
`sli`, `runbook`). Each output item is rendered from the corresponding
|
||||
Jinja template.
|
||||
5. The SLI and Runbook templates set `codeBundle.repoUrl` to the internal
|
||||
airgap URL for `rw-generic-codecollection`, and `pathToRobot` to
|
||||
`k8s-kubectl-cmd/{sli,runbook}.robot`. That's where the actual runtime
|
||||
lives — this codecollection ships only the discovery and templating
|
||||
logic.
|
||||
|
||||
## Health scoring
|
||||
|
||||
- **SLI** — the `KUBECTL_COMMAND` runs `kubectl get bucket ... -o json`, pipes
|
||||
through `jq` to compute the fraction of `.status.conditions[]` whose
|
||||
`status == "True"`, and pushes that number (0.0 to 1.0) as the metric.
|
||||
A healthy Crossplane Bucket has `Ready=True` **and** `Synced=True`,
|
||||
producing an SLI of `1.0`.
|
||||
- **TaskSet** — the same generic bundle in JSON-issue mode. The `jq`
|
||||
expression emits `{ issuesIdentified: true|false, issues: [...] }`.
|
||||
Each condition whose status is not `True` becomes one issue with a
|
||||
severity (higher for `Ready`), a `reproduce_hint`, and human-readable
|
||||
`next_steps`.
|
||||
|
||||
## Why this pattern is useful
|
||||
|
||||
- **Reuse over rewrite**: no need to fork or maintain another robot file.
|
||||
- **Small blast radius**: a private repo like this one holds just the
|
||||
organization-specific discovery logic and messaging.
|
||||
- **Fast iteration**: change the `jq` filter and the workspace-builder
|
||||
picks it up on the next reconcile — no runner image rebuild required.
|
||||
Reference in New Issue
Block a user