CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-terraformpy

Python library and CLI tool for generating Terraform JSON configurations using full Python programming capabilities

Overview
Eval results
Files

resource-collections.mddocs/

Resource Collections

Framework for creating reusable, parameterized groups of Terraform resources that can be instantiated with different configurations. Resource collections support environment-specific variants, inheritance patterns, and validation using the schematics library.

Capabilities

ResourceCollection Base Class

Base class for creating reusable groups of Terraform resources with parameter validation and environment-specific variants.

class ResourceCollection(schematics.Model):
    def __init__(self, **kwargs):
        """
        Create a resource collection instance.

        Parameters:
        - **kwargs: Collection-specific parameters defined as schematics types

        The constructor automatically validates parameters and calls create_resources().
        """

    def create_resources(self):
        """
        Abstract method that must be implemented by subclasses.

        This method should create the Terraform resources for this collection.
        Access collection parameters via self.parameter_name.
        """
        raise NotImplementedError("Subclasses must implement create_resources()")

    # Variant support
    def __init__(self, **kwargs):
        """
        Supports variant-specific parameter overrides.

        Parameters ending with '_variant' are used as overrides when
        within a matching Variant context.

        Example:
        MyCollection(count=2, production_variant={'count': 5})
        """

Variant Context Manager

Context manager for environment-specific configurations that enables automatic parameter overrides based on environment context.

class Variant:
    def __init__(self, name: str):
        """
        Create a variant context.

        Parameters:
        - name: str - Variant name (e.g., 'production', 'staging', 'development')

        Example:
        with Variant('production'):
            # Collections instantiated here use production-specific overrides
            pass
        """

    def __enter__(self):
        """Enter variant context - subsequent collections use variant overrides."""

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Exit variant context."""

Usage Examples

Basic Resource Collection

from terraformpy import ResourceCollection, Resource
import schematics

class WebServerStack(ResourceCollection):
    # Define collection parameters using schematics types
    instance_type = schematics.StringType(default='t3.micro')
    instance_count = schematics.IntType(default=1, min_value=1)
    environment = schematics.StringType(required=True)

    def create_resources(self):
        # Create resources using collection parameters
        for i in range(self.instance_count):
            Resource('aws_instance', f'web_{i}',
                instance_type=self.instance_type,
                ami='ami-12345678',
                tags={
                    'Name': f'WebServer-{i}-{self.environment}',
                    'Environment': self.environment
                }
            )

# Instantiate the collection
web_stack = WebServerStack(
    instance_count=3,
    environment='production'
)

Collection with Dependencies

from terraformpy import ResourceCollection, Resource, Data
import schematics

class DatabaseStack(ResourceCollection):
    db_instance_class = schematics.StringType(default='db.t3.micro')
    db_name = schematics.StringType(required=True)
    subnet_group_name = schematics.StringType(required=True)

    def create_resources(self):
        # Query existing security group
        db_sg = Data('aws_security_group', 'db_sg',
            filters={'tag:Name': f'{self.db_name}-db-sg'}
        )

        # Create RDS instance
        db_instance = Resource('aws_db_instance', 'main',
            identifier=self.db_name,
            instance_class=self.db_instance_class,
            engine='postgres',
            engine_version='13.7',
            allocated_storage=20,
            db_name=self.db_name,
            username='postgres',
            manage_master_user_password=True,
            db_subnet_group_name=self.subnet_group_name,
            vpc_security_group_ids=[db_sg.id]
        )

        # Create parameter group
        Resource('aws_db_parameter_group', 'main',
            family='postgres13',
            name=f'{self.db_name}-params',
            parameters=[
                {'name': 'log_connections', 'value': '1'},
                {'name': 'log_checkpoints', 'value': '1'}
            ]
        )

# Use the collection
db_stack = DatabaseStack(
    db_name='myapp',
    db_instance_class='db.r6g.large',
    subnet_group_name='myapp-db-subnets'
)

Environment-Specific Variants

from terraformpy import ResourceCollection, Resource, Variant
import schematics

class ApplicationStack(ResourceCollection):
    instance_type = schematics.StringType(default='t3.micro')
    min_size = schematics.IntType(default=1)
    max_size = schematics.IntType(default=3)
    desired_capacity = schematics.IntType(default=2)

    def create_resources(self):
        # Auto Scaling Group
        Resource('aws_autoscaling_group', 'app',
            min_size=self.min_size,
            max_size=self.max_size,
            desired_capacity=self.desired_capacity,
            launch_template={
                'id': '${aws_launch_template.app.id}',
                'version': '$Latest'
            }
        )

        # Launch Template
        Resource('aws_launch_template', 'app',
            instance_type=self.instance_type,
            image_id='ami-12345678'
        )

# Development environment
with Variant('development'):
    dev_stack = ApplicationStack(
        instance_type='t3.micro',
        min_size=1,
        max_size=2,
        desired_capacity=1,
        # Development-specific overrides
        development_variant={
            'instance_type': 't3.nano',  # Smaller instances in dev
            'min_size': 0,               # Allow scaling to zero
            'desired_capacity': 0        # Start with no instances
        }
    )

# Production environment
with Variant('production'):
    prod_stack = ApplicationStack(
        instance_type='t3.medium',
        min_size=2,
        max_size=10,
        desired_capacity=4,
        # Production-specific overrides
        production_variant={
            'instance_type': 'c5.large',  # More powerful instances
            'min_size': 3,                # Higher minimum
            'max_size': 20,               # Higher maximum
            'desired_capacity': 6         # More initial capacity
        }
    )

Collection Composition

from terraformpy import ResourceCollection
import schematics

class NetworkingStack(ResourceCollection):
    vpc_cidr = schematics.StringType(default='10.0.0.0/16')

    def create_resources(self):
        # VPC resources
        Resource('aws_vpc', 'main', cidr_block=self.vpc_cidr)
        # ... other networking resources

class SecurityStack(ResourceCollection):
    vpc_id = schematics.StringType(required=True)

    def create_resources(self):
        # Security groups, NACLs, etc.
        Resource('aws_security_group', 'web',
            vpc_id=self.vpc_id,
            # ... security group rules
        )

class FullStack(ResourceCollection):
    environment = schematics.StringType(required=True)

    def create_resources(self):
        # Compose multiple stacks
        network = NetworkingStack()

        # Reference network resources in security stack
        security = SecurityStack(vpc_id='${aws_vpc.main.id}')

# Deploy complete infrastructure
full_stack = FullStack(environment='staging')

Parameter Validation

from terraformpy import ResourceCollection
import schematics

class ValidatedStack(ResourceCollection):
    # String with choices
    environment = schematics.StringType(
        required=True,
        choices=['dev', 'staging', 'production']
    )

    # Integer with validation
    instance_count = schematics.IntType(
        default=1,
        min_value=1,
        max_value=10
    )

    # Custom validation
    def validate_instance_count(self, value):
        if self.environment == 'production' and value < 2:
            raise schematics.ValidationError(
                'Production environment requires at least 2 instances'
            )
        return value

    def create_resources(self):
        for i in range(self.instance_count):
            Resource('aws_instance', f'app_{i}',
                instance_type='t3.micro',
                tags={'Environment': self.environment}
            )

# This will raise ValidationError
try:
    ValidatedStack(environment='production', instance_count=1)
except schematics.ValidationError as e:
    print(f"Validation failed: {e}")

# This will succeed
ValidatedStack(environment='production', instance_count=3)

Install with Tessl CLI

npx tessl i tessl/pypi-terraformpy

docs

aws-hooks.md

cli.md

compilation-hooks.md

core-objects.md

helpers.md

index.md

resource-collections.md

tile.json