terraspace 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/README.md +57 -30
  4. data/lib/templates/base/arg/terraform.rb.tt +3 -0
  5. data/lib/templates/base/helper/%name%_helper.rb.tt +2 -0
  6. data/lib/templates/base/hook/%kind%.rb.tt +7 -0
  7. data/lib/terraspace.rb +7 -4
  8. data/lib/terraspace/all/base.rb +0 -1
  9. data/lib/terraspace/app.rb +1 -0
  10. data/lib/terraspace/autoloader.rb +20 -3
  11. data/lib/terraspace/cli.rb +2 -0
  12. data/lib/terraspace/cli/all.rb +1 -1
  13. data/lib/terraspace/cli/bundle.rb +0 -1
  14. data/lib/terraspace/cli/clean/base.rb +0 -1
  15. data/lib/terraspace/cli/clean/cache.rb +0 -1
  16. data/lib/terraspace/cli/cloud.rb +2 -0
  17. data/lib/terraspace/cli/help/all/init.md +33 -0
  18. data/lib/terraspace/cli/help/logs.md +4 -4
  19. data/lib/terraspace/cli/help/new/arg.md +19 -0
  20. data/lib/terraspace/cli/help/new/helper.md +39 -0
  21. data/lib/terraspace/cli/help/new/hook.md +25 -0
  22. data/lib/terraspace/cli/help/new/test.md +34 -0
  23. data/lib/terraspace/cli/info.rb +12 -0
  24. data/lib/terraspace/cli/list.rb +2 -1
  25. data/lib/terraspace/cli/logs/concern.rb +1 -0
  26. data/lib/terraspace/cli/new.rb +22 -16
  27. data/lib/terraspace/cli/new/arg.rb +62 -0
  28. data/lib/terraspace/cli/new/helper.rb +44 -12
  29. data/lib/terraspace/cli/new/helpers.rb +22 -0
  30. data/lib/terraspace/cli/new/helpers/plugin_gem.rb +25 -0
  31. data/lib/terraspace/cli/new/hook.rb +70 -0
  32. data/lib/terraspace/cli/new/module.rb +0 -11
  33. data/lib/terraspace/cli/new/plugin.rb +4 -4
  34. data/lib/terraspace/cli/new/plugin/helper.rb +1 -1
  35. data/lib/terraspace/cli/new/project.rb +16 -7
  36. data/lib/terraspace/cli/new/sequence.rb +3 -10
  37. data/lib/terraspace/cli/new/source/core.rb +1 -1
  38. data/lib/terraspace/cli/new/stack.rb +1 -12
  39. data/lib/terraspace/cli/new/test.rb +50 -0
  40. data/lib/terraspace/cli/summary.rb +0 -1
  41. data/lib/terraspace/command.rb +16 -0
  42. data/lib/terraspace/compiler/builder.rb +2 -0
  43. data/lib/terraspace/compiler/dsl/mod.rb +2 -0
  44. data/lib/terraspace/compiler/dsl/syntax/mod.rb +2 -0
  45. data/lib/terraspace/compiler/dsl/syntax/mod/backend.rb +1 -1
  46. data/lib/terraspace/compiler/erb/context.rb +2 -0
  47. data/lib/terraspace/compiler/helper_extender.rb +27 -0
  48. data/lib/terraspace/core.rb +0 -6
  49. data/lib/terraspace/ext/core/module.rb +16 -0
  50. data/lib/terraspace/hooks/builder.rb +6 -7
  51. data/lib/terraspace/hooks/concern.rb +2 -2
  52. data/lib/terraspace/logger.rb +6 -0
  53. data/lib/terraspace/mod.rb +0 -1
  54. data/lib/terraspace/plugin.rb +8 -4
  55. data/lib/terraspace/plugin/config/interface.rb +2 -2
  56. data/lib/terraspace/plugin/helper/interface.rb +31 -0
  57. data/lib/terraspace/shell.rb +5 -33
  58. data/lib/terraspace/shell/error.rb +46 -0
  59. data/lib/terraspace/terraform/args/custom.rb +2 -3
  60. data/lib/terraspace/terraform/args/default.rb +9 -19
  61. data/lib/terraspace/terraform/runner.rb +6 -14
  62. data/lib/terraspace/terraform/runner/retryer.rb +69 -0
  63. data/lib/terraspace/version.rb +1 -1
  64. data/spec/terraspace/terraform/args/custom_spec.rb +6 -4
  65. data/terraspace.gemspec +4 -4
  66. metadata +30 -21
  67. data/lib/terraspace/cli/help/new/bootstrap_test.md +0 -8
  68. data/lib/terraspace/cli/help/new/module_test.md +0 -12
  69. data/lib/terraspace/cli/help/new/project_test.md +0 -8
  70. data/lib/terraspace/cli/new/helper/plugin_gem.rb +0 -12
  71. data/lib/terraspace/cli/new/test/base.rb +0 -17
  72. data/lib/terraspace/cli/new/test/bootstrap.rb +0 -18
  73. data/lib/terraspace/cli/new/test/module.rb +0 -15
  74. data/lib/terraspace/cli/new/test/project.rb +0 -15
