Module: Pangea::ArchDsl

Defined in:
lib/pangea/arch_dsl.rb

Constant Summary collapse

IDENTIFIER_PATTERN =

══════════════════════════════════════════════════════════════════Helpers ══════════════════════════════════════════════════════════════════

/\A[a-z0-9_]+\z/

Class Method Summary collapse

Class Method Details

.managed_id(base, suffix: nil) ⇒ Object

Canonical resource identifier: underscore-separated, lowercase, optional suffix. Used for every tf address so downstream references never drift between hyphen and underscore forms.

Examples:

Pangea::ArchDsl.managed_id('alpha', suffix: 'system_ng')
  # => :alpha_system_ng

Raises:

  • (ArgumentError)


130
131
132
133
134
135
# File 'lib/pangea/arch_dsl.rb', line 130

def self.managed_id(base, suffix: nil)
  raise ArgumentError, ':base must not be empty' if base.nil? || base.to_s.empty?
  id = base.to_s.downcase.tr('-', '_')
  id = "#{id}_#{suffix.to_s.downcase.tr('-', '_')}" if suffix
  id.to_sym
end

.ref_set_first(resource_type, resource_name, set_attr, element_attr) ⇒ Object

Emit ‘$.element_attr` for set-returning terraform attributes. Works around the newer AWS provider where fields like `certificate_authority` and `identity` are sets (unindexable) rather than ordered lists.

Examples:

ref_set_first(:aws_eks_cluster, :alpha, :certificate_authority, :data)
  # => "${tolist(aws_eks_cluster.alpha.certificate_authority)[0].data}"


149
150
151
# File 'lib/pangea/arch_dsl.rb', line 149

def self.ref_set_first(resource_type, resource_name, set_attr, element_attr)
  "${tolist(#{resource_type}.#{resource_name}.#{set_attr})[0].#{element_attr}}"
end

.register_data(synth, type:, name:, attrs:) ⇒ Object

Register a terraform data source via the synth.data DSL. Uses the block form with explicit setters so every attr is typed by Pangea’s schema validation path (when the provider gem registers it) or the raw synth.data path (hand-typed hash) when it does not.

Parameters:

  • synth (TerraformSynthesizer)
  • type (Symbol)

    terraform data source type (e.g. :aws_network_interface)

  • name (Symbol, String)

    local name

  • attrs (Hash)

    attribute hash (string values)



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/pangea/arch_dsl.rb', line 63

def self.register_data(synth, type:, name:, attrs:)
  validate_identifier!(name)
  captured_attrs = attrs
  synth.instance_eval do
    data type do
      public_send(name) do
        captured_attrs.each { |k, v| public_send(k, v) }
      end
    end
  end
end

.register_raw_resource(synth, type:, name:, attrs:, **meta) ⇒ Object

Register a terraform resource where we don’t have a typed Pangea provider-gem method. Takes explicit meta-arg kwargs so those are never silently dropped.

Parameters:

  • synth (TerraformSynthesizer)
  • type (Symbol)

    terraform resource type (e.g. :aws_vpc_endpoint)

  • name (Symbol, String)

    local name (canonical underscore form)

  • attrs (Hash)

    declared resource attributes

  • meta (Hash)

    a customizable set of options

Options Hash (**meta):

  • :provider (Symbol, String)

    provider alias reference

  • :lifecycle (Hash)

    lifecycle block

  • :depends_on (Array<String>)

    explicit dependencies

  • :count (Integer, String)

    count meta-arg

  • :for_each (String)

    for_each meta-arg



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/pangea/arch_dsl.rb', line 92

def self.register_raw_resource(synth, type:, name:, attrs:, **meta)
  validate_identifier!(name)
  captured_attrs = attrs
  captured_meta  = meta
  synth.instance_eval do
    resource type, name do
      captured_attrs.each { |k, v| public_send(k, v) }
      captured_meta.each { |k, v| public_send(k, v) }
    end
  end
end

.remote_state_output(template:, output:) ⇒ String, ...

Fetch a cross-template output. **Never accepts a state_key override.** Default convention (pangea/template/tr/terraform.tfstate) matches the pangea S3 backend layout exactly; explicit overrides 404.

Parameters:

  • template (String)

    upstream template name (e.g. ‘platform-vpc’)

  • output (Symbol, String)

    output key (e.g. :vpc_id)

Returns:



115
116
117
# File 'lib/pangea/arch_dsl.rb', line 115

def self.remote_state_output(template:, output:)
  Pangea::RemoteState.output(template: template, output: output)
end

.synth_eval(synth) { ... } ⇒ Object

Run ‘block` with `synth` as `self` so nested DSL calls like `terraform do … end` resolve the way Pangea templates expect. Closure-over-args is captured explicitly by the caller (pass them into the block) — inside the block, `self` is the synthesizer.

Parameters:

  • synth (TerraformSynthesizer)

Yields:

  • evaluated with self = synth

Raises:

  • (ArgumentError)


45
46
47
48
# File 'lib/pangea/arch_dsl.rb', line 45

def self.synth_eval(synth, &block)
  raise ArgumentError, 'block required' unless block
  synth.instance_eval(&block)
end

.validate_identifier!(name) ⇒ Object

Raises:

  • (ArgumentError)


159
160
161
162
163
164
165
# File 'lib/pangea/arch_dsl.rb', line 159

def self.validate_identifier!(name)
  s = name.to_s
  return if s.match?(IDENTIFIER_PATTERN)
  raise ArgumentError,
        "identifier '#{s}' must be lowercase snake_case (matching #{IDENTIFIER_PATTERN.source}); " \
        'use Pangea::ArchDsl.managed_id to canonicalize'
end