CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-troposphere

AWS CloudFormation creation library that facilitates building infrastructure templates programmatically in Python

Overview
Eval results
Files

validation.mddocs/

Validation

Comprehensive validation system with built-in validators for AWS-specific constraints, data types, and custom validation functions to ensure CloudFormation template correctness.

Capabilities

Core Validators

Basic data type and format validators for common CloudFormation parameter types.

def boolean(x) -> bool:
    """
    Convert value to boolean.
    
    Args:
        x: Value to convert (accepts various truthy/falsy formats)
        
    Returns:
        bool: Boolean value
    """

def integer(x) -> int:
    """
    Validate and convert to integer.
    
    Args:
        x: Value to validate
        
    Returns:
        int: Integer value
        
    Raises:
        ValueError: If value cannot be converted to integer
    """

def positive_integer(x) -> int:
    """
    Validate positive integer (>= 0).
    
    Args:
        x: Value to validate
        
    Returns:
        int: Positive integer value
        
    Raises:
        ValueError: If value is not a positive integer
    """

def integer_range(minimum: int, maximum: int) -> Callable:
    """
    Create validator for integer within specified range.
    
    Args:
        minimum: Minimum allowed value (inclusive)
        maximum: Maximum allowed value (inclusive)
        
    Returns:
        Callable: Validator function
    """

def double(x) -> float:
    """
    Validate and convert to floating point number.
    
    Args:
        x: Value to validate
        
    Returns:
        float: Float value
        
    Raises:
        ValueError: If value cannot be converted to float
    """

def network_port(x) -> int:
    """
    Validate network port number (0-65535).
    
    Args:
        x: Port number to validate
        
    Returns:
        int: Valid port number
        
    Raises:
        ValueError: If port is outside valid range
    """

AWS-Specific Validators

Validators for AWS resource naming and format requirements.

def s3_bucket_name(b) -> str:
    """
    Validate S3 bucket name format.
    
    Args:
        b: Bucket name to validate
        
    Returns:
        str: Valid bucket name
        
    Raises:
        ValueError: If bucket name doesn't meet S3 requirements
    """

def elb_name(b) -> str:
    """
    Validate Elastic Load Balancer name format.
    
    Args:
        b: ELB name to validate
        
    Returns:
        str: Valid ELB name
        
    Raises:
        ValueError: If name doesn't meet ELB requirements
    """

def encoding(encoding) -> str:
    """
    Validate encoding type.
    
    Args:
        encoding: Encoding name to validate
        
    Returns:
        str: Valid encoding name
        
    Raises:
        ValueError: If encoding is not supported
    """

def json_checker(data) -> dict:
    """
    Validate JSON structure.
    
    Args:
        data: Data to validate as JSON
        
    Returns:
        dict: Validated JSON data
        
    Raises:
        ValueError: If data is not valid JSON
    """

Constraint Validators

Validators for enforcing property constraints and dependencies.

def one_of(class_name: str, properties: dict, property: str, conditionals: list) -> None:
    """
    Validate that property value is from allowed list.
    
    Args:
        class_name: Class name for error messages
        properties: Properties dictionary
        property: Property name to validate
        conditionals: List of allowed values
        
    Raises:
        ValueError: If property value not in allowed list
    """

def mutually_exclusive(class_name: str, properties: dict, conditionals: list) -> None:
    """
    Validate that only one of the specified properties is set.
    
    Args:
        class_name: Class name for error messages
        properties: Properties dictionary
        conditionals: List of mutually exclusive property names
        
    Raises:
        ValueError: If multiple exclusive properties are set
    """

def exactly_one(class_name: str, properties: dict, conditionals: list) -> None:
    """
    Validate that exactly one of the specified properties is set.
    
    Args:
        class_name: Class name for error messages
        properties: Properties dictionary
        conditionals: List of property names (exactly one required)
        
    Raises:
        ValueError: If zero or multiple properties are set
    """

def check_required(class_name: str, properties: dict, conditionals: list) -> None:
    """
    Validate that required properties are present.
    
    Args:
        class_name: Class name for error messages
        properties: Properties dictionary
        conditionals: List of required property names
        
    Raises:
        ValueError: If required properties are missing
    """

Custom Validation Functions

Examples of creating custom validators for specific use cases.

def validate_cidr_block(cidr: str) -> str:
    """
    Custom validator for CIDR blocks.
    
    Args:
        cidr: CIDR block string
        
    Returns:
        str: Valid CIDR block
        
    Raises:
        ValueError: If CIDR format is invalid
    """

def validate_email(email: str) -> str:
    """
    Custom validator for email addresses.
    
    Args:
        email: Email address string
        
    Returns:
        str: Valid email address
        
    Raises:
        ValueError: If email format is invalid
    """

def validate_tags(tags: dict) -> dict:
    """
    Custom validator for tag dictionaries.
    
    Args:
        tags: Dictionary of tags
        
    Returns:
        dict: Valid tags dictionary
        
    Raises:
        ValueError: If tags format is invalid
    """

Usage Examples

Basic Type Validation

from troposphere import Parameter
from troposphere.validators import positive_integer, network_port, boolean

# Parameter with positive integer validation
memory_size = Parameter(
    "MemorySize",
    Type="Number",
    Default=128,
    Description="Lambda function memory size in MB",
    props={
        "MemorySize": (positive_integer, True)
    }
)

# Parameter with port validation
app_port = Parameter(
    "ApplicationPort",
    Type="Number",
    Default=8080,
    Description="Application port number",
    props={
        "ApplicationPort": (network_port, True)
    }
)

