| name | pangea-resource-testing |
| description | Creates and tests Pangea Ruby function resources with synthesis testing. Use when creating new resources, writing synthesis tests, generating test coverage for Terraform DSL resources, or filling test gaps for AWS/Cloudflare/Hetzner resources. |
Pangea Resource Testing
Creates Ruby function resources and comprehensive synthesis tests for the Pangea infrastructure tool.
When to Use This Skill
- Creating new resource types (AWS, Cloudflare, Hetzner)
- Writing synthesis tests for existing resources
- Filling test coverage gaps
- Generating synthesis specs that validate Terraform JSON output
Resource File Structure
Each resource lives in lib/pangea/resources/<resource_name>/ with two files:
resource.rb Pattern
require 'pangea/resources/base'
require 'pangea/resources/reference'
require 'pangea/resources/<resource_name>/types'
require 'pangea/resource_registry'
module Pangea
module Resources
module AWS
def <resource_name>(name, attributes = {})
attrs = Types::Types::<ResourceName>Attributes.new(attributes)
resource(:<resource_name>, name) do
attribute_name attrs.attribute_name
optional_attr attrs.optional_attr if attrs.optional_attr
if attrs.nested_block
nested_block do
end
end
if attrs.tags&.any?
tags do
attrs.tags.each { |k, v| public_send(k, v) }
end
end
end
ResourceReference.new(
type: '<resource_name>',
name: name,
resource_attributes: attrs.to_h,
outputs: {
id: "${<resource_name>.#{name}.id}",
arn: "${<resource_name>.#{name}.arn}",
}
)
end
end
end
end
Pangea::ResourceRegistry.register(:aws, Pangea::Resources::AWS)
types.rb Pattern
require 'dry-struct'
require 'pangea/resources/types'
module Pangea
module Resources
module AWS
module Types
class <ResourceName>Attributes < Dry::Struct
transform_keys(&:to_sym)
attribute :required_attr, Resources::Types::String
attribute :optional_attr?, Resources::Types::String.optional.default(nil)
attribute :with_default, Resources::Types::Bool.default(false)
def computed_property
end
end
Synthesis Test Pattern
Each test lives in spec/resources/<resource_name>/synthesis_spec.rb:
require 'spec_helper'
require 'terraform-synthesizer'
require 'pangea/resources/<resource_name>/resource'
RSpec.describe '<resource_name> synthesis' do
let(:synthesizer) { TerraformSynthesizer.new }
describe 'terraform synthesis' do
it 'synthesizes basic resource' do
synthesizer.instance_eval do
extend Pangea::Resources::AWS
<resource_name>(:example, {
required_attr: 'value'
})
end
result = synthesizer.synthesis
resource = result[:resource][:<resource_name>][:example]
expect(resource[:required_attr]).to eq('value')
end
it 'synthesizes with optional attributes' do
synthesizer.instance_eval do
extend Pangea::Resources::AWS
<resource_name>(:with_optional, {
required_attr: 'value',
optional_attr: 'optional_value'
})
end
result = synthesizer.synthesis
resource = result[:resource][][]
expect(resource[]).to eq()
it
synthesizer.instance_eval
<resource_name>(, { })
result = synthesizer.synthesis
resource = result[][][]
expect(resource[]).to eq()
it
synthesizer.instance_eval
<resource_name>(, {
,
{ : , : }
})
result = synthesizer.synthesis
resource = result[][][]
expect(resource[][]).to eq()
describe
it
ref = synthesizer.instance_eval
<resource_name>(, { })
expect(ref.id).to eq()
expect(ref.outputs[]).to eq()
Test Validation Checklist
Each synthesis test should validate:
- Basic synthesis - Required attributes produce valid Terraform JSON
- Optional attributes - Optional fields are included when provided
- Default values - Defaults are applied correctly
- Tags support - Tags block renders properly (if applicable)
- Nested blocks - Complex nested structures synthesize correctly
- Resource references - Interpolation strings are correct
Provider-Specific Patterns
AWS Resources
- Module:
Pangea::Resources::AWS
- Registry:
Pangea::ResourceRegistry.register(:aws, ...)
- Common outputs:
id, arn, resource-specific attributes
Cloudflare Resources
- Module:
Pangea::Resources::Cloudflare
- Registry:
Pangea::ResourceRegistry.register_module(...)
- Common:
zone_id, account_id (32-char hex)
Hetzner Resources
- Module:
Pangea::Resources::Hetzner
- Common:
id, name, location, labels
File Size Guidelines
Per CLAUDE.md:
- Keep files under 200 lines
- Split complex resources into focused files
Running Tests
nix run .#synthesizer-tests
bundle exec rspec spec/resources/<resource_name>/synthesis_spec.rb
Adding to Test Configuration
After creating tests, add to synthesizer-tests.yaml:
enabled_tests:
- <resource_name>/synthesis_spec.rb