Module: Pangea::Magma::TestSupport
- Defined in:
- lib/pangea/magma/test_support.rb
Overview
Reusable test scaffolding for Pangea::Magma-driven rspec suites. Centralizes the four patterns every magma integration spec ends up needing:
1. Skip-when-magma-not-installed — `TestSupport.skip_unless_installed!`
2. Minimal `.tf.json` rendering — `TestSupport.render_minimal_workspace`
3. Two-workspace chain fixture — `TestSupport.two_workspace_chain`
4. Tempdir teardown — yield-based scope so cleanup is automatic
Example:
require 'pangea/magma/test_support'
RSpec.describe 'something' do
before(:all) { Pangea::Magma::TestSupport.skip_unless_installed!(self) }
it 'plans cleanly' do
Pangea::Magma::TestSupport.with_two_workspace_chain do |chain, dirs|
report = chain.reconcile_all
expect(report['workspaces'].size).to eq(2)
end
end
end
Class Method Summary collapse
-
.mock_magma_binary(script_stdout: '{}', script_exit_code: 0) ⇒ Object
Yield a block with a mocked magma binary at ‘MAGMA_BINARY`.
-
.render_minimal_workspace(dir, resource_type:, resource_name: 'r', attributes: {}, outputs: {}) ⇒ Object
Render a minimal Pangea-shaped ‘.tf.json` file at the given directory.
-
.skip_unless_installed!(example_group) ⇒ Object
Skip the current rspec example if the magma binary is not on PATH.
-
.with_chain(workspaces:, edges: []) ⇒ Object
Build an arbitrary chain over a tempdir-backed workspace set.
-
.with_two_workspace_chain ⇒ Object
Yield a (Chain, { vpc:, cluster: }) pair for a canonical 2-workspace chain.
Class Method Details
.mock_magma_binary(script_stdout: '{}', script_exit_code: 0) ⇒ Object
Yield a block with a mocked magma binary at ‘MAGMA_BINARY`. The mocked binary is a tiny shell script that:
* prints `script_stdout` to stdout (default: "{}"),
* exits with `script_exit_code` (default: 0).
Useful for unit tests that should not actually invoke the real magma binary. Restores the previous MAGMA_BINARY + memoized ‘installed?` state when the block returns.
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/pangea/magma/test_support.rb', line 149 def mock_magma_binary(script_stdout: '{}', script_exit_code: 0) Dir.mktmpdir('magma-mock') do |tmp| path = File.join(tmp, 'magma') File.write(path, <<~SH) #!/usr/bin/env bash # Mocked magma binary for tests. Outputs a fixed stdout + # exits with a fixed code regardless of argv. cat <<'JSON' #{script_stdout} JSON exit #{script_exit_code} SH FileUtils.chmod('+x', path) prev_env = ENV['MAGMA_BINARY'] Pangea::Magma.reset! ENV['MAGMA_BINARY'] = path begin yield path ensure ENV['MAGMA_BINARY'] = prev_env Pangea::Magma.reset! end end end |
.render_minimal_workspace(dir, resource_type:, resource_name: 'r', attributes: {}, outputs: {}) ⇒ Object
Render a minimal Pangea-shaped ‘.tf.json` file at the given directory. `outputs:` is an optional hash of name → value.
44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/pangea/magma/test_support.rb', line 44 def render_minimal_workspace(dir, resource_type:, resource_name: 'r', attributes: {}, outputs: {}) FileUtils.mkdir_p(dir) body = { provider: { aws: { region: 'us-east-1' } }, resource: { resource_type => { resource_name => attributes } }, } body[:output] = outputs.transform_values { |v| { value: v } } unless outputs.empty? File.write(File.join(dir, 'main.tf.json'), JSON.pretty_generate(body)) dir end |
.skip_unless_installed!(example_group) ⇒ Object
Skip the current rspec example if the magma binary is not on PATH. Pass ‘self` from a `before(:all)` block.
38 39 40 |
# File 'lib/pangea/magma/test_support.rb', line 38 def skip_unless_installed!(example_group) example_group.skip 'magma not installed' unless Pangea::Magma.installed? end |
.with_chain(workspaces:, edges: []) ⇒ Object
Build an arbitrary chain over a tempdir-backed workspace set. ‘specs` is an Array of:
{ name: :vpc, resource_type: 'aws_vpc',
attributes: { ... }, outputs: { vpc_id: 'vpc-x' },
workspace_outputs: { vpc_id: { type: String } },
workspace_inputs: {} }
‘edges` is the same shape Pangea::Magma::Chain.edge accepts. Cleans up tempdirs automatically; yields (chain, dirs Hash).
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/pangea/magma/test_support.rb', line 102 def with_chain(workspaces:, edges: []) require 'pangea/magma/chain' require 'pangea/magma/workspace' Dir.mktmpdir('magma-chain') do |tmp| dirs = {} declared = {} workspaces.each do |spec| name = spec.fetch(:name) dir = File.join(tmp, name.to_s) render_minimal_workspace(dir, resource_type: spec.fetch(:resource_type, 'aws_iam_role'), resource_name: spec.fetch(:resource_name, 'r'), attributes: spec.fetch(:attributes, {}), outputs: spec.fetch(:outputs, {})) dirs[name] = dir declared[name] = Pangea::Magma::Workspace.declare( name: name, template: 'noop.rb', workspace_dir: dir, inputs: spec.fetch(:workspace_inputs, {}), outputs: spec.fetch(:workspace_outputs, {}), ) end chain = Pangea::Magma::Chain.build do |c| declared.each_value { |w| c.workspace w } edges.each do |e| c.edge( from: declared.fetch(e.fetch(:from)), output: e.fetch(:output), to: declared.fetch(e.fetch(:to)), input: e.fetch(:input), ) end end yield chain, dirs end end |
.with_two_workspace_chain ⇒ Object
Yield a (Chain, { vpc:, cluster: }) pair for a canonical 2-workspace chain. Cleans up tempdirs automatically.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/pangea/magma/test_support.rb', line 58 def with_two_workspace_chain require 'pangea/magma/chain' require 'pangea/magma/workspace' Dir.mktmpdir('magma-ts') do |tmp| vpc_dir = File.join(tmp, 'vpc') cluster_dir = File.join(tmp, 'cluster') render_minimal_workspace(vpc_dir, resource_type: 'aws_vpc', attributes: { cidr_block: '10.0.0.0/16' }, outputs: { vpc_id: 'vpc-test-support' }) render_minimal_workspace(cluster_dir, resource_type: 'aws_iam_role', attributes: { name: 'magma-ts-node' }) vpc = Pangea::Magma::Workspace.declare( name: :vpc, template: 'noop.rb', workspace_dir: vpc_dir, outputs: { vpc_id: { type: String } }, ) cluster = Pangea::Magma::Workspace.declare( name: :cluster, template: 'noop.rb', workspace_dir: cluster_dir, inputs: { vpc_id: { type: String } }, ) chain = Pangea::Magma::Chain.build do |c| c.workspace vpc c.workspace cluster c.edge from: vpc, output: :vpc_id, to: cluster, input: :vpc_id end yield chain, { vpc: vpc_dir, cluster: cluster_dir } end end |