Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
apiVersion: runwhen.com/v1
kind: GenerationRules
spec:
generationRules:
# One SLX per namespace that has at least one VAST-backed PVC.
- resourceTypes:
- persistentvolumeclaim
matchRules:
- type: pattern
pattern: ".+"
properties: [name]
mode: substring
- type: or
matches:
- type: pattern
pattern: "vast"
properties: [spec/storageClassName]
mode: substring
- type: pattern
pattern: "vast"
properties: [metadata/annotations]
mode: substring
slxs:
- baseName: vast-k8s-csi-health
shortenedBaseName: vast-csi-hlth
qualifiers: ["namespace", "cluster"]
baseTemplateName: vast-k8s-csi-health
levelOfDetail: basic
outputItems:
- type: slx
- type: sli
- type: runbook
templateName: vast-k8s-csi-health-taskset.yaml

# Optional cluster-level SLX for the CSI driver install namespace when
# operators want driver health monitoring before workload namespaces exist.
- resourceTypes:
- namespace
matchRules:
- type: pattern
pattern: "vast-csi"
properties: [name]
mode: substring
slxs:
- baseName: vast-csi-driver
shortenedBaseName: vast-csi-drv
qualifiers: ["namespace", "cluster"]
baseTemplateName: vast-k8s-csi-health
levelOfDetail: basic
outputItems:
- type: slx
- type: sli
- type: runbook
templateName: vast-k8s-csi-health-taskset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
apiVersion: runwhen.com/v1
kind: ServiceLevelIndicator
metadata:
name: {{slx_name}}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
displayUnitsLong: OK
displayUnitsShort: ok
locations:
- {{default_location}}
description: Measures VAST CSI health using CSI pod readiness, PVC binding, mount success, and NFS xprt congestion.
codeBundle:
{% if repo_url %}
repoUrl: {{repo_url}}
{% else %}
repoUrl: https://github.com/runwhen-contrib/rw-cli-codecollection.git
{% endif %}
{% if ref %}
ref: {{ref}}
{% else %}
ref: main
{% endif %}
pathToRobot: codebundles/vast-k8s-csi-health/sli.robot
intervalStrategy: intermezzo
intervalSeconds: 300
configProvided:
- name: CONTEXT
value: "{{context}}"
- name: NAMESPACE
value: "{{match_resource.resource.metadata.namespace | default(namespace.name)}}"
- name: CSI_NAMESPACE
value: "{{ custom.vast_csi_namespace | default('vast-csi') }}"
- name: KUBERNETES_DISTRIBUTION_BINARY
value: "{{ custom.kubernetes_distribution_binary | default('kubectl') }}"
- name: XPRT_PENDING_THRESHOLD
value: "{{ custom.xprt_pending_threshold | default('100') }}"
- name: RPC_ERROR_RATE_THRESHOLD
value: "{{ custom.rpc_error_rate_threshold | default('5') }}"
secretsProvided:
{% if wb_version %}
{% include "kubernetes-auth.yaml" ignore missing %}
{% else %}
- name: kubeconfig
workspaceKey: {{ custom.kubeconfig_secret_name | default("kubeconfig") }}
{% endif %}
alertConfig:
tasks:
persona: eager-edgar
sessionTTL: 10m
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apiVersion: runwhen.com/v1
kind: ServiceLevelX
metadata:
name: {{slx_name}}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
imageURL: https://storage.googleapis.com/runwhen-nonprod-shared-images/icons/kubernetes/resources/labeled/pvc.svg
alias: {{namespace.name}} VAST CSI Health
asMeasuredBy: Aggregate score from CSI pod readiness, PVC binding, mount health, and NFS xprt metrics.
configProvided:
- name: OBJECT_NAME
value: {{match_resource.resource.metadata.name}}
owners:
- {{workspace.owner_email}}
statement: VAST CSI-backed storage in this namespace should have healthy driver pods, bound PVCs, and successful workload mounts.
additionalContext:
{% include "kubernetes-hierarchy.yaml" ignore missing %}
qualified_name: "{{ match_resource.qualified_name }}"
tags:
{% include "kubernetes-tags.yaml" ignore missing %}
- name: access
value: read-only
- name: storage
value: vast-csi
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
apiVersion: runwhen.com/v1
kind: Runbook
metadata:
name: {{slx_name}}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
location: {{default_location}}
description: Monitors VAST CSI driver health and traces workload storage for the namespace.
codeBundle:
{% if repo_url %}
repoUrl: {{repo_url}}
{% else %}
repoUrl: https://github.com/runwhen-contrib/rw-cli-codecollection.git
{% endif %}
{% if ref %}
ref: {{ref}}
{% else %}
ref: main
{% endif %}
pathToRobot: codebundles/vast-k8s-csi-health/runbook.robot
configProvided:
- name: CONTEXT
value: "{{context}}"
- name: NAMESPACE
value: "{{match_resource.resource.metadata.namespace | default(namespace.name)}}"
- name: CSI_NAMESPACE
value: "{{ custom.vast_csi_namespace | default('vast-csi') }}"
- name: KUBERNETES_DISTRIBUTION_BINARY
value: "{{ custom.kubernetes_distribution_binary | default('kubectl') }}"
- name: VAST_VMS_ENDPOINT
value: "{{ custom.vast_vms_endpoint | default('') }}"
- name: VAST_CLUSTER_NAME
value: "{{ custom.vast_cluster_name | default('') }}"
- name: XPRT_PENDING_THRESHOLD
value: "{{ custom.xprt_pending_threshold | default('100') }}"
- name: RPC_ERROR_RATE_THRESHOLD
value: "{{ custom.rpc_error_rate_threshold | default('5') }}"
secretsProvided:
{% if wb_version %}
{% include "kubernetes-auth.yaml" ignore missing %}
{% else %}
- name: kubeconfig
workspaceKey: {{ custom.kubeconfig_secret_name | default("kubeconfig") }}
{% endif %}
{% if custom.vast_vms_credentials_secret_name %}
- name: vast_vms_credentials
workspaceKey: {{ custom.vast_vms_credentials_secret_name }}
{% endif %}
18 changes: 18 additions & 0 deletions codebundles/vast-k8s-csi-health/.test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Test infrastructure for vast-k8s-csi-health

