Add support for Terraform 1.x+ while maintaining backward compatibility
Description
This PR adds support for modern Terraform versions (1.x+) to terraform-landscape while maintaining full backward compatibility with Terraform 0.11.x.
Problem
As noted in issue #101, terraform-landscape was designed for Terraform 0.11.x and fails to parse the output from modern Terraform versions due to significant changes in the plan output format.
Key differences in modern Terraform output:
- Resource headers use comment syntax:
# resource.name will be created - Resource blocks use explicit type declaration:
resource "type" "name" { ... } - Attribute changes use different formatting
- Nested structures and complex objects have different representations
Solution
This PR enhances the printer module to automatically detect the Terraform version based on output format and apply the appropriate parsing strategy:
- Automatic format detection: The parser detects modern format by looking for specific patterns in the output
- Dual parsing modes: Maintains original parsing for 0.11.x while adding new logic for 1.x+
- Unified output: Both parsing modes produce consistent, beautifully formatted output
Changes Made
lib/terraform_landscape/printer.rb
- Added format detection logic to identify modern Terraform output
- Integrated modern parsing directly into
process_stringmethod (no separate functions) - Added support for all resource actions: create (+), destroy (-), update (~), replace (-/+)
- Enhanced attribute parsing to handle -> and => operators
- Added proper handling for nested objects and complex data structures
- Maintained all original parsing logic for backward compatibility
grammar/terraform_plan.treetop
- Extended grammar to support modern resource header format
- Added rules for handling "will be" and "must be" action phrases
- Enhanced attribute parsing for modern format
- Preserved all original grammar rules
Testing
Tested with various Terraform operations:
- ✅ Resource creation
- ✅ Resource destruction
- ✅ Resource updates (in-place)
- ✅ Resource replacement
- ✅ Complex nested attributes
- ✅ Multiple resources in single plan
- ✅ No changes scenario
- ✅ Backward compatibility with 0.11.x format
Example Output
Before (raw Terraform 1.x output):
# module.ecs_service.aws_ecs_service.main will be updated in-place
~ resource "aws_ecs_service" "main" {
id = "arn:aws:ecs:region:123:service/cluster/service"
name = "my-service"
~ tags = {
"Environment" = "prod"
+ "Team" = "platform"
}
}
After (terraform-landscape formatted):
~ aws_ecs_service.module.ecs_service.main
id: "arn:aws:ecs:region:123:service/cluster/service"
name: "my-service"
tags: {
"Environment": "prod"
"Team": => "platform"
}
Compatibility
- ✅ Terraform 0.11.x (existing support maintained)
- ✅ Terraform 1.0+
- ✅ Ruby 2.5+ (per gemspec requirements)
Future Considerations
This implementation focuses on supporting the most common Terraform output patterns. Edge cases or provider-specific output formats may require additional enhancements.
References
- Related to #101
- Tested with Terraform v1.12.1
🟡 Heimdall Review Status
| Requirement | Status | More Info | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Reviews |
🟡
0/1
|
Denominator calculation
|