# Boolean parameter with validation
enable_monitoring = Parameter(
    "EnableMonitoring",
    Type="String",
    Default="true",
    AllowedValues=["true", "false"],
    Description="Enable CloudWatch monitoring",
    props={
        "EnableMonitoring": (boolean, False)
    }
)

AWS Resource Validation

from troposphere.validators import s3_bucket_name, elb_name
from troposphere import Parameter

# S3 bucket name validation
bucket_name = Parameter(
    "BucketName",
    Type="String",
    Description="S3 bucket name",
    props={
        "BucketName": (s3_bucket_name, True)
    }
)

# ELB name validation  
load_balancer_name = Parameter(
    "LoadBalancerName",
    Type="String",
    Description="Load balancer name",
    props={
        "LoadBalancerName": (elb_name, True)
    }
)

Range Validation

from troposphere.validators import integer_range
from troposphere import Parameter

# Create range validator
port_range_validator = integer_range(1024, 65535)

# Parameter with range validation
app_port = Parameter(
    "ApplicationPort",
    Type="Number",
    Default=8080,
    Description="Application port (1024-65535)",
    props={
        "ApplicationPort": (port_range_validator, True)
    }
)

# Database storage size validation
storage_range_validator = integer_range(20, 1000)

db_storage = Parameter(
    "DBStorageSize",
    Type="Number",
    Default=100,
    Description="Database storage size in GB (20-1000)",
    props={
        "DBStorageSize": (storage_range_validator, True)
    }
)

Constraint Validation in Resources

from troposphere import AWSProperty
from troposphere.validators import mutually_exclusive, exactly_one

class CustomProperty(AWSProperty):
    props = {
        "SourceType": (str, False),
        "SourceValue": (str, False),
        "SourceArn": (str, False),
        "SourceAccount": (str, False)
    }
    
    def validate(self):
        # Exactly one source must be specified
        exactly_one(
            self.__class__.__name__,
            self.properties,
            ["SourceValue", "SourceArn", "SourceAccount"]
        )
        
        # Source type and value are mutually exclusive with ARN
        mutually_exclusive(
            self.__class__.__name__,
            self.properties,
            [["SourceType", "SourceValue"], ["SourceArn"]]
        )

Custom Validators

import re
import ipaddress
from troposphere import Parameter
from troposphere.validators import one_of

def validate_cidr_block(cidr):
    """Validate CIDR block format."""
    try:
        ipaddress.IPv4Network(cidr, strict=False)
        return cidr
    except ValueError:
        raise ValueError(f"Invalid CIDR block: {cidr}")

def validate_email(email):
    """Validate email address format."""
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    if not re.match(pattern, email):
        raise ValueError(f"Invalid email address: {email}")
    return email

def validate_instance_family(instance_type):
    """Validate instance type belongs to allowed families."""
    allowed_families = ['t2', 't3', 'm5', 'c5', 'r5']
    family = instance_type.split('.')[0]
    if family not in allowed_families:
        raise ValueError(f"Instance family {family} not allowed")
    return instance_type

# Use custom validators in parameters
vpc_cidr = Parameter(
    "VpcCidr",
    Type="String",
    Default="10.0.0.0/16",
    Description="VPC CIDR block",
    props={
        "VpcCidr": (validate_cidr_block, True)
    }
)

notification_email = Parameter(
    "NotificationEmail",
    Type="String",
    Description="Email for notifications",
    props={
        "NotificationEmail": (validate_email, True)
    }
)

instance_type = Parameter(
    "InstanceType",
    Type="String",
    Default="t3.micro",
    Description="EC2 instance type (restricted families)",
    props={
        "InstanceType": (validate_instance_family, True)
    }
)

Conditional Validation

from troposphere import AWSObject
from troposphere.validators import check_required

class ConditionalResource(AWSObject):
    props = {
        "Type": (str, True),
        "DatabaseConfig": (dict, False),
        "CacheConfig": (dict, False),
        "DatabaseEndpoint": (str, False),
        "CacheEndpoint": (str, False)
    }
    
    def validate(self):
        # Check conditional requirements based on type
        if self.properties.get("Type") == "database":
            check_required(
                self.__class__.__name__,
                self.properties,
                ["DatabaseConfig", "DatabaseEndpoint"]
            )
        elif self.properties.get("Type") == "cache":
            check_required(
                self.__class__.__name__,
                self.properties,
                ["CacheConfig", "CacheEndpoint"]
            )

Validation with Error Handling

from troposphere import Template, Parameter
from troposphere.validators import positive_integer

def safe_create_parameter(template, name, param_type, default_value, validator=None):
    """Safely create parameter with validation and error handling."""
    try:
        props = {}
        if validator:
            props[name] = (validator, True)
            
        param = Parameter(
            name,
            Type=param_type,
            Default=default_value,
            props=props
        )
        
        return template.add_parameter(param)
        
    except ValueError as e:
        print(f"Validation error for parameter {name}: {e}")
        raise
    except Exception as e:
        print(f"Error creating parameter {name}: {e}")
        raise

# Usage
template = Template()

# This will succeed
memory_param = safe_create_parameter(
    template, "MemorySize", "Number", 128, positive_integer
)

# This would fail validation
try:
    invalid_param = safe_create_parameter(
        template, "InvalidMemory", "Number", -1, positive_integer
    )
except ValueError:
    print("Caught validation error for negative memory size")

Install with Tessl CLI

npx tessl i tessl/pypi-troposphere

docs

aws-resources.md

constants.md

helper-utilities.md

index.md

intrinsic-functions.md

openstack-support.md

parameters-outputs.md

tags-metadata.md

template-management.md

validation.md

tile.json