eb8160e659
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>
48 lines
3.5 KiB
YAML
48 lines
3.5 KiB
YAML
apiVersion: runwhen.com/v1
|
|
kind: Runbook
|
|
metadata:
|
|
name: {{slx_name}}
|
|
labels:
|
|
{% include "common-labels.yaml" %}
|
|
annotations:
|
|
{% include "common-annotations.yaml" %}
|
|
spec:
|
|
location: {{default_location}}
|
|
# See the SLI template for the rationale on hardcoding the generic
|
|
# codecollection URL here.
|
|
codeBundle:
|
|
repoUrl: http://rw-airgap-cc-catalog-svc.runwhen-env-airgap:8080/git/rw-generic-codecollection.git
|
|
ref: main
|
|
pathToRobot: codebundles/k8s-kubectl-cmd/runbook.robot
|
|
configProvided:
|
|
- name: TASK_TITLE
|
|
value: 'Inspect Crossplane GCP Bucket {{match_resource.resource.metadata.name}} conditions'
|
|
- name: TIMEOUT_SECONDS
|
|
value: '300'
|
|
# Enable JSON-issue mode in the generic runbook: it will parse the
|
|
# stdout JSON, check the trigger key, and emit one RunWhen issue per
|
|
# element in the issues array.
|
|
- name: ISSUE_JSON_QUERY_ENABLED
|
|
value: 'true'
|
|
- name: ISSUE_JSON_TRIGGER_KEY
|
|
value: issuesIdentified
|
|
- name: ISSUE_JSON_TRIGGER_VALUE
|
|
value: 'true'
|
|
- name: ISSUE_JSON_ISSUES_KEY
|
|
value: issues
|
|
# The `jq` expression below emits the JSON envelope that the generic
|
|
# runbook expects:
|
|
# { issuesIdentified: <bool>, issues: [ {title,severity,...}, ... ] }
|
|
# One issue per condition whose status is not "True". Severity 2 for
|
|
# Ready failures (data-plane visible), 3 for others (e.g. Synced).
|
|
- name: KUBECTL_COMMAND
|
|
value: |
|
|
kubectl get buckets.storage.gcp.upbound.io {{match_resource.resource.metadata.name}} -o json | jq -c '(.status.conditions // []) as $c | { issuesIdentified: (($c|length)==0 or ([$c[]|select(.status!="True")]|length > 0)), issues: ( if ($c|length)==0 then [ { title: "Crossplane Bucket {{match_resource.resource.metadata.name}} has no status conditions yet", severity: 3, expected: "Bucket should have Ready and Synced conditions populated by the Crossplane provider", actual: "status.conditions is empty or missing", reproduce_hint: "kubectl get buckets.storage.gcp.upbound.io {{match_resource.resource.metadata.name}} -o yaml", next_steps: "1. Check that the crossplane-system provider pod for provider-gcp-storage is Running.\n2. kubectl describe buckets.storage.gcp.upbound.io {{match_resource.resource.metadata.name}} to see reconciliation events.\n3. Verify the referenced ProviderConfig exists and is Healthy.\n4. Wait one reconcile interval and re-check.", details: (.status | tostring) } ] else [ $c[] | select(.status!="True") | { title: ("Crossplane Bucket " + .type + " condition is not True: {{match_resource.resource.metadata.name}}"), severity: (if .type=="Ready" then 2 else 3 end), expected: (.type + " condition should be True"), actual: (.type + "=" + .status + " reason=" + (.reason // "n/a") + " message=" + (.message // "n/a")), reproduce_hint: "kubectl get buckets.storage.gcp.upbound.io {{match_resource.resource.metadata.name}} -o yaml", next_steps: "1. kubectl describe buckets.storage.gcp.upbound.io {{match_resource.resource.metadata.name}}\n2. Inspect the crossplane-system provider-gcp-storage pod logs for reconcile errors.\n3. Verify the ProviderConfig references a Secret with valid GCP credentials.\n4. Check GCP IAM permissions on the target bucket / project.\n5. Look for spec drift and wait for the next reconcile.", details: (. | tostring) } ] end ) }'
|
|
secretsProvided:
|
|
{% if wb_version %}
|
|
{% include "kubernetes-auth.yaml" ignore missing %}
|
|
{% else %}
|
|
- name: kubeconfig
|
|
workspaceKey: {{custom.kubeconfig_secret_name}}
|
|
{% endif %}
|