terraspace 1.1.7 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.cody/all/{role.rb → iam_role.rb} +0 -0
  3. data/.cody/all/project.rb +6 -2
  4. data/.cody/aws/bin/build.sh +5 -0
  5. data/.cody/aws/{role.rb → iam_role.rb} +0 -0
  6. data/.cody/aws/project.rb +6 -2
  7. data/.cody/azurerm/bin/build.sh +5 -0
  8. data/.cody/azurerm/{role.rb → iam_role.rb} +0 -0
  9. data/.cody/azurerm/project.rb +5 -3
  10. data/.cody/google/bin/build.sh +5 -0
  11. data/.cody/google/{role.rb → iam_role.rb} +0 -0
  12. data/.cody/google/project.rb +5 -3
  13. data/.cody/none/bin/build.sh +5 -0
  14. data/.cody/none/{role.rb → iam_role.rb} +0 -0
  15. data/.cody/none/project.rb +6 -2
  16. data/.cody/shared/script/install/terraform.sh +2 -1
  17. data/.cody/shared/script/update/gemfile.sh +2 -0
  18. data/.cody/unit/project.rb +2 -2
  19. data/.gitignore +2 -0
  20. data/.pipedream/pipeline.rb +3 -3
  21. data/CHANGELOG.md +29 -0
  22. data/exe/terraspace +0 -7
  23. data/lib/templates/base/project/config/app.rb +3 -0
  24. data/lib/templates/plugin/ci/%gem_name%.gemspec.tt +32 -0
  25. data/lib/templates/plugin/ci/.gitignore +12 -0
  26. data/lib/templates/plugin/{.rspec → ci/.rspec} +0 -0
  27. data/lib/templates/plugin/ci/.rubocop.yml +13 -0
  28. data/lib/templates/plugin/ci/CHANGELOG.md.tt +5 -0
  29. data/lib/templates/plugin/ci/Gemfile +10 -0
  30. data/lib/templates/plugin/ci/LICENSE.txt +21 -0
  31. data/lib/templates/plugin/ci/README.md.tt +19 -0
  32. data/lib/templates/plugin/ci/Rakefile +12 -0
  33. data/lib/templates/plugin/ci/lib/%gem_name%/autoloader.rb.tt +23 -0
  34. data/lib/templates/plugin/ci/lib/%gem_name%/interface.rb.tt +15 -0
  35. data/lib/templates/plugin/ci/lib/%gem_name%/pr.rb.tt +15 -0
  36. data/lib/templates/plugin/ci/lib/%gem_name%/vars.rb.tt +26 -0
  37. data/lib/templates/plugin/ci/lib/%gem_name%/version.rb.tt +5 -0
  38. data/lib/templates/plugin/ci/lib/%gem_name%.rb.tt +17 -0
  39. data/lib/templates/plugin/ci/spec/%gem_name%_spec.rb.tt +7 -0
  40. data/lib/templates/plugin/ci/spec/spec_helper.rb.tt +15 -0
  41. data/lib/templates/plugin/{.gitignore → core/.gitignore} +0 -0
  42. data/lib/templates/plugin/core/.rspec +3 -0
  43. data/lib/templates/plugin/{CHANGELOG.md → core/CHANGELOG.md} +0 -0
  44. data/lib/templates/plugin/{Gemfile → core/Gemfile} +0 -0
  45. data/lib/templates/plugin/{LICENSE.txt → core/LICENSE.txt} +0 -0
  46. data/lib/templates/plugin/{README.md.tt → core/README.md.tt} +0 -0
  47. data/lib/templates/plugin/{Rakefile → core/Rakefile} +0 -0
  48. data/lib/templates/plugin/{bin → core/bin}/console.tt +0 -0
  49. data/lib/templates/plugin/{bin → core/bin}/setup +0 -0
  50. data/lib/templates/plugin/{lib → core/lib}/templates/hcl/module/main.tf +0 -0
  51. data/lib/templates/plugin/{lib → core/lib}/templates/hcl/module/outputs.tf +0 -0
  52. data/lib/templates/plugin/{lib → core/lib}/templates/hcl/module/variables.tf +0 -0
  53. data/lib/templates/plugin/{lib → core/lib}/templates/hcl/project/config/terraform/backend.tf.tt +0 -0
  54. data/lib/templates/plugin/{lib → core/lib}/templates/hcl/project/config/terraform/provider.tf +0 -0
  55. data/lib/templates/plugin/{lib → core/lib}/templates/hcl/stack/main.tf +0 -0
  56. data/lib/templates/plugin/{lib → core/lib}/templates/hcl/stack/outputs.tf +0 -0
  57. data/lib/templates/plugin/{lib → core/lib}/templates/hcl/stack/variables.tf +0 -0
  58. data/lib/templates/plugin/{lib → core/lib}/templates/ruby/module/main.rb +0 -0
  59. data/lib/templates/plugin/{lib → core/lib}/templates/ruby/module/outputs.rb +0 -0
  60. data/lib/templates/plugin/{lib → core/lib}/templates/ruby/module/variables.rb +0 -0
  61. data/lib/templates/plugin/{lib → core/lib}/templates/ruby/project/config/terraform/backend.rb.tt +0 -0
  62. data/lib/templates/plugin/{lib → core/lib}/templates/ruby/project/config/terraform/provider.rb +0 -0
  63. data/lib/templates/plugin/{lib → core/lib}/templates/ruby/stack/main.rb +0 -0
  64. data/lib/templates/plugin/{lib → core/lib}/templates/ruby/stack/outputs.rb +0 -0
  65. data/lib/templates/plugin/{lib → core/lib}/templates/ruby/stack/variables.rb +0 -0
  66. data/lib/templates/plugin/{lib → core/lib}/templates/test/rspec/module/test/.rspec +0 -0
  67. data/lib/templates/plugin/{lib → core/lib}/templates/test/rspec/module/test/Gemfile +0 -0
  68. data/lib/templates/plugin/{lib → core/lib}/templates/test/rspec/module/test/spec/fixtures/stack/main.tf +0 -0
  69. data/lib/templates/plugin/{lib → core/lib}/templates/test/rspec/module/test/spec/fixtures/stack/outputs.tf +0 -0
  70. data/lib/templates/plugin/{lib → core/lib}/templates/test/rspec/module/test/spec/fixtures/stack/variables.tf +0 -0
  71. data/lib/templates/plugin/{lib → core/lib}/templates/test/rspec/module/test/spec/main_spec.rb +0 -0
  72. data/lib/templates/plugin/{lib → core/lib}/templates/test/rspec/module/test/spec/spec_helper.rb +0 -0
  73. data/lib/templates/plugin/{lib → core/lib}/terraspace_plugin_%name%/autoloader.rb.tt +0 -0
  74. data/lib/templates/plugin/{lib → core/lib}/terraspace_plugin_%name%/clients.rb.tt +0 -0
  75. data/lib/templates/plugin/{lib → core/lib}/terraspace_plugin_%name%/interfaces/backend.rb.tt +0 -0
  76. data/lib/templates/plugin/{lib → core/lib}/terraspace_plugin_%name%/interfaces/config.rb.tt +0 -0
  77. data/lib/templates/plugin/{lib → core/lib}/terraspace_plugin_%name%/interfaces/expander.rb.tt +0 -0
  78. data/lib/templates/plugin/{lib → core/lib}/terraspace_plugin_%name%/interfaces/layer.rb.tt +0 -0
  79. data/lib/templates/plugin/{lib → core/lib}/terraspace_plugin_%name%/version.rb.tt +0 -0
  80. data/lib/templates/plugin/{lib → core/lib}/terraspace_plugin_%name%.rb.tt +0 -0
  81. data/lib/templates/plugin/{spec → core/spec}/spec_helper.rb.tt +0 -0
  82. data/lib/templates/plugin/{spec → core/spec}/terraspace_provider_%name%_spec.rb.tt +0 -0
  83. data/lib/templates/plugin/{terraspace_plugin_%name%.gemspec.tt → core/terraspace_plugin_%name%.gemspec.tt} +0 -0
  84. data/lib/terraspace/all/runner.rb +2 -0
  85. data/lib/terraspace/all/summary.rb +2 -0
  86. data/lib/terraspace/app.rb +23 -4
  87. data/lib/terraspace/builder.rb +1 -1
  88. data/lib/terraspace/cli/concerns/plan_path.rb +8 -0
  89. data/lib/terraspace/cli/down.rb +4 -0
  90. data/lib/terraspace/cli/init.rb +1 -1
  91. data/lib/terraspace/cli/new/ci.rb +121 -0
  92. data/lib/terraspace/cli/new/example.rb +1 -1
  93. data/lib/terraspace/cli/new/helpers/plugin_gem.rb +1 -1
  94. data/lib/terraspace/cli/new/plugin/ci.rb +46 -0
  95. data/lib/terraspace/cli/new/plugin/core.rb +26 -0
  96. data/lib/terraspace/cli/new/plugin/helper.rb +4 -1
  97. data/lib/terraspace/cli/new/plugin.rb +8 -15
  98. data/lib/terraspace/cli/new/test.rb +1 -1
  99. data/lib/terraspace/cli/new.rb +17 -13
  100. data/lib/terraspace/cli/plan.rb +13 -0
  101. data/lib/terraspace/cli/setup/check.rb +8 -0
  102. data/lib/terraspace/cli/up.rb +8 -12
  103. data/lib/terraspace/cli.rb +2 -2
  104. data/lib/terraspace/cloud/api/cani.rb +30 -0
  105. data/lib/terraspace/cloud/api/concern/errors.rb +12 -0
  106. data/lib/terraspace/cloud/api/concern/record.rb +18 -0
  107. data/lib/terraspace/cloud/api/concern.rb +38 -0
  108. data/lib/terraspace/cloud/api/http_methods.rb +116 -0
  109. data/lib/terraspace/cloud/api/validate.rb +24 -0
  110. data/lib/terraspace/cloud/api.rb +33 -0
  111. data/lib/terraspace/cloud/base.rb +97 -0
  112. data/lib/terraspace/cloud/ci/generic.rb +25 -0
  113. data/lib/terraspace/cloud/ci/manual.rb +81 -0
  114. data/lib/terraspace/cloud/ci/vcs/base.rb +36 -0
  115. data/lib/terraspace/cloud/ci/vcs/bitbucket.rb +11 -0
  116. data/lib/terraspace/cloud/ci/vcs/github.rb +11 -0
  117. data/lib/terraspace/cloud/ci/vcs/gitlab.rb +11 -0
  118. data/lib/terraspace/cloud/ci/vcs.rb +18 -0
  119. data/lib/terraspace/cloud/ci.rb +56 -0
  120. data/lib/terraspace/cloud/context.rb +14 -0
  121. data/lib/terraspace/cloud/folder/base.rb +17 -0
  122. data/lib/terraspace/cloud/folder/package.rb +33 -0
  123. data/lib/terraspace/cloud/folder/tidy.rb +54 -0
  124. data/lib/terraspace/cloud/folder/uploader.rb +37 -0
  125. data/lib/terraspace/cloud/folder.rb +11 -0
  126. data/lib/terraspace/cloud/plan.rb +47 -0
  127. data/lib/terraspace/cloud/update.rb +37 -0
  128. data/lib/terraspace/command.rb +16 -1
  129. data/lib/terraspace/compiler/dsl/syntax/mod.rb +2 -2
  130. data/lib/terraspace/compiler/dsl/syntax/tfvar.rb +1 -1
  131. data/lib/terraspace/compiler/expander/backend.rb +1 -1
  132. data/lib/terraspace/compiler/expander.rb +1 -1
  133. data/lib/terraspace/compiler/strategy/tfvar/layer.rb +56 -29
  134. data/lib/terraspace/core.rb +44 -3
  135. data/lib/terraspace/ext/core/module.rb +9 -4
  136. data/lib/terraspace/hooks/builder.rb +1 -1
  137. data/lib/terraspace/logger.rb +32 -5
  138. data/lib/terraspace/mod.rb +21 -9
  139. data/lib/terraspace/plugin/expander/interface.rb +16 -11
  140. data/lib/terraspace/plugin.rb +14 -5
  141. data/lib/terraspace/shell.rb +7 -2
  142. data/lib/terraspace/terraform/args/thor.rb +8 -2
  143. data/lib/terraspace/terraform/ihooks/after/apply.rb +8 -0
  144. data/lib/terraspace/terraform/ihooks/after/destroy.rb +8 -0
  145. data/lib/terraspace/terraform/ihooks/after/plan.rb +31 -2
  146. data/lib/terraspace/terraform/ihooks/base.rb +7 -3
  147. data/lib/terraspace/terraform/ihooks/before/apply.rb +8 -0
  148. data/lib/terraspace/terraform/ihooks/before/destroy.rb +8 -0
  149. data/lib/terraspace/terraform/ihooks/before/plan.rb +11 -3
  150. data/lib/terraspace/terraform/runner.rb +19 -5
  151. data/lib/terraspace/version.rb +1 -1
  152. data/lib/terraspace.rb +2 -0
  153. data/terraspace.gemspec +1 -0
  154. metadata +116 -52
  155. data/.pipedream/schedule.rb +0 -3
