🧩 Component Model¶
Pyvider's component model provides a powerful, decorator-based system for building Terraform providers. This document explores the architecture of how components are defined, discovered, registered, and managed.
🤖 AI-Generated Content
This documentation was generated with AI assistance and is still being audited. Some, or potentially a lot, of this information may be inaccurate. Learn more.
📊 Component Hierarchy¶
graph TB
subgraph "Component Types"
P[Provider]
R[Resources]
D[Data Sources]
F[Functions]
E[Ephemeral Resources]
C[Capabilities]
end
P --> R
P --> D
P --> F
P --> E
R -.-> C
D -.-> C
E -.-> C
style P fill:#f9f,stroke:#333,stroke-width:4px
style C fill:#bbf,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5
🎯 Component Types¶
1. Provider Component¶
Purpose: Root component that configures authentication and shared settings
Key Characteristics: - Singleton: Only one provider instance per Terraform configuration - Configuration Hub: Stores shared configuration for all resources - Authentication: Manages API credentials and client initialization - Metadata: Defines provider name, version, and capabilities
Registration: @register_provider("name")
See: Creating Providers Guide for complete examples
2. Resource Component¶
Purpose: Manages infrastructure with full CRUD lifecycle
Lifecycle Methods:
- _create_apply() - Creates new infrastructure
- read() - Refreshes current state
- _update_apply() - Modifies existing infrastructure
- _delete_apply() - Removes infrastructure
Key Features:
- State tracking via State class
- Private state for sensitive data
- Configuration validation
- Drift detection
Registration: @register_resource("name")
See: Creating Resources Guide for complete examples
3. Data Source Component¶
Purpose: Read-only access to existing infrastructure
Lifecycle Methods:
- read() - Fetches data from external systems
Key Features: - No state modification - Query-based data retrieval - Computed-only attributes - Caching support
Registration: @register_data_source("name")
See: Creating Data Sources Guide for complete examples
4. Function Component¶
Purpose: Pure, callable transformations
Lifecycle Methods:
- call() - Executes transformation logic
Key Features: - Stateless operations - Input/output type safety - No side effects - Terraform-native functions
Registration: @register_function(name="name")
See: Creating Functions Guide for complete examples
5. Ephemeral Resource Component¶
Purpose: Short-lived connections or sessions
Lifecycle Methods:
- open() - Creates ephemeral resource
- renew() - Extends lifetime
- close() - Destroys resource
Key Features: - Not persisted in state - Automatic lifecycle management - Time-based renewal - Perfect for credentials, connections
Registration: @register_ephemeral_resource("name")
See: Ephemeral Resources API for complete examples
🔍 Component Discovery¶
Discovery Mechanism¶
Pyvider uses a multi-stage discovery process:
- Entry Point Scanning: Looks for
pyvider.componentsentry points in installed packages - Package Traversal: Recursively scans packages for decorated classes
- Decorator Detection: Identifies classes with
@register_*decorators - Validation: Ensures components meet interface requirements
- Registration: Adds valid components to the component hub
Entry Points¶
Components can be discovered through Python entry points in pyproject.toml:
Manual Registration¶
For testing or dynamic scenarios:
| Python | |
|---|---|
🎨 Decorator System¶
Registration Decorators¶
Each component type has its own registration decorator:
| Decorator | Component Type |
|---|---|
@register_provider("name") |
Provider |
@register_resource("name") |
Resource |
@register_data_source("name") |
Data Source |
@register_function(name="name") |
Function |
@register_ephemeral_resource("name") |
Ephemeral |
@register_capability("name") |
Capability |
Decorator Metadata¶
Decorators attach metadata to classes for discovery:
| Python | |
|---|---|
🔗 Component Relationships¶
Provider Access¶
Resources and other components can access the provider instance via the component hub:
| Python | |
|---|---|
Capability Composition¶
Components can use capabilities for cross-cutting concerns:
| Python | |
|---|---|
📋 Schema Generation¶
Automatic Type Mapping¶
Pyvider automatically generates Terraform schemas from Python type annotations:
| Python Type | Terraform Type |
|---|---|
str |
string |
int, float |
number |
bool |
bool |
list[T] |
list(T) |
dict[str, T] |
map(T) |
set[T] |
set(T) |
@attrs.define class |
object |
Schema Definition¶
Components define schemas using factory functions:
| Python | |
|---|---|
See: Schema System and Schema Documentation
🔄 Component Lifecycle¶
Initialization Flow¶
stateDiagram-v2
[*] --> Decorated: @register_* applied
Decorated --> Discovered: Discovery scan
Discovered --> Registered: Added to hub
Registered --> Validated: Schema validation
Validated --> Ready: Available for use
Ready --> Instantiated: Request received
Instantiated --> Configured: Provider injected
Configured --> Active: Processing requests
Active --> [*]: Request complete
Invocation Pattern¶
| Python | |
|---|---|
🛡️ Validation¶
Component Validation¶
During registration, components are validated for:
- Correct base class inheritance
- Required methods present
- Schema class definitions
- Type signature correctness
Schema Validation¶
Runtime validation ensures:
- Configuration matches schema
- Required fields present
- Type constraints satisfied
- Custom validators pass
🎯 Best Practices¶
1. Component Design¶
Do: - Focus on single responsibility - Use descriptive, Terraform-friendly names - Implement comprehensive error handling - Document all attributes and methods
Don't: - Mix multiple concerns in one component - Use generic names - Ignore validation - Skip documentation
2. Naming Conventions¶
- Resources: Nouns describing infrastructure (
server,database,network) - Data Sources: Plural or descriptive (
images,availability_zones,account_info) - Functions: Action verbs (
encode,parse,transform)
3. State Management¶
- Store only essential state data
- Use private state for sensitive information
- Implement proper
read()for drift detection - Handle missing resources gracefully
4. Error Handling¶
- Provide clear, actionable error messages
- Use appropriate exception types
- Include relevant context in errors
- Log errors with structured data
📚 Advanced Topics¶
Dynamic Component Registration¶
Create components at runtime:
| Python | |
|---|---|
Component Inheritance¶
Share functionality across components:
| Python | |
|---|---|
🔗 Related Documentation¶
- Architecture Overview - System architecture and data flow
- Schema System - Type-safe data modeling
- Creating Providers - Step-by-step provider guide
- Creating Resources - Resource implementation guide
- Creating Data Sources - Data source patterns
- Creating Functions - Function development
- Best Practices - Production-focused patterns
Continue to Schema System →