Resource Lifecycle API Reference¶
Alpha Status
pyvider is in alpha. This reference covers stable APIs.
Complete API reference for resource lifecycle methods and the ResourceContext object.
Base Resource Class¶
Class Attributes¶
| Attribute | Type | Required | Description |
|---|---|---|---|
config_class |
Type[attrs.define] |
Yes | Configuration attrs class |
state_class |
Type[attrs.define] |
Yes | State attrs class |
Lifecycle Methods¶
Required Methods¶
read()¶
async def read(self, ctx: ResourceContext) -> StateType | None:
"""Refresh state from remote system."""
Purpose: Check if the resource still exists and return its current state.
Parameters:
- ctx: ResourceContext with current state
Returns:
- StateType: Current state if resource exists
- None: Resource no longer exists (deleted outside Terraform)
When Called: During terraform plan and terraform refresh
Example:
async def read(self, ctx: ResourceContext) -> ServerState | None:
if not ctx.state:
return None
try:
server = await api.get_server(ctx.state.id)
return ServerState(
id=server["id"],
name=server["name"],
status=server["status"],
)
except NotFoundError:
return None # Server deleted
_delete_apply()¶
Purpose: Remove the resource from the remote system.
Parameters:
- ctx: ResourceContext with current state
Returns: None
When Called: During terraform destroy or when resource removed from config
Example:
async def _delete_apply(self, ctx: ResourceContext) -> None:
if not ctx.state:
return
await api.delete_server(ctx.state.id)
Optional Methods¶
_create_apply()¶
async def _create_apply(
self,
ctx: ResourceContext
) -> tuple[StateType | None, PrivateData | None]:
"""Create the resource."""
Purpose: Create a new resource.
Parameters:
- ctx: ResourceContext with configuration
Returns:
- Tuple of (state, private_data)
- state: New state to track
- private_data: Sensitive data (not in state file)
When Called: During terraform apply when creating new resource
Default Behavior: Calls _update_apply() if not overridden
Example:
async def _create_apply(self, ctx: ResourceContext) -> tuple[ServerState | None, None]:
if not ctx.config:
return None, None
server = await api.create_server(
name=ctx.config.name,
size=ctx.config.size,
)
return ServerState(
id=server["id"],
name=server["name"],
size=server["size"],
status=server["status"],
), None
_update_apply()¶
async def _update_apply(
self,
ctx: ResourceContext
) -> tuple[StateType | None, PrivateData | None]:
"""Update the resource."""
Purpose: Modify an existing resource.
Parameters:
- ctx: ResourceContext with configuration and current state
Returns:
- Tuple of (state, private_data)
- state: Updated state
- private_data: Sensitive data (not in state file)
When Called: During terraform apply when updating existing resource
Example:
async def _update_apply(self, ctx: ResourceContext) -> tuple[ServerState | None, None]:
if not ctx.config or not ctx.state:
return None, None
server = await api.update_server(
id=ctx.state.id,
name=ctx.config.name,
size=ctx.config.size,
)
return ServerState(
id=ctx.state.id,
name=server["name"],
size=server["size"],
status=server["status"],
), None
_validate_config()¶
Purpose: Validate user configuration before applying.
Parameters:
- config: Typed configuration object
Returns: - List of error messages (empty list = valid)
When Called: During terraform plan and terraform apply
Example:
async def _validate_config(self, config: ServerConfig) -> list[str]:
errors = []
if len(config.name) < 3:
errors.append("Name must be at least 3 characters")
if config.size not in ["small", "medium", "large"]:
errors.append("Size must be small, medium, or large")
return errors
ResourceContext API¶
Properties¶
config¶
Typed configuration attrs instance. None if configuration contains unknown values.
Example:
config_cty¶
Raw CTY value from Terraform, always available even with unknown values.
Example:
state¶
Current state. None during create operations.
Example:
planned_state¶
Planned state from plan phase.
Example:
Methods¶
is_field_unknown()¶
Check if a configuration field has an unknown value (e.g., depends on another resource).
Parameters:
- field_name: Name of the configuration field
Returns: True if value is unknown
Example:
add_error()¶
Add an error diagnostic to show in Terraform output.
Parameters:
- message: Error message
Example:
add_warning()¶
Add a warning diagnostic to show in Terraform output.
Parameters:
- message: Warning message
Example:
Schema Definition¶
get_schema()¶
Returns: PvsSchema object defining the resource schema
Example:
from pyvider.schema import s_resource, a_str, a_num, a_bool
@classmethod
def get_schema(cls) -> PvsSchema:
return s_resource({
# User inputs
"name": a_str(required=True, description="Server name"),
"size": a_str(default="small", description="Server size"),
"enabled": a_bool(default=True, description="Enabled status"),
# Provider outputs
"id": a_str(computed=True, description="Server ID"),
"status": a_str(computed=True, description="Server status"),
"created_at": a_num(computed=True, description="Creation timestamp"),
})
Type Signatures¶
Configuration Class¶
import attrs
@attrs.define
class ServerConfig:
"""User-provided configuration."""
name: str
size: str = "small"
enabled: bool = True
State Class¶
import attrs
@attrs.define
class ServerState:
"""Provider-managed state."""
id: str
name: str
size: str
enabled: bool
status: str
created_at: int
Private Data¶
Sensitive data that shouldn't be stored in state:
async def _create_apply(self, ctx: ResourceContext) -> tuple[State, dict]:
server = await api.create_server(...)
state = ServerState(
id=server["id"],
name=server["name"],
)
private_data = {
"api_key": server["api_key"], # Not in state
"password": server["password"], # Not in state
}
return state, private_data
Access private data:
async def _update_apply(self, ctx: ResourceContext):
if hasattr(ctx, "private"):
api_key = ctx.private.get("api_key")
Lifecycle Sequence¶
Create Resource¶
- User adds resource to Terraform config
terraform plan:- Calls
_validate_config()with configuration - Calls
get_schema()to validate schema terraform apply:- Calls
_create_apply()with ctx.config - Stores returned state
Update Resource¶
- User modifies resource in Terraform config
terraform plan:- Calls
read()to get current state - Calls
_validate_config()with new configuration - Compares current state with planned state
terraform apply:- Calls
_update_apply()with ctx.config and ctx.state - Stores returned state
Delete Resource¶
- User removes resource from Terraform config
terraform plan:- Shows resource will be deleted
terraform apply:- Calls
_delete_apply()with ctx.state - Removes resource from state
Refresh State¶
terraform refreshorterraform plan:- Calls
read()with ctx.state - Updates state if changed
- Removes from state if
read()returnsNone
See Also¶
- Create a Resource - How-to guide
- Building Your First Resource - Tutorial
- Add Validation - Validation patterns
- API Reference - Auto-generated API docs