Adding a Provider
Purpose: For contributors, shows how to implement a new provider interface.
Prerequisites
- Go 1.25.2+ and mise installed (see CLI Development Setup)
- Understanding of the CLI's dependency injection pattern (
internal/di/) - Access to the target cloud provider's API documentation
Steps
1. Create the provider package
Add a new package under internal/provision/ (or internal/cloud/ for cloud-specific API clients). The CLI already supports OpenStack (via gophercloud), VMware, AWS, and Kind.
openCenter-cli/internal/provision/
├── openstack/ # existing
├── vmware/ # existing
├── aws/ # existing
├── kind/ # existing
└── myprovider/ # your new provider
├── provider.go
├── provider_test.go
└── templates/
2. Implement the provider interface
Each provider must satisfy the provisioning interface used by the CLI's cluster commands. At minimum, implement:
- Infrastructure generation (OpenTofu/Terraform
main.tf) - Inventory generation (Kubespray
inventory.yaml) - Credential handling (how the provider authenticates)
// provider.go
package myprovider
// Provider implements the infrastructure provisioning interface
// for the target cloud platform.
type Provider struct {
// Inject dependencies via constructor, not globals
}
func NewProvider(cfg *config.ClusterConfig) *Provider {
return &Provider{}
}
3. Add Go templates for infrastructure artifacts
Place Go templates in your provider's templates/ directory. The CLI's template engine (internal/template/) renders these using Go's text/template with Sprig functions. Templates receive the cluster configuration struct as their data context.
myprovider/templates/
├── main.tf.tmpl # OpenTofu infrastructure
├── variables.tf.tmpl # Terraform variables
├── provider.tf.tmpl # Provider configuration
└── inventory.yaml.tmpl # Kubespray inventory
4. Register the provider
Wire the provider into the CLI's dependency injection container in internal/di/. The container resolves providers by the opencenter.provider field in the cluster configuration.
5. Add configuration schema fields
If the provider requires new configuration fields (e.g., API endpoints, regions), add them to the config structs in internal/config/. Include validate struct tags using go-playground/validator syntax.
type MyProviderConfig struct {
Endpoint string `yaml:"endpoint" validate:"required,url"`
Region string `yaml:"region" validate:"required"`
}
6. Write tests
- Unit tests for the provider logic in
myprovider/provider_test.go - BDD scenarios in
tests/features/for end-to-end cluster init/setup with the new provider - Property tests for any validation logic (see
internal/config/for examples)
mise run test
mise run godog
Verification
# Build and test
mise run build
mise run test
# Init a cluster with the new provider
./bin/opencenter cluster init test-cluster --force
# Edit to set provider
./bin/opencenter cluster edit test-cluster
# Validate
./bin/opencenter cluster validate test-cluster
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
unknown provider error at runtime | Provider not registered in DI container | Check internal/di/ wiring |
| Template rendering fails | Missing Sprig function or wrong data context | Test templates with opencenter cluster render |
| Validation errors on new fields | Missing or incorrect validate struct tags | Review go-playground/validator docs for tag syntax |