terraspace 0.3.5 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/README.md +56 -29
  4. data/lib/templates/base/project/README.md +1 -1
  5. data/lib/terraspace/all/runner.rb +1 -0
  6. data/lib/terraspace/all/summary.rb +8 -1
  7. data/lib/terraspace/app.rb +9 -5
  8. data/lib/terraspace/builder.rb +10 -6
  9. data/lib/terraspace/cli.rb +12 -16
  10. data/lib/terraspace/cli/all.rb +6 -0
  11. data/lib/terraspace/cli/bundle.rb +2 -1
  12. data/lib/terraspace/cli/clean.rb +18 -6
  13. data/lib/terraspace/cli/clean/all.rb +18 -0
  14. data/lib/terraspace/cli/clean/base.rb +15 -0
  15. data/lib/terraspace/cli/clean/cache.rb +25 -0
  16. data/lib/terraspace/cli/{logs/tasks.rb → clean/logs.rb} +16 -5
  17. data/lib/terraspace/cli/help/all/init.md +33 -0
  18. data/lib/terraspace/cli/help/clean/all.md +10 -0
  19. data/lib/terraspace/cli/help/clean/cache.md +12 -0
  20. data/lib/terraspace/cli/help/clean/logs.md +17 -0
  21. data/lib/terraspace/cli/help/logs.md +48 -0
  22. data/lib/terraspace/cli/info.rb +12 -0
  23. data/lib/terraspace/cli/init.rb +3 -7
  24. data/lib/terraspace/cli/list.rb +2 -1
  25. data/lib/terraspace/cli/logs.rb +106 -9
  26. data/lib/terraspace/cli/{log → logs}/concern.rb +2 -1
  27. data/lib/terraspace/cli/new/helper.rb +9 -2
  28. data/lib/terraspace/dependency/helper/output.rb +1 -1
  29. data/lib/terraspace/hooks/builder.rb +52 -0
  30. data/lib/terraspace/hooks/concern.rb +9 -0
  31. data/lib/terraspace/{terraform/hooks → hooks}/dsl.rb +3 -2
  32. data/lib/terraspace/hooks/runner.rb +23 -0
  33. data/lib/terraspace/mod.rb +11 -2
  34. data/lib/terraspace/plugin/summary/interface.rb +3 -1
  35. data/lib/terraspace/shell.rb +15 -10
  36. data/lib/terraspace/terraform/args/custom.rb +1 -1
  37. data/lib/terraspace/terraform/args/default.rb +9 -19
  38. data/lib/terraspace/terraform/remote_state/output_proxy.rb +3 -3
  39. data/lib/terraspace/terraform/remote_state/{null_object.rb → unresolved.rb} +1 -1
  40. data/lib/terraspace/terraform/runner.rb +3 -8
  41. data/lib/terraspace/version.rb +1 -1
  42. data/spec/terraspace/{terraform/hooks → hooks}/builder_spec.rb +4 -5
  43. data/spec/terraspace/terraform/remote_state/output_proxy_spec.rb +3 -3
  44. data/terraspace.gemspec +1 -1
  45. metadata +21 -14
  46. data/lib/terraspace/cli/help/clean.md +0 -5
  47. data/lib/terraspace/cli/help/log.md +0 -48
  48. data/lib/terraspace/cli/log.rb +0 -112
  49. data/lib/terraspace/terraform/hooks/builder.rb +0 -40
@@ -0,0 +1,9 @@
1
+ module Terraspace::Hooks
2
+ module Concern
3
+ def run_hooks(dsl_file, name, &block)
4
+ hooks = Builder.new(@mod, "#{Terraspace.root}/config/hooks/#{dsl_file}", name)
5
+ hooks.build # build hooks
6
+ hooks.run_hooks(&block)
7
+ end
8
+ end
9
+ end
@@ -1,4 +1,4 @@
1
- module Terraspace::Terraform::Hooks
1
+ module Terraspace::Hooks
2
2
  module Dsl
3
3
  def before(*commands, **props)
4
4
  commands.each do |name|
