terraspace 1.0.5 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/lib/templates/base/project/.gitignore +1 -0
  4. data/lib/templates/base/project/config/app.rb +1 -1
  5. data/lib/terraspace/all/grapher.rb +11 -3
  6. data/lib/terraspace/all/runner.rb +17 -10
  7. data/lib/terraspace/app.rb +4 -1
  8. data/lib/terraspace/autodetect.rb +3 -7
  9. data/lib/terraspace/builder/children.rb +42 -0
  10. data/lib/terraspace/builder.rb +34 -32
  11. data/lib/terraspace/cli/all.rb +2 -0
  12. data/lib/terraspace/cli/build/placeholder.rb +3 -1
  13. data/lib/terraspace/cli/help/all/plan.md +11 -1
  14. data/lib/terraspace/cli/help/all/up.md +10 -0
  15. data/lib/terraspace/cli/help/check_setup.md +2 -2
  16. data/lib/terraspace/cli/help/plan.md +9 -1
  17. data/lib/terraspace/cli/help/up.md +9 -1
  18. data/lib/terraspace/cli/init.rb +1 -1
  19. data/lib/terraspace/cli/new/shim.rb +1 -1
  20. data/lib/terraspace/cli/setup/check.rb +7 -3
  21. data/lib/terraspace/cli.rb +3 -2
  22. data/lib/terraspace/command.rb +1 -1
  23. data/lib/terraspace/compiler/dirs_concern.rb +6 -1
  24. data/lib/terraspace/compiler/expander/backend.rb +1 -1
  25. data/lib/terraspace/compiler/expander.rb +38 -14
  26. data/lib/terraspace/compiler/{builder → perform}/skip.rb +1 -1
  27. data/lib/terraspace/compiler/{builder.rb → perform.rb} +21 -20
  28. data/lib/terraspace/compiler/select.rb +2 -7
  29. data/lib/terraspace/compiler/strategy/mod/text_file.rb +14 -13
  30. data/lib/terraspace/compiler/strategy/tfvar/layer.rb +3 -2
  31. data/lib/terraspace/compiler/strategy/tfvar.rb +2 -1
  32. data/lib/terraspace/core.rb +1 -1
  33. data/lib/terraspace/dependency/resolver.rb +20 -0
  34. data/lib/terraspace/ext/core/module.rb +8 -1
  35. data/lib/terraspace/mod.rb +1 -0
  36. data/lib/terraspace/plugin/summary/interface.rb +1 -1
  37. data/lib/terraspace/terraform/args/expand.rb +25 -0
  38. data/lib/terraspace/terraform/args/thor.rb +14 -11
  39. data/lib/terraspace/terraform/ihooks/after/plan.rb +2 -2
  40. data/lib/terraspace/terraform/ihooks/base.rb +5 -0
  41. data/lib/terraspace/terraform/ihooks/before/plan.rb +3 -5
  42. data/lib/terraspace/terraform/remote_state/fetcher.rb +12 -5
  43. data/lib/terraspace/terraform/remote_state/marker/output.rb +1 -1
  44. data/lib/terraspace/version.rb +1 -1
  45. data/spec/terraspace/all/runner_spec.rb +1 -0
  46. data/spec/terraspace/compiler/erb/render_spec.rb +5 -1
  47. data/terraspace.gemspec +1 -1
  48. metadata +8 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cfdfafd180a61f7e43131770457ffa446c8bae59d3db9e68c9b9a8930fa6ca88
4
- data.tar.gz: 684480a5c4454ee457c5e236574ace9424a514d0822c2693190de41354aea40d
3
+ metadata.gz: 6ad5587827bc4c9dcbae4cd2a42904e69ccf930bfa1a04c7e65d753178ff94f7
4
+ data.tar.gz: 122e5fb3135447e92bf12e7f5947ee665f5f77e024e6aea5499ad63a184eceea
5
5
  SHA512:
6
- metadata.gz: 73bef840c84345011a8246128537d81d76fee4c73215ac3856e43814e04304bfcf16d54213eee2fb940650f3fe4c13df249d1476805090cc0fbd7524f00fed00
7
- data.tar.gz: a4b3f901aa19c01de17a059bd907197d4b2f8276a72de4ea29381ee803291ea9e4f33cc8c9667358247868297fb3b784dab1f0b127c7a04a98f37a56c4e2a773
6
+ metadata.gz: 0b6a0f432037f072acad01d60efb86d6e06314cea7ff75556dfb0de4ec077fe2479b215867702c8c6a615358a17c4568f30cfcf4a45011233f03b9c595a258ec
7
+ data.tar.gz: ed255135382340d2a44cd04f863f8fc9d8bb6562b413e04024a13f6e4bb31c2b19f837dbb7c05ee1220210ee4bf0bd6ce4a5d4e5628fb23eab61dd8a338c6b5b
data/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
5
 
