terraspace 0.6.20 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.cody/README.md +2 -0
  3. data/.cody/azurerm/bin/az/configure.sh +5 -1
  4. data/.cody/azurerm/project.rb +4 -0
  5. data/.cody/azurerm/role.rb +0 -1
  6. data/.cody/google/bin/gcloud/configure.sh +2 -1
  7. data/.cody/google/project.rb +4 -0
  8. data/.cody/google/role.rb +0 -1
  9. data/.cody/none/bin/build.sh +15 -0
  10. data/.cody/none/buildspec.yml +10 -0
  11. data/.cody/none/project.rb +2 -0
  12. data/.cody/none/role.rb +4 -0
  13. data/.cody/shared/script/install/terraform.sh +14 -6
  14. data/.cody/unit/buildspec.yml +1 -0
  15. data/.pipedream/pipeline.rb +1 -0
  16. data/CHANGELOG.md +38 -0
  17. data/Gemfile +6 -0
  18. data/README.md +1 -1
  19. data/lib/templates/examples/hcl/module/main.tf +3 -0
  20. data/lib/templates/examples/hcl/module/outputs.tf +4 -0
  21. data/lib/templates/examples/hcl/module/variables.tf +5 -0
  22. data/lib/templates/examples/hcl/stack/main.tf +4 -0
  23. data/lib/templates/examples/hcl/stack/outputs.tf +4 -0
  24. data/lib/templates/examples/hcl/stack/variables.tf +5 -0
  25. data/lib/templates/examples/ruby/module/main.rb +3 -0
  26. data/lib/templates/examples/ruby/module/outputs.rb +4 -0
  27. data/lib/templates/examples/ruby/module/variables.rb +5 -0
  28. data/lib/templates/examples/ruby/stack/main.rb +4 -0
  29. data/lib/templates/examples/ruby/stack/outputs.rb +4 -0
  30. data/lib/templates/examples/ruby/stack/variables.rb +5 -0
  31. data/lib/templates/hcl/project/config/terraform/backend.tf.tt +5 -13
  32. data/lib/templates/hcl/project/config/terraform/provider.tf +4 -14
  33. data/lib/terraspace/autodetect.rb +15 -0
  34. data/lib/terraspace/autoloader.rb +6 -1
  35. data/lib/terraspace/builder.rb +1 -9
  36. data/lib/terraspace/bundle.rb +54 -0
  37. data/lib/terraspace/cli/concern.rb +113 -0
  38. data/lib/terraspace/cli/help/new/example.md +7 -1
  39. data/lib/terraspace/cli/help.rb +7 -8
  40. data/lib/terraspace/cli/new/example.rb +36 -0
  41. data/lib/terraspace/cli/new/helpers/plugin_gem.rb +2 -14
  42. data/lib/terraspace/cli/new/helpers.rb +1 -1
  43. data/lib/terraspace/cli/new/module.rb +1 -1
  44. data/lib/terraspace/cli/new/plugin/helper.rb +1 -1
  45. data/lib/terraspace/cli/new/plugin.rb +1 -1
  46. data/lib/terraspace/cli/new/project.rb +11 -17
  47. data/lib/terraspace/cli/new/sequence.rb +1 -1
  48. data/lib/terraspace/cli/new/source/core.rb +7 -6
  49. data/lib/terraspace/cli/new/source/plugin.rb +2 -2
  50. data/lib/terraspace/cli/new/stack.rb +3 -2
  51. data/lib/terraspace/cli/new/test.rb +12 -2
  52. data/lib/terraspace/cli/new.rb +4 -0
  53. data/lib/terraspace/cli/{check_setup.rb → setup/check.rb} +5 -3
  54. data/lib/terraspace/cli/setup.rb +9 -0
  55. data/lib/terraspace/cli/tfc_concern.rb +1 -1
  56. data/lib/terraspace/cli.rb +34 -27
  57. data/lib/terraspace/command.rb +3 -2
  58. data/lib/terraspace/compiler/commands_concern.rb +0 -8
  59. data/lib/terraspace/compiler/expander/backend.rb +44 -0
  60. data/lib/terraspace/compiler/expander.rb +11 -19
  61. data/lib/terraspace/compiler/strategy/mod/text_file.rb +35 -0
  62. data/lib/terraspace/compiler/strategy/mod.rb +2 -5
  63. data/lib/terraspace/core.rb +10 -0
  64. data/lib/terraspace/plugin/expander/friendly.rb +1 -0
  65. data/lib/terraspace/plugin/expander/interface.rb +13 -2
  66. data/lib/terraspace/terraform/api/client.rb +1 -1
  67. data/lib/terraspace/terraform/args/custom.rb +11 -6
  68. data/lib/terraspace/terraform/args/pass.rb +110 -0
  69. data/lib/terraspace/terraform/args/{default.rb → thor.rb} +1 -3
  70. data/lib/terraspace/{compiler → terraform/runner}/backend/parser.rb +1 -1
  71. data/lib/terraspace/{compiler → terraform/runner}/backend.rb +14 -1
  72. data/lib/terraspace/terraform/runner/retryer.rb +1 -1
  73. data/lib/terraspace/terraform/runner.rb +25 -15
  74. data/lib/terraspace/terraform/tfc/sync.rb +1 -1
  75. data/lib/terraspace/version.rb +1 -1
  76. data/lib/terraspace.rb +1 -0
  77. data/spec/terraspace/seeder/content_spec.rb +2 -2
  78. data/spec/terraspace/terraform/args/custom_spec.rb +4 -4
  79. data/spec/terraspace/terraform/args/pass_spec.rb +101 -0
  80. data/terraspace.gemspec +3 -4
  81. metadata +61 -50