@@ -31,6 +31,7 @@ module Terraspace::All
31
31
  line.include?("complete! Resources:") || # success: handles both apply and destroy output
32
32
  line.include?("Changes to Outputs") ||
33
33
  line.include?("No changes") ||
34
+ line.include?("Terraspace Cloud ") ||
34
35
  line.include?("Error: ") # error
35
36
  end
36
37
  end
@@ -53,6 +54,7 @@ module Terraspace::All
53
54
  line.include?("Changes to Outputs") ||
54
55
  line.include?("Plan:") ||
55
56
  line.include?("Changes to ") ||
57
+ line.include?("Terraspace Cloud ") ||
56
58
  line.include?("Error: ") # error
57
59
  end
58
60
  end
@@ -36,33 +36,52 @@ module Terraspace
36
36
  config.auto_create_backend = true
37
37
  config.autodetect = ActiveSupport::OrderedOptions.new
38
38
  config.autodetect.expander = nil
39
+
39
40
  config.build = ActiveSupport::OrderedOptions.new
40
- config.build.cache_dir = ":CACHE_ROOT/:REGION/:ENV/:BUILD_DIR"
41
- config.build.cache_root = nil # defaults to /full/path/to/.terraspace-cache
42
- config.build.clean_cache = nil # defaults to /full/path/to/.terraspace-cache
41
+ config.build.cache_dir = ":REGION/:APP/:ROLE/:ENV/:BUILD_DIR"
42
+ config.build.clean_cache = nil # defaults to true
43
43
  config.build.default_pass_files = ["/files/"]
