ResourcePlugin Interface
The ResourcePlugin interface is the core contract between your plugin and the formae agent. This page documents all methods, their parameters, return types, and behavioral contracts.
Interface Definition
type ResourcePlugin interface {
// Configuration
RateLimit() RateLimitConfig
DiscoveryFilters() []MatchFilter
LabelConfig() LabelConfig
// CRUD Operations
Create(ctx context.Context, req *resource.CreateRequest) (*resource.CreateResult, error)
Read(ctx context.Context, req *resource.ReadRequest) (*resource.ReadResult, error)
Update(ctx context.Context, req *resource.UpdateRequest) (*resource.UpdateResult, error)
Delete(ctx context.Context, req *resource.DeleteRequest) (*resource.DeleteResult, error)
Status(ctx context.Context, req *resource.StatusRequest) (*resource.StatusResult, error)
List(ctx context.Context, req *resource.ListRequest) (*resource.ListResult, error)
}
Configuration Methods
RateLimit
Returns rate limiting configuration for your plugin.
func (p *Plugin) RateLimit() plugin.RateLimitConfig
Returns:
type RateLimitConfig struct {
Scope RateLimitScope
MaxRequestsPerSecondForNamespace int
}
type RateLimitScope string
const (
RateLimitScopeNamespace RateLimitScope = "Namespace"
)
| Field | Description |
|---|---|
Scope |
Currently only RateLimitScopeNamespace is supported |
MaxRequestsPerSecondForNamespace |
Maximum requests per second across all resource types in this plugin |
Example:
func (p *Plugin) RateLimit() plugin.RateLimitConfig {
return plugin.RateLimitConfig{
Scope: plugin.RateLimitScopeNamespace,
MaxRequestsPerSecondForNamespace: 10,
}
}
DiscoveryFilters
Returns filters to exclude resources from discovery.
func (p *Plugin) DiscoveryFilters() []plugin.MatchFilter
Returns:
type MatchFilter struct {
ResourceTypes []string
Conditions []FilterCondition
}
type FilterCondition struct {
PropertyPath string // JSONPath expression
PropertyValue string // Expected value (empty = existence check)
}
Resources matching all conditions in a filter are excluded from discovery.
Example:
func (p *Plugin) DiscoveryFilters() []plugin.MatchFilter {
return []plugin.MatchFilter{
{
ResourceTypes: []string{"MYCLOUD::Compute::Instance"},
Conditions: []plugin.FilterCondition{
{
PropertyPath: "$.Tags[?(@.Key=='formae:skip')].Value",
PropertyValue: "true",
},
},
},
}
}
Return nil to discover all resources.
LabelConfig
Returns configuration for extracting human-readable labels from discovered resources.
func (p *Plugin) LabelConfig() plugin.LabelConfig
Returns:
type LabelConfig struct {
DefaultQuery string
ResourceOverrides map[string]string
}
| Field | Description |
|---|---|
DefaultQuery |
JSONPath expression applied to all resources |
ResourceOverrides |
Per-resource-type JSONPath overrides |
Example:
func (p *Plugin) LabelConfig() plugin.LabelConfig {
return plugin.LabelConfig{
DefaultQuery: "$.Tags[?(@.Key=='Name')].Value",
ResourceOverrides: map[string]string{
"MYCLOUD::IAM::Policy": "$.PolicyName",
"MYCLOUD::IAM::Role": "$.RoleName",
},
}
}
CRUD Methods
Create
Provisions a new resource.
func (p *Plugin) Create(ctx context.Context, req *resource.CreateRequest) (*resource.CreateResult, error)
Request:
type CreateRequest struct {
ResourceType string // e.g., "MYCLOUD::Compute::Instance"
Properties json.RawMessage // Desired resource configuration
TargetConfig json.RawMessage // Credentials and endpoint config
}
Result:
type CreateResult struct {
ProgressResult *ProgressResult
}
Contract:
- On success: Set
OperationStatustoSuccess, provideNativeIDandResourceProperties - On async: Set
OperationStatustoInProgress, provideRequestIDfor polling - On failure: Set
OperationStatustoFailure, provideErrorCodeandStatusMessage - Return Go error only for unexpected/unrecoverable errors
Read
Fetches current state of an existing resource.
func (p *Plugin) Read(ctx context.Context, req *resource.ReadRequest) (*resource.ReadResult, error)
Request:
type ReadRequest struct {
ResourceType string
NativeID string
TargetConfig json.RawMessage
}
Result:
type ReadResult struct {
ResourceType string
NativeID string
ResourceProperties json.RawMessage
ErrorCode OperationErrorCode
}
Contract:
- On success: Provide
ResourcePropertieswith current state - If not found: Set
ErrorCodetoOperationErrorCodeNotFound - Never return Go error for "not found"
Update
Modifies an existing resource.
func (p *Plugin) Update(ctx context.Context, req *resource.UpdateRequest) (*resource.UpdateResult, error)
Request:
type UpdateRequest struct {
ResourceType string
NativeID string
PriorProperties json.RawMessage // State before update
DesiredProperties json.RawMessage // Requested new state
PatchDocument json.RawMessage // JSON Patch of changes
TargetConfig json.RawMessage
}
Result:
type UpdateResult struct {
ProgressResult *ProgressResult
}
Contract:
- Use
DesiredPropertiesfor full replacement orPatchDocumentfor partial update - On success: Provide updated
ResourceProperties - On async: Return
InProgresswithRequestID
Delete
Removes a resource.
func (p *Plugin) Delete(ctx context.Context, req *resource.DeleteRequest) (*resource.DeleteResult, error)
Request:
type DeleteRequest struct {
ResourceType string
NativeID string
TargetConfig json.RawMessage
}
Result:
type DeleteResult struct {
ProgressResult *ProgressResult
}
Contract:
- Must be idempotent—deleting a non-existent resource should succeed
- On success: Set
OperationStatustoSuccess - On async: Return
InProgresswithRequestID
Status
Polls for completion of an async operation.
func (p *Plugin) Status(ctx context.Context, req *resource.StatusRequest) (*resource.StatusResult, error)
Request:
type StatusRequest struct {
ResourceType string
RequestID string // From the original InProgress response
TargetConfig json.RawMessage
}
Result:
type StatusResult struct {
ProgressResult *ProgressResult
}
Contract:
- Called when Create/Update/Delete returns
InProgress - Return
InProgressto continue polling - Return
SuccessorFailurewhen complete - Provide
NativeIDandResourcePropertieson success
List
Returns all resource identifiers of a given type for discovery.
func (p *Plugin) List(ctx context.Context, req *resource.ListRequest) (*resource.ListResult, error)
Request:
type ListRequest struct {
ResourceType string
TargetConfig json.RawMessage
PageToken *string // For pagination
PageSize int // Suggested page size
}
Result:
type ListResult struct {
NativeIDs []string
NextPageToken *string
}
Contract:
- Return all native IDs for resources of the given type
- Use pagination for large result sets
- Set
NextPageTokenif more pages available
ProgressResult
Common result structure for operations:
type ProgressResult struct {
Operation Operation
OperationStatus OperationStatus
RequestID string
NativeID string
ResourceProperties json.RawMessage
ErrorCode OperationErrorCode
StatusMessage string
}
Operation
type Operation string
const (
OperationCreate Operation = "CREATE"
OperationRead Operation = "READ"
OperationUpdate Operation = "UPDATE"
OperationDelete Operation = "DELETE"
OperationCheckStatus Operation = "CHECK_STATUS"
)
OperationStatus
type OperationStatus string
const (
OperationStatusSuccess OperationStatus = "SUCCESS"
OperationStatusFailure OperationStatus = "FAILURE"
OperationStatusInProgress OperationStatus = "IN_PROGRESS"
OperationStatusPending OperationStatus = "PENDING"
)
OperationErrorCode
type OperationErrorCode string
const (
OperationErrorCodeNotFound OperationErrorCode = "NOT_FOUND"
OperationErrorCodeAlreadyExists OperationErrorCode = "ALREADY_EXISTS"
OperationErrorCodeInvalidRequest OperationErrorCode = "INVALID_REQUEST"
OperationErrorCodeAccessDenied OperationErrorCode = "ACCESS_DENIED"
OperationErrorCodeThrottling OperationErrorCode = "THROTTLING"
OperationErrorCodeServiceUnavailable OperationErrorCode = "SERVICE_UNAVAILABLE"
OperationErrorCodeInternalFailure OperationErrorCode = "INTERNAL_FAILURE"
OperationErrorCodeNotStabilized OperationErrorCode = "NOT_STABILIZED"
)
| Error Code | Retriable | Description |
|---|---|---|
NOT_FOUND |
No | Resource does not exist |
ALREADY_EXISTS |
No | Resource already exists (Create) |
INVALID_REQUEST |
No | Invalid parameters |
ACCESS_DENIED |
No | Permission denied |
THROTTLING |
Yes | Rate limited by provider |
SERVICE_UNAVAILABLE |
Yes | Temporary provider outage |
INTERNAL_FAILURE |
Maybe | Unexpected error |
NOT_STABILIZED |
Yes | Resource not yet ready |
See Also
- Tutorial: CRUD Operations - Implementing Create, Read, Update, Delete
- Tutorial: Discovery - Implementing List for discovery