@@ -68,5 +68,15 @@ module Terraspace
68
68
  def argv
69
69
  @@argv
70
70
  end
71
+
72
+ @@check_project = true
73
+ def check_project
74
+ @@check_project
75
+ end
76
+
77
+ # allow testing frameworks to disable
78
+ def check_project=(v)
79
+ @@check_project = v
80
+ end
71
81
  end
72
82
  end
@@ -4,6 +4,7 @@ module Terraspace::Plugin::Expander
4
4
  # Terraspace::Compiler::Strategy::Tfvar::Layer
5
5
  # Terraspace::Plugin::Expander::Interface
6
6
  def friendly_name(name)
7
+ return '' if name.nil?
7
8
  Terraspace.config.layering.names[name.to_sym] || name
8
9
  end
9
10
  end
@@ -70,12 +70,15 @@ module Terraspace::Plugin::Expander
70
70
  #
71
71
  def strip(string)
72
72
  string.sub(/^-+/,'').sub(/-+$/,'') # remove leading and trailing -
73
- .sub(%r{/+$},'') # only remove trailing / or else /home/ec2-user => home/ec2-user
73
+ .sub(%r{/+$},'') # only remove trailing / or else /home/ec2-user => home/ec2-user
74
+ .sub(/:\/\//, 'TMP_KEEP_HTTP') # so we can keep ://. IE: https:// or http://
75
+ .gsub(%r{/+},'/') # remove double slashes are more. IE: // -> / Useful of region is '' in generic expander
76
+ .sub('TMP_KEEP_HTTP', '://') # restore :// IE: https:// or http://
74
77
  end
75
78
 
76
79
  def var_value(name)
77
80
  name = name.sub(':','').downcase
78
- value = send(name)
81
+ value = send(name).to_s
79
82
  if name == "namespace" && Terraspace.config.layering.enable_names.expansion
80
83
  value = friendly_name(value)
81
84
  end
@@ -102,5 +105,13 @@ module Terraspace::Plugin::Expander
102
105
  def cache_root
103
106
  Terraspace.cache_root
104
107
  end
108
+
109
+ # So default config works:
110
+ # config.cache_dir = ":CACHE_ROOT/:REGION/:ENV/:BUILD_DIR"
111
+ # For when folks configure it with the http backend for non-cloud providers
112
+ # The double slash // will be replace with a single slash in expander/interface.rb
113
+ def region
114
+ ''
115
+ end
105
116
  end
106
117
  end
@@ -16,7 +16,7 @@ class Terraspace::Terraform::Api
16
16
 
17
17
  # backend may be overridden in classes including this Concern
18
18
  def backend
19
- Terraspace::Compiler::Backend::Parser.new(@mod).result
19
+ Terraspace::Terraform::Runner::Backend::Parser.new(@mod).result
20
20
  end
21
21
  memoize :backend
22
22
 
@@ -18,23 +18,28 @@ module Terraspace::Terraform::Args
18
18
  memoize :build
19
19
 
20
20
  def args
21
+ terraform_args + var_file_args
22
+ end
23
+
24
+ def env_vars
25
+ build
26
+ dig("env", {})
27
+ end
28
+
29
+ private
30
+ def terraform_args
21
31
  build
22
32
  args = dig("args")
23
33
  args.compact.flatten
24
34
  end
25
35
 
26
- def var_files
36
+ def var_file_args
27
37
  build
28
38
  var_files = dig("var_files")
29
39
  var_files.select! { |f| var_file_exist?(f) }
30
40
  var_files.map { |f| "-var-file=#{f}" }
31
41
  end
32
42
 
33
- def env_vars
34
- build
35
- dig("env", {})
36
- end
37
-
38
43
  def var_file_exist?(var_file)
39
44
  File.exist?("#{@mod.cache_dir}/#{var_file}")
40
45
  end
@@ -0,0 +1,110 @@
1
+ module Terraspace::Terraform::Args
2
+ class Pass
3
+ def initialize(mod, name, options={})
4
+ @mod, @name, @options = mod, name.underscore, options
5
+ end
6
+
7
+ # map to terraform options and only allow valid terraform options
8
+ # Arg Examples:
9
+ # -refresh-only
10
+ # -refresh=false
11
+ # -var 'foo=bar'
12
+ def args
13
+ args = pass_args.select do |arg|
14
+ arg_name = get_arg_name(arg)
15
+ terraform_arg_types.include?(arg_name)
16
+ end
17
+
18
+ args.map { |arg| "-#{arg}" } # add back in the leading single dash (-)
19
+ end
20
+
21
+ private
22
+ def pass_args
23
+ args = (@options[:args] || []).map do |o|
24
+ o.sub(/^-{1,2}/,'') # strips the - or --
25
+ end
26
+ reconstruct_hash_args(args)
27
+ end
28
+
29
+ # Thor parses CLI args -var 'foo=bar'
30
+ # as:
31
+ # ["-var", "foo=bar"]
32
+ # instead of:
33
+ # ["-var 'foo=bar'"]
34
+ #
35
+ # So reconstruct it to what works with terraform CLI args
36
+ def reconstruct_hash_args(args)
37
+ result = []
38
+ flatten = []
39
+ skip = false
40
+ args.each do |arg|
41
+ arg_type = terraform_arg_types[arg]
42
+ if arg_type == :hash || skip
43
+ skip = true
44
+ if flatten.size == 1
45
+ flatten << "'#{arg}'" # surround hash value with single quotes
46
+ else
47
+ flatten << arg
48
+ end
49
+ if flatten.size == 2 # time to grab value and end skipping
50
+ result << flatten.join(' ')
51
+ # reset flags
52
+ skip = false
53
+ flatten = []
54
+ end
55
+ next if skip
56
+ else
57
+ result << arg # boolean (-no-color) or assignment (-refresh=false)
58
+ end
59
+ end
60
+ result
61
+ end
62
+
63
+ # Parses terraform COMMAND -help output for arg types.
64
+ # Return Example:
65
+ #
66
+ # {
67
+ # destroy: :boolean,
68
+ # refresh: :assignment,
69
+ # var: :hash,
70
+ # }
71
+ #
72
+ def terraform_arg_types
73
+ out = terraform_help(@name)
74
+ lines = out.split("\n")
75
+ lines.select! do |line|
76
+ line =~ /^ -/
77
+ end
78
+ lines.inject({}) do |result, line|
79
+ # in: " -replace=resource Force replacement of a particular resource instance using",
80
+ # out: "-replace=resource Force replacement of a particular resource instance using",
81
+ line.sub!(' -', '') # remove leading whitespace and -
82
+
83
+ # in: " -var 'foo=bar' Set a value for one of the input variables in the root",
84
+ # out: "var"
85
+ # in: " -refresh=false Skip checking for external changes to remote objects",
86
+ # out: "refresh"
87
+ arg_name = get_arg_name(line)
88
+
89
+ if line.match(/'\w+=\w+'/) # hash. IE: -var 'foo=bar'
90
+ result[arg_name] = :hash
91
+ elsif line.match(/\w+=/) # value IE: -refresh=false
92
+ result[arg_name] = :assignment # can include string and numeric values
93
+ else # boolean IE: -refresh-only
94
+ result[arg_name] = :boolean
95
+ end
96
+ result
97
+ end
98
+ end
99
+
100
+ def get_arg_name(line)
101
+ line.sub(/\s+.*/,'').split('=').first # strips everything except arg name only
102
+ end
103
+
104
+ @@terraform_help = {}
105
+ def terraform_help(name)
106
+ @@terraform_help[name] ||= `terraform #{name} -help`
107
+ end
108
+ end
109
+ end
110
+
@@ -1,7 +1,7 @@
1
1
  require "tempfile"
2
2
 
3
3
  module Terraspace::Terraform::Args
4
- class Default
4
+ class Thor
5
5
  def initialize(mod, name, options={})
6
6
  @mod, @name, @options = mod, name.underscore, options
7
7
  @quiet = @options[:quiet].nil? ? true : @options[:quiet]
@@ -81,7 +81,6 @@ module Terraspace::Terraform::Args
81
81
 
82
82
  def output_args
83
83
  args = []
84
- args << "-json" if @options[:format] == "json"
85
84
  args << "> #{expanded_out}" if @options[:out]
86
85
  args
87
86
  end
@@ -98,7 +97,6 @@ module Terraspace::Terraform::Args
98
97
 
99
98
  def show_args
100
99
  args = []
101
- args << " -json" if @options[:json]
102
100
  plan = @options[:plan]
103
101
  if plan
104
102
  copy_to_cache(@options[:plan])
@@ -1,6 +1,6 @@
1
1
  require "hcl_parser"
2
2
 
3
- class Terraspace::Compiler::Backend
3
+ class Terraspace::Terraform::Runner::Backend
4
4
  class Parser
5
5
  extend Memoist
6
6
 
@@ -1,6 +1,7 @@
1
- module Terraspace::Compiler
1
+ class Terraspace::Terraform::Runner
2
2
  class Backend
3
3
  extend Memoist
4
+ include Terraspace::Compiler::CommandsConcern
4
5
 
5
6
  def initialize(mod)
6
7
  @mod = mod
@@ -9,6 +10,9 @@ module Terraspace::Compiler
9
10
  @@created = {}
10
11
  def create
11
12
  return if @@created[cache_key]
13
+ return if Terraspace.config.auto_create_backend == false
14
+ return unless requires_backend?
15
+
12
16
  # set immediately, since local storage wont reach bottom.
13
17
  # if fail for other backends, there will be an exception anyway
14
18
  @@created[cache_key] = true
@@ -16,6 +20,7 @@ module Terraspace::Compiler
16
20
  klass = backend_interface(backend_name)
17
21
  return unless klass # in case auto-creation is not supported for specific backend
18
22
 
23
+ # IE: TerraspacePluginAws::Interfaces::Backend.new
19
24
  interface = klass.new(backend_info)
20
25
  interface.call
21
26
  end
@@ -44,5 +49,13 @@ module Terraspace::Compiler
44
49
  klass_name.constantize if klass_name
45
50
  rescue NameError
46
51
  end
52
+
53
+ def requires_backend?
54
+ command_is?(requires_backend_commands)
55
+ end
56
+
57
+ def requires_backend_commands
58
+ %w[down init output plan providers refresh show up validate]
59
+ end
47
60
  end
48
61
  end
@@ -9,7 +9,7 @@ class Terraspace::Terraform::Runner
9
9
  end
10
10
 
11
11
  def retry?
12
- max_retries = ENV['TS_MAX_RETRIES'] ? ENV['TS_MAX_RETRIES'].to_i : 3
12
+ max_retries = ENV['TS_MAX_RETRIES'] ? ENV['TS_MAX_RETRIES'].to_i : 1
13
13
  if @retries <= max_retries && !@stop_retrying
14
14
  true # will retry
15
15
  else
@@ -16,12 +16,37 @@ module Terraspace::Terraform
16
16
  end
17
17
  end
18
18
 
19
+ # default at end in case of redirection. IE: terraform output > /path
20
+ def args
21
+ args = custom.args + thor.args + pass.args
22
+ args.uniq
23
+ end
24
+
25
+ # From config/args/terraform.rb https://terraspace.cloud/docs/config/args/terraform/
26
+ def custom
27
+ Args::Custom.new(@mod, @name)
28
+ end
29
+ memoize :custom
30
+
31
+ # From Thor defined/managed cli @options
32
+ def thor
33
+ Args::Thor.new(@mod, @name, @options)
34
+ end
35
+ memoize :thor
36
+
37
+ # From Thor passthrough cli @options[:args]
38
+ def pass
39
+ Args::Pass.new(@mod, @name, @options)
40
+ end
41
+ memoize :pass
42
+
19
43
  def terraform(name, *args)
20
44
  current_dir_message # only show once
21
45
 
22
46
  params = args.flatten.join(' ')
23
47
  command = "terraform #{name} #{params}".squish
24
48
  run_hooks("terraform.rb", name) do
49
+ Backend.new(@mod).create
25
50
  run_internal_hook(:before, name)
26
51
  Terraspace::Shell.new(@mod, command, @options.merge(env: custom.env_vars)).run
27
52
  run_internal_hook(:after, name)
@@ -58,21 +83,6 @@ module Terraspace::Terraform
58
83
  @options[:quiet] ? logger.debug(msg) : logger.info(msg)
59
84
  end
60
85
 
61
- def args
62
- # base at end in case of redirection. IE: terraform output > /path
63
- custom.args + custom.var_files + default.args
64
- end
65
-
66
- def custom
67
- Args::Custom.new(@mod, @name)
68
- end
69
- memoize :custom
70
-
71
- def default
72
- Args::Default.new(@mod, @name, @options)
73
- end
74
- memoize :default
75
-
76
86
  private
77
87
  def time_took
78
88
  t1 = Time.now
@@ -35,7 +35,7 @@ module Terraspace::Terraform::Tfc
35
35
 
36
36
  # already memoized in Api::Client
37
37
  def backend
38
- Terraspace::Compiler::Backend::Parser.new(@mod).result
38
+ Terraspace::Terraform::Runner::Backend::Parser.new(@mod).result
39
39
  end
40
40
  end
41
41
  end
@@ -1,3 +1,3 @@
1
1
  module Terraspace
2
- VERSION = "0.6.20"
2
+ VERSION = "0.7.0"
3
3
  end
data/lib/terraspace.rb CHANGED
@@ -5,6 +5,7 @@ $:.unshift(File.expand_path("../", __FILE__))
5
5
  require "terraspace/autoloader"
6
6
  Terraspace::Autoloader.setup
7
7
 
8
+ require "active_support"
8
9
  require "active_support/concern"
9
10
  require "active_support/core_ext/class"
10
11
  require "active_support/core_ext/hash"
@@ -37,8 +37,8 @@ describe Terraspace::Seeder::Content do
37
37
  result = content.build
38
38
  expected =<<~EOL
39
39
  # Required variables:
40
- name = "string"
41
- azs = [...] # list(string)
40
+ name = "string"
41
+ azs = [...] # list(string)
42
42
 
43
43
  # Optional variables:
44
44
  # project = "project-name"
@@ -20,10 +20,10 @@ describe Terraspace::Terraform::Args::Custom do
20
20
  expect(custom.args).to eq(["-lock-timeout=20m"])
21
21
  end
22
22
 
23
- it "var_files" do
23
+ it "var_file_args" do
24
24
  custom.evaluate_file(file)
25
25
  allow(custom).to receive(:var_file_exist?).and_return(true)
26
- expect(custom.var_files).to eq(["-var-file=a.tfvars", "-var-file=b.tfvars"])
26
+ expect(custom.send(:var_file_args)).to eq(["-var-file=a.tfvars", "-var-file=b.tfvars"])
27
27
  end
28
28
  end
29
29
 
@@ -41,10 +41,10 @@ describe Terraspace::Terraform::Args::Custom do
41
41
  expect(custom.args).to eq(["-lock-timeout=20m"])
42
42
  end
43
43
 
44
- it "var_files" do
44
+ it "var_file_args" do
45
45
  custom.evaluate_file(file)
46
46
  allow(custom).to receive(:var_file_exist?).and_return(true)
47
- expect(custom.var_files).to eq([])
47
+ expect(custom.send(:var_file_args)).to eq([])
48
48
  end
49
49
  end
50
50
  end
@@ -0,0 +1,101 @@
1
+ describe Terraspace::Terraform::Args::Pass do
2
+ let(:pass) do
3
+ described_class.new(mod, name, options)
4
+ end
5
+ let(:mod) { double(:mod).as_null_object }
6
+ let(:options) { {args: args} }
7
+ # defaults
8
+ let(:name) { "plan" }
9
+ let(:args) { [] }
10
+
11
+ context "boolean flag" do
12
+ let(:args) { ["-refresh-only"] }
13
+ it "pass through args" do
14
+ args = pass.args
15
+ expect(args).to eq ["-refresh-only"]
16
+ end
17
+ end
18
+
19
+ context "assignment arg" do
20
+ context "-refresh=false" do
21
+ let(:args) { ["-refresh=false"] }
22
+ it "pass through args" do
23
+ args = pass.args
24
+ expect(args).to eq ["-refresh=false"]
25
+ end
26
+ end
27
+
28
+ context "-lock-timeout=5s" do
29
+ let(:args) { ["-lock-timeout=5s"] }
30
+ it "pass through args" do
31
+ args = pass.args
32
+ expect(args).to eq ["-lock-timeout=5s"]
33
+ end
34
+ end
35
+
36
+ context "-var-file=filename -lock-timeout=5s" do
37
+ let(:args) { ["-var-file=filename', '-lock-timeout=5s"] }
38
+ it "pass through args" do
39
+ args = pass.args
40
+ expect(args).to eq ["-var-file=filename', '-lock-timeout=5s"]
41
+ end
42
+ end
43
+
44
+ # normalizes -- to -
45
+ context "--var-file=filename --lock-timeout=5s" do
46
+ let(:args) { ["--var-file=filename", "--lock-timeout=5s"] }
47
+ it "pass through args" do
48
+ args = pass.args
49
+ expect(args).to eq ["-var-file=filename", "-lock-timeout=5s"]
50
+ end
51
+ end
52
+ end
53
+
54
+ context "hash arg" do
55
+ context "-var 'foo=bar'" do
56
+ let(:args) { ["-var 'foo=bar'"] }
57
+ it "pass through args" do
58
+ args = pass.args
59
+ expect(args).to eq ["-var 'foo=bar'"]
60
+ end
61
+ end
62
+
63
+ context "['-var', 'foo=bar'] improperly passed due to Thor CLI parsing" do
64
+ let(:args) { ["-var", "foo=bar"] }
65
+ it "reconstruct to work with terraform cli" do
66
+ args = pass.send(:pass_args)
67
+ expect(args).to eq ["var 'foo=bar'"]
68
+ end
69
+ end
70
+ end
71
+
72
+ # Works at the parsing level. Also works at Thor CLI parsing level. To test:
73
+ #
74
+ # terraspace plan demo -refresh=false -no-color -var 'foo=bar' -var 'foo2=bar2'
75
+ #
76
+ # Results in:
77
+ #
78
+ # terraform plan -input=false -refresh=false -no-color -var 'foo=bar' -var 'foo2=bar2'
79
+ #
80
+ context "multiple hash arg" do
81
+ context "-var 'foo=bar' -var 'foo2=bar2'" do
82
+ let(:args) { ["-var 'foo=bar'", "-var 'foo2=bar2'"] }
83
+ it "pass through args" do
84
+ args = pass.args
85
+ expect(args).to eq ["-var 'foo=bar'", "-var 'foo2=bar2'"]
86
+ end
87
+ end
88
+ end
89
+
90
+ # Could mock out Pass#terraform_help with fixtures,
91
+ # but will call out to terraform in specs so to see breakage more quickly.
92
+ context "terraform_arg_types" do
93
+ it "parses help output to determine arg types" do
94
+ args = pass.send(:terraform_arg_types)
95
+ # checking specific keys so spec is more robust to terraform cli changes
96
+ expect(args['destroy']).to eq(:boolean)
97
+ expect(args['refresh']).to eq(:assignment)
98
+ expect(args['var']).to eq(:hash)
99
+ end
100
+ end
101
+ end
data/terraspace.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "activesupport"
22
+ spec.add_dependency "bundler"
22
23
  spec.add_dependency "cli-format"
23
24
  spec.add_dependency "deep_merge"
24
25
  spec.add_dependency "dsl_evaluator"
@@ -28,15 +29,13 @@ Gem::Specification.new do |spec|
28
29
  spec.add_dependency "memoist"
29
30
  spec.add_dependency "rainbow"
30
31
  spec.add_dependency "render_me_pretty"
31
- spec.add_dependency "terraspace-bundler", "~> 0.4.0"
32
+ spec.add_dependency "rexml"
33
+ spec.add_dependency "terraspace-bundler", "~> 0.4.4"
32
34
  spec.add_dependency "thor"
33
35
  spec.add_dependency "tty-tree"
34
36
  spec.add_dependency "zeitwerk"
35
37
 
36
38
  # core baseline plugins
37
- spec.add_dependency "terraspace_plugin_aws", "~> 0.3.0"
38
- spec.add_dependency "terraspace_plugin_azurerm", "~> 0.3.0"
39
- spec.add_dependency "terraspace_plugin_google", "~> 0.3.0"
40
39
  spec.add_dependency "rspec-terraspace", "~> 0.3.0"
41
40
 
42
41
  spec.add_development_dependency "bundler"