From etcd-druid
Use for any etcd-druid API field addition or modification — CEL validation, kubebuilder markers, two-commit generate workflow, CRD tests. Not for controller or test-only work.
How this skill is triggered — by the user, by Claude, or both
Slash command
/etcd-druid:api-changeapi/core/v1alpha1/*.goThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Complete workflow for adding or modifying fields in `api/core/v1alpha1/`. Covers struct design, all validation types, code generation, tests, and PR requirements.
Complete workflow for adding or modifying fields in api/core/v1alpha1/. Covers struct design, all validation types, code generation, tests, and PR requirements.
NO CEL RULE SHIPS WITHOUT A TEST IN test/it/crdvalidation/.
| Rationalization | Why it fails |
|---|---|
| "The rule is simple, obviously correct" | CEL syntax errors are silent until the CRD is applied — the test catches them |
| "I tested it manually with kubectl" | Manual tests don't run in CI; the integration test suite does |
| "The field-scoped rule is covered, cross-field is obvious" | Cross-field rules reference self.metadata — they fail differently, test separately |
| "K8s < 1.29 doesn't support CEL anyway" | Two CRD variants exist; missing the test means the CEL variant is unverified |
Before modifying any API types or running generation, apply the worktree gate (skills/worktree-gate/SKILL.md).
If already in a worktree (e.g., dispatched from implement): use it.
If standalone: the gate creates a worktree branched from upstream/master.
All API changes, cd api && make generate, and CRD validation tests happen inside the worktree. Use git diff upstream/master...HEAD to verify exactly what changed before committing.
Before writing any code: Read the ## API Delta section of the plan file for this task.
This is the canonical statement of what this change should add, modify, or remove.
Your Commit 1 diff must match every row in that table — no more, no less.
If the plan has no ## API Delta section, stop and ask the plan author to add one.
API types: api/core/v1alpha1/etcd.go
OpsTask: api/core/v1alpha1/etcdopstask.go
Struct hierarchy in etcd.go:
Etcd <- root; cross-field CEL goes here
└── EtcdSpec
├── Replicas <- scalar with field-level CEL
├── EtcdConfig <- etcd process config; field-scoped CEL goes here
│ └── AdditionalAdvertisePeerURLs []AdditionalPeerURL
├── BackupSpec <- backup config; struct-level CEL goes here
├── SharedConfig <- autoCompaction
└── SchedulingConstraints
Rule: Place the annotation on the innermost struct where all referenced fields live. If a rule references self.metadata or self.spec.* from two different sub-structs, it must go on Etcd (root).
// AdditionalPeerURL is an example of a new struct.
type AdditionalPeerURL struct {
// MemberName is the etcd member name (e.g., etcd-main-0).
// +required
// +kubebuilder:validation:Required
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=253
// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?-[0-9]+$`
MemberName string `json:"memberName"`
// URLs is a list of additional peer URLs for this member.
// +required
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=5
// +listType=atomic
URLs []string `json:"urls"`
}
Standard markers checklist:
| Marker | When to use |
|---|---|
+optional / +required | All fields — never omit |
omitempty in JSON tag | Optional fields only |
+kubebuilder:validation:Enum=... | Fixed set of string values |
+kubebuilder:validation:Pattern=... | String format constraint |
+kubebuilder:validation:MinLength/MaxLength | String length bounds |
+kubebuilder:validation:MinItems/MaxItems | Slice cardinality |
+kubebuilder:validation:MinProperties=1 | Must set at least one sub-field |
+listType=atomic | Slices where order matters or items aren't uniquely keyed |
+kubebuilder:default=<value> | Optional fields with a documented default — sets the value at admission time so the handler never sees nil. Do NOT hardcode defaults in handler/controller code when a kubebuilder marker can express the same default. Convention: OnDemandSnapshotConfig and other existing API fields use this pattern. |
MaxItems cost budget: CEL validation cost scales with list length. Use MaxItems=10 for lists that will be iterated in CEL rules — this keeps cost within the CRD admission webhook budget.
Default values: When an optional field has a documented default, set it via +kubebuilder:default=<value> on the struct field. The API type is the single source of truth for defaults — never define defaults only in handler code. If using metav1.Duration, apply +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" for format validation.
Add kubebuilder markers, field-scoped CEL, cross-field CEL, and immutability rules as needed. Full details, code examples, has() guard explanation, silent-pass failure mode, and cross-field checklist are in CEL-VALIDATION.md.
Commit 1 — hand-written API changes only:
Files in this commit: api/core/v1alpha1/*.go (your edits)
Nothing generated. Message style: feat(api): add <field> to <type> (#<issue>)
Commit 2 — generated output only:
cd api && make generate
Generated files:
api/core/v1alpha1/zz_generated.deepcopy.goapi/core/v1alpha1/crds/druid.gardener.cloud_etcds.yaml (with CEL)api/core/v1alpha1/crds/druid.gardener.cloud_etcds_without_cel.yaml (CEL stripped)charts/crds/druid.gardener.cloud_etcds.yamldocs/api-reference/etcd-druid-api.mdMessage style: chore: generate CRDs and deepcopy for <field> (#<issue>)
NEVER manually edit generated files. Verify generation is clean before committing:
cd api && make check-generate # fails if make generate would produce a diff
cd api && make check-apidiff # fails on breaking API changes
Two CRD variants: make generate produces both automatically. The _without_cel.yaml variant strips all x-kubernetes-validations blocks via yq. You do not need to maintain them separately.
Common CEL patterns for guards, immutability, duration comparison, list iteration, and string operations: CEL-QUICK-REFERENCE.md.
After completing the API change:
/etcd-druid:implement Phase 3 (verify gate)/etcd-druid:debugskills/tdd/SKILL.md (use skipCELTestsForOlderK8sVersions(t) guard)npx claudepluginhub seshachalam-yv/etcd-druid-skills --plugin etcd-druid-skillsGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.