Imported from openshift/external-secrets-operator (
AGENTS.md). Install upstream withnpx skills add openshift/external-secrets-operator. Copyright stays with the author.
External Secrets Operator — Agentic Documentation
Component: External Secrets Operator for Red Hat OpenShift Repository: openshift/external-secrets-operator
Platform Patterns: See openshift/enhancements/ai-docs/ for operator patterns, testing practices, security guidelines, and cross-repo ADRs.
What is ESO?
Manages the lifecycle of the upstream external-secrets project on OpenShift. Deploys and configures the operand via static YAML manifests embedded as bindata — it is not a fork.
Key Principle: The operator owns the operand deployment; users configure via two singleton CRs (ExternalSecretsConfig, ExternalSecretsManager), both named cluster.
Core Components
| Component | Purpose | Location |
|---|---|---|
| ExternalSecrets Controller | Operand lifecycle (install, update, delete) | pkg/controller/external_secrets/ |
| ESM Controller | Status aggregation, default ESM creation | pkg/controller/external_secrets_manager/ |
| CRD Annotator | cert-manager CA injection on CRDs (conditional) | pkg/controller/crd_annotator/ |
Quick Start: oc get esc cluster -o yaml | oc get esm cluster -o yaml | oc get pods -n external-secrets
Critical Patterns
- NOT Server-Side Apply — all updates use
UpdateWithRetry(Get → set ResourceVersion → Update). Co-managed resources (Secret, ConfigMap) usepatchResourceMetadatafor metadata-only JSON Patch. Never introduce SSA. - Bindata pipeline — operand manifests are pre-rendered from upstream Helm charts at build time (
hack/update-external-secrets-manifests.sh), embedded viaopenshift/build-machinery-go.pkg/operator/assets/bindata.gois generated — never hand-edit. - Immutable cert-manager fields —
mode,injectAnnotations,issuerRefin CertManagerConfig are immutable via CELself == oldSelf. Network policy entries (name+componentName) also cannot be removed once added.
Domain Guidelines
Detailed rules for each domain are in harness-evals/harness-docs/. Read the relevant file before modifying that area.
| Guideline | Scope |
|---|---|
| Security | CEL validation, annotation/label restrictions, container hardening, RBAC, network policies, TLS |
| Performance | Label-filtered caches, change detection, event predicates, requeue strategy, concurrency |
| Error Handling | Error classification (Irrecoverable/Retry/UserConfig), status conditions, requeue matrix, events |
| API Contracts | Singleton enforcement, field immutability, CEL rules, list map keys, .testsuite.yaml patterns |
| Testing | Unit tests, API integration tests (envtest), E2E with Ginkgo labels, make targets |
| Integration | cert-manager, OLM, proxy, CNO trusted CA, console, metrics, multi-arch, webhooks |
Cross-Cutting Conventions
- Generated files: Never hand-edit
bindata.go,fake_ctrl_client.go,zz_generated.deepcopy.go, or CRD YAML inconfig/crd/bases/. Regenerate withmake manifests generate update-bindataorgo generate. - Go style: stdlib
testingonly (no Ginkgo for unit tests, no testify except E2E utils). Table-driven tests witht.Run. Callt.Parallel()on outer function and each subtest. Uset.Setenv()instead ofos.Setenv. - Constants: All string constants (asset names, label keys, env var names) live in
constants.go. Do not scatter literals across source files. - New managed resources: Must be added to
controllerManagedResources,buildCacheObjectList(),HasObjectChangedtype-switch, and the ordered install sequence. Seeharness-evals/harness-docs/ESO_DEVELOPMENT.mdsection 2. - Commit messages: Always include the Jira ticket number and a clear imperative description. Format:
<JIRA-ID>: short description(e.g.,ESO-142: add proxy egress network policy). The Jira project can be any valid project (ESO, OAPE, etc.). If no Jira ticket exists, use a descriptive imperative summary. Never use generic messages like "fix bug" or "update code". - PR checklist: Run
make verify(vet, fmt, deps, bindata, generated files, govulncheck, markdownlint, git diff),make test, andmake lintbefore submitting.make verifyis the single gate that CI enforces.
Common Pitfalls
- Never return both
RequeueAfterand a non-nil error fromReconcile— return one or the other. - Use the cached client for managed resources (
app=external-secrets). UseUncachedClientonly for objects outside the cache (cert-manager Issuers, user-provided Secrets). Decode*ObjByteshelpers panic on failure — intentional for build-time-constant assets; do not wrap them in error handling.- Operator RBAC markers (
+kubebuilder:rbac) go in controller Go files; operand RBAC lives in static YAML underbindata/. - More contributor pitfalls:
harness-evals/harness-docs/ESO_DEVELOPMENT.md→ Common Mistakes.
Documentation Structure
harness-evals/harness-docs/
├── *-guidelines.md # Enforceable domain guidelines (security, testing, API, …)
├── domain/ # ExternalSecretsConfig, ExternalSecretsManager API docs
├── architecture/ # Controller internals, resource management, bindata pipeline
│ └── components.md
├── decisions/ # Component-specific ADRs (bindata, update strategy, NP naming)
├── exec-plans/ # Feature planning
├── references/
│ ├── ecosystem.md # Links to Platform patterns
│ └── enhancements.md # Enhancement proposals catalog
├── ESO_DEVELOPMENT.md # Development workflows, build targets, common tasks
└── ESO_TESTING.md # Test suites, patterns, E2E labels
AI Agent Path: harness-evals/harness-docs/*-guidelines.md (as needed) → domain/ → architecture/ → decisions/ → ESO_DEVELOPMENT.md
OpenSpec (planning / evals)
| Path | Role |
|---|---|
AGENTS.md (this file) |
Agent routing + architecture for /opsx-* |
harness-evals/harness-docs/ |
Source docs for /opsx-constitute |
harness-evals/constitution.md |
Guardrails required before plan.md |
harness-evals/evals/ |
Stage eval quality gates (/opsx-continue, /opsx-apply) |
eval-generation/ |
Retrospective /eval-loop (fill input/feature-bundle.yaml) |
See harness-evals/README.md. Stage eval cases in harness-evals/evals/ are populated and active when the OpenSpec workflow loads them; /eval-loop accumulates further cases from completed features.
Namespaces & Image Resolution
| Namespace | Purpose |
|---|---|
external-secrets-operator |
Operator deployment (OLM-managed) |
external-secrets |
Operand namespace (operator-created) |
| Env Var | Purpose |
|---|---|
RELATED_IMAGE_EXTERNAL_SECRETS |
Operand image (OLM disconnected convention) |
RELATED_IMAGE_BITWARDEN_SDK_SERVER |
Bitwarden image |
Error Classification
| Type | Requeue | Example |
|---|---|---|
IrrecoverableError |
No | Missing RELATED_IMAGE_* env var |
RetryRequiredError |
30s | Transient API server error |
UserConfigurationError |
Only NotFound | Invalid cert-manager issuer ref |
Conditional Deployments
| Operand Component | Condition |
|---|---|
external-secrets (core) |
Always |
external-secrets-webhook |
Always |
external-secrets-cert-controller |
cert-manager disabled |
bitwarden-sdk-server |
Bitwarden plugin enabled |
Key References
- Enhancement: ESO on OpenShift
- Enhancement: Network Policies
- Enhancement: Component Config
- Upstream external-secrets | OpenShift Docs
Platform Documentation: openshift/enhancements/ai-docs/