@@ -13,7 +13,8 @@ module Terraspace::Terraform::Hooks
13
13
  end
14
14
 
15
15
  def each_hook(type, name, props={})
16
- @hooks[type][name] = props
16
+ @hooks[type][name] ||= []
17
+ @hooks[type][name] << props
17
18
  end
18
19
  end
19
20
  end
@@ -0,0 +1,23 @@
1
+ module Terraspace::Hooks
2
+ class Runner
3
+ include Terraspace::Util
4
+
5
+ def initialize(mod, hook)
6
+ @mod, @hook = mod, hook
7
+ @execute = @hook["execute"]
8
+ end
9
+
10
+ def run
11
+ case @execute
12
+ when String
13
+ Terraspace::Shell.new(@mod, @execute, exit_on_fail: @hook["exit_on_fail"]).run
14
+ when -> (e) { e.respond_to?(:public_instance_methods) && e.public_instance_methods.include?(:call) }
15
+ @execute.new.call
16
+ when -> (e) { e.respond_to?(:call) }
17
+ @execute.call
18
+ else
19
+ logger.warn "WARN: execute option not set for hook: #{@hook.inspect}"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -34,8 +34,17 @@ module Terraspace
34
34
  Terraspace.check_project!
35
35
  return if root
36
36
 
37
- pretty_paths = paths.map { |p| Terraspace::Util.pretty_path(p) }
38
- logger.error "ERROR: Unable to find #{@name.color(:green)} module. Searched paths: #{pretty_paths}"
37
+ pretty_paths = paths.map { |p| Terraspace::Util.pretty_path(p) }.join(", ")
38
+ logger.error <<~EOL
39
+ ERROR: Unable to find #{@name.color(:green)}. Searched paths:
40
+
41
+ #{pretty_paths}
42
+
43
+ To see available stacks, try running:
44
+
45
+ terraspace list
46
+
47
+ EOL
39
48
  ENV['TS_TEST'] ? raise : exit(1)
40
49
  end
41
50
 
@@ -64,7 +64,9 @@ module Terraspace::Plugin::Summary
64
64
 
65
65
  def show_each(path)
66
66
  data = JSON.load(IO.read(path))
67
+ return unless data # edge case: blank file
67
68
  resources = data['resources']
69
+ return unless resources
68
70
  remove_statefile(path) if resources && resources.size == 0 && !ENV['TS_KEEP_EMPTY_STATEFILES']
69
71
  return unless resources && resources.size > 0
70
72
 
@@ -75,7 +77,7 @@ module Terraspace::Plugin::Summary
75
77
  identifier = r['instances'].map do |i|
76
78
  i['attributes']['name'] || i['attributes']['id']
77
79
  end.join(',')
78
- return if @options[:short]
80
+ return unless @options[:details]
79
81
  logger.info " #{r['type']} #{r['name']}: #{identifier}"
80
82
  end
81
83
  end
@@ -6,7 +6,8 @@ module Terraspace
6
6
 
7
7
  def initialize(mod, command, options={})
8
8
  @mod, @command, @options = mod, command, options
9
- @error_type, @error_messages = nil, ''
9
+ # error_messages holds aggregation of all error lines
10
+ @known_error, @error_messages = nil, ''
10
11
  end
11
12
 
12
13
  # requires @mod to be set
@@ -32,10 +33,9 @@ module Terraspace
32
33
  Open3.popen3(env, @command, chdir: @mod.cache_dir) do |stdin, stdout, stderr, wait_thread|
33
34
  mimic_terraform_input(stdin, stdout)
34
35
  while err = stderr.gets
35
- @error_type ||= known_error_type(err)
36
- if @error_type
37
- @error_messages << err
38
- else
36
+ @error_messages << err # aggregate all error lines
37
+ @known_error ||= known_error_type(err)
38
+ unless @known_error
39
39
  # Sometimes may print a "\e[31m\n" which like during dependencies fetcher init
40
40
  # suppress it so dont get a bunch of annoying "newlines"
41
41
  next if err == "\e[31m\n" && @options[:suppress_error_color]
