Add dynamic resource generation from AWS CloudFormation schemas#199
Add dynamic resource generation from AWS CloudFormation schemas#199Jordi Soucheiron (jsoucheiron) wants to merge 7 commits intomasterfrom
Conversation
This adds a schema_generator module that can dynamically create pycfmodel
Resource classes from AWS CloudFormation resource provider schemas.
Features:
- Downloads and caches CloudFormation schemas from AWS
- Generates Pydantic models with proper type hints from JSON schemas
- Supports all CloudFormation intrinsic functions (Ref, Fn::Sub, Fn::GetAtt,
Fn::Join, Fn::Select, Fn::Split, Fn::If, Fn::ImportValue, Fn::FindInMap,
Fn::Base64, Fn::GetAZs)
- Supports CloudFormation conditions (Fn::And, Fn::Or, Fn::Not, Fn::Equals)
- Handles all resource attributes (DependsOn, Condition, DeletionPolicy,
UpdateReplacePolicy, Metadata)
- Handles optional properties, arrays, and nested objects
- Filters out read-only properties automatically
Usage:
from pycfmodel.schema_generator import generate_resource_from_schema
DynamicLambdaFunction = generate_resource_from_schema("AWS::Lambda::Function")
function = DynamicLambdaFunction(
Type="AWS::Lambda::Function",
Properties={"FunctionName": "my-function", ...}
)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces dynamic resource generation from AWS CloudFormation schemas, enabling automatic creation of pycfmodel Resource classes without manual definition. The implementation downloads and caches CloudFormation schemas from AWS, generates Pydantic models with proper type hints, and automatically filters read-only properties.
Changes:
- Adds schema download and caching functionality from AWS CloudFormation schema registry
- Implements dynamic Pydantic model generation with type mapping from JSON schemas
- Provides comprehensive test coverage for CloudFormation intrinsic functions, conditions, and resource attributes
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| pycfmodel/schema_generator/init.py | Exports the public API for schema-based resource generation |
| pycfmodel/schema_generator/generator.py | Core implementation for schema downloading, parsing, and dynamic model creation |
| tests/schema_generator/test_generator.py | Comprehensive test suite covering intrinsic functions, conditions, metadata, and resource generation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Adds a test suite that validates parsing a realistic CloudFormation template containing: - ECS Cluster with container insights - ECS Task Definition with Fargate configuration - ECS Service with load balancer integration - Application Load Balancer with listener and target group - Security groups for ALB and ECS tasks - IAM roles for task execution and task - CloudWatch Log Group - Application Auto Scaling (conditional on environment) The tests verify: - All 11 resource types can be dynamically generated and parsed - Complex nested properties (NetworkConfiguration, ContainerDefinitions) - All CloudFormation intrinsic functions (Ref, Fn::Sub, Fn::GetAtt, Fn::Join, Fn::If) - Conditional resources and properties - Resource attributes (DependsOn, Condition) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This adds comprehensive validation for all CloudFormation intrinsic functions when parsing templates. The FunctionDict class now validates the format of each intrinsic function according to AWS documentation. Validated functions: - Ref: must be a non-empty string - Fn::Sub: string or [string, dict] format - Fn::GetAtt: [resource, attr] list or "resource.attr" string - Fn::Join: [delimiter, list] with string delimiter - Fn::Select: [index, list] format - Fn::Split: [delimiter, string] with string delimiter - Fn::If: [condition, true_value, false_value] - exactly 3 elements - Fn::And/Fn::Or: list of 2-10 conditions - Fn::Not: list with exactly 1 condition - Fn::Equals: list with exactly 2 values - Fn::FindInMap: [map, key1, key2] - exactly 3 elements - Fn::Base64: string or function - Fn::GetAZs: string or function - Fn::ImportValue: string or function - Condition: non-empty string This helps detect malformed CloudFormation templates at parse time rather than at deployment time. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Caching is already handled by @lru_cache decorator on _download_schemas. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When enabled via enable_dynamic_generation(), pycfmodel will now dynamically generate typed Pydantic models for CloudFormation resource types that are not explicitly modeled in the library. This uses the AWS CloudFormation schema registry to create proper models instead of falling back to GenericResource. Features: - enable_dynamic_generation() / disable_dynamic_generation() to toggle the feature - is_dynamic_generation_enabled() to check current state - clear_dynamic_model_cache() to clear cached dynamically generated models - All functions exported from pycfmodel package The feature is opt-in and disabled by default to maintain backward compatibility. When disabled, unmodeled resources continue to use GenericResource as before. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds 4 realistic CloudFormation YAML templates as test fixtures: - s3_static_website.yaml: S3 bucket with website hosting and bucket policy - lambda_api_gateway.yaml: Lambda function with API Gateway, DynamoDB, IAM roles - ecs_fargate_service.yaml: ECS Fargate service with ALB, auto-scaling - vpc_network.yaml: VPC with subnets, NAT Gateway, VPC endpoints, flow logs Tests verify: - Template metadata (version, description) is correctly parsed - Parameters with defaults, allowed values, constraints - Conditions (Fn::Equals, Fn::And, Fn::Not) are preserved - Mappings are correctly parsed - Resources are parsed (with and without dynamic generation) - Intrinsic functions (Ref, Fn::Sub, Fn::GetAtt, Fn::Join, etc.) are preserved - Resource attributes (DependsOn, Condition) work correctly - Outputs with exports are parsed - Template resolution with parameter substitution Includes custom YAML loader to handle CloudFormation intrinsic function tags. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… schemas
This script creates permanent Python resource files that can be integrated
into the pycfmodel codebase, as an alternative to dynamic generation at runtime.
Usage:
python scripts/generate_resource_from_schema.py AWS::Lambda::Function
python scripts/generate_resource_from_schema.py AWS::Lambda::Function --output-dir pycfmodel/model/resources
python scripts/generate_resource_from_schema.py --list-types
Features:
- Downloads CloudFormation schemas from AWS (cached during execution)
- Generates Properties class with proper type annotations (ResolvableStr, etc.)
- Generates Resource class inheriting from Resource base class
- Follows existing pycfmodel conventions (naming, structure, docstrings)
- Handles optional vs required properties correctly
- Supports multiple resource types in a single invocation
- --dry-run option to preview generated code
- --list-types option to list all available AWS resource types
The generated code is compatible with existing pycfmodel patterns and can be
used directly in templates, supporting intrinsic functions like Ref, Fn::Sub, etc.
Tests verify:
- Generated code compiles without errors
- Generated classes inherit from Resource correctly
- Generated classes can be instantiated and work with intrinsic functions
- Generated code matches pycfmodel conventions
- CLI options work correctly
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
| if type_name: | ||
| schemas[type_name] = schema | ||
|
|
||
| _schemas_cache = schemas |
Check notice
Code scanning / CodeQL
Unused global variable Note
Copilot Autofix
AI 2 months ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
Summary
schema_generatormodule that dynamically creates pycfmodel Resource classes from AWS CloudFormation resource provider schemasFeatures Supported
Dynamic Resource Generation During Parsing
When enabled, pycfmodel will automatically generate typed models for resource types that are not explicitly modeled:
Available functions:
enable_dynamic_generation()- Enable dynamic generationdisable_dynamic_generation()- Disable dynamic generation (default)is_dynamic_generation_enabled()- Check current stateclear_dynamic_model_cache()- Clear cached dynamically generated modelsIntrinsic Function Validation
All CloudFormation intrinsic functions are now validated at parse time:
RefFn::Sub[string, dict]formatFn::GetAtt[resource, attr]list or"resource.attr"stringFn::Join[delimiter, list]with string delimiterFn::Select[index, list]formatFn::Split[delimiter, string]with string delimiterFn::If[condition, true_value, false_value]- exactly 3 elementsFn::And/Fn::OrFn::NotFn::EqualsFn::FindInMap[map, key1, key2]- exactly 3 elementsFn::Base64Fn::GetAZsFn::ImportValueConditionManual Dynamic Resource Generation
DependsOn,Condition,DeletionPolicy,UpdateReplacePolicy,MetadataMalformed Template Detection
Invalid intrinsic functions are now rejected at parse time:
Test plan
Total: 780 tests
🤖 Generated with Claude Code