pkg/cmd/roachprod-centralized/docs/DEVELOPMENT.md
This guide covers local development setup, testing practices, and contribution guidelines for the roachprod-centralized service.
š Related Documentation:
Ensure you have the CockroachDB development environment set up:
# Verify your development environment
./dev doctor
For testing cloud provider integration:
gcloud CLICreate a development configuration file:
# Create local config directory
mkdir -p ~/.roachprod
# Create development configuration
cat > ~/.roachprod/dev-config.yaml << EOF
log:
level: debug
api:
port: 8080
authentication:
disabled: true
database:
type: memory
tasks:
workers: 1
EOF
pkg/cmd/roachprod-centralized/
āāā README.md # Main documentation
āāā main.go # Application entry point
āāā config.yml # Default configuration
āāā BUILD.bazel # Bazel build configuration
ā
āāā app/ # Application initialization
ā āāā app.go # Main app structure
ā āāā api.go # API server setup
ā āāā factory.go # Service factory
ā āāā options.go # App configuration options
ā
āāā cmd/ # CLI commands (Cobra)
ā āāā root.go # Root command
ā āāā api.go # API server command
ā āāā workers.go # Workers-only command
ā
āāā config/ # Configuration management
ā āāā env/ # Environment variable handling
ā āāā flags/ # CLI flag handling
ā āāā processing/ # Config processing
ā āāā recursive/ # Recursive config handling
ā āāā types/ # Config type definitions
ā
āāā controllers/ # HTTP request handlers
ā āāā clusters/ # Cluster endpoints
ā āāā health/ # Health check endpoints
ā āāā tasks/ # Task endpoints
ā āāā public-dns/ # DNS endpoints
ā
āāā services/ # Business logic layer
ā āāā clusters/ # Cluster management
ā ā āāā tasks/ # Cluster-related background tasks
ā ā āāā models/ # Cluster-specific models
ā āāā tasks/ # Task processing
ā āāā health/ # Health monitoring
ā ā āāā tasks/ # Health check tasks
ā āāā public-dns/ # DNS management
ā āāā tasks/ # DNS-related background tasks
ā āāā models/ # DNS-specific models
ā
āāā repositories/ # Data access layer
ā āāā clusters/ # Cluster storage
ā ā āāā memory/ # In-memory implementation
ā ā āāā cockroachdb/ # CockroachDB implementation
ā ā āāā mocks/ # Test mocks
ā āāā tasks/ # Task storage
ā ā āāā memory/
ā ā āāā cockroachdb/
ā ā āāā mocks/
ā āāā health/ # Health storage
ā āāā memory/
ā āāā cockroachdb/
ā āāā mocks/
ā
āāā utils/ # Shared utilities
ā āāā api/ # API utilities
ā ā āāā bindings/ # Request binding helpers
ā āāā database/ # Database utilities
ā āāā filters/ # Query filtering
ā ā āāā types/ # Filter type definitions
ā ā āāā memory/ # In-memory filter implementation
ā ā āāā sql/ # SQL filter implementation
ā āāā logger/ # Logging utilities
ā
āāā docker/ # Docker configuration
ā āāā Dockerfile # Multi-stage build definition
ā āāā cloudbuild.yaml # Google Cloud Build config
ā āāā README.md # Docker deployment guide
ā āāā image/ # Files used during image build
ā ā āāā install-deps.sh # Install dependencies (Azure CLI, AWS CLI)
ā ā āāā entrypoint.sh # Container entrypoint script
ā āāā scripts/ # Build orchestration scripts
ā āāā build-local.sh # Local Podman builds (multi-arch)
ā āāā build-remote.sh # Remote Cloud Build (amd64)
ā
āāā docs/ # Documentation
ā āāā API.md
ā āāā ARCHITECTURE.md
ā āāā DEVELOPMENT.md # This file
ā āāā EXAMPLES.md
ā āāā CLOUD_PROVIDER_CONFIG.md
ā
āāā examples/ # Example configurations
āāā development-config.yaml
āāā cloud_config.yaml.example
āāā docker-compose.yml
# Build the binary (from CockroachDB root)
./dev build roachprod-centralized
# Build with race detection (for development)
./dev build roachprod-centralized --race
# Run with development configuration
./bin/roachprod-centralized api --config ~/.roachprod/dev-config.yaml
# Run with in-memory storage
export ROACHPROD_DATABASE_TYPE=memory
export ROACHPROD_API_AUTHENTICATION_METHOD=disabled
./bin/roachprod-centralized api
# Run with debug logging
export ROACHPROD_LOG_LEVEL=debug
./bin/roachprod-centralized api
To test the horizontally scaled deployment mode locally, you'll need CockroachDB running:
1. Start a local CockroachDB instance:
# Start single-node CockroachDB (in a separate terminal)
cockroach start-single-node --insecure --listen-addr=localhost:26257 --http-addr=localhost:8080
# Create the roachprod database
cockroach sql --insecure -e "CREATE DATABASE IF NOT EXISTS roachprod;"
2. Run API instances (no workers):
# Terminal 1: API instance 1
export ROACHPROD_DATABASE_TYPE=cockroachdb
export ROACHPROD_DATABASE_URL="postgresql://root@localhost:26257/roachprod?sslmode=disable"
export ROACHPROD_API_AUTHENTICATION_METHOD=disabled
export ROACHPROD_API_PORT=8090
export ROACHPROD_LOG_LEVEL=debug
./bin/roachprod-centralized api --no-workers
# Terminal 2: API instance 2
export ROACHPROD_DATABASE_TYPE=cockroachdb
export ROACHPROD_DATABASE_URL="postgresql://root@localhost:26257/roachprod?sslmode=disable"
export ROACHPROD_API_AUTHENTICATION_METHOD=disabled
export ROACHPROD_API_PORT=8091
export ROACHPROD_LOG_LEVEL=debug
./bin/roachprod-centralized api --no-workers
3. Run worker instances:
# Terminal 3: Worker instance 1
export ROACHPROD_DATABASE_TYPE=cockroachdb
export ROACHPROD_DATABASE_URL="postgresql://root@localhost:26257/roachprod?sslmode=disable"
export ROACHPROD_TASKS_WORKERS=2
export ROACHPROD_API_METRICS_PORT=9091
export ROACHPROD_LOG_LEVEL=debug
./bin/roachprod-centralized workers
# Terminal 4: Worker instance 2
export ROACHPROD_DATABASE_TYPE=cockroachdb
export ROACHPROD_DATABASE_URL="postgresql://root@localhost:26257/roachprod?sslmode=disable"
export ROACHPROD_TASKS_WORKERS=2
export ROACHPROD_API_METRICS_PORT=9092
export ROACHPROD_LOG_LEVEL=debug
./bin/roachprod-centralized workers
4. Verify the setup:
# Check API instances
curl http://localhost:8090/health
curl http://localhost:8091/health
# Check worker metrics
curl http://localhost:9091/metrics
curl http://localhost:9092/metrics
# Create a task via API and watch workers process it
curl -X POST http://localhost:8090/clusters/sync
# Check task status
curl http://localhost:8090/tasks
Expected log messages to verify correct mode:
API instances should log:
health service: skipping instance registration (workers disabled)
clusters service: skipping background work (workers disabled)
Task workers disabled (Workers=0), skipping task processing routine
Worker instances should log:
Starting in metrics-only mode (workers)
Starting tasks processing routine
health service: starting health service
# Run all tests
./dev test pkg/cmd/roachprod-centralized/...
# Run tests for specific package
./dev test pkg/cmd/roachprod-centralized/services/clusters
# Run tests with race detection
./dev test pkg/cmd/roachprod-centralized/... --race
# Run tests with coverage
./dev test pkg/cmd/roachprod-centralized/... --coverage
# Run specific test
./dev test pkg/cmd/roachprod-centralized/services/clusters -f TestClustersService
# Verbose test output
./dev test pkg/cmd/roachprod-centralized/services/clusters -v
# Run integration tests (if available)
./dev test pkg/cmd/roachprod-centralized/... --tags=integration
# Test with real database
export ROACHPROD_DATABASE_TYPE=cockroachdb
export ROACHPROD_DATABASE_URL="postgresql://root@localhost:26257/roachprod_test?sslmode=disable"
./dev test pkg/cmd/roachprod-centralized/repositories/...
func TestClustersService_GetAllClusters(t *testing.T) {
tests := []struct {
name string
filters filters.FilterSet
mockData []cloud.Cluster
expected []cloud.Cluster
wantError bool
}{
{
name: "success - no filters",
filters: filters.FilterSet{},
mockData: []cloud.Cluster{testCluster1, testCluster2},
expected: []cloud.Cluster{testCluster1, testCluster2},
},
// More test cases...
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Test implementation
})
}
}
Follow standard Go conventions and CockroachDB coding standards:
# Format code
./dev generate go
# Run linting
./dev lint
# Run specific linters
./dev lint --short
// ClusterService handles cluster management operations.
// It provides CRUD operations and synchronization with cloud providers.
type ClusterService struct {
repo clusters.IRepository
logger *logger.Logger
}
// GetAllClusters retrieves all clusters matching the provided filters.
// Returns an empty slice if no clusters match the criteria.
func (s *ClusterService) GetAllClusters(ctx context.Context, logger *logger.Logger, input InputGetAllClustersDTO) ([]cloud.Cluster, error) {
// Implementation...
}
# Enable debug logging
export ROACHPROD_LOG_LEVEL=debug
# Log specific operations
curl -X POST http://localhost:8080/clusters/sync
# Check logs for detailed operation traces
# Check API health
curl http://localhost:8080/health
# Monitor metrics
curl http://localhost:8081/metrics | grep roachprod
Create Feature Branch:
git checkout -b feature/new-functionality
Make Changes:
Test Changes:
./dev test pkg/cmd/roachprod-centralized/...
./dev lint
Commit Changes:
git add .
git commit -m "roachprod-centralized: add new functionality
This commit adds X functionality to support Y use case.
- Implement Z feature
- Add tests for Z
- Update documentation
Release notes: None
Epic: CRDB-12345"
Pre-Review Checklist:
Review Criteria:
Create Controller Handler:
// In controllers/clusters/clusters.go
func (ctrl *Controller) NewOperation(c *gin.Context) {
// Implementation
}
Add Route:
// In NewController()
&controllers.ControllerHandler{
Method: "POST",
Path: ControllerPath + "/new-operation",
Func: ctrl.NewOperation,
}
Add Service Method:
// In services/clusters/clusters.go
func (s *Service) NewOperation(ctx context.Context, ...) error {
// Business logic
}
Add Tests:
func TestController_NewOperation(t *testing.T) {
// Test implementation
}
Implement Provider Interface in the roachprod library
Register Provider:
// In service factory
switch providerType {
case "new-provider":
return &NewProvider{}, nil
}
Add Configuration:
// In config/config.go
type CloudProvider struct {
NewProvider NewProviderOptions `env:"NEWPROVIDER"`
}
Create Migration:
// In repositories/*/cockroachdb/migrations_definition.go
func Migration_001_AddNewTable() string {
return `CREATE TABLE IF NOT EXISTS new_table (...);`
}
Update Repository:
// Add new methods to repository interface and implementation
Test Migration:
# Test with CockroachDB
./dev test pkg/cmd/roachprod-centralized/repositories/*/cockroachdb/...
# Error: module not found
# Solution: Ensure you're in the CockroachDB repository root
cd /path/to/cockroach
./dev build roachprod-centralized
# Error: Bazel build failed
# Solution: Clean and rebuild
bazel clean
./dev build roachprod-centralized
# Error: Port already in use
# Solution: Use different port or kill existing process
export ROACHPROD_API_PORT=9090
# Or find and kill the process
lsof -ti:8080 | xargs kill
# Error: Database connection failed
# Solution: Use memory database for development
export ROACHPROD_DATABASE_TYPE=memory
# Error: Tests fail with timeout
# Solution: Increase test timeout
./dev test pkg/cmd/roachprod-centralized/... --timeout=60s
# Error: Race conditions detected
# Solution: Fix race conditions or use build constraints
./dev test pkg/cmd/roachprod-centralized/... --race
# Monitor memory usage
top -p $(pgrep roachprod-centralized)
# Profile memory usage
go tool pprof http://localhost:8080/debug/pprof/heap
# Profile CPU usage
go tool pprof http://localhost:8080/debug/pprof/profile
/docs/ in the CockroachDB repository