@@ -0,0 +1,25 @@
1
+ ## Examples
2
+
3
+ Project-level hook:
4
+
5
+ $ terraspace new hook --type project
6
+ create config/hooks
7
+ create config/hooks/terraform.rb
8
+
9
+ Stack-level hook:
10
+
11
+ $ terraspace new hook demo --type stack
12
+ create app/stacks/demo/config/hooks
13
+ create app/stacks/demo/config/hooks/terraform.rb
14
+
15
+ Stack-level hook with kind option:
16
+
17
+ $ terraspace new hook demo --type stack --kind terraspace
18
+ exist app/stacks/demo/config/hooks
19
+ create app/stacks/demo/config/hooks/terraspace.rb
20
+
21
+ Module-level hook:
22
+
23
+ $ terraspace new hook example --type module
24
+ create app/modules/example/config/hooks
25
+ create app/modules/example/config/hooks/terraform.rb
@@ -0,0 +1,34 @@
1
+ ## Stack Examples
2
+
3
+ $ terraspace new test demo --type stack
4
+ => Creating stack test: example
5
+ exist app/stacks/example
6
+ create app/stacks/example/test/.rspec
7
+ create app/stacks/example/test/Gemfile
8
+ create app/stacks/example/test/spec/fixtures/stack/main.tf
9
+ create app/stacks/example/test/spec/fixtures/stack/outputs.tf
10
+ create app/stacks/example/test/spec/main_spec.rb
11
+ create app/stacks/example/test/spec/spec_helper.rb
12
+ $
13
+
14
+ ## Module Examples
15
+
16
+ $ terraspace new test example --type module
17
+ => Creating module test: example
18
+ exist app/modules/example
19
+ create app/modules/example/test/.rspec
20
+ create app/modules/example/test/Gemfile
21
+ create app/modules/example/test/spec/fixtures/stack/main.tf
22
+ create app/modules/example/test/spec/fixtures/stack/outputs.tf
23
+ create app/modules/example/test/spec/main_spec.rb
24
+ create app/modules/example/test/spec/spec_helper.rb
25
+ $
26
+
27
+ ## Project Examples
28
+
29
+ $ terraspace new test my --type project
30
+ => Creating test bootstrap structure
31
+ exist
32
+ create .rspec
33
+ create spec/spec_helper.rb
34
+ $
@@ -3,6 +3,14 @@ class Terraspace::CLI
3
3
  extend Memoist
4
4
 
5
5
  def run
6
+ if @options[:path]
7
+ show_path
8
+ else
9
+ show_all
10
+ end
11
+ end
12
+
13
+ def show_all
6
14
  presenter = CliFormat::Presenter.new(@options)
7
15
  presenter.header = %w[Name Value]
8
16
  info.each do |k,v|
@@ -11,6 +19,10 @@ class Terraspace::CLI
11
19
  presenter.show
12
20
  end
13
21
 
22
+ def show_path
23
+ puts info[:cache_dir]
24
+ end
25
+
14
26
  def info
15
27
  @mod.to_info
16
28
  end
@@ -6,7 +6,8 @@ class Terraspace::CLI
6
6
  end
7
7
 
8
8
  def run
