Module: Pangea::Magma

Defined in:
lib/pangea/magma.rb,
lib/pangea/magma/chain.rb,
lib/pangea/magma/stack.rb,
lib/pangea/magma/runner.rb,
lib/pangea/magma/runner.rb,
lib/pangea/magma/matchers.rb,
lib/pangea/magma/migration.rb,
lib/pangea/magma/workspace.rb,
lib/pangea/magma/distribution.rb,
lib/pangea/magma/optimization.rb,
lib/pangea/magma/orchestrator.rb,
lib/pangea/magma/test_support.rb

Overview

Ruby wrapper around the ‘magma` CLI’s fixture / capabilities surface.

Per theory/MAGMA.md §II.8 interface 1 (drop-in CLI), §II.11 (backend auto-discovery), and §II.6 (test corpus). This module exists so pangea-* gems’ rspec suites can verify “this workspace works under magma” with one matcher invocation — no shelling out manually, no JSON parsing per consumer.

# Usage

require 'pangea/magma'

# Direct API:
report = Pangea::Magma.verify_workspace('workspaces/seph-vpc')
report['resource_change_count'] # => 3
report['providers']             # => ["hashicorp/aws"]

# Or rspec matchers (require 'pangea/magma/matchers'):
it 'plans cleanly under magma' do
  expect('workspaces/seph-vpc').to plan_cleanly_under_magma
end

# Binary resolution

‘MAGMA_BINARY` env var overrides the binary path. Default is `magma` (PATH lookup). When magma isn’t installed, ‘installed?` returns false and rspec matchers skip-with-print rather than failing hard so CI on machines without magma doesn’t break.

Defined Under Namespace

Modules: Matchers, TestSupport Classes: Chain, Distribution, Error, Migration, Optimization, Orchestrator, Runner, Stack, VerificationFailed, Workspace

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.binaryObject

Path to the magma binary. Override via ‘MAGMA_BINARY` env var.



40
41
42
# File 'lib/pangea/magma.rb', line 40

def binary
  @binary ||= ENV['MAGMA_BINARY'] || 'magma'
end

Class Method Details

.capabilitiesObject

Probe magma’s capability manifest. Returns the parsed JSON Hash (matching the schema in theory/MAGMA.md §II.11) or raises Pangea::Backend::BackendUnavailable if magma isn’t on PATH.



58
59
60
# File 'lib/pangea/magma.rb', line 58

def capabilities
  @capabilities ||= probe_capabilities
end

.flow(flow_hash) ⇒ Object

Drive ‘magma flow run <flow.json>` and parse the AggregateReport. `flow` is the typed flow shape (workspaces + edges); see `magma-flow` / theory/PANGEA-MAGMA-ORCHESTRATION.md §IV.



85
86
87
88
89
# File 'lib/pangea/magma.rb', line 85

def flow(flow_hash)
  Runner.invoke('flow', json_arg: flow_hash)
rescue Runner::SubprocessError => e
  raise VerificationFailed, e.message
end

.installed?Boolean

True if the magma binary is reachable + responsive.

Returns:

  • (Boolean)


47
48
49
50
51
52
53
# File 'lib/pangea/magma.rb', line 47

def installed?
  return @installed unless @installed.nil?
  _out, _err, status = Open3.capture3(binary, '--version')
  @installed = status.success?
rescue Errno::ENOENT
  @installed = false
end

.merge(args) ⇒ Object

Drive ‘magma merge` directly. `args` keys: `:from, :from_state, :to, :to_state, :dry_run (bool)`.



115
116
117
118
119
120
121
122
123
124
# File 'lib/pangea/magma.rb', line 115

def merge(args)
  extras = ['--from',       args.fetch(:from).to_s,
            '--from-state', args.fetch(:from_state).to_s,
            '--to',         args.fetch(:to).to_s,
            '--to-state',   args.fetch(:to_state).to_s]
  extras << '--dry-run' if args[:dry_run]
  Runner.invoke('merge', argv_extras: extras)
rescue Runner::SubprocessError => e
  raise VerificationFailed, e.message
end

.migrate(plan_hash) ⇒ Object

Drive ‘magma migrate <plan.json>` and parse the MigrationReceipt. `plan` is the typed magma_migrate::MigrationPlan shape.



93
94
95
96
97
# File 'lib/pangea/magma.rb', line 93

def migrate(plan_hash)
  Runner.invoke('migrate', json_arg: plan_hash)
rescue Runner::SubprocessError => e
  raise VerificationFailed, e.message
end

.reset!Object

Reset memoization — for tests that mutate MAGMA_BINARY env.



127
128
129
130
131
# File 'lib/pangea/magma.rb', line 127

def reset!
  @installed = nil
  @binary = nil
  @capabilities = nil
end

.split(args) ⇒ Object

Drive ‘magma split` directly. `args` keys: `:from, :from_state, :to, :to_state, :resources (Array<String>), :dry_run (bool)`.



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/pangea/magma.rb', line 101

def split(args)
  extras = ['--from',       args.fetch(:from).to_s,
            '--from-state', args.fetch(:from_state).to_s,
            '--to',         args.fetch(:to).to_s,
            '--to-state',   args.fetch(:to_state).to_s]
  Array(args.fetch(:resources, [])).each { |r| extras += ['--resource', r] }
  extras << '--dry-run' if args[:dry_run]
  Runner.invoke('split', argv_extras: extras)
rescue Runner::SubprocessError => e
  raise VerificationFailed, e.message
end

.verify_directory(dir) ⇒ Object

Verify every ‘.tf.json` under `dir`. Returns the parsed AggregateReport Hash with passed/failed counts + per-workspace breakdown. Allow exit=1 since the CLI still emits JSON when some fixtures fail.



75
76
77
78
79
80
# File 'lib/pangea/magma.rb', line 75

def verify_directory(dir)
  Runner.invoke('fixture', argv_extras: ['verify-dir', dir.to_s],
                allow_exit: [1])
rescue Runner::SubprocessError => e
  raise VerificationFailed, e.message
end

.verify_workspace(path) ⇒ Object

Verify a single workspace (directory or single ‘.tf.json` file). Returns the parsed WorkspaceReport Hash; raises VerificationFailed on non-zero exit.



65
66
67
68
69
# File 'lib/pangea/magma.rb', line 65

def verify_workspace(path)
  Runner.invoke('fixture', argv_extras: ['verify', path.to_s])
rescue Runner::SubprocessError => e
  raise VerificationFailed, e.message
end