AI Agent Instructions for service-ca-operator
June 25, 2026 · View on GitHub
Also read ARCHITECTURE.md for design decisions, CONTRIBUTING.md for PR workflow, OWNERS for reviewers/approvers.
What This Repo Is
An OpenShift ClusterOperator that manages the service-serving CA — a cluster-scoped certificate authority that automatically provisions TLS certificates for in-cluster Services. The operator manages the CA keypair and deploys a controller that signs serving certificates and injects CA bundles into annotated resources.
Two-process architecture from a single binary (service-ca-operator):
- Operator (
pkg/operator/): Manages the signing CA, controller Deployment lifecycle, and ClusterOperator status - Controller (
pkg/controller/): Signs TLS certs for annotated Services, injects CA bundles into ConfigMaps/APIServices/Webhooks/CRDs
Repository Layout
cmd/service-ca-operator/ Single binary, two subcommands: operator | controller
cmd/service-ca-operator-tests-ext/ OTE e2e test binary
pkg/operator/ Operator process — CA lifecycle, deployment sync, status
pkg/controller/ Controller process — serving cert signer, CA bundle injectors
pkg/controller/api/ Annotation constants, resource names
pkg/controller/cabundleinjector/ CA bundle injection into ConfigMaps, webhooks, CRDs, APIServices
pkg/controller/servingcert/ Serving cert signing controller
pkg/cmd/ CLI wiring (cobra commands)
bindata/assets/ Embedded static manifests (Go embed.FS)
manifests/ CVO-managed manifests (operator deployment, RBAC, monitoring)
profile-patches/ HyperShift / managed profile patches
test/e2e/ E2e tests (OTE framework)
Build and Test Commands
make build # Build operator + OTE test binary
make test-unit # Run all unit tests
go test ./pkg/operator/ -run TestName -count 1 # Single unit test
make test-e2e # E2e tests (requires cluster + KUBECONFIG)
make verify # Verify generated files
make update # Update generated files
go mod tidy && go mod vendor # Update vendored dependencies
Critical Rules
-
Never create FeatureGate/ClusterVersion informers in the controller process. MicroShift lacks these CRDs — informers for them crash the controller (OCPBUGS-82110). The operator detects feature gates and forwards them to the controller as
--feature-gates=Key=trueCLI args. Seepkg/operator/sync_common.goandpkg/cmd/controller/cmd.go. -
Separate code commits from vendor commits. PRs must keep source changes and vendored artifacts (
go.mod,go.sum,vendor/) in separate commits. Vendor commit message:vendor: bump(*). -
New e2e tests go in
test/e2e/e2e.go(OTE format), nottest/e2e/e2e_test.go(legacy, being phased out).
Key Patterns
- Embedded assets: Static manifests in
bindata/assets/*.yamlare embedded via Go'sembed.FS(declared inbindata/assets.go). Access withbindata.MustAsset("assets/<file>.yaml"). No code generation step needed. - Feature gate forwarding: Operator reads gates via
FeatureGateAccess→ sets--feature-gatesargs on controller Deployment → controller receivesmap[string]boolinpkg/cmd/controller/cmd.go. Adding a new gate means checking the map key where needed — no function signature changes. - Controller framework: Uses
openshift/library-gocontroller framework (controllercmd), not controller-runtime. - User-facing annotations: Defined in
pkg/controller/api/api.go. Bothservice.beta.openshift.ioand legacyservice.alpha.openshift.ioprefixes are supported.
What NOT to Do
- Don't detect features at runtime in the controller — no
ClusterVersionorFeatureGatewatches. MicroShift will crash. Use the CLI args forwarding pattern instead. - Don't use
go-bindata— the repo migrated to Go's nativeembed.FS(PR #326). - Don't modify
test/e2e/e2e_test.gofor new tests — usetest/e2e/e2e.go(OTE). - Don't mix code and vendor changes in the same commit.
Architecture
See ARCHITECTURE.md for full details including component overview, controller table, CA rotation lifecycle, manifest management, platform/topology behavior, and design decisions.
Key namespaces:
openshift-service-ca-operator: Where the operator runsopenshift-service-ca: Where the controller Deployment runs
Key constants:
- Resource names:
pkg/controller/api/resourcenames.go - Namespace constants:
pkg/operator/operatorclient/interfaces.go