44
44
  config.build.pass_files = []
45
+
45
46
  config.bundle = ActiveSupport::OrderedOptions.new
46
47
  config.bundle.logger = ts_logger
48
+
49
+ config.cloud = ActiveSupport::OrderedOptions.new
50
+ config.cloud.project = "main"
51
+ config.cloud.org = ENV['TS_ORG'] # required for Terraspace cloud
52
+ config.cloud.record = "changes" # IE: changes or all
53
+ config.cloud.stack = ":APP-:ROLE-:MOD_NAME-:ENV-:EXTRA-:REGION"
54
+
55
+ config.hooks = ActiveSupport::OrderedOptions.new
56
+ config.hooks.show = true
57
+
47
58
  config.init = ActiveSupport::OrderedOptions.new
48
59
  config.init.mode = "auto" # auto, never, always
60
+
49
61
  config.log = ActiveSupport::OrderedOptions.new
50
62
  config.log.root = Terraspace.log_root
51
63
  config.logger = ts_logger
52
64
  config.logger.formatter = Logger::Formatter.new
53
65
  config.logger.level = ENV['TS_LOG_LEVEL'] || :info
66
+
54
67
  config.layering = ActiveSupport::OrderedOptions.new
55
- config.layering.names = {}
56
68
  config.layering.enable_names = ActiveSupport::OrderedOptions.new
