Imported from openshift/lvm-operator (
AGENTS.md). Install upstream withnpx skills add openshift/lvm-operator. Copyright stays with the author.
This file provides guidance to AI agents working with the LVM Operator repository. It is an index into deeper documentation — read the linked files for full details.
Repo Orientation
This is the LVM Operator, part of LVMS (Logical Volume Manager Storage) for OpenShift. It manages LVM volume groups on cluster nodes via a Kubernetes operator and the TopoLVM CSI driver. The operator and TopoLVM are compiled into a single binary for edge/single-node efficiency.
- README.md — what LVMS is, deployment, known limitations
- CONTRIBUTING.md — build commands, testing, commit conventions, AI attribution
- Official product documentation
Build Commands
make build— compile the operator binarymake test— run unit testsmake docker-test— run unit tests inside a Linux container (useful for non-Linux hosts)make lint— run lintersmake verify— formatting and generated file checksmake generate— update deepcopy methods after API type changesmake manifests— regenerate CRD YAML and RBAC after API type changesmake bundle— regenerate OLM bundle manifestsmake catalog— regenerate OLM catalogmake e2e— run end-to-end tests (requires live cluster)
Documentation Index
| Document | Purpose |
|---|---|
| docs/core-beliefs.md | Non-negotiable design principles — read this first |
| docs/conventions/ | Implementation conventions enforced in review (split by area) |
| docs/domain/glossary.md | LVMS terminology — canonical definitions matching Go types and CRD fields |
| docs/domain/concepts.md | How LVMS concepts relate — resource flow, filter chain, reconciliation, deletion |
| docs/decisions/ | Architectural Decision Records (ADRs) — why the codebase looks the way it does |
| docs/architecture.md | Design rationale, component diagram, reconciliation lifecycle, CRD relationships, finalizer hierarchy |
| docs/design/lvm-operator-manager.md | LVM Operator Manager internals |
| docs/design/vg-manager.md | Volume Group Manager design |
| docs/design/thin-provisioning.md | Thin provisioning design |
| docs/design/raid-support.md | RAID support design |
| docs/upstream.md | Upstream TopoLVM workflow, when to contribute upstream vs. downstream fork |
| docs/dependency-management.md | Updating Go, Kubernetes, and TopoLVM dependencies |
| docs/known-limitations.md | Device filters, RAID/encryption workarounds, snapshot constraints |
| docs/loop-devices.md | Using loop devices for testing and development |
| docs/security.md | Snyk vulnerability scanning |
| docs/troubleshooting.md | Troubleshooting guide |
| docs/playbooks/ | Step-by-step implementation guides for common tasks |
Modifying CRDs
When changing API types in api/v1alpha1/, follow this sequence:
- Edit the type definition in
api/v1alpha1/*_types.go. - Add kubebuilder markers for validation, defaults, and documentation.
- Run
make generateto update deepcopy methods. - Run
make manifeststo regenerate CRD YAML and RBAC manifests. - Run
make bundle && make catalogto regenerate OLM bundle and catalog. - Update or add controller logic to handle the new field.
- Add unit tests for validation and controller behavior.
- Add e2e tests if the change affects user workflows.
Validation Markers
Use kubebuilder markers to express validation constraints. All constraints must be documented in the field's godoc comment:
// +optional
// +kubebuilder:validation:Optional
// +kubebuilder:validation:MinItems=1
Paths []string `json:"paths,omitempty"`
API Version Policy
- Current production API:
v1alpha1(the name is historical — treat as stable). - New fields should be optional to maintain backward compatibility.
- Breaking changes require migration support and careful review.
Boundaries
This operator manages physical storage. Mistakes destroy data. See docs/core-beliefs.md for non-negotiable invariants and docs/conventions/ for implementation patterns.
Always do:
- Run
make generate && make manifestsafter changingapi/v1alpha1/types - Run
make bundle && make catalogafter any change that affects CRDs, RBAC, config, or monitoring - Run
make verifybefore considering work complete - Use pointer types (
*StructType) for optional API fields - Treat
nilas "upgraded from before this field existed"
Ask first:
- Adding new dependencies to
go.mod - Modifying webhook validation logic
- Changing device selector behavior
- Any schema migration or breaking API change
Never do:
- Edit generated files:
zz_generated*.go,config/crd/bases/,vendor/ - Run destructive LVM commands:
wipefs,vgremove,pvremove,lvremove,mkfs,dd - Skip finalizer logic — three-level hierarchy prevents orphaned storage. See docs/architecture.md
- Commit secrets, credentials, or personal registry references
Key architecture facts:
- VG Manager runs as a privileged DaemonSet and executes LVM commands (
vgcreate,vgextend,lvcreate,wipefs) directly on nodes - VG Manager requeue interval depends on configuration, in precedence order: RAID: 60s for health monitoring; explicit device paths (any policy) or Static: no periodic requeue; Dynamic discovery without explicit paths: 30s; after VG creation/extension: always requeue (verification step). See
determineFinishedRequeueininternal/controllers/vgmanager/controller.go. Controllers must handle partial states and retries safely (idempotency) - Data loss from incorrect device selection is unrecoverable — verify device selectors carefully in tests
Path-Scoped Guidance
Claude Code loads context-specific rules when you touch files in these areas:
| Rule File | Triggered By | Content |
|---|---|---|
.claude/rules/api-types.md |
api/v1alpha1/** |
CRD workflow, validation markers, API version policy, CEL nil-bypass gotcha |
.claude/rules/vgmanager.md |
internal/controllers/vgmanager/** |
LVM command safety, filter chain, wipe eligibility |
.claude/rules/reconciliation.md |
internal/controllers/** |
MutateFn convention, ownership/finalizer rules, requeue patterns |
.claude/rules/testing.md |
test/**, **/*_test.go |
Ginkgo/Gomega conventions, E2E patterns, cleanup, envtest vs fakeclient |
Agent Skills
Reusable multi-step workflows invocable as slash commands:
| Skill | Command | Purpose |
|---|---|---|
| CRD Modification | /modify-crd |
Full CRD change workflow: types → markers → generate → manifests → bundle → controller → tests |
| E2E Testing | /run-e2e |
E2E test execution with cluster verification, loop devices, and cleanup |
| New ADR | /new-adr |
Create a new Architectural Decision Record from template |
Cross-Tool Compatibility
This repo provides instruction files for multiple AI coding tools:
- Claude Code:
CLAUDE.md→AGENTS.md,.claude/settings.json,.claude/rules/,.claude/commands/ - GitHub Copilot:
.github/copilot-instructions.md,.github/instructions/ - Cursor:
.cursor/rules/lvms.mdc
Testing
Unit tests use Ginkgo/Gomega and are located alongside source files. E2E tests are in test/e2e/ and require a live cluster with available block devices. See CONTRIBUTING.md for build, deploy, and test commands. See docs/conventions/testing.md for testing conventions.
Key Directories
| Path | Contents |
|---|---|
api/v1alpha1/ |
CRD type definitions and webhook validation |
cmd/ |
Binary entrypoints (operator and vgmanager subcommands) |
internal/controllers/ |
Reconcilers: lvmcluster, vgmanager, persistent-volume, persistent-volume-claim, node removal |
internal/controllers/lvmcluster/resource/ |
Resource managers (DaemonSet, StorageClass, CSIDriver, etc.) |
config/ |
Kustomize overlays, CRD manifests, RBAC, samples |
test/e2e/ |
End-to-end test suite |
test/performance/ |
Performance and stress test tooling |
hack/ |
Vendor patches and build scripts |
release/ |
Konflux build configuration and RPM lock files |
docs/ |
Architecture, design, troubleshooting, upstream workflow |