Static Kubernetes manifests under `kubernetes/manifest.yaml` create:

- Namespace `test-vast-csi-health`
- StorageClass `vast-test-sc` with provisioner `csi.vastdata.com`
- PVC and Deployment referencing VAST storage

## Usage

```bash
task build-infra # kubectl apply manifests
task validate-generation-rules
task default # requires pushed commits + RunWhen Local
task clean
```

The PVC will remain Pending without a real VAST CSI driver; generation rules still match the StorageClass name and annotations for SLX discovery testing.
132 changes: 132 additions & 0 deletions codebundles/vast-k8s-csi-health/.test/Taskfile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
version: "3"

tasks:
default:
desc: "Run/refresh config"
cmds:
- task: check-unpushed-commits
- task: generate-rwl-config
- task: run-rwl-discovery

clean:
desc: "Run cleanup tasks"
cmds:
- task: remove-kubernetes-objects
- task: delete-slxs
- task: clean-rwl-discovery

build-infra:
desc: "Build test infrastructure"
cmds:
- task: create-kubernetes-objects

create-kubernetes-objects:
desc: "Apply manifests from kubernetes directory using kubectl"
cmds:
- kubectl apply -f kubernetes/*
silent: true

remove-kubernetes-objects:
desc: "Delete kubernetes objects"
cmds:
- kubectl delete -f kubernetes/* --ignore-not-found
silent: true

check-unpushed-commits:
desc: Check if outstanding commits or file updates need to be pushed before testing.
vars:
BASE_DIR: "../"
cmds:
- |
echo "Checking for uncommitted changes in $BASE_DIR and $BASE_DIR.runwhen, excluding '.test'..."
UNCOMMITTED_FILES=$(git diff --name-only HEAD | grep -E "^${BASE_DIR}(\.runwhen|[^/]+)" | grep -v "/\.test/" || true)
if [ -n "$UNCOMMITTED_FILES" ]; then
echo "Uncommitted changes found:"
echo "$UNCOMMITTED_FILES"
exit 1
fi
- |
echo "Checking for unpushed commits..."
git fetch origin
UNPUSHED_FILES=$(git diff --name-only origin/$(git rev-parse --abbrev-ref HEAD) HEAD | grep -E "^${BASE_DIR}(\.runwhen|[^/]+)" | grep -v "/\.test/" || true)
if [ -n "$UNPUSHED_FILES" ]; then
echo "Unpushed commits found:"
echo "$UNPUSHED_FILES"
exit 1
fi
silent: true

generate-rwl-config:
desc: "Generate RunWhen Local configuration (workspaceInfo.yaml)"
env:
RW_WORKSPACE: '{{.RW_WORKSPACE | default "my-workspace"}}'
cmds:
- |
repo_url=$(git config --get remote.origin.url)
branch_name=$(git rev-parse --abbrev-ref HEAD)
codebundle=$(basename "$(dirname "$PWD")")
namespace=$(yq e 'select(.kind == "Namespace") | .metadata.name' kubernetes/manifest.yaml -N)
cat <<EOF > workspaceInfo.yaml
workspaceName: "$RW_WORKSPACE"
workspaceOwnerEmail: authors@runwhen.com
defaultLocation: location-01
defaultLOD: none
cloudConfig:
kubernetes:
kubeconfigFile: /shared/kubeconfig
namespaceLODs:
$namespace: detailed
namespaces:
- $namespace
codeCollections:
- repoURL: "$repo_url"
branch: "$branch_name"
codeBundles: ["$codebundle"]
custom:
kubeconfig_secret_name: "kubeconfig"
kubernetes_distribution_binary: kubectl
vast_csi_namespace: vast-csi
EOF
silent: true

run-rwl-discovery:
desc: "Run RunWhen Local Discovery on test infrastructure"
cmds:
- |
CONTAINER_NAME="RunWhenLocal"
docker rm -f $CONTAINER_NAME 2>/dev/null || true
sudo rm -rf output || true
mkdir -p output && chmod 777 output
kubeconfig=$(echo "$RW_FROM_FILE" | jq -r .kubeconfig)
docker run --name $CONTAINER_NAME -p 8081:8081 \
-v "$(pwd)":/shared -v "$kubeconfig":/shared/kubeconfig \
-d ghcr.io/runwhen-contrib/runwhen-local:latest
docker exec -w /workspace-builder $CONTAINER_NAME ./run.sh --verbose
silent: true

validate-generation-rules:
desc: "Validate YAML files in .runwhen/generation-rules"
cmds:
- |
temp_dir=$(mktemp -d)
curl -s -o "$temp_dir/generation-rule-schema.json" \
https://raw.githubusercontent.com/runwhen-contrib/runwhen-local/refs/heads/main/src/generation-rule-schema.json
for yaml_file in ../.runwhen/generation-rules/*.yaml; do
json_file="$temp_dir/$(basename "${yaml_file%.*}.json")"
yq -o=json "$yaml_file" > "$json_file"
ajv validate -s "$temp_dir/generation-rule-schema.json" -d "$json_file" --spec=draft2020 --strict=false
done
rm -rf "$temp_dir"

clean-rwl-discovery:
desc: "Clean up RunWhen Local discovery output"
cmds:
- sudo rm -rf output
- rm -f workspaceInfo.yaml
silent: true

delete-slxs:
desc: "Placeholder for platform SLX deletion (requires RW API credentials)"
cmds:
- echo "Configure RW_WORKSPACE, RW_API, and RW_PAT to delete SLXs from the platform."
silent: true
Loading
Loading