57
69
  config.layering.enable_names.expansion = true
70
+ config.layering.names = {}
71
+ config.layering.show = false
72
+ config.layering.mode = ENV['TS_LAYERING_MODE'] || "simple" # simple, namespace, provider
73
+
58
74
  config.summary = ActiveSupport::OrderedOptions.new
59
75
  config.summary.prune = false
76
+
60
77
  config.terraform = ActiveSupport::OrderedOptions.new
61
78
  config.terraform.plugin_cache = ActiveSupport::OrderedOptions.new
62
79
  config.terraform.plugin_cache.dir = ENV['TF_PLUGIN_CACHE_DIR'] || "#{Terraspace.tmp_root}/plugin_cache"
63
80
  config.terraform.plugin_cache.enabled = false
64
81
  config.terraform.plugin_cache.purge_on_error = true
82
+
65
83
  config.test_framework = "rspec"
84
+
66
85
  config.tfc = ActiveSupport::OrderedOptions.new
67
86
  config.tfc.auto_sync = true
68
87
  config.tfc.hostname = nil
@@ -44,7 +44,7 @@ module Terraspace
44
44
  run_hooks("terraspace.rb", "build") do
45
45
  build_dir("modules") if modules
46
46
  build_stacks
47
- logger.info "Built in #{build_dir}" unless @options[:quiet] # from terraspace all
47
+ logger.debug "Built in #{build_dir}"
48
48
  end
49
49
  end
50
50
 
@@ -0,0 +1,8 @@
1
+ module Terraspace::CLI::Concerns
2
+ module PlanPath
3
+ # Use when --out option not used
4
+ def plan_path
5
+ ".terraspace-cache/_cache2/plan/plan.binary"
6
+ end
7
+ end
8
+ end
@@ -1,6 +1,7 @@
1
1
  class Terraspace::CLI
2
2
  class Down < Base
3
3
  include TfcConcern
4
+ include Concerns::PlanPath
4
5
 
5
6
  def run
6
7
  plan if @options[:yes] && !tfc?
@@ -9,6 +10,9 @@ class Terraspace::CLI
9
10
 
10
11
  private
11
12
  def plan
13
+ if Terraspace.cloud? && !@options[:out]
14
+ @options[:out] = plan_path
15
+ end
12
16
  Commander.new("plan", @options.merge(destroy: true)).run
13
17
  end
14
18
 
@@ -65,7 +65,7 @@ class Terraspace::CLI
65
65
  end
66
66
 
67
67
  def auto_init?
68
- # terraspace commands not terraform commands. included some extra terraform commands here in case terrapace adds those later
68
+ # terraspace commands not terraform commands. included some extra terraform commands here in case terraspace adds those later
69
69
  commands = %w[all apply console down output plan providers refresh show state up validate]
70
70
  commands.include?(calling_command)
71
71
  end