6
+ ## [1.1.2] - 2022-02-17
7
+ - [#200](https://github.com/boltops-tools/terraspace/pull/200) fix terraspace typos
8
+ - [#202](https://github.com/boltops-tools/terraspace/pull/202) Windows support: fix include_dir for windows
9
+ - [#203](https://github.com/boltops-tools/terraspace/pull/203) Fix ERB for windows
10
+ - [#204](https://github.com/boltops-tools/terraspace/pull/204) improve file check
11
+ - setup check terraform_bin windows support
12
+ - slight layering improvement strip trailing slash, helps with custom layering
13
+
14
+ ## [1.1.1] - 2022-02-02
15
+ - [#199](https://github.com/boltops-tools/terraspace/pull/199) build required dependent stacks as part of terraspace up
16
+
17
+ ## [1.1.0] - 2022-01-30
18
+ - [#196](https://github.com/boltops-tools/terraspace/pull/196) terraspace all: build modules in batches and only each specific stack
19
+ - [#197](https://github.com/boltops-tools/terraspace/pull/197) all plan --output and all up --plan options
20
+ - simplify starter config/app.rb
21
+
22
+ ## [1.0.6] - 2022-01-24
23
+ - [#195](https://github.com/boltops-tools/terraspace/pull/195) improve autodetection for plugin expander for backend like remote
24
+
6
25
  ## [1.0.5] - 2022-01-23
7
26
  - [#194](https://github.com/boltops-tools/terraspace/pull/194) ability to allow and deny envs, regions, and stacks
8
27
 
@@ -5,6 +5,7 @@ terraform.tfvars
5
5
  *.tfstate*
6
6
 
7
7
  .terraspace-cache
8
+ *.plan
8
9
 
9
10
  # OS X files
10
11
  .history
@@ -1,4 +1,4 @@
1
+ # Docs: https://terraspace.cloud/docs/config/reference/
1
2
  Terraspace.configure do |config|
2
3
  config.logger.level = :info
3
- config.test_framework = "rspec"
4
4
  end
@@ -3,14 +3,13 @@ require "tty-tree"
3
3
 
4
4
  module Terraspace::All
5
5
  class Grapher < Base
6
+ include Terraspace::Compiler::DirsConcern
6
7
  include Terraspace::Util::Logging
7
8
 
8
9
  def run
9
10
  check_graphviz!
10
11
  logger.info "Building graph..."
11
- builder = Terraspace::Builder.new(@options.merge(mod: "placeholder", quiet: true, draw_full_graph: draw_full_graph))
12
- builder.run
13
- graph = builder.graph
12
+ graph = build_graph
14
13
  if @options[:format] == "text"
15
14
  text(graph.top_nodes)
16
15
  else
@@ -18,6 +17,15 @@ module Terraspace::All
18
17
  end
19
18
  end
20
19
 
20
+ def build_graph
21
+ resolver = Terraspace::Dependency::Resolver.new(@options.merge(quiet: true, draw_full_graph: draw_full_graph))
22
+ resolver.resolve
23
+ dependencies = Terraspace::Dependency::Registry.data # populated after build_unresolved
24
+ graph = Terraspace::Dependency::Graph.new(stack_names, dependencies, @options)
25
+ graph.build
26
+ graph
27
+ end
28
+
21
29
  def text(nodes)
22
30
  Rainbow.enabled = false unless @options[:full]
23
31
  data = build_tree_data(nodes)
@@ -1,6 +1,7 @@
1
1
  module Terraspace::All
2
2
  class Runner < Base
3
3
  include Terraspace::Util
4
+ extend Memoist
4
5
 
5
6
  def initialize(command, options={})
6
7
  @command, @options = command, options
@@ -21,32 +22,27 @@ module Terraspace::All
21
22
  end
22
23
 
23
24
  def build_batches
24
- @batches = run_builder(quiet: false)
25
+ @batches = Terraspace::Dependency::Resolver.new(@options).resolve
25
26
  @batches.reverse! if @command == "down"
26
27
  @batches
27
28
  end
28
29
 
29
30
  def deploy_batches
30
31
  truncate_logs if ENV['TS_TRUNCATE_LOGS']
32
+ build_modules
31
33
  @batches.each_with_index do |batch,i|
32
34
  logger.info "Batch Run #{i+1}:"
33
- run_builder unless i == 0 # already handled by build_batches the first time
34
35
  deploy_batch(batch)
35
36
  end
36
37
  end
37
38
 
38
- # Should run after each batch run. run_builder also calls replace_outputs.
39
- # Important: rebuild from source so placeholders are in place.
40
- def run_builder(quiet: true)
41
- Terraspace::Builder.new(@options.merge(mod: "placeholder", quiet: quiet)).run
42
- end
43
-
44
39
  def deploy_batch(batch)
45
40
  @pids = {} # stores child processes pids. map of pid to mod_name, reset this list on each batch run
46
41
  concurrency = Terraspace.config.all.concurrency
47
42
  batch.sort_by(&:name).each_slice(concurrency) do |slice|
48
43
  slice.each do |node|
49
44
  pid = fork do
45
+ build_stack(node.name)
50
46
  run_terraspace(node.name)
51
47
  end
52
48
  @pids[pid] = node.name # store mod_name mapping
@@ -57,6 +53,16 @@ module Terraspace::All
57
53
  report_errors # reports finall errors and possibly exit
58
54
  end
59
55
 
56
+ def build_modules
57
+ builder = Terraspace::Builder.new(@options.merge(mod: "placeholder", clean: true, quiet: true, include_stacks: :none))
58
+ builder.build(modules: true)
59
+ end
60
+
61
+ def build_stack(name)
62
+ builder = Terraspace::Builder.new(@options.merge(mod: name, clean: false, quiet: true, include_stacks: :root_only))
63
+ builder.build(modules: false)
64
+ end
65
+
60
66
  def wait_for_child_proccess
61
67
  @errors = [] # stores child processes pids that errored
62
68
  @pids.each do |pid, _|
@@ -70,7 +76,7 @@ module Terraspace::All
70
76
  @errors.each do |pid|
71
77
  mod_name = @pids[pid]
72
78
  terraspace_command = terraspace_command(mod_name)
73
- logger.error "Error running: #{terraspace_command}. Check logs and fix the error.".color(:red)
79
+ logger.error "Error running: #{terraspace_command}. Fix the error above or check logs for the error.".color(:red)
74
80
  end
75
81
  unless @errors.empty?
76
82
  exit 2 if exit_on_fail?
@@ -97,7 +103,8 @@ module Terraspace::All
97
103
  log_path: log_path(mod_name),
98
104
  terraspace_command: terraspace_command(mod_name),
99
105
  }
100
- Summary.new(data).run
106
+ # Its possible for log file to not get created if RemoteState::Fetcher#validate! fails
107
+ Summary.new(data).run if File.exist?(data[:log_path])
101
108
  end
102
109
  end
103
110
 
@@ -16,7 +16,8 @@ module Terraspace
16
16
  config.all = ActiveSupport::OrderedOptions.new
17
17
  config.all.concurrency = 5
18
18
  config.all.exit_on_fail = ActiveSupport::OrderedOptions.new
19
- config.all.exit_on_fail.down = true
19
+ config.all.exit_on_fail.down = false
20
+ config.all.exit_on_fail.plan = true
20
21
  config.all.exit_on_fail.up = true
21
22
 
22
23
  config.allow = ActiveSupport::OrderedOptions.new
@@ -33,6 +34,8 @@ module Terraspace
33
34
  config.all.consider_allow_deny_stacks = true
34
35
 
35
36
  config.auto_create_backend = true
37
+ config.autodetect = ActiveSupport::OrderedOptions.new
38
+ config.autodetect.expander = nil
36
39
  config.build = ActiveSupport::OrderedOptions.new
37
40
  config.build.cache_dir = ":CACHE_ROOT/:REGION/:ENV/:BUILD_DIR"
38
41
  config.build.cache_root = nil # defaults to /full/path/to/.terraspace-cache
@@ -2,13 +2,9 @@ module Terraspace
2
2
  class Autodetect
3
3
  def plugin
4
4
  plugins = Terraspace::Plugin.meta.keys
5
- if plugins.size == 1
6
- plugins.first
7
- else
8
- precedence = %w[aws azurerm google]
9
- precedence.find do |p|
10
- plugins.include?(p)
11
- end
5
+ precedence = %w[aws azurerm google]
6
+ precedence.find do |p|
7
+ plugins.include?(p)
12
8
  end
13
9
  end
14
10
  end
@@ -0,0 +1,42 @@
1
+ class Terraspace::Builder
2
+ class Children
3
+ include Terraspace::Util::Logging
4
+
5
+ def initialize(mod, options={})
6
+ @mod, @options = mod, options
7
+ @queue = []
8
+ end
9
+
10
+ def build
11
+ dependencies = Terraspace::Dependency::Registry.data
12
+ # Find out if current deploy stack contains dependency
13
+ found = dependencies.find do |parent_child|
14
+ parent, _ = parent_child.split(':')
15
+ parent == @mod.name
16
+ end
17
+ return unless found
18
+
19
+ # Go down graph children, which are the dependencies to build a queue
20
+ parent, _ = found.split(':')
21
+ node = Terraspace::Dependency::Node.find_by(name: parent)
22
+ build_queue(node)
23
+
24
+ logger.debug "Terraspace::Builder::Children @queue #{@queue}"
25
+
26
+ # Process queue in reverse order to build leaf nodes first
27
+ @queue.reverse.each do |node|
28
+ mod = Terraspace::Mod.new(node.name, @options)
29
+ Terraspace::Compiler::Perform.new(mod).compile
30
+ end
31
+ end
32
+
33
+ # Use depth first traversal to build queue
34
+ def build_queue(node)
35
+ node.children.each do |child|
36
+ @queue << child
37
+ build_queue(child)
38
+ end
39
+ @queue
40
+ end
41
+ end
42
+ end
@@ -4,64 +4,66 @@ module Terraspace
4
4
  include Compiler::DirsConcern
5
5
  include Hooks::Concern
6
6
 
7
- attr_reader :graph
7
+ # @include_stacks can be 3 values: root_with_children, none, root_only
8
+ #
9
+ # none: dont build any stacks at all. used by `terraspace all up`
10
+ # root_only: only build root stack. used by `terraspace all up`
11
+ # root_with_children: build all parent stacks as well as the root stack. normal `terraspace up`
12
+ #
13
+ def initialize(options={})
14
+ super
15
+ @include_stacks = @options[:include_stacks] || :root_with_children
16
+ end
8
17
 
9
18
  def run
10
19
  return if @options[:build] == false
11
20
  Terraspace::CLI::Setup::Check.check!
21
+ check_allow!
12
22
  @mod.root_module = true
13
23
  clean
24
+ resolve_dependencies if @include_stacks == :root_with_children
25
+ build
26
+ end
27
+
28
+ def resolve_dependencies
29
+ resolver = Terraspace::Dependency::Resolver.new(@options.merge(quiet: true))
30
+ resolver.resolve # returns batches
31
+ end
32
+
33
+ def build(modules: true)
14
34
  build_dir = Util.pretty_path(@mod.cache_dir)
15
35
  placeholder_stack_message
16
36
  logger.info "Building #{build_dir}" unless @options[:quiet] # from terraspace all
17
-
18
- batches = nil
19
37
  FileUtils.mkdir_p(@mod.cache_dir) # so terraspace before build hooks work
20
38
  run_hooks("terraspace.rb", "build") do
21
- check_allow!
22
- build_unresolved
23
- batches = build_batches
24
- build_all
39
+ build_dir("modules") if modules
40
+ build_stacks
25
41
  logger.info "Built in #{build_dir}" unless @options[:quiet] # from terraspace all
26
42
  end
27
- batches
28
43
  end
29
44
 
30
45
  def check_allow!
31
46
  Allow.new(@mod).check!
32
47
  end
33
48
 
34
- # Builds dependency graph and returns the batches to run
35
- def build_batches
36
- dependencies = Terraspace::Dependency::Registry.data # populated after build_unresolved
37
- @graph = Terraspace::Dependency::Graph.new(stack_names, dependencies, @options)
38
- @graph.build
39
- end
40
-
41
- def build_all
42
- # At this point dependencies have been resolved.
43
- Terraspace::Terraform::RemoteState::Fetcher.flush!
44
- @resolved = true
45
- build_unresolved
46
- end
47
-
48
- def build_unresolved
49
- build_dir("modules")
50
- build_dir("stacks")
51
- build_root_module
49
+ def build_stacks
50
+ return if @include_stacks == :none
51
+ build_children_stacks if @include_stacks == :root_with_children
52
+ Compiler::Perform.new(@mod).compile # @include_stacks :root or :root_with_children
52
53
  end
53
54
 
54
- def build_root_module
55
- @mod.resolved = @resolved
56
- Compiler::Builder.new(@mod).build
55
+ # Build stacks that are part of the dependency graph. Because .terraspace-cache folders
56
+ # need to exist so `terraform state pull` works to get the state info.
57
+ def build_children_stacks
58
+ children = Children.new(@mod, @options)
59
+ children.build
57
60
  end
58
61
 
59
62
  def build_dir(type_dir)
60
63
  with_each_mod(type_dir) do |mod|
61
- mod.resolved = @resolved
62
64
  is_root_module = mod.cache_dir == @mod.cache_dir
63
- next if is_root_module # handled by build_root_module
64
- Compiler::Builder.new(mod).build
65
+ next if is_root_module # handled by build_stacks
66
+ Compiler::Perform.new(mod).compile
65
67
  end
66
68
  end
67
69
 
@@ -38,6 +38,7 @@ class Terraspace::CLI
38
38
 
39
39
  desc "plan", "Run plan for all or multiple stacks."
40
40
  long_desc Help.text("all/plan")
41
+ option :out, aliases: :o, desc: "Output path. Can be a pattern like :MOD_NAME.plan"
41
42
  def plan(*stacks)
42
43
  Terraspace::All::Runner.new("plan", @options.merge(stacks: stacks)).run
43
44
  end
@@ -56,6 +57,7 @@ class Terraspace::CLI
56
57
 
57
58
  desc "up", "Deploy all or multiple stacks."
58
59
  long_desc Help.text("all/up")
60
+ option :plan, desc: "Plan path. Can be a pattern like :MOD_NAME.plan"
59
61
  def up(*stacks)
60
62
  Terraspace::All::Runner.new("up", @options.merge(stacks: stacks)).run
61
63
  end
@@ -3,6 +3,7 @@
3
3
  # It's useful for the summary command.
4
4
  module Terraspace::CLI::Build
5
5
  class Placeholder
6
+ include Terraspace::Compiler::DirsConcern
6
7
  include Terraspace::Util::Logging
7
8
 
8
9
  def initialize(options={})
@@ -28,7 +29,8 @@ module Terraspace::CLI::Build
28
29
  def find_stack
29
30
  stack_paths = Dir.glob("{app,vendor}/stacks/*")
30
31
  stack_paths.select! do |path|
31
- select = Terraspace::Compiler::Select.new(path)
32
+ stack_name = extract_stack_name(path)
33
+ select = Terraspace::Compiler::Select.new(stack_name)
32
34
  select.selected?
33
35
  end
34
36
  mod_path = stack_paths.last
@@ -22,4 +22,14 @@
22
22
  terraspace plan a1: Plan: 2 to add, 0 to change, 0 to destroy.
23
23
  terraspace plan a1: Changes to Outputs:
24
24
  Time took: 11s
25
- $
25
+ $
26
+
27
+ ## Using Plan Outputs
28
+
29
+ Using plan output path. You can specify an output path for the plan that contains pattern for expansion. Example:
30
+
31
+ $ terraspace all plan --out ":MOD_NAME.plan"
32
+
33
+ You can then use this later in terraspace up:
34
+
35
+ $ terraspace all up --plan ":MOD_NAME.plan"
@@ -25,3 +25,13 @@ Once you confirm, Terraspace deploys the batches in parallel. Essentially, Terra
25
25
  Time took: 25s
26
26
 
27
27
  Terraspace provides a reduced-noise summary of the runs. The full logs are also written for further inspection and debugging. The [terraspace log](https://terraspace.cloud/reference/terraspace-log/) command is useful for viewing the logs.
28
+
29
+ ## Using Plans
30
+
31
+ Using plan output path. You can specify an output path for the plan that contains pattern for expansion. Example:
32
+
33
+ $ terraspace all plan --out ":MOD_NAME.plan"
34
+
35
+ You can then use this later in terraspace up:
36
+
37
+ $ terraspace all up --plan ":MOD_NAME.plan"
@@ -1,9 +1,9 @@
1
1
  ## Example
2
2
 
3
3
  $ terraspace check_setup
4
- Detected Terrspace version: 0.3.3
4
+ Detected Terraspace version: 0.3.3
5
5
  Detected Terraform bin: /home/ec2-user/.tfenv/bin/terraform
6
6
  Detected Terraform v0.13.2
7
7
  Terraspace requires Terraform v0.12.x and above
8
8
  You're all set!
9
- $
9
+ $
@@ -26,4 +26,12 @@
26
26
  can't guarantee that exactly these actions will be performed if
27
27
  "terraform apply" is subsequently run.
28
28
 
29
- $
29
+ $
30
+
31
+ Using plan output path. You can specify an output path for the plan. Example:
32
+
33
+ $ terraspace plan demo --out "my.plan"
34
+
35
+ You can then use this later in terraspace up:
36
+
37
+ $ terraspace up demo --plan "my.plan"
@@ -27,4 +27,12 @@
27
27
 
28
28
  bucket_name = bucket-trusty-marmoset
29
29
  Time took: 39s
30
- $
30
+ $
31
+
32
+ Using plan output path. You can specify an output path for the plan. Example:
33
+
34
+ $ terraspace plan demo --out "my.plan"
35
+
36
+ You can then use this later in terraspace up:
37
+
38
+ $ terraspace up demo --plan "my.plan"
@@ -52,7 +52,7 @@ class Terraspace::CLI
52
52
  return if meta['Dir'] == '.' # root is already built
53
53
 
54
54
  remote_mod = Terraspace::Mod::Remote.new(meta, @mod)
55
- Terraspace::Compiler::Builder.new(remote_mod).build
55
+ Terraspace::Compiler::Perform.new(remote_mod).build
56
56
  end
57
57
 
58
58
  def auto?
@@ -50,7 +50,7 @@ class Terraspace::CLI::New
50
50
 
51
51
  private
52
52
  def switch_ruby_version_line
53
- rbenv_installed = system("type rbenv 2>&1 > /dev/null")
53
+ rbenv_installed = system("type rbenv > /dev/null 2>&1")
54
54
  if rbenv_installed
55
55
  'eval "$(rbenv init -)"'
56
56
  end
@@ -11,7 +11,7 @@ class Terraspace::CLI::Setup
11
11
 
12
12
  # Used for the CLI
13
13
  def run
14
- puts "Detected Terrspace version: #{Terraspace::VERSION}"
14
+ puts "Detected Terraspace version: #{Terraspace::VERSION}"
15
15
  if terraform_bin
16
16
  puts "Detected Terraform bin: #{terraform_bin}"
17
17
  puts "Detected #{terraform_version_message}"
@@ -65,8 +65,12 @@ class Terraspace::CLI::Setup
65
65
  end
66
66
 
67
67
  def terraform_bin
68
- out = `type terraform 2>&1`.strip
69
- return unless $?.success?
68
+ if Gem.win_platform?
69
+ out = "is terraform.exe".strip
70
+ else
71
+ out = `type terraform 2>&1`.strip
72
+ return unless $?.success?
73
+ end
70
74
  md = out.match(/is (.*)/)
71
75
  md[1] if md
72
76
  end
@@ -9,7 +9,7 @@ module Terraspace
9
9
  option :yes, aliases: :y, type: :boolean, desc: "-auto-approve the terraform apply"
10
10
  }
11
11
  out_option = Proc.new {
12
- option :out, aliases: :o, desc: "Write the output to path"
12
+ option :out, aliases: :o, desc: "Output path. Can be a pattern like :MOD_NAME.plan"
13
13
  }
14
14
  input_option = Proc.new {
15
15
  option :input, type: :boolean, desc: "Ask for input for variables if not directly set."
@@ -55,6 +55,7 @@ module Terraspace
55
55
  option :quiet, type: :boolean, desc: "quiet output"
56
56
  instance_option.call
57
57
  yes_option.call
58
+ option :clean, type: :boolean, default: nil, desc: "Whether or not clean out .terraspace-cache folder first", hide: true
58
59
  def build(mod="placeholder")
59
60
  Terraspace::Builder.new(options.merge(mod: mod)).run # building any stack builds them all
60
61
  end
@@ -190,7 +191,7 @@ module Terraspace
190
191
  desc "show STACK", "Run show."
191
192
  long_desc Help.text(:show)
192
193
  instance_option.call
193
- option :plan, desc: "path to created.plan"
194
+ option :plan, desc: "Plan path. Can be a pattern like :MOD_NAME.plan"
194
195
  def show(mod, *args)
195
196
  Commander.new("show", options.merge(mod: mod, args: args)).run
196
197
  end
@@ -30,7 +30,7 @@ module Terraspace
30
30
  include Terraspace::Util::Logging
31
31
 
32
32
  def dispatch(m, args, options, config)
33
- # Terraspace.argv provides consistency when terraspace is being called by rspec-terrspace test harness
33
+ # Terraspace.argv provides consistency when terraspace is being called by rspec-terraspace test harness
34
34
  Terraspace.argv = args.clone # important to clone since Thor removes the first argv
35
35
 
36
36
  check_standalone_install!
@@ -37,10 +37,15 @@ module Terraspace::Compiler
37
37
  # path /home/ec2-user/environment/downloads/infra/app/stacks/demo
38
38
  def select_stack?(type_dir, path)
39
39
  return true unless type_dir == "stacks"
40
- select = Terraspace::Compiler::Select.new(path)
40
+ stack_name = extract_stack_name(path)
41
+ select = Terraspace::Compiler::Select.new(stack_name)
41
42
  select.selected?
42
43
  end
43
44
 
45
+ def extract_stack_name(path)
46
+ path.sub(%r{.*(app|vendor)/stacks/}, '')
47
+ end
48
+
44
49
  def local_paths(type_dir)
45
50
  dirs("app/#{type_dir}/*") + dirs("vendor/#{type_dir}/*")
46
51
  end
@@ -12,7 +12,7 @@ class Terraspace::Compiler::Expander
12
12
  @mod = mod
13
13
  end
14
14
 
15
- COMMENT = /^\s+#/
15
+ COMMENT = /^\s*#/
16
16
  # Works for both backend.rb DSL and backend.tf ERB
17
17
  def detect
18
18
  return nil unless src_path # no backend file. returning nil means a local backend
@@ -3,8 +3,8 @@ module Terraspace::Compiler
3
3
  extend Memoist
4
4
  delegate :expand, :expansion, to: :expander
5
5
 
6
- def initialize(mod, name)
7
- @mod, @name = mod, name
6
+ def initialize(mod, backend=nil)
7
+ @mod, @backend = mod, backend
8
8
  end
9
9
 
10
10
  def expander
@@ -12,27 +12,51 @@ module Terraspace::Compiler
12
12
  end
13
13
  memoize :expander
14
14
 
15
+ # IE: TerraspacePluginAws::Interfaces::Expander
15
16
  def expander_class
16
- # IE: TerraspacePluginAws::Interfaces::Expander
17
- klass_name = Terraspace::Plugin.klass("Expander", backend: @name)
18
- klass_name ? klass_name.constantize : Terraspace::Plugin::Expander::Generic
19
- rescue NameError
17
+ class_name = expander_class_name
18
+ class_name ? class_name.constantize : Terraspace::Plugin::Expander::Generic
19
+ rescue NameError => e
20
+ logger.debug "#{e.class}: #{e.message}"
20
21
  Terraspace::Plugin::Expander::Generic
21
22
  end
22
23
 
24
+ def expander_class_name
25
+ plugin = Terraspace.config.autodetect.expander # contains plugin name. IE: aws, azurerm, google
26
+ if plugin
27
+ # early return for user override of autodetection
28
+ return Terraspace::Plugin.klass("Expander", plugin: plugin) # can return nil
29
+ end
30
+
31
+ backend = @backend || parse_backend
32
+ class_name = Terraspace::Plugin.klass("Expander", backend: backend) # can return nil
33
+ unless class_name
34
+ backend = plugin_backend
35
+ class_name = Terraspace::Plugin.klass("Expander", backend: backend) # can return nil
36
+ end
37
+ class_name
38
+ end
39
+
40
+ # autodetect by parsing backend.tf or backend.rb
41
+ def parse_backend
42
+ Backend.new(@mod).detect
43
+ end
44
+
45
+ # autodetect by looking up loaded plugins
46
+ def plugin_backend
47
+ plugin = Terraspace::Autodetect.new.plugin # IE: aws, azurerm, google
48
+ if plugin
49
+ data = Terraspace::Plugin.meta[plugin]
50
+ data[:backend] # IE: s3, azurerm, gcs
51
+ end
52
+ end
53
+
23
54
  class << self
24
55
  extend Memoist
25
-
26
56
  def autodetect(mod, opts={})
27
- backend = opts[:backend] || find_backend(mod)
28
- new(mod, backend)
57
+ new(mod, opts)
29
58
  end
30
59
  memoize :autodetect
31
-
32
- def find_backend(mod)
33
- Backend.new(mod).detect
34
- end
35
- memoize :find_backend
36
60
  end
37
61
  end
38
62
  end
@@ -1,4 +1,4 @@
1
- class Terraspace::Compiler::Builder
1
+ class Terraspace::Compiler::Perform
2
2
  class Skip
3
3
  def initialize(mod, src_path)
4
4
  @mod, @src_path = mod, src_path
@@ -1,5 +1,5 @@
1
1
  module Terraspace::Compiler
2
- class Builder
2
+ class Perform
3
3
  include CommandsConcern
4
4
  include Basename
5
5
 
@@ -7,44 +7,45 @@ module Terraspace::Compiler
7
7
  @mod = mod
8
8
  end
9
9
 
10
- def build
11
- build_config
12
- build_module if @mod.resolved
13
- build_tfvars unless command_is?(:seed) # avoid dependencies being built and erroring when backend bucket doesnt exist
10
+ def compile
11
+ compile_config
12
+ compile_module if @mod.resolved
13
+ compile_tfvars
14
14
  end
15
15
 
16
- # build common config files: provider and backend for the root module
17
- def build_config
18
- return unless build?
19
- build_config_terraform
16
+ # compile common config files: provider and backend for the root module
17
+ def compile_config
18
+ return unless compile?
19
+ compile_config_terraform
20
20
  end
21
21
 
22
- def build_module
22
+ def compile_module
23
23
  with_mod_file do |src_path|
24
- build_mod_file(src_path)
24
+ compile_mod_file(src_path)
25
25
  end
26
26
  end
27
27
 
28
- def build_tfvars
29
- return unless build?
30
- Strategy::Tfvar.new(@mod).run # writer within Strategy to control file ordering
28
+ def compile_tfvars(write: true)
29
+ return unless compile?
30
+ return if command_is?(:seed) # avoid dependencies being built and erroring when backend bucket doesnt exist
31
+ Strategy::Tfvar.new(@mod).run(write: write) # writer within Strategy to control file ordering
31
32
  end
32
33
 
33
34
  private
34
- def build?
35
+ def compile?
35
36
  @mod.type == "stack" || @mod.root_module?
36
37
  end
37
38
 
38
- def build_config_terraform
39
+ def compile_config_terraform
39
40
  expr = "#{Terraspace.root}/config/terraform/**/*"
40
41
  search(expr).each do |path|
41
42
  next unless File.file?(path)
42
43
  next if path.include?('config/terraform/tfvars')
43
- build_config_file(basename(path))
44
+ compile_config_file(basename(path))
44
45
  end
45
46
  end
46
47
 
47
- def build_config_file(file)
48
+ def compile_config_file(file)
48
49
  existing = search("#{@mod.root}/#{file}").first
49
50
  return if existing && existing.ends_with?(".tf") # do not overwrite existing backend.tf, provider.tf, etc
50
51
 
@@ -52,10 +53,10 @@ module Terraspace::Compiler
52
53
  src_path = search("#{@mod.root}/#{basename(file)}").first # existing source. IE: backend.rb in module folder
53
54
  end
54
55
  src_path ||= search("#{Terraspace.root}/config/terraform/#{file}").first
55
- build_mod_file(src_path) if src_path
56
+ compile_mod_file(src_path) if src_path
56
57
  end
57
58
 
58
- def build_mod_file(src_path)
59
+ def compile_mod_file(src_path)
59
60
  content = Strategy::Mod.new(@mod, src_path).run
60
61
  Writer.new(@mod, src_path: src_path).write(content)
61
62
  end
@@ -3,9 +3,8 @@ module Terraspace::Compiler
3
3
  include Terraspace::App::CallableOption::Concern
4
4
  include Terraspace::Util::Logging
5
5
 
6
- def initialize(path)
7
- @path = path
8
- @stack_name = extract_stack_name(path)
6
+ def initialize(stack_name)
7
+ @stack_name = stack_name
9
8
  end
10
9
 
11
10
  def selected?
@@ -61,10 +60,6 @@ module Terraspace::Compiler
61
60
  Terraspace.config
62
61
  end
63
62
 
64
- def extract_stack_name(path)
65
- path.sub(%r{.*(app|vendor)/stacks/}, '')
66
- end
67
-
68
63
  @@ignore_stacks_deprecation_warning = nil
69
64
  def ignore_stacks_deprecation_warning
70
65
  return unless config.all.ignore_stacks
@@ -8,28 +8,29 @@ class Terraspace::Compiler::Strategy::Mod
8
8
  @filename = filename
9
9
  end
10
10
 
11
- @@already_reported = false
12
11
  def check
13
- unless file_installed?
14
- return true if @@already_reported
15
- logger.warn <<~EOL.color(:yellow)
16
- WARN: The command 'file' is not installed.
17
- Unable to check if files are text or binary files as a part of the Terraspace compile processing.
18
- Assuming all files are not binary file.
12
+ return true if Gem.win_platform? # assume text file if on windows
13
+ return true unless file_installed?
19
14
 
20
- Please install the file command to remove this warning message.
21
- EOL
22
- @@already_reported = true
23
- return true
24
- end
25
15
  # Thanks: https://stackoverflow.com/questions/2355866/ruby-how-to-determine-if-file-being-read-is-binary-or-text
26
16
  file_type, status = Open3.capture2e("file", @filename)
27
17
  status.success? && file_type.include?("text")
28
18
  end
29
19
 
30
20
  private
21
+ @@has_file = nil
31
22
  def file_installed?
32
- system("type file > /dev/null 2>&1")
23
+ return @@has_file unless @@has_file.nil?
24
+ @@has_file = system("type file > /dev/null 2>&1")
25
+ unless @@has_file
26
+ logger.warn <<~EOL.color(:yellow)
27
+ WARN: The command 'file' is not installed.
28
+ Unable to check if files are text or binary files as a part of the Terraspace compile processing.
29
+ Assuming all files are not binary file.
30
+ Please install the file command to remove this warning message.
31
+ EOL
32
+ end
33
+ @@has_file
33
34
  end
34
35
  end
35
36
  end
@@ -58,8 +58,9 @@ class Terraspace::Compiler::Strategy::Tfvar
58
58
  end
59
59
 
60
60
  def full_layering
61
- # layers is defined in Terraspace::Layering module
62
- layers.inject([]) do |sum, layer|
61
+ # layers defined in Terraspace::Layering module
62
+ all = layers.map { |layer| layer.sub(/\/$/,'') } # strip trailing slash
63
+ all.inject([]) do |sum, layer|
63
64
  sum += layer_levels(layer) unless layer.nil?
64
65
  sum
65
66
  end
@@ -5,7 +5,7 @@ module Terraspace::Compiler::Strategy
5
5
  @order = 0
6
6
  end
7
7
 
8
- def run
8
+ def run(write: true)
9
9
  layer_paths.each do |layer_path|
10
10
  ext = File.extname(layer_path).sub('.','')
11
11
  klass = strategy_class(ext)
@@ -14,6 +14,7 @@ module Terraspace::Compiler::Strategy
14
14
  strategy = klass.new(@mod, layer_path)
15
15
  content = strategy.run
16
16
 
17
+ next unless write
17
18
  dest_name = ordered_name(layer_path)
18
19
  writer = Terraspace::Compiler::Writer.new(@mod, dest_name: dest_name)
19
20
  writer.write(content)
@@ -59,7 +59,7 @@ module Terraspace
59
59
  end
60
60
  end
61
61
 
62
- # Terraspace.argv provides consistency when terraspace is being called by rspec-terrspace test harness
62
+ # Terraspace.argv provides consistency when terraspace is being called by rspec-terraspace test harness
63
63
  # So use Terraspace.argv instead of ARGV constant
64
64
  def argv=(argv)
65
65
  @@argv = argv
@@ -0,0 +1,20 @@
1
+ module Terraspace::Dependency
2
+ class Resolver
3
+ include Terraspace::Compiler::DirsConcern
4
+
5
+ def initialize(options={})
6
+ @options = options
7
+ end
8
+
9
+ def resolve
10
+ with_each_mod("stacks") do |mod|
11
+ mod.resolved = false
12
+ Terraspace::Compiler::Perform.new(mod).compile_tfvars(write: false)
13
+ end
14
+
15
+ dependencies = Terraspace::Dependency::Registry.data # populated dependencies resolved
16
+ @graph = Terraspace::Dependency::Graph.new(stack_names, dependencies, @options)
17
+ @graph.build # Returns batches to run
18
+ end
19
+ end
20
+ end
@@ -5,8 +5,15 @@ class Module
5
5
  # include Provider
6
6
  # # etc
7
7
  #
8
+ # Caller lines are different for OSes:
9
+ #
10
+ # windows: "C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/terraspace-1.1.1/lib/terraspace/builder.rb:34:in `build'"
11
+ # linux: "/home/ec2-user/.rvm/gems/ruby-3.0.3/gems/terraspace-1.1.1//lib/terraspace/compiler/dsl/syntax/mod.rb:4:in `<module:Mod>'"
12
+ #
8
13
  def include_dir(dir)
9
- calling_file = caller[0].split(':').first # IE: /home/ec2-user/environment/terraspace/lib/terraspace/compiler/dsl/syntax/mod.rb
14
+ caller_line = caller[0]
15
+ parts = caller_line.split(':')
16
+ calling_file = caller_line.match(/^[a-zA-Z]:/) ? parts[1] : parts[0]
10
17
  parent_dir = File.dirname(calling_file)
11
18
 
12
19
  full_dir = "#{parent_dir}/#{dir}"
@@ -15,6 +15,7 @@ module Terraspace
15
15
  @name, @options = placeholder(name), options
16
16
  @consider_stacks = options[:consider_stacks].nil? ? true : options[:consider_stacks]
17
17
  @instance = options[:instance]
18
+ @resolved = true # more common case
18
19
  end
19
20
 
20
21
  def placeholder(name)
@@ -49,7 +49,7 @@ module Terraspace::Plugin::Summary
49
49
  def download_statefiles
50
50
  return unless download?
51
51
  FileUtils.rm_rf(@dest_folder)
52
- logger.info("Downloading statefiles to #{@dest_folder}")
52
+ logger.debug("Downloading statefiles to #{@dest_folder}")
53
53
  download # INTERFACE METHOD
54
54
  end
55
55
 
@@ -0,0 +1,25 @@
1
+ module Terraspace::Terraform::Args
2
+ class Expand
3
+ class << self
4
+ def option_method(*names)
5
+ names.compact.each do |name|
6
+ option_method_each(name)
7
+ end
8
+ end
9
+
10
+ def option_method_each(name)
11
+ define_method name do
12
+ return unless @options[name]
13
+ expander = Terraspace::Compiler::Expander.autodetect(@mod)
14
+ expander.expansion(@options[name]) # pattern is a String that contains placeholders for substitutions
15
+ end
16
+ end
17
+ end
18
+
19
+ def initialize(mod, options={})
20
+ @mod, @options = mod, options
21
+ end
22
+
23
+ option_method :plan, :out
24
+ end
25
+ end
@@ -2,6 +2,8 @@ require "tempfile"
2
2
 
3
3
  module Terraspace::Terraform::Args
4
4
  class Thor
5
+ extend Memoist
6
+
5
7
  def initialize(mod, name, options={})
6
8
  @mod, @name, @options = mod, name.underscore, options
7
9
  @quiet = @options[:quiet].nil? ? true : @options[:quiet]
@@ -48,7 +50,7 @@ module Terraspace::Terraform::Args
48
50
  args << input_option
49
51
 
50
52
  # must be at the end
51
- plan = @options[:plan]
53
+ plan = expand.plan
52
54
  if plan
53
55
  copy_to_cache(plan)
54
56
  args << " #{plan}"
@@ -81,7 +83,7 @@ module Terraspace::Terraform::Args
81
83
 
82
84
  def output_args
83
85
  args = []
84
- args << "> #{expanded_out}" if @options[:out]
86
+ args << "> #{expand.out}" if expand.out
85
87
  args
86
88
  end
87
89
 
@@ -89,26 +91,22 @@ module Terraspace::Terraform::Args
89
91
  args = []
90
92
  args << input_option
91
93
  args << "-destroy" if @options[:destroy]
92
- args << "-out #{expanded_out}" if @options[:out]
93
- # Note: based on the @options[:out] will run an internal hook to copy plan
94
+ args << "-out #{expand.out}" if expand.out
95
+ # Note: based on the expand.out will run an internal hook to copy plan
94
96
  # file back up to the root project folder for use. Think this is convenient and expected behavior.
95
97
  args
96
98
  end
97
99
 
98
100
  def show_args
99
101
  args = []
100
- plan = @options[:plan]
102
+ plan = expand.plan
101
103
  if plan
102
- copy_to_cache(@options[:plan])
103
- args << " #{@options[:plan]}" # terraform show /path/to/plan
104
+ copy_to_cache(expand.plan)
105
+ args << " #{expand.plan}" # terraform show /path/to/plan
104
106
  end
105
107
  args
106
108
  end
107
109
 
108
- def expanded_out
109
- @options[:out]
110
- end
111
-
112
110
  def destroy_args
113
111
  auto_approve_arg
114
112
  end
@@ -147,5 +145,10 @@ module Terraspace::Terraform::Args
147
145
  FileUtils.mkdir_p(File.dirname(dest))
148
146
  FileUtils.cp(src, dest) unless same_file?(src, dest)
149
147
  end
148
+
149
+ def expand
150
+ Terraspace::Terraform::Args::Expand.new(@mod, @options)
151
+ end
152
+ memoize :expand
150
153
  end
151
154
  end
@@ -1,8 +1,8 @@
1
1
  module Terraspace::Terraform::Ihooks::After
2
2
  class Plan < Terraspace::Terraform::Ihooks::Base
3
3
  def run
4
- return if !@options[:out] || @options[:copy_to_root] == false
5
- copy_to_root(@options[:out])
4
+ return if !out_option || @options[:copy_to_root] == false
5
+ copy_to_root(out_option)
6
6
  end
7
7
 
8
8
  def copy_to_root(file)
@@ -4,5 +4,10 @@ module Terraspace::Terraform::Ihooks
4
4
  @name = name
5
5
  super(options)
6
6
  end
7
+
8
+ def out_option
9
+ expand = Terraspace::Terraform::Args::Expand.new(@mod, @options)
10
+ expand.out
11
+ end
7
12
  end
8
13
  end
@@ -1,12 +1,10 @@
1
1
  module Terraspace::Terraform::Ihooks::Before
2
2
  class Plan < Terraspace::Terraform::Ihooks::Base
3
3
  def run
4
- out = @options[:out]
5
- return unless out
6
- return if out =~ %r{^/} # not need to create parent dir for copy with absolute path
4
+ return unless out_option
5
+ return if out_option =~ %r{^/} # not need to create parent dir for copy with absolute path
7
6
 
8
- out = @options[:out]
9
- name = out.sub("#{Terraspace.root}/",'')
7
+ name = out_option.sub("#{Terraspace.root}/",'')
10
8
  dest = "#{@mod.cache_dir}/#{name}"
11
9
  FileUtils.mkdir_p(File.dirname(dest))
12
10
  end
@@ -2,6 +2,7 @@ module Terraspace::Terraform::RemoteState
2
2
  class Fetcher
3
3
  extend Memoist
4
4
  include Terraspace::Compiler::CommandsConcern
5
+ include Terraspace::Compiler::DirsConcern
5
6
  include Terraspace::Util::Logging
6
7
 
7
8
  def initialize(parent, identifier, options={})
@@ -47,7 +48,7 @@ module Terraspace::Terraform::RemoteState
47
48
  def output_error(type)
48
49
  msg = case type
49
50
  when :key_not_found
50
- "Output #{@output_key} was not found for the #{@parent.name} tfvars file. Either #{@child.name} stack has not been deployed yet or it does not have this output: #{@output_key}"
51
+ "Output #{@output_key} was not found for the #{@parent.name} tfvars file. Either #{@child.name} stack has not been deployed yet or it does not have this output: #{@output_key}. Also, if local backend is being used and has been removed/cleaned, then it will also result zero-byte state.json with the 'terraform state pull' used to download the terraform state and output will not be found."
51
52
  when :state_not_found
52
53
  "Output #{@output_key} could not be looked up for the #{@parent.name} tfvars file. #{@child.name} stack needs to be deployed"
53
54
  when :bucket_not_found
@@ -62,7 +63,7 @@ module Terraspace::Terraform::RemoteState
62
63
  @@download_shown = false
63
64
  def pull
64
65
  return if @@pull_successes[cache_key]
65
- logger.info "Downloading tfstate files for dependencies defined in tfvars..." unless @@download_shown || @options[:quiet]
66
+ logger.debug "Downloading tfstate files for dependencies defined in tfvars..." unless @@download_shown || @options[:quiet]
66
67
  @@download_shown = true
67
68
  logger.debug "Downloading tfstate for stack: #{@child.name}"
68
69
 
@@ -130,9 +131,15 @@ module Terraspace::Terraform::RemoteState
130
131
 
131
132
  # Note we already validate mod exist at the terraform_output helper. This is just in case that logic changes.
132
133
  def validate!
133
- return if @child.exist?
134
- logger.error "ERROR: stack #{@child.name} not found".color(:red)
135
- exit 1
134
+ unless @child.exist?
135
+ logger.error "ERROR: stack #{@child.name} not found".color(:red)
136
+ exit 1
137
+ end
138
+ select = Terraspace::Compiler::Select.new(@child.name)
139
+ unless select.selected?
140
+ logger.error "ERROR: stack #{@child.name} is configured to not be included. IE: config.all.include_stacks or config.all.exclude_stacks".color(:red)
141
+ exit 1
142
+ end
136
143
  end
137
144
 
138
145
  # Using debug level because all the tfvar files always get evaluated.
@@ -25,7 +25,7 @@ module Terraspace::Terraform::RemoteState::Marker
25
25
  end
26
26
 
27
27
  def warning
28
- logger.warn "WARN: The #{@child_name} stack does not exist".color(:yellow)
28
+ logger.warn "WARN: The #{@child_name} stack does not exist or is configured to be not included. IE: config.all.include_stacks or config.all.exclude_stacks".color(:yellow)
29
29
  caller_line = caller.find { |l| l.include?('.tfvars') }
30
30
  return unless caller_line # specs dont have a tfvars file
31
31
  source_code = PrettyTracer.new(caller_line).source_code
@@ -1,3 +1,3 @@
1
1
  module Terraspace
2
- VERSION = "1.0.5"
2
+ VERSION = "1.1.2"
3
3
  end
@@ -1,6 +1,7 @@
1
1
  describe Terraspace::All::Runner do
2
2
  let(:runner) do
3
3
  runner = described_class.new(command: "up", yes: true)
4
+ allow(runner).to receive(:build_modules)
4
5
  allow(runner).to receive(:build_batches).and_return(batches)
5
6
  allow(runner).to receive(:preview)
6
7
  # Just test to the point of the run_builder and deploy_batch
@@ -1,6 +1,10 @@
1
1
  describe Terraspace::Compiler::Erb::Render do
2
2
  let(:render) { described_class.new(mod, src_path) }
3
- let(:mod) { Terraspace::Mod.new("a1") }
3
+ let(:mod) do
4
+ mod = Terraspace::Mod.new("a1")
5
+ mod.resolved = false
6
+ mod
7
+ end
4
8
 
5
9
  # Only testing mod unresolved as a sanity check and its worth the ROI.
6
10
  # The resolved would the Fetcher. We have unit tests to cover those other changes.
data/terraspace.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Tung Nguyen"]
10
10
  spec.email = ["tung@boltops.com"]
11
11
  spec.summary = "Terraspace: The Terraspace Framework"
12
- spec.homepage = "https://github.com/boltops-tools/terraspace"
12
+ spec.homepage = "https://terraspace.cloud"
13
13
  spec.license = "Apache-2.0"
14
14
 
15
15
  spec.files = File.directory?('.git') ? `git ls-files`.split($/) : Dir.glob("**/*")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terraspace
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-23 00:00:00.000000000 Z
11
+ date: 2022-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -490,6 +490,7 @@ files:
490
490
  - lib/terraspace/builder/allow/env.rb
491
491
  - lib/terraspace/builder/allow/region.rb
492
492
  - lib/terraspace/builder/allow/stack.rb
493
+ - lib/terraspace/builder/children.rb
493
494
  - lib/terraspace/bundle.rb
494
495
  - lib/terraspace/cli.rb
495
496
  - lib/terraspace/cli/all.rb
@@ -602,8 +603,6 @@ files:
602
603
  - lib/terraspace/cli/up.rb
603
604
  - lib/terraspace/command.rb
604
605
  - lib/terraspace/compiler/basename.rb
605
- - lib/terraspace/compiler/builder.rb
606
- - lib/terraspace/compiler/builder/skip.rb
607
606
  - lib/terraspace/compiler/cleaner.rb
608
607
  - lib/terraspace/compiler/cleaner/backend_change.rb
609
608
  - lib/terraspace/compiler/commands_concern.rb
@@ -633,6 +632,8 @@ files:
633
632
  - lib/terraspace/compiler/expander.rb
634
633
  - lib/terraspace/compiler/expander/backend.rb
635
634
  - lib/terraspace/compiler/helper_extender.rb
635
+ - lib/terraspace/compiler/perform.rb
636
+ - lib/terraspace/compiler/perform/skip.rb
636
637
  - lib/terraspace/compiler/select.rb
637
638
  - lib/terraspace/compiler/strategy/abstract_base.rb
638
639
  - lib/terraspace/compiler/strategy/mod.rb
@@ -655,6 +656,7 @@ files:
655
656
  - lib/terraspace/dependency/helper/output.rb
656
657
  - lib/terraspace/dependency/node.rb
657
658
  - lib/terraspace/dependency/registry.rb
659
+ - lib/terraspace/dependency/resolver.rb
658
660
  - lib/terraspace/dotenv.rb
659
661
  - lib/terraspace/ext.rb
660
662
  - lib/terraspace/ext/bundler.rb
@@ -703,6 +705,7 @@ files:
703
705
  - lib/terraspace/terraform/api/workspace.rb
704
706
  - lib/terraspace/terraform/args/custom.rb
705
707
  - lib/terraspace/terraform/args/dsl.rb
708
+ - lib/terraspace/terraform/args/expand.rb
706
709
  - lib/terraspace/terraform/args/pass.rb
707
710
  - lib/terraspace/terraform/args/shorthands.rb
708
711
  - lib/terraspace/terraform/args/thor.rb
@@ -864,7 +867,7 @@ files:
864
867
  - spec/terraspace/terraform/remote_state/marker/output_spec.rb
865
868
  - spec/terraspace/terraform/remote_state/output_proxy_spec.rb
866
869
  - terraspace.gemspec
867
- homepage: https://github.com/boltops-tools/terraspace
870
+ homepage: https://terraspace.cloud
868
871
  licenses:
869
872
  - Apache-2.0
870
873
  metadata: {}