terraspace 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/lib/templates/base/arg/terraform.rb.tt +3 -0
  4. data/lib/templates/base/helper/%name%_helper.rb.tt +2 -0
  5. data/lib/templates/base/hook/%kind%.rb.tt +7 -0
  6. data/lib/terraspace.rb +4 -3
  7. data/lib/terraspace/all/base.rb +0 -1
  8. data/lib/terraspace/app.rb +1 -0
  9. data/lib/terraspace/autoloader.rb +20 -3
  10. data/lib/terraspace/cli/bundle.rb +0 -1
  11. data/lib/terraspace/cli/clean/base.rb +0 -1
  12. data/lib/terraspace/cli/clean/cache.rb +0 -1
  13. data/lib/terraspace/cli/help/new/arg.md +19 -0
  14. data/lib/terraspace/cli/help/new/helper.md +39 -0
  15. data/lib/terraspace/cli/help/new/hook.md +25 -0
  16. data/lib/terraspace/cli/help/new/test.md +34 -0
  17. data/lib/terraspace/cli/new.rb +22 -16
  18. data/lib/terraspace/cli/new/arg.rb +62 -0
  19. data/lib/terraspace/cli/new/helper.rb +44 -12
  20. data/lib/terraspace/cli/new/helpers.rb +22 -0
  21. data/lib/terraspace/cli/new/helpers/plugin_gem.rb +25 -0
  22. data/lib/terraspace/cli/new/hook.rb +70 -0
  23. data/lib/terraspace/cli/new/module.rb +0 -11
  24. data/lib/terraspace/cli/new/plugin.rb +4 -4
  25. data/lib/terraspace/cli/new/plugin/helper.rb +1 -1
  26. data/lib/terraspace/cli/new/project.rb +16 -7
  27. data/lib/terraspace/cli/new/sequence.rb +3 -10
  28. data/lib/terraspace/cli/new/source/core.rb +1 -1
  29. data/lib/terraspace/cli/new/stack.rb +1 -12
  30. data/lib/terraspace/cli/new/test.rb +50 -0
  31. data/lib/terraspace/cli/summary.rb +0 -1
  32. data/lib/terraspace/command.rb +16 -0
  33. data/lib/terraspace/compiler/builder.rb +2 -0
  34. data/lib/terraspace/compiler/dsl/mod.rb +2 -0
  35. data/lib/terraspace/compiler/dsl/syntax/mod.rb +2 -0
  36. data/lib/terraspace/compiler/dsl/syntax/mod/backend.rb +1 -1
  37. data/lib/terraspace/compiler/erb/context.rb +2 -0
  38. data/lib/terraspace/compiler/helper_extender.rb +27 -0
  39. data/lib/terraspace/core.rb +0 -6
  40. data/lib/terraspace/ext/core/module.rb +16 -0
  41. data/lib/terraspace/hooks/builder.rb +6 -7
  42. data/lib/terraspace/hooks/concern.rb +2 -2
  43. data/lib/terraspace/logger.rb +6 -0
  44. data/lib/terraspace/mod.rb +0 -1
  45. data/lib/terraspace/plugin.rb +8 -4
  46. data/lib/terraspace/plugin/config/interface.rb +2 -2
  47. data/lib/terraspace/plugin/helper/interface.rb +31 -0
  48. data/lib/terraspace/terraform/args/custom.rb +2 -3
  49. data/lib/terraspace/terraform/runner/retryer.rb +7 -3
  50. data/lib/terraspace/version.rb +1 -1
  51. data/spec/terraspace/terraform/args/custom_spec.rb +6 -4
  52. data/terraspace.gemspec +4 -4
  53. metadata +27 -21
  54. data/lib/terraspace/cli/help/new/bootstrap_test.md +0 -8
  55. data/lib/terraspace/cli/help/new/module_test.md +0 -12
  56. data/lib/terraspace/cli/help/new/project_test.md +0 -8
  57. data/lib/terraspace/cli/new/helper/plugin_gem.rb +0 -12
  58. data/lib/terraspace/cli/new/test/base.rb +0 -17
  59. data/lib/terraspace/cli/new/test/bootstrap.rb +0 -18
  60. data/lib/terraspace/cli/new/test/module.rb +0 -15
  61. data/lib/terraspace/cli/new/test/project.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bae908fcf2dc448dc5b0d2bba463eedd9487c428a296b74955975b66e2faa7c3