@@ -0,0 +1,121 @@
1
+ class Terraspace::CLI::New
2
+ class Ci < Sequence
3
+ argument :name, required: false
4
+
5
+ def self.options
6
+ [
7
+ [:force, aliases: %w[y], type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files"],
8
+ ]
9
+ end
10
+ options.each { |args| class_option(*args) }
11
+
12
+ def generate
13
+ unless template_root_exist? # template not provided in the CI plugin
14
+ puts "This CI plugin did not include template. CI plugin: #{meta[:name]}"
15
+ puts "Searched path: #{template_root}"
16
+ exit 1
17
+ end
18
+ set_source_paths(template_root)
19
+ directory ".", exclude_pattern: "partials"
20
+ end
21
+
22
+ def make_executable
23
+ exe = meta[:exe]
24
+ return unless exe
25
+ if File.directory?(exe)
26
+ Dir.glob("#{exe}/*").each do |path|
27
+ chmod path, 0755
28
+ end
29
+ else
30
+ chmod exe, 0755
31
+ end
32
+ end
33
+
34
+ def message
35
+ puts <<~EOL
36
+ A CI structure has been generated for #{meta[:name]}.
37
+ It's a starter example and should be adjusted for your needs.
38
+ EOL
39
+ end
40
+
41
+ private
42
+ def cloud
43
+ # dont use memoize :cloud as Thor Sequence hides the private methods from Memoist
44
+ @cloud ||= Terraspace::Plugin.meta.keys.first # IE: aws azurerm google
45
+ end
46
+
47
+ def template_root
48
+ if meta[:root]
49
+ ["#{meta[:root]}/template", @options[:folder]].compact.join('/')
50
+ end
51
+ end
52
+
53
+ def template_root_exist?
54
+ template_root && File.exist?(template_root)
55
+ end
56
+
57
+ def set_source_paths(*paths)
58
+ # https://github.com/erikhuda/thor/blob/34df888d721ecaa8cf0cea97d51dc6c388002742/lib/thor/actions.rb#L128
59
+ instance_variable_set(:@source_paths, nil) # unset instance variable cache
60
+ # Using string with instance_eval because block doesnt have access to path at runtime.
61
+ self.class.instance_eval %{
62
+ def self.source_paths
63
+ #{paths.flatten.inspect}
64
+ end
65
+ }
66
+ end
67
+
68
+ def meta
69
+ if @name
70
+ find_meta
71
+ else
72
+ first_meta
73
+ end
74
+ end
75
+
76
+ def find_meta
77
+ found = Terraspace::Cloud::Ci.meta.find do |m|
78
+ m[:name] == @name
79
+ end
80
+ return found if found
81
+
82
+ logger.error "Unable to find CI plugin to handle #{@name}".color(:red)
83
+ exit 1
84
+ end
85
+
86
+ def first_meta
87
+ first = Terraspace::Cloud::Ci.meta.first
88
+ return first if first
89
+
90
+ logger.error "Unable to find Ci class".color(:red)
91
+ logger.error <<~EOL
92
+ Maybe you need to add one of the terraspace_ci_* gems to the Gemfile. IE:
93
+
94
+ Gemfile
95
+
96
+ gem "terraspace_ci_github"
97
+
98
+ EOL
99
+ exit 1
100
+ end
101
+
102
+ def partial(path)
103
+ RenderMePretty.result("#{template_root}/partials/#{path}", context: self)
104
+ end
105
+
106
+ def plugin_env_vars(indent: 6)
107
+ lines = plugin_env_vars_data.map do |k,v|
108
+ " " * indent + "#{k}: #{v}"
109
+ end
110
+ lines.join("\n") + "\n"
111
+ end
112
+
113
+ def plugin_env_vars_data
114
+ name = Terraspace::Plugin.autodetect
115
+ meta = Terraspace::Plugin.meta[name]
116
+ ci_class = meta[:ci_class]
117
+ return {} unless ci_class
118
+ ci_class.new.vars
119
+ end
120
+ end
121
+ end
@@ -22,7 +22,7 @@ class Terraspace::CLI::New
22
22
 
23
23
  private
24
24
  def cli_args
25
- plugin = @options[:plugin] || Terraspace::Autodetect.new.plugin
25
+ plugin = @options[:plugin] || Terraspace::Plugin.autodetect
26
26
  args = if plugin
27
27
  ['--plugin', plugin]
28
28
  else
@@ -5,7 +5,7 @@ module Terraspace::CLI::New::Helpers
5
5
  if @options[:plugin_gem]
6
6
  @options[:plugin_gem]
7
7
  else
8
- plugin = @options[:plugin] || Terraspace::Autodetect.new.plugin
8
+ plugin = @options[:plugin] || Terraspace::Plugin.autodetect
9
9
  "terraspace_plugin_#{plugin}" if plugin and plugin != "none"
10
10
  end
11
11
  end
@@ -0,0 +1,46 @@
1
+ class Terraspace::CLI::New::Plugin
2
+ class Ci < Terraspace::CLI::New::Sequence
3
+ include Helper
4
+
5
+ argument :name
6
+
7
+ def self.options
8
+ [
9
+ [:force, aliases: %w[y], type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files"],
10
+ [:pr, type: :boolean, desc: "Generate pr code also. Most CI systems don't have PR support"],
11
+ ]
12
+ end
13
+ options.each { |args| class_option(*args) }
14
+
15
+ def create_plugin
16
+ puts "=> Creating new ci plugin: #{name}"
17
+ core_template_source("plugin/ci")
18
+ exclude_pattern = "pr\.rb" unless options[:pr]
19
+ directory ".", "terraspace_ci_#{name}", exclude_pattern: exclude_pattern
20
+ end
21
+
22
+ def finish_message
23
+ files = [
24
+ "#{gem_name}.gemspec",
25
+ "lib/#{gem_name}.rb",
26
+ "lib/#{gem_name}/vars.rb",
27
+ "lib/#{gem_name}/interface.rb",
28
+ "README.md",
29
+ ]
30
+ files << "lib/#{gem_name}/pr.rb" if @options[:pr]
31
+ files.sort!
32
+ list = files.map { |file| " #{file}" }.join("\n")
33
+ puts <<~EOL
34
+ Files in #{gem_name} to review and update:
35
+
36
+ #{list}
37
+ EOL
38
+ end
39
+
40
+ private
41
+ def gem_name
42
+ "terraspace_ci_#{name}"
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,26 @@
1
+ class Terraspace::CLI::New::Plugin
2
+ class Core < Terraspace::CLI::New::Sequence
3
+ include Helper
4
+
5
+ argument :name
6
+
7
+ def self.options
8
+ [
9
+ [:force, aliases: %w[y], type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files"],
10
+ ]
11
+ end
12
+ options.each { |args| class_option(*args) }
13
+
14
+ def create_plugin
15
+ puts "=> Creating new plugin: #{name}"
16
+ core_template_source("plugin/core")
17
+ directory ".", "terraspace_plugin_#{name}"
18
+ end
19
+
20
+ private
21
+ def gem_name
22
+ "terraspace_plugin_#{name}"
23
+ end
24
+
25
+ end
26
+ end
@@ -1,7 +1,10 @@
1
1
  class Terraspace::CLI::New::Plugin
2
2
  module Helper
3
3
  private
4
- # helper
4
+ def gem_class_name
5
+ gem_name.camelize
6
+ end
7
+
5
8
  def camel_name
6
9
  name.camelize
7
10
  end
@@ -1,20 +1,13 @@
1
1
  class Terraspace::CLI::New
2
- class Plugin < Sequence
3
- include Helper
2
+ class Plugin < Terraspace::Command
3
+ Help = Terraspace::CLI::Help
4
4
 
5
- argument :name
5
+ long_desc Help.text("new/plugin/ci")
6
+ Ci.options.each { |args| option(*args) }
7
+ register(Ci, "ci", "ci NAME", "Generates CI Plugin.")
6
8
 
7
- def self.options
8
- [
9
- [:force, aliases: %w[y], type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files"],
10
- ]
11
- end
12
- options.each { |args| class_option(*args) }
13
-
14
- def create_plugin
15
- puts "=> Creating new plugin: #{name}"
16
- core_template_source("plugin")
17
- directory ".", "terraspace_plugin_#{name}"
18
- end
9
+ long_desc Help.text("new/plugin/core")
10
+ Core.options.each { |args| option(*args) }
11
+ register(Core, "core", "core NAME", "Generates Core plugin.")
19
12
  end
20
13
  end
@@ -54,7 +54,7 @@ class Terraspace::CLI::New
54
54
  # Used in ERB template
55
55
  # rspec-terraspace/lib/templates/stack/test/spec/fixtures/config/terraform/provider.tf.tt
56
56
  def autodetect_provider
57
- Terraspace::Autodetect.new.plugin
57
+ Terraspace::Plugin.autodetect
58
58
  end
59
59
  end
60
60
  end
@@ -2,11 +2,15 @@ class Terraspace::CLI
2
2
  class New < Terraspace::Command
3
3
  long_desc Help.text("new/arg")
4
4
  Arg.options.each { |args| option(*args) }
5
- register(Arg, "arg", "arg NAME", "Generates new arg.")
5
+ register(Arg, "arg", "arg NAME", "Generates arg.")
6
+
7
+ long_desc Help.text("new/ci")
8
+ Ci.options.each { |cis| option(*cis) }
9
+ register(Ci, "ci", "ci NAME", "Generates ci starter structure.")
6
10
 
7
11
  long_desc Help.text("new/git_hook")
8
12
  GitHook.cli_options.each { |args| option(*args) }
9
- register(GitHook, "git_hook", "git_hook", "Generates new git hook.")
13
+ register(GitHook, "git_hook", "git_hook", "Generates git hook.")
10
14
 
11
15
  long_desc Help.text("new/shim")
12
16
  Shim.cli_options.each { |args| option(*args) }
@@ -14,37 +18,37 @@ class Terraspace::CLI
14
18
 
15
19
  long_desc Help.text("new/helper")
16
20
  Helper.options.each { |args| option(*args) }
17
- register(Helper, "helper", "helper NAME", "Generates new helper.")
21
+ register(Helper, "helper", "helper NAME", "Generates helper.")
18
22
 
19
23
  long_desc Help.text("new/hook")
20
24
  Hook.options.each { |args| option(*args) }
21
- register(Hook, "hook", "hook NAME", "Generates new hook.")
25
+ register(Hook, "hook", "hook NAME", "Generates hook.")
22
26
 
23
27
  long_desc Help.text("new/module")
24
28
  Module.base_options.each { |args| option(*args) }
25
29
  Module.component_options.each { |args| option(*args) }
26
- register(Module, "module", "module NAME", "Generates new module.")
30
+ register(Module, "module", "module NAME", "Generates module.")
27
31
 
28
32
  long_desc Help.text("new/project")
29
33
  Project.base_options.each { |args| option(*args) }
30
34
  Project.project_options.each { |args| option(*args) }
31
- register(Project, "project", "project NAME", "Generates new project.")
32
-
33
- long_desc Help.text("new/plugin")
34
- Plugin.options.each { |args| option(*args) }
35
- register(Plugin, "plugin", "plugin NAME", "Generates plugin.")
35
+ register(Project, "project", "project NAME", "Generates project.")
36
36
 
37
37
  long_desc Help.text("new/stack")
38
38
  Stack.base_options.each { |args| option(*args) }
39
39
  Stack.component_options.each { |args| option(*args) }
40
- register(Stack, "stack", "stack NAME", "Generates new stack.")
40
+ register(Stack, "stack", "stack NAME", "Generates stack.")
41
41
 
42
42
  long_desc Help.text("new/test")
43
43
  Test.options.each { |args| option(*args) }
44
- register(Test, "test", "test NAME", "Generates new test.")
44
+ register(Test, "test", "test NAME", "Generates test.")
45
45
 
46
46
  long_desc Help.text("new/example")
47
47
  Example.options.each { |args| option(*args) }
48
- register(Example, "example", "example [NAME]", "Generates new example.")
48
+ register(Example, "example", "example [NAME]", "Generates example.")
49
+
50
+ desc "plugin SUBCOMMAND", "plugin subcommands"
51
+ long_desc Help.text("new/plugin")
52
+ subcommand "plugin", Plugin
49
53
  end
50
54
  end
@@ -0,0 +1,13 @@
1
+ class Terraspace::CLI
2
+ class Plan < Base
3
+ include TfcConcern
4
+ include Concerns::PlanPath
5
+
6
+ def run
7
+ if Terraspace.cloud? && !@options[:out]
8
+ @options[:out] = plan_path
9
+ end
10
+ Commander.new("plan", @options).run
11
+ end
12
+ end
13
+ end
@@ -93,6 +93,14 @@ class Terraspace::CLI::Setup
93
93
  end
94
94
  memoize :terraform_version_message
95
95
 
96
+ def terraform_version
97
+ terraform_version_message.sub(/.*v/,'')
98
+ end
99
+
100
+ def terraspace_version
101
+ Terraspace::VERSION
102
+ end
103
+
96
104
  class << self
97
105
  # Used as library call
98
106
  def check!
@@ -3,12 +3,18 @@ require 'securerandom'
3
3
  class Terraspace::CLI
4
4
  class Up < Base
5
5
  include TfcConcern
6
+ include Concerns::PlanPath
6
7
 
7
8
  def run
8
9
  build
9
10
  if @options[:yes] && !@options[:plan] && !tfc?
10
- plan
11
- Commander.new("apply", @options.merge(plan: plan_path)).run
11
+ if Terraspace.cloud? && !@options[:plan]
12
+ @options[:plan] = plan_path # for terraform apply
13
+ @options[:out] = plan_path # for terraform plan
14
+ end
15
+ Commander.new("plan", @options).run
16
+ return unless File.exist?(plan_path) if Terraspace.cloud? # happens if plan fails
17
+ Commander.new("apply", @options).run
12
18
  else
13
19
  Commander.new("apply", @options).run
14
20
  end
@@ -20,15 +26,5 @@ class Terraspace::CLI
20
26
  Terraspace::Builder.new(@options).run
21
27
  @options[:build] = false
22
28
  end
23
-
24
- def plan
25
- FileUtils.mkdir_p(File.dirname(plan_path))
26
- Commander.new("plan", @options.merge(out: plan_path)).run
27
- end
28
-
29
- def plan_path
30
- @@random ||= SecureRandom.hex
31
- "#{Terraspace.tmp_root}/plans/#{@mod.name}-#{@@random}.plan"
32
- end
33
29
  end
34
30
  end
@@ -21,7 +21,7 @@ module Terraspace
21
21
  option :instance, aliases: %w[i], desc: "Instance of stack"
22
22
  }
23
23
  init_option = Proc.new {
24
- option :init, type: :boolean, default: true, desc: "Instance of stack"
24
+ option :init, type: :boolean, default: true, desc: "Whether or not to run init"
25
25
  }
26
26
  reconfigure_option = Proc.new {
27
27
  option :reconfigure, type: :boolean, desc: "Add terraform -reconfigure option"
@@ -152,7 +152,7 @@ module Terraspace
152
152
  reconfigure_option.call
153
153
  option :copy_to_root, type: :boolean, default: true, desc: "Copy plan file generated in the cache folder back to project root"
154
154
  def plan(mod, *args)
155
- Commander.new("plan", options.merge(mod: mod, args: args)).run
155
+ Plan.new(options.merge(mod: mod, args: args)).run
156
156
  end
157
157
 
158
158
  desc "providers STACK", "Show providers."
@@ -0,0 +1,30 @@
1
+ class Terraspace::Cloud::Api
2
+ class Cani
3
+ include Terraspace::Util::Logging
4
+
5
+ def initialize(result)
6
+ @result = result
7
+ end
8
+
9
+ # {"data":{"attributes":{"detail":"You are authorized to perform this action.","status":200,"title":"Authoriz
10
+ # {"errors":[{"detail":"You are not authorized to perform this action. Double check your token or check with your admin that you have permissions.","status":403,"title":"Forbidden"}]}
11
+ def handle
12
+ yes = false # assume do not have permission
13
+ detail = @result&.dig('data', 'attributes', 'detail')
14
+ if detail&.include?('You are authorized to perform this action')
15
+ yes = true # confirm have permission
16
+ end
17
+ return if yes
18
+
19
+ if @result.nil? # 400 Bad Request
20
+ logger.info "ERROR: It doesn't look like TS_TOKEN is valid".color(:red)
21
+ else
22
+ errors = @result.dig('errors')
23
+ detail = errors.first['detail']
24
+ # {"errors":[{"detail":"You are not authorized to perform this action. Double check your token or check with your admin that you have permissions.","status":403,"title":"Forbidden"}]}
25
+ logger.info "ERROR: #{detail}".color(:red)
26
+ end
27
+ exit 1
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,12 @@
1
+ module Terraspace::Cloud::Api::Concern
2
+ module Errors
3
+ def errors?(result)
4
+ result.is_a?(Hash) && result.key?("errors")
5
+ end
6
+
7
+ def error_message(result)
8
+ $stderr.puts "ERROR: #{result["errors"]}"
9
+ $stderr.puts "Your current settings. org: #{@org} project: #{@project}"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ module Terraspace::Cloud::Api::Concern
2
+ module Record
3
+ def load_record(result)
4
+ record = {}
5
+ data = result['data']
6
+ record['id'] = data['id']
7
+ record.merge!(data['attributes'])
8
+ record
9
+ end
10
+
11
+ def load_records(result)
12
+ result['data'].map do |item|
13
+ record = { id: item['id'] }
14
+ record.merge(item['attributes'])
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,38 @@
1
+ class Terraspace::Cloud::Api
2
+ module Concern
3
+ extend Memoist
4
+ include Errors
5
+ include Record
6
+ include Validate
7
+
8
+ def api
9
+ validate("stack", cloud_stack_name)
10
+ @options = @options.merge(
11
+ app: Terraspace.app,
12
+ role: Terraspace.role,
13
+ env: Terraspace.env,
14
+ extra: Terraspace.extra,
15
+ region: region,
16
+ name: cloud_stack_name,
17
+ )
18
+ @options.reject! { |k,v| v.nil? }
19
+ Terraspace::Cloud::Api.new(@options) # @options are CLI options
20
+ end
21
+
22
+ def cloud_stack_name
23
+ pattern = Terraspace.config.cloud.stack
24
+ expanded = expander.expansion(pattern) # pattern is a String that contains placeholders for substitutions
25
+ expanded.gsub(%r{-+},'-') # remove double dashes are more. IE: -- -> -
26
+ .sub(/^-+/,'').sub(/-+$/,'') # remove leading and trailing -
27
+ end
28
+
29
+ def region
30
+ expander.expansion(":REGION")
31
+ end
32
+
33
+ def expander
34
+ Terraspace::Compiler::Expander.autodetect(@mod)
35
+ end
36
+ memoize :expander
37
+ end
38
+ end