@@ -49,8 +49,8 @@ module Terraspace
49
49
  end
50
50
 
51
51
  def known_error_type(err)
52
- if reinitialization_required?(err)
53
- :reinitialization_required
52
+ if reinit_required?(err)
53
+ :reinit_required
54
54
  elsif bucket_not_found?(err)
55
55
  :bucket_not_found
56
56
  end
@@ -61,7 +61,12 @@ module Terraspace
61
61
  err.include?("Failed to get existing workspaces")
62
62
  end
63
63
 
64
- def reinitialization_required?(err)
64
+ def reinit_required?(err)
65
+ # Example error: https://gist.github.com/tongueroo/f7e0a44b64f0a2e533089b18f331c21e
66
+ squeezed = @error_messages.gsub("\n", ' ').squeeze(' ') # remove double whitespaces and newlines
67
+ general_check = squeezed.include?("terraform init") && squeezed.include?("Error:")
68
+
69
+ general_check ||
65
70
  err.include?("reinitialization required") ||
66
71
  err.include?("terraform init") ||
67
72
  err.include?("require reinitialization")
@@ -71,9 +76,9 @@ module Terraspace
71
76
  return if status == 0
72
77
 
73
78
  exit_on_fail = @options[:exit_on_fail].nil? ? true : @options[:exit_on_fail]
74
- if @error_type == :reinitialization_required
79
+ if @known_error == :reinit_required
75
80
  raise InitRequiredError.new(@error_messages)
76
- elsif @error_type == :bucket_not_found
81
+ elsif @known_error == :bucket_not_found
77
82
  raise BucketNotFoundError.new(@error_messages)
78
83
  elsif exit_on_fail
79
84
  logger.error "Error running command: #{@command}".color(:red)
@@ -7,7 +7,7 @@ module Terraspace::Terraform::Args
7
7
  attr_accessor :name
8
8
  def initialize(mod, name)
9
9
  @mod, @name = mod, name
10
- @file = "#{Terraspace.root}/config/cli/args.rb"
10
+ @file = "#{Terraspace.root}/config/args/terraform.rb"
11
11
  @commands = {}
12
12
  end
13
13
 
@@ -26,7 +26,7 @@ module Terraspace::Terraform::Args
26
26
  args << var_files.map { |f| "-var-file #{Dir.pwd}/#{f}" }.join(' ')
27
27
  end
28
28
 
29
- args << input_option if input_option
29
+ args << input_option
30
30
 
31
31
  # must be at the end
32
32
  plan = @options[:plan]
@@ -45,27 +45,17 @@ module Terraspace::Terraform::Args
45
45
  end
46
46
 
47
47
  def input_option
48
- option = nil
49
- if @options[:auto] && @options[:input].nil?
50
- option = " -input=false"
51
- end
52
- unless @options[:input].nil?
53
- input = @options[:input] ? "true" : "false"
54
- option = " -input=#{input}" # = sign required for apply when there's a plan at the end. so input=false works input false doesnt
55
- end
56
- option
48
+ option = if @options[:auto]
49
+ "false"
50
+ else
51
+ @options[:input] ? @options[:input] : "false"
52
+ end
53
+ " -input=#{option}"
57
54
  end
58
55
 
59
56
  def init_args
60
57
  args = "-get"
61
- if @options[:auto] && @options[:input].nil?
62
- args << " -input=false"
63
- end
64
- unless @options[:input].nil?
65
- input = @options[:input] ? "true" : "false"
66
- args << " -input=#{input}"
67
- end
68
-
58
+ args << input_option
69
59
  args << " -reconfigure" if @options[:reconfigure]
70
60
 
71
61
  # must be at the end
@@ -86,7 +76,7 @@ module Terraspace::Terraform::Args
86
76
 
87
77
  def plan_args
88
78
  args = []
89
- args << input_option if input_option
79
+ args << input_option
90
80
  args << "-destroy" if @options[:destroy]
91
81
  args << "-out #{expanded_out}" if @options[:out]
92
82
  args
@@ -11,18 +11,18 @@ module Terraspace::Terraform::RemoteState
11
11
  # Should always return a String