4
- data.tar.gz: bef0979ecaeab8eca50387da95a119719696a759ecff7de55659ff0d8cbac322
3
+ metadata.gz: bbf29f1226e7dc336c0eaf99892e158aff3b804bd56bbd1dc744fd17a65c6ff0
4
+ data.tar.gz: 6c32f1fe94e9dc53f6ddbfca3cef7c1178a11d788b32ad6ad3fdc88d64e268fa
5
5
  SHA512:
6
- metadata.gz: 882b9a94cf48af9399a66540385dcd7dbcdbb8118df046c6af833e053f265e57dfeb0a3692f32e315b6a13bb59334c51cfc856db0fc68a067cee4800bc1a3a32
7
- data.tar.gz: 720aa71881469e415445a1ff83e853c1ece6d71873830111eb1de59c121e9408e478ddaabdd30e6c29e2d48d39b1ec1c96c739e16ca682b3e13e129253594d44
6
+ metadata.gz: b5e45213f23aaed8b4348d4a68179b2706577d6cdf7cf2588f979feb6433e742851392331a8d2909be4a745b6ef9089c419d22d4dd6140ec981c536e809c29df
7
+ data.tar.gz: f9e436d5ee96f410c66d673819a789ffdca814f8d53c8f7c97b2b005c9d2bd5cd48fc9a6619407ec7da42e0d3ca503666a5e3d2f2124f30b211a22ba87ec7075
@@ -3,6 +3,21 @@
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
+ ## [0.5.0] - 2020-11-15
7
+ - [#55](https://github.com/boltops-tools/terraspace/pull/55) custom helpers support
8
+ - plugin helpers support: aws_secret, aws_ssm, google_secret, etc
9
+ - introduce stack-level test concept and change project-level test concept
10
+ - generators: standardize and unifiy new test
11
+ - new generators: arg, hook, helper
12
+ - clean up Terraspace check project
13
+ - setup up autoloader and bundler/setup earlier. removes need for shim
14
+ - test generator plugin autodetection
15
+ - remove internal run_generator_hook_script
16
+ - stack-level args customization support
17
+ - improve test output noise-level
18
+ - new setting: config.terraform.plugin_cache.purge_on_error
19
+ - quiet option for project generator
20
+
6
21
  ## [0.4.4]
7
22
  - #50 retry logic for shared cache error
8
23
  - #51 fix cloud sync: call build first
@@ -0,0 +1,3 @@
1
+ command("<%= arg_name %>",
2
+ args: ["-lock-timeout=22m"],
3
+ )
@@ -0,0 +1,2 @@
1
+ module <%= helper_class %>
2
+ end
@@ -0,0 +1,7 @@
1
+ before("<%= hook_name %>",
2
+ execute: "echo '<%= hook_path %>: test <%= type %> before hook for <%= kind %> <%= hook_name %>'",
3
+ )
4
+
5
+ after("<%= hook_name %>",
6
+ execute: "echo '<%= hook_path %>: test <%= type %> after hook for <%= kind %> <%= hook_name %>'"
7
+ )
@@ -1,6 +1,10 @@
1
1
  $stdout.sync = true unless ENV["TS_STDOUT_SYNC"] == "0"
2
2
 
3
3
  $:.unshift(File.expand_path("../", __FILE__))
4
+
5
+ require "terraspace/autoloader"
6
+ Terraspace::Autoloader.setup
7
+
4
8
  require "active_support/concern"
5
9
  require "active_support/core_ext/class"
6
10
  require "active_support/core_ext/hash"
@@ -18,9 +22,6 @@ require "set"
18
22
  require "terraspace/ext"
19
23
  require "terraspace/version"
20
24
 
21
- require "terraspace/autoloader"
22
- Terraspace::Autoloader.setup
23
-
24
25
  DslEvaluator.backtrace_reject = "lib/terraspace"
25
26
 
26
27
  module Terraspace
@@ -2,7 +2,6 @@ module Terraspace::All
2
2
  class Base
3
3
  def initialize(options={})
4
4
  @options = options
5
- Terraspace.check_project! unless ENV['TS_TEST']
6
5
  end
7
6
  end
8
7
  end
@@ -47,6 +47,7 @@ module Terraspace
47
47
  config.terraform.plugin_cache = ActiveSupport::OrderedOptions.new
48
48
  config.terraform.plugin_cache.dir = ENV['TF_PLUGIN_CACHE_DIR'] || "#{Terraspace.tmp_root}/plugin_cache"
49
49
  config.terraform.plugin_cache.enabled = true
50
+ config.terraform.plugin_cache.purge_on_error = true
50
51
  config.test_framework = "rspec"
51
52
  config
52
53
  end
@@ -1,8 +1,15 @@
1
- require "terraspace/bundle"
2
- Terraspace::Bundle.setup
1
+ if File.exist?("config/app.rb")
2
+ require "terraspace/bundle"
3
+ Terraspace::Bundle.setup
4
+ end
3
5
  require "zeitwerk"
4
6
 
5
7
  module Terraspace
8
+ # These modules are namespaces for user-defined custom helpers
9
+ module Module; end
10
+ module Project; end
11
+ module Stack; end
12
+
6
13
  class Autoloader
7
14
  class Inflector < Zeitwerk::Inflector
8
15
  def camelize(basename, _abspath)
@@ -16,10 +23,20 @@ module Terraspace
16
23
  loader = Zeitwerk::Loader.new
17
24
  loader.inflector = Inflector.new
18
25
  loader.push_dir(File.dirname(__dir__)) # lib
26
+ loader.push_dir(project_helpers, namespace: Terraspace::Project) if File.exist?(project_helpers)
19
27
  loader.log! if ENV["TS_AUTOLOAD_LOG"]
20
- loader.ignore("#{__dir__}/core_ext.rb")
28
+ loader.ignore("#{__dir__}/ext.rb")
21
29
  loader.setup
22
30
  end
31
+
32
+ def project_helpers
33
+ "#{ts_root}/config/helpers"
34
+ end
35
+
36
+ # Duplicate definition because autoloader logic runs very early and doesnt have access to core methods yet
37
+ def ts_root
38
+ ENV['TS_ROOT'] || Dir.pwd
39
+ end
23
40
  end
24
41
  end
25
42
  end
@@ -7,7 +7,6 @@ class Terraspace::CLI
7
7
  end
8
8
 
9
9
  def run
10
- Terraspace.check_project!
11
10
  TerraspaceBundler.config.deep_merge!(Terraspace.config.bundle)
12
11
  TerraspaceBundler::CLI.start(args)
13
12
  end
@@ -5,7 +5,6 @@ class Terraspace::CLI::Clean
5
5
 
6
6
  def initialize(options={})
7
7
  @options = options
8
- Terraspace.check_project!
9
8
  end
10
9
 
11
10
  def pretty(path)
@@ -1,7 +1,6 @@
1
1
  class Terraspace::CLI::Clean
2
2
  class Cache < Base
3
3
  def run
4
- Terraspace.check_project!
5
4
  paths = [Terraspace.cache_root, Terraspace.tmp_root]
6
5
  are_you_sure?(paths)
7
6
  paths.each do |path|
@@ -0,0 +1,19 @@
1
+ ## Examples
2
+
3
+ Project-level arg:
4
+
5
+ $ terraspace new arg --type project
6
+ create config/args
7
+ create config/args/terraform.rb
8
+
9
+ Stack-level arg:
10
+
11
+ $ terraspace new arg demo --type stack
12
+ create app/stacks/demo/config/args
13
+ create app/stacks/demo/config/args/terraform.rb
14
+
15
+ Module-level arg:
16
+
17
+ $ terraspace new arg example --type module
18
+ create app/modules/example/config/args
19
+ create app/modules/example/config/args/terraform.rb
@@ -0,0 +1,39 @@
1
+ ## Project Examples
2
+
3
+ Conventionally name the helper custom.
4
+
5
+ $ terraspace new helper custom --type project
6
+ create config/helpers
7
+ create config/helpers/custom_helper.rb
8
+
9
+ ## Stack Examples
10
+
11
+ Conventionally name the helper to be the same as the stack name.
12
+
13
+ $ terraspace new helper demo --type stack
14
+ create app/stacks/demo/config/helpers
15
+ create app/stacks/demo/config/helpers/demo_helper.rb
16
+ $
17
+
18
+ Explictly name helper method. IE: custom here.
19
+
20
+ $ terraspace new helper demo --type stack --name custom
21
+ create app/stacks/demo/config/helpers
22
+ create app/stacks/demo/config/helpers/custom_helper.rb
23
+ $
24
+
25
+ ## Module Examples
26
+
27
+ Conventionally name the helper to be the same as the module name.
28
+
29
+ $ terraspace new helper example --type module
30
+ create app/module/example/config/helpers
31
+ create app/module/example/config/helpers/example_helper.rb
32
+ $
33
+
34
+ Explictly name helper method. IE: custom here.
35
+
36
+ $ terraspace new helper example --type module --name custom
37
+ create app/module/example/config/helpers
38
+ create app/module/example/config/helpers/custom_helper.rb
39
+ $
@@ -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
+ $
@@ -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