9
- Dir.glob("{app,vendor}/{modules,stacks}/*").sort.each do |path|
9
+ dirs = Dir.glob("{app,vendor}/{modules,stacks}/*").select { |p| File.directory?(p) }
10
+ dirs.sort.each do |path|
10
11
  if @type_dir
11
12
  puts path if path.include?("/#{@type_dir}/")
12
13
  else
@@ -17,6 +17,7 @@ class Terraspace::CLI::Logs
17
17
 
18
18
  # [2020-09-06T21:58:25 #11313 terraspace up b1]:
19
19
  def pid(line)
20
+ return @options[:pid] if @options && @options[:pid] # Terraspace::All::Summary: doesnt have @options set
20
21
  md = line.match(/:\d{2} #(\d+) /)
21
22
  md[1] if md
22
23
  end
@@ -1,5 +1,9 @@
1
1
  class Terraspace::CLI
2
2
  class New < Terraspace::Command
3
+ long_desc Help.text("new/arg")
4
+ Arg.options.each { |args| option(*args) }
5
+ register(Arg, "arg", "arg NAME", "Generates new arg.")
6
+
3
7
  long_desc Help.text("new/git_hook")
4
8
  GitHook.cli_options.each { |args| option(*args) }
5
9
  register(GitHook, "git_hook", "git_hook", "Generates new git hook.")
@@ -8,33 +12,35 @@ class Terraspace::CLI
8
12
  Shim.cli_options.each { |args| option(*args) }
9
13
  register(Shim, "shim", "shim", "Generates terraspace shim.")
10
14
 
15
+ long_desc Help.text("new/helper")
16
+ Helper.options.each { |args| option(*args) }
17
+ register(Helper, "helper", "helper NAME", "Generates new helper.")
18
+
19
+ long_desc Help.text("new/hook")
20
+ Hook.options.each { |args| option(*args) }
21
+ register(Hook, "hook", "hook NAME", "Generates new hook.")
22
+
11
23
  long_desc Help.text("new/module")
12
24
  Module.base_options.each { |args| option(*args) }
13
25
  Module.component_options.each { |args| option(*args) }
14
26
  register(Module, "module", "module NAME", "Generates new module.")
15
27
 
16
- long_desc Help.text("new/stack")
17
- Stack.base_options.each { |args| option(*args) }
18
- Stack.component_options.each { |args| option(*args) }
19
- register(Stack, "stack", "stack NAME", "Generates new stack.")
20
-
21
28
  long_desc Help.text("new/project")
22
29
  Project.base_options.each { |args| option(*args) }
23
30
  Project.project_options.each { |args| option(*args) }
24
31
  register(Project, "project", "project NAME", "Generates new project.")
25
32
 
26
- long_desc Help.text("new/project_test")
27
- register(Test::Project, "project_test", "project_test NAME", "Generates new project test.")
28
-
29
- long_desc Help.text("new/module_test")
30
- register(Test::Module, "module_test", "module_test NAME", "Generates new module test.")
31
-
32
- long_desc Help.text("new/bootstrap_test")
33
- Test::Bootstrap.options.each { |args| option(*args) }
34
- register(Test::Bootstrap, "bootstrap_test", "bootstrap_test", "Generates bootstrap test setup.")
35
-
36
33
  long_desc Help.text("new/plugin")
37
34
  Plugin.options.each { |args| option(*args) }
38
- register(Plugin, "plugin", "plugin", "Generates plugin.")
35
+ register(Plugin, "plugin", "plugin NAME", "Generates plugin.")
36
+
37
+ long_desc Help.text("new/stack")
38
+ Stack.base_options.each { |args| option(*args) }
39
+ Stack.component_options.each { |args| option(*args) }
40
+ register(Stack, "stack", "stack NAME", "Generates new stack.")
41
+
42
+ long_desc Help.text("new/test")
43
+ Test.options.each { |args| option(*args) }
44
+ register(Test, "test", "test NAME", "Generates new test.")
39
45
  end
40
46
  end
@@ -0,0 +1,62 @@
1
+ class Terraspace::CLI::New
2
+ class Arg < Thor::Group
3
+ include Thor::Actions
4
+
5
+ argument :stack, required: false
6
+
7
+ def self.options
8
+ [
9
+ [:force, aliases: %w[y], type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files"],
10
+ [:name, default: "apply", desc: "command name"],
11
+ [:type, default: "project", desc: "project, stack or module"],
12
+ ]
13
+ end
14
+ options.each { |args| class_option(*args) }
15
+
16
+ def self.source_root
17
+ File.expand_path("../../../templates/base/arg", __dir__)
18
+ end
19
+
20
+ private
21
+ def type
22
+ valid_types = %w[project stack module]
23
+ type = @options[:type]
24
+ valid_types.include?(type) ? type : "project" # fallback to project if user provides invalid type
25
+ end
26
+
27
+ def name
28
+ options[:name] ? options[:name] : "apply"
29
+ end
30
+
31
+ def dest
32
+ map = {
33
+ project: "config/args",
34
+ stack: "app/stacks/#{stack}/config/args",
35
+ module: "app/modules/#{stack}/config/args",
36
+ }
37
+ map[type.to_sym]
38
+ end
39
+
40
+ def arg_path
41
+ "#{dest}/#{kind}.rb"
42
+ end
43
+
44
+ public
45
+
46
+ def check_stack_arg
47
+ return if type == "project"
48
+ return unless stack.nil?
49
+ # Else check for STACK argument for type module or stack
50
+ puts <<~EOL
51
+ Required STACK argument, either the module or stack name. Usage:
52
+
53
+ terraspace new arg STACK --type #{type}
54
+ EOL
55
+ exit 1
56
+ end
57
+
58
+ def create
59
+ directory ".", dest
60
+ end
61
+ end
62
+ end
@@ -1,22 +1,54 @@
1
1
  class Terraspace::CLI::New
2
- module Helper
3
- include Helper::PluginGem
2
+ class Helper < Thor::Group
3
+ include Thor::Actions
4
+
5
+ argument :stack
6
+
7
+ def self.options
8
+ [
9
+ [:force, aliases: %w[y], type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files"],
10
+ [:name, desc: "Helper name used for the filename. Defaults to the project, module or stack name"],
11
+ [:type, default: "project", desc: "project, stack or module"],
12
+ ]
13
+ end
14
+ options.each { |args| class_option(*args) }
15
+
16
+ def self.source_root
17
+ File.expand_path("../../../templates/base/helper", __dir__)
18
+ end
4
19
 
5
20
  private
6
- def build_gemfile(*list)
7
- lines = []
8
- list.each do |name|
9
- lines << gem_line(name)
10
- end
11
- lines.join("\n")
21
+ def type
22
+ valid_types = %w[project stack module]
23
+ type = @options[:type]
24
+ valid_types.include?(type) ? type : "project" # fallback to project if user provides invalid type
12
25
  end
13
26
 
14
- def gem_line(name)
15
- if name == "terraspace"
16
- %Q|gem "#{name}", '~> #{Terraspace::VERSION}'|
27
+ def helper_class
28
+ if type == "project"
29
+ "Terraspace::#{type.camelize}::#{name.camelize}Helper"
17
30
  else
18
- %Q|gem "#{name}"|
31
+ "Terraspace::#{type.camelize}::#{stack.camelize}::#{name.camelize}Helper"
19
32
  end
20
33
  end
34
+
35
+ def name
36
+ options[:name] || stack
37
+ end
38
+
39
+ def dest
40
+ map = {
41
+ project: "config/helpers",
42
+ stack: "app/stacks/#{stack}/config/helpers",
43
+ module: "app/modules/#{stack}/config/helpers",
44
+ }
45
+ map[type.to_sym]
46
+ end
47
+
48
+ public
49
+
50
+ def create
51
+ directory ".", dest
52
+ end
21
53
  end
22
54
  end
@@ -0,0 +1,22 @@
1
+ class Terraspace::CLI::New
2
+ module Helpers
3
+ include Helpers::PluginGem
4
+
5
+ private
6
+ def build_gemfile(*list)
7
+ lines = []
8
+ list.each do |name|
9
+ lines << gem_line(name)
10
+ end
11
+ lines.join("\n")
12
+ end
13
+
14
+ def gem_line(name)
15
+ if name == "terraspace"
16
+ %Q|gem "#{name}", '~> #{Terraspace::VERSION}'|
17
+ else
18
+ %Q|gem "#{name}"|
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module Terraspace::CLI::New::Helpers
2
+ module PluginGem
3
+ private
4
+ def plugin_gem_name
5
+ if @options[:plugin_gem]
6
+ @options[:plugin_gem]
7
+ else
8
+ plugin = @options[:plugin] || autodetect_provider
9
+ "terraspace_plugin_#{plugin}"
10
+ end
11
+ end
12
+
13
+ def autodetect_provider
14
+ providers = Terraspace::Plugin.meta.keys
15
+ if providers.size == 1
16
+ providers.first
17
+ else
18
+ precedence = %w[aws azurerm google]
19
+ precedence.find do |p|
20
+ providers.include?(p)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,70 @@
1
+ class Terraspace::CLI::New
2
+ class Hook < Thor::Group
3
+ include Thor::Actions
4
+
5
+ argument :stack, required: false
6
+
7
+ def self.options
8
+ [
9
+ [:force, aliases: %w[y], type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files"],
10
+ [:kind, default: "terraform", desc: "terraform or terraspace"],
11
+ [:name, desc: "Command name. Defaults to apply for terraform kind and build for terraspace kind"],
12
+ [:type, default: "project", desc: "project, stack or module"],
13
+ ]
14
+ end
15
+ options.each { |args| class_option(*args) }
16
+
17
+ def self.source_root
18
+ File.expand_path("../../../templates/base/hook", __dir__)
19
+ end
20
+
21
+ private
22
+ def kind
23
+ valid_kinds = %w[terraform terraspace]
24
+ kind = @options[:kind]
25
+ valid_kinds.include?(kind) ? kind : "terraform" # fallback to terraform if user provides invalid type
26
+ end
27
+
28
+ def type
29
+ valid_types = %w[project stack module]
30
+ type = @options[:type]
31
+ valid_types.include?(type) ? type : "project" # fallback to project if user provides invalid type
32
+ end
33
+
34
+ def name
35
+ return options[:name] if options[:name]
36
+ kind == "terraform" ? "apply" : "build"
37
+ end
38
+
39
+ def dest
40
+ map = {
41
+ project: "config/hooks",
42
+ stack: "app/stacks/#{stack}/config/hooks",
43
+ module: "app/modules/#{stack}/config/hooks",
44
+ }
45
+ map[type.to_sym]
46
+ end
47
+
48
+ def hook_path
49
+ "#{dest}/#{kind}.rb"
50
+ end
51
+
52
+ public
53
+
54
+ def check_stack_arg
55
+ return if type == "project"
56
+ return unless stack.nil?
57
+ # Else check for STACK argument for type module or stack
58
+ puts <<~EOL
59
+ Required STACK argument, either the module or stack name. Usage:
60
+
61
+ terraspace new hook STACK --type #{type}
62
+ EOL
63
+ exit 1
64
+ end
65
+
66
+ def create
67
+ directory ".", dest
68
+ end
69
+ end
70
+ end
@@ -11,16 +11,5 @@ class Terraspace::CLI::New
11
11
  dest = "#{@options[:project_name]}/#{dest}" if @options[:project_name]
12
12
  directory ".", dest
13
13
  end
14
-
15
- def create_test
16
- args = component_args(name, @options[:project_name])
17
- Test::Module.start(args)
18
- end
19
-
20
- def run_generator_hook_script
21
- script = ENV['TS_GENERATOR_MODULE']
22
- return unless script
23
- run_script(script, "app/modules/#{name}")
24
- end
25
14
  end
26
15
  end
@@ -1,16 +1,16 @@
1
1
  class Terraspace::CLI::New
2
2
  class Plugin < Sequence
3
- include Helper
3
+ include Helpers
4
+
5
+ argument :name
4
6
 
5
7
  def self.options
6
8
  [
7
- [:force, type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files"],
9
+ [:force, aliases: %w[y], type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files"],
8
10
  ]
9
11
  end
10
12
  options.each { |args| class_option(*args) }
11
13
 
12
- argument :name
13
-
14
14
  def create_plugin
15
15
  puts "=> Creating new plugin: #{name}"
16
16
  core_template_source("plugin")