Integration points - Factory functions and registry
CLI commands - User-facing command line interface
JSON schemas - Validation for manifests and API requests
Documentation - User and design documentation
CCM Studio - Web-based manifest designer
File Checklist
File
Action
Purpose
model/resource_<type>.go
Create
Properties, state, metadata structs
model/resource_<type>_test.go
Create
Property validation tests
model/resource.go
Modify
Add case to factory function
resources/<type>/<type>.go
Create
Provider interface definition
resources/<type>/type.go
Create
Resource type implementation
resources/<type>/type_test.go
Create
Resource type tests
resources/<type>/provider_mock_test.go
Generate
Mock provider for tests
resources/<type>/<provider>/factory.go
Create
Provider factory
resources/<type>/<provider>/<provider>.go
Create
Provider implementation
resources/<type>/<provider>/<provider>_test.go
Create
Provider tests
resources/resources.go
Modify
Add case to NewResourceFromProperties
cmd/ensure_<type>.go
Create
CLI command handler
cmd/ensure.go
Modify
Register CLI command
internal/fs/schemas/manifest.json
Modify
Add resource schema definitions
internal/fs/schemas/resource_ensure_request.json
Modify
Add API request schema
docs/content/resources/<type>.md
Create
User documentation
docs/content/design/<type>/_index.md
Create
Design documentation
docs/content/design/<type>/<provider>.md
Create
Provider documentation
Step 1: Model Definitions
Create model/resource_<type>.go with the following components.
Constants
const (
// ResourceStatus<Type>Protocol is the protocol identifier for <type> resource stateResourceStatus<Type>Protocol = "io.choria.ccm.v1.resource.<type>.state"// <Type>TypeName is the type name for <type> resources <Type>TypeName = "<type>")
Properties Struct
The properties struct must satisfy model.ResourceProperties:
type <Type>Metadatastruct {
Namestring`json:"name" yaml:"name"`Providerstring`json:"provider,omitempty" yaml:"provider,omitempty"`// Add fields describing current system state}
type <Type>Statestruct {
CommonResourceStateMetadata*<Type>Metadata`json:"metadata,omitempty"`}
Embedding *base.Base provides implementations for Apply(), Healthcheck(), Type(), Name(), Properties(), and NewTransactionEvent(). The type must implement:
See resources/archive/type.go for a complete constructor example.
ApplyResource Method
The ApplyResource method (part of base.EmbeddedResource) contains the core logic. It should follow this pattern:
Get initial state via provider.Status()
Check if already in desired state (implement isDesiredState() helper)
If stable, call t.FinalizeState() and return early
Apply changes, respecting t.mgr.NoopMode()
Get final state and verify desired state was achieved
Call t.FinalizeState() with appropriate flags
See resources/archive/type.go:ApplyResource() for a complete example.
Provider Selection Methods
The SelectProvider() method should use registry.FindSuitableProvider() to select an appropriate provider. See resources/archive/type.go for the standard implementation pattern.
if !noop {
// Make actual changest.log.Info("Applying changes")
err = p.SomeAction(ctx, properties)
} else {
t.log.Info("Skipping changes as noop")
noopMessage = "Would have applied changes"}
Error Handling
Use sentinel errors from model/errors.go:
var (
ErrResourceInvalid = errors.New("resource invalid")
ErrProviderNotFound = errors.New("provider not found")
ErrNoSuitableProvider = errors.New("no suitable provider")
ErrDesiredStateFailed = errors.New("desired state not achieved")
)
Wrap errors with context:
err:=os.Remove(path)
iferr!=nil {
returnfmt.Errorf("could not remove file: %w", err)
}
Template Resolution
The ResolveTemplates method (part of model.ResourceProperties) should resolve all user-facing string fields using templates.ResolveTemplateString(). Always call the embedded CommonResourceProperties.ResolveTemplates(env) first.
Provider Selection
Providers declare manageability via IsManageable on the factory (see model.ProviderFactory in Step 3). Multiple providers can match; the one with highest priority is selected.
Documentation
Create user documentation in docs/content/resources/<type>.md covering:
Overview and use cases
Ensure states table
Properties table with descriptions
Usage examples (manifest, CLI, API)
Create design documentation in docs/content/design/<type>/_index.md covering:
Provider interface specification
State checking logic
Apply logic flowchart
Create provider documentation in docs/content/design/<type>/<provider>.md covering:
Provider selection criteria
Platform requirements
Implementation details
CCM Studio
CCM Studio is a web-based manifest designer. After adding a new resource type, update CCM Studio to support it:
Note
CCM Studio is a closed-source project. The maintainers will complete this step.
Add the new resource type to the resource palette
Create property editors for type-specific fields
Add validation matching the JSON schema definitions
Update any resource type documentation or help text