This document provides comprehensive guidelines for new contributors developing the Open Cluster Management (OCM) project. It also serves as a reference for AI tools performing code reviews and analysis.
- Project Overview
- Development Environment Setup
- Code Organization
- Development Workflow
- Code Standards and Style
- Testing Guidelines
- API Development
- Build and Release
- Troubleshooting
Open Cluster Management (OCM) is a CNCF sandbox project that provides multicluster and multicloud management capabilities for Kubernetes. The project consists of five core components:
- registration: Manages cluster registration and certificate lifecycle
- placement: Handles content placement decisions across clusters
- work: Distributes and applies manifests to managed clusters
- registration-operator: Deploys and manages OCM components
- addon-manager: Manages OCM add-ons lifecycle
- Language: Go 1.25.0
- Framework: Kubernetes operators with controller-runtime
- Build System: Make with OpenShift build machinery
- Testing: Ginkgo/Gomega for BDD-style tests
- Packaging: Helm charts and OLM bundles
- Go 1.25.0 (installation guide)
- Docker or Podman (container engine)
- Kind (local Kubernetes clusters)
- kubectl (Kubernetes CLI)
- clusteradm (OCM CLI)
-
Create development cluster:
kind create cluster --name ocm-dev
-
Initialize OCM control plane:
# Replace <TAG> with a concrete release (e.g., vX.Y.Z) curl -fsSL https://raw.githubusercontent.com/open-cluster-management-io/clusteradm/<TAG>/hack/install.sh | bash clusteradm init --wait --bundle-version="<BUNDLE_VERSION>"
-
Join cluster as managed cluster:
clusteradm join --hub-token <token> --hub-apiserver <url> --wait --cluster-name cluster1 --force-internal-endpoint-lookup --bundle-version="<BUNDLE_VERSION>" clusteradm accept --clusters cluster1
-
Verify installation:
kubectl get clustermanager,managedcluster kubectl get pods -A | grep open-cluster-management
ocm/
├── cmd/ # Main applications entry points
│ ├── addon/ # Addon manager
│ ├── placement/ # Placement controller
│ ├── registration/ # Registration controller
│ ├── registration-operator/ # Operator
│ ├── server/ # GRPC server
│ └── work/ # Work controller
├── pkg/ # Core business logic
│ ├── addon/ # Addon framework and controllers
│ ├── operator/ # Operator controllers
│ ├── placement/ # Placement logic and controllers
│ ├── registration/ # Registration logic
│ └── work/ # Work distribution logic
├── manifests/ # Deployment manifests
├── deploy/ # Helm charts and OLM bundles
├── test/ # Test suites
│ ├── e2e/ # End-to-end tests
│ └── integration/ # Integration tests
└── solutions/ # Usage examples and solutions
pkg/common/: Shared utilities and helperspkg/registration/hub/: Hub-side registration controllerspkg/registration/spoke/: Managed cluster registration logicpkg/work/hub/: Hub-side work distributionpkg/work/spoke/: Managed cluster work applicationpkg/placement/controllers/: Placement scheduling and decision logicpkg/addon/controllers/: Addon lifecycle management controllers
# Fork and clone the repository
git clone https://github.com/<your-username>/ocm.git
cd ocm
# Create feature branch
git checkout -b feature/your-feature-name
# Make changes and commit with DCO sign-off
git commit -s -m "Add new feature: description"Build all images:
IMAGE_REGISTRY=quay.io/your-org IMAGE_TAG=dev make imagesBuild specific component:
IMAGE_REGISTRY=quay.io/your-org IMAGE_TAG=dev make image-registrationLoad images to kind cluster:
kind load docker-image quay.io/your-org/registration:dev --name ocm-devUpdate operator images:
kubectl set image -n open-cluster-management deployment/cluster-manager registration-operator=quay.io/your-org/registration-operator:devUpdate component images via CustomResource:
kubectl edit clustermanager cluster-manager # For hub components
kubectl edit klusterlet klusterlet # For spoke components- Follow standard Go conventions: Use
gofmt,go vet, andgolangci-lint - Variable naming: Use camelCase for local variables, PascalCase for exported items
- Comments: Write clear comments for exported functions and complex logic
- Interface design: Keep interfaces small and focused (interface segregation principle)
Imports must be organized in the following order:
- Standard library packages
- Third-party packages
- OCM packages
import (
// Standard library
"context"
"fmt"
"time"
// Third-party
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/controller-runtime/pkg/client"
// OCM packages
"open-cluster-management.io/api/cluster/v1"
"open-cluster-management.io/ocm/pkg/common/helpers"
)All code must pass these checks:
make verify # Run all verification checks
make verify-gocilint # Linting with golangci-lint
make verify-fmt-imports # Import formatting verification
make verify-crds # CRD consistency checksAuto-format imports:
make fmt-imports # Automatically format import statements- Files: Use snake_case (e.g.,
cluster_controller.go) - Packages: Use lowercase, single words when possible
- Constants: Use CamelCase (PascalCase for exported constants); reserve ALL_CAPS only when mirroring external specs
- Controllers: Suffix with
Controller(e.g.,PlacementController) - Interfaces: Use descriptive names, often ending with
-er(e.g.,ClusterLister)
- All exported functions, types, and constants must have comments
- Comments should start with the name of the item being documented
- Use complete sentences and proper punctuation
- Include examples for complex APIs
make test-unit # Run all unit tests
go test ./pkg/registration/... # Test specific packageIntegration tests use controller-runtime's envtest framework:
make test-integration # All integration tests
make test-registration-integration # Registration only
make test-placement-integration # Placement only
make test-work-integration # Work only
make test-addon-integration # Addon onlyEnd-to-end tests run against real clusters and require a kind cluster with proper setup:
# 1. Create kind cluster and set KUBECONFIG
kind get kubeconfig --name ocm-e2e > /tmp/kubeconfig-ocm-e2e
export KUBECONFIG=/tmp/kubeconfig-ocm-e2e
# 2. Run E2E tests with required variables
IMAGE_TAG=e2e KLUSTERLET_DEPLOY_MODE=Singleton make test-e2eE2E test variables:
IMAGE_TAG: Tag for container images (default: latest)KLUSTERLET_DEPLOY_MODE: Deployment mode (Default, Singleton, SingletonHosted)MANAGED_CLUSTER_NAME: Name of the managed cluster (default: cluster1)KUBECONFIG: Must be set to point to test cluster
- Unit tests:
*_test.gofiles alongside source code - Integration tests:
test/integration/directory - E2E tests:
test/e2e/directory - Test utilities:
test/framework/andpkg/*/testing/
- Use Ginkgo/Gomega for BDD-style tests
- Write descriptive test names using
Describe,Context, andIt - Use table-driven tests for multiple scenarios
- Mock external dependencies appropriately
- Ensure tests are deterministic and can run in parallel
OCM APIs are defined in the separate api repository. To modify APIs:
-
Clone both repositories:
git clone https://github.com/<your-username>/api.git git clone https://github.com/<your-username>/ocm.git
-
Make API changes in the api repository and run:
cd api make update # Generates CRDs and DeepCopy methods
-
Use local API changes in ocm repository:
cd ocm go mod edit -replace open-cluster-management.io/api=/path/to/local/api go mod tidy && go mod vendor make update # Updates CRDs, Helm charts, and operator manifests
-
Remove replace directive before submitting PR
The make update command handles:
- CRD copying from api repository
- Helm chart updates
- Operator manifest generation
- ClusterServiceVersion updates
The project uses OpenShift's build-machinery-go:
make all # Build all binaries
make images # Build all container images
make update # Update all generated manifestsImages are built for multiple architectures:
linux/amd64linux/arm64
Registry configuration:
export IMAGE_REGISTRY=quay.io/open-cluster-management
export IMAGE_TAG=v0.x.xmake build # Build binaries
make images # Build container images
make test-unit # Run unit tests
make test-integration # Run integration tests
make test-e2e # Run E2E tests
make verify # Run all verification checks
make update # Update generated files
make clean # Clean build artifacts-
API Server Connection Issues:
kubectl cluster-info # Verify cluster connectivity kubectl get nodes # Check cluster health
-
Image Pull Failures:
kind load docker-image <image> # Load to kind cluster kubectl describe pod <pod> # Check image pull status
-
Certificate Issues:
kubectl get csr # Check certificate requests kubectl get secrets -A | grep tls # Check TLS secrets
-
Operator Issues:
kubectl logs -n open-cluster-management deployment/cluster-manager kubectl get clustermanager cluster-manager -o yaml
- Enable debug logging: Set
--v=4or higher in component flags - Use
kubectl describefor resource status - Check controller logs in
open-cluster-management*namespaces - Verify RBAC permissions with
kubectl auth can-i
- Use
go tool pproffor CPU/memory profiling - Monitor metrics endpoints (when enabled)
- Check resource utilization with
kubectl top
- Submit an issue describing proposed changes
- Fork and develop following this guide
- Add tests for new functionality
- Run quality checks:
make verify test-unit - Submit pull request with DCO sign-off
- Address review feedback promptly
For detailed contribution guidelines, see CONTRIBUTING.md.