12
12
  def to_s
13
13
  if @mod.resolved
14
- # Dont use NullObject wrapper because Integer get changed to Strings.
14
+ # Dont use Unresolved wrapper because Integer get changed to Strings.
15
15
  # Want raw value to be used for the to_json call
16
16
  value = @raw.nil? ? mock_or_error : @raw
17
17
  value.to_json
18
18
  else
19
- NullObject.new # to_s => (unresolved)
19
+ Unresolved.new
20
20
  end
21
21
  end
22
22
 
23
23
  def to_ruby
24
24
  data = @raw.nil? ? mock_or_error : @raw
25
- @mod.resolved ? data : NullObject.new
25
+ @mod.resolved ? data : Unresolved.new
26
26
  end
27
27
 
28
28
  private
@@ -1,5 +1,5 @@
1
1
  module Terraspace::Terraform::RemoteState
2
- class NullObject
2
+ class Unresolved
3
3
  def to_a
4
4
  []
5
5
  end
@@ -1,6 +1,7 @@
1
1
  module Terraspace::Terraform
2
2
  class Runner < Terraspace::CLI::Base
3
3
  extend Memoist
4
+ include Terraspace::Hooks::Concern
4
5
  include Terraspace::Util
5
6
 
6
7
  attr_reader :name
@@ -20,8 +21,8 @@ module Terraspace::Terraform
20
21
  current_dir_message # only show once
21
22
 
22
23
  params = args.flatten.join(' ')
23
- command = "terraform #{name} #{params}"
24
- run_hooks(name) do
24
+ command = "terraform #{name} #{params}".squish
25
+ run_hooks("terraform.rb", name) do
25
26
  Terraspace::Shell.new(@mod, command, @options.merge(env: custom.env_vars)).run
26
27
  end
27
28
  rescue Terraspace::InitRequiredError => e
@@ -53,12 +54,6 @@ module Terraspace::Terraform
53
54
  @options[:quiet] ? logger.debug(msg) : logger.info(msg)
54
55
  end
55
56
 
56
- def run_hooks(name, &block)
57
- hooks = Hooks::Builder.new(@mod, name)
58
- hooks.build # build hooks
59
- hooks.run_hooks(&block)
60
- end
61
-
62
57
  def args
63
58
  # base at end in case of redirection. IE: terraform output > /path
64
59
  custom.args + custom.var_files + default.args
@@ -1,3 +1,3 @@
1
1
  module Terraspace
2
- VERSION = "0.3.5"
2
+ VERSION = "0.4.3"
3
3
  end
@@ -1,7 +1,6 @@
1
- describe Terraspace::Terraform::Hooks::Builder do
1
+ describe Terraspace::Hooks::Builder do
2
2
  let(:builder) do
3
- builder = described_class.new(mod, name)
4
- builder.instance_variable_set(:@file, file) # override @file for spec
3
+ builder = described_class.new(mod, dsl_file, name)
5
4
  builder
6
5
  end
7
6
  let(:mod) do
@@ -11,7 +10,7 @@ describe Terraspace::Terraform::Hooks::Builder do
11
10
  end
12
11
 
13
12
  context "single" do
14
- let(:file) { fixture("terraform/hooks/single.rb") }
13
+ let(:dsl_file) { fixture("terraform/hooks/single.rb") }
15
14
  let(:name) { "apply" }
16
15
  it "build creates the @hooks structure" do
17
16
  hooks = builder.build
@@ -25,7 +24,7 @@ describe Terraspace::Terraform::Hooks::Builder do
25
24
  end
26
25
 
27
26
  context "multiple" do
28
- let(:file) { fixture("terraform/hooks/multiple.rb") }
27
+ let(:dsl_file) { fixture("terraform/hooks/multiple.rb") }
29
28
  let(:name) { "apply" }
30
29
  it "build creates the @hooks structure" do
31
30
  hooks = builder.build
@@ -1,4 +1,4 @@
1
- NullObject = Terraspace::Terraform::RemoteState::NullObject
1
+ Unresolved = Terraspace::Terraform::RemoteState::Unresolved
2
2
 
3
3
  describe Terraspace::Terraform::RemoteState::OutputProxy do
4
4
  let(:proxy) do
@@ -10,9 +10,9 @@ describe Terraspace::Terraform::RemoteState::OutputProxy do
10
10
 
11
11
  context "unresolved" do
12
12
  before(:each) { mod.resolved = false }
13
- it "always return NullObject" do
13
+ it "always return Unresolved" do
14
14
  value = proxy.to_s
15
- expect(value).to be_a(NullObject)
15
+ expect(value).to be_a(Unresolved)
16
16
  expect(value.to_str).to eq "(unresolved)"
17
17
  end
18
18
  end
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency "memoist"
29
29
  spec.add_dependency "rainbow"
30
30
  spec.add_dependency "render_me_pretty"
31
- spec.add_dependency "terraspace-bundler", "~> 0.2.0"
31
+ spec.add_dependency "terraspace-bundler", "~> 0.3.0"
32
32
  spec.add_dependency "thor"
33
33
  spec.add_dependency "tty-tree"
34
34
  spec.add_dependency "zeitwerk"
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: 0.3.5
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-29 00:00:00.000000000 Z
11
+ date: 2020-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -156,14 +156,14 @@ dependencies:
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: 0.2.0
159
+ version: 0.3.0
160
160
  type: :runtime
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: 0.2.0
166
+ version: 0.3.0
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: thor
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -470,6 +470,10 @@ files:
470
470
  - lib/terraspace/cli/bundle.rb
471
471
  - lib/terraspace/cli/check_setup.rb
472
472
  - lib/terraspace/cli/clean.rb
473
+ - lib/terraspace/cli/clean/all.rb
474
+ - lib/terraspace/cli/clean/base.rb
475
+ - lib/terraspace/cli/clean/cache.rb
476
+ - lib/terraspace/cli/clean/logs.rb
473
477
  - lib/terraspace/cli/cloud.rb
474
478
  - lib/terraspace/cli/cloud/runs.rb
475
479
  - lib/terraspace/cli/commander.rb
@@ -477,6 +481,7 @@ files:
477
481
  - lib/terraspace/cli/help.rb
478
482
  - lib/terraspace/cli/help/all/down.md
479
483
  - lib/terraspace/cli/help/all/graph.md
484
+ - lib/terraspace/cli/help/all/init.md
480
485
  - lib/terraspace/cli/help/all/output.md
481
486
  - lib/terraspace/cli/help/all/plan.md
482
487
  - lib/terraspace/cli/help/all/providers.md
@@ -487,7 +492,9 @@ files:
487
492
  - lib/terraspace/cli/help/build.md
488
493
  - lib/terraspace/cli/help/bundle.md
489
494
  - lib/terraspace/cli/help/check_setup.md
490
- - lib/terraspace/cli/help/clean.md
495
+ - lib/terraspace/cli/help/clean/all.md
496
+ - lib/terraspace/cli/help/clean/cache.md
497
+ - lib/terraspace/cli/help/clean/logs.md
491
498
  - lib/terraspace/cli/help/cloud/destroy.md
492
499
  - lib/terraspace/cli/help/cloud/list.md
493
500
  - lib/terraspace/cli/help/cloud/runs/list.md
@@ -500,7 +507,7 @@ files:
500
507
  - lib/terraspace/cli/help/info.md
501
508
  - lib/terraspace/cli/help/init.md
502
509
  - lib/terraspace/cli/help/list.md
503
- - lib/terraspace/cli/help/log.md
510
+ - lib/terraspace/cli/help/logs.md
504
511
  - lib/terraspace/cli/help/logs/remove.md
505
512
  - lib/terraspace/cli/help/logs/truncate.md
506
513
  - lib/terraspace/cli/help/new/bootstrap_test.md
@@ -526,10 +533,8 @@ files:
526
533
  - lib/terraspace/cli/info.rb
527
534
  - lib/terraspace/cli/init.rb
528
535
  - lib/terraspace/cli/list.rb
529
- - lib/terraspace/cli/log.rb
530
- - lib/terraspace/cli/log/concern.rb
531
536
  - lib/terraspace/cli/logs.rb
532
- - lib/terraspace/cli/logs/tasks.rb
537
+ - lib/terraspace/cli/logs/concern.rb
533
538
  - lib/terraspace/cli/new.rb
534
539
  - lib/terraspace/cli/new/git_hook.rb
535
540
  - lib/terraspace/cli/new/helper.rb
@@ -610,6 +615,10 @@ files:
610
615
  - lib/terraspace/ext.rb
611
616
  - lib/terraspace/ext/bundler.rb
612
617
  - lib/terraspace/ext/core/module.rb
618
+ - lib/terraspace/hooks/builder.rb
619
+ - lib/terraspace/hooks/concern.rb
620
+ - lib/terraspace/hooks/dsl.rb
621
+ - lib/terraspace/hooks/runner.rb
613
622
  - lib/terraspace/logger.rb
614
623
  - lib/terraspace/logger/formatter.rb
615
624
  - lib/terraspace/mod.rb
@@ -655,13 +664,11 @@ files:
655
664
  - lib/terraspace/terraform/cloud/sync.rb
656
665
  - lib/terraspace/terraform/cloud/syncer.rb
657
666
  - lib/terraspace/terraform/cloud/workspace.rb
658
- - lib/terraspace/terraform/hooks/builder.rb
659
- - lib/terraspace/terraform/hooks/dsl.rb
660
667
  - lib/terraspace/terraform/remote_state/fetcher.rb
661
668
  - lib/terraspace/terraform/remote_state/marker/output.rb
662
669
  - lib/terraspace/terraform/remote_state/marker/pretty_tracer.rb
663
- - lib/terraspace/terraform/remote_state/null_object.rb
664
670
  - lib/terraspace/terraform/remote_state/output_proxy.rb
671
+ - lib/terraspace/terraform/remote_state/unresolved.rb
665
672
  - lib/terraspace/terraform/runner.rb
666
673
  - lib/terraspace/tester.rb
667
674
  - lib/terraspace/tester/finder.rb
@@ -791,11 +798,11 @@ files:
791
798
  - spec/terraspace/dependency/graph_spec.rb
792
799
  - spec/terraspace/dependency/helper/depends_on_spec.rb
793
800
  - spec/terraspace/dependency/helper/output_spec.rb
801
+ - spec/terraspace/hooks/builder_spec.rb
794
802
  - spec/terraspace/provider/expander/generic_spec.rb
795
803
  - spec/terraspace/seeder/content_spec.rb
796
804
  - spec/terraspace/seeder_spec.rb
797
805
  - spec/terraspace/terraform/args/custom_spec.rb
798
- - spec/terraspace/terraform/hooks/builder_spec.rb
799
806
  - spec/terraspace/terraform/remote_state/fetcher_spec.rb
800
807
  - spec/terraspace/terraform/remote_state/marker/output_spec.rb
801
808
  - spec/terraspace/terraform/remote_state/output_proxy_spec.rb
@@ -944,11 +951,11 @@ test_files:
944
951
  - spec/terraspace/dependency/graph_spec.rb
945
952
  - spec/terraspace/dependency/helper/depends_on_spec.rb
946
953
  - spec/terraspace/dependency/helper/output_spec.rb
954
+ - spec/terraspace/hooks/builder_spec.rb
947
955
  - spec/terraspace/provider/expander/generic_spec.rb
948
956
  - spec/terraspace/seeder/content_spec.rb
949
957
  - spec/terraspace/seeder_spec.rb
950
958
  - spec/terraspace/terraform/args/custom_spec.rb
951
- - spec/terraspace/terraform/hooks/builder_spec.rb
952
959
  - spec/terraspace/terraform/remote_state/fetcher_spec.rb
953
960
  - spec/terraspace/terraform/remote_state/marker/output_spec.rb
954
961
  - spec/terraspace/terraform/remote_state/output_proxy_spec.rb