terraspace 2.0.1 → 2.1.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.cody/README.md +1 -1
  3. data/.cody/all/project.rb +4 -0
  4. data/.cody/aws/project.rb +4 -0
  5. data/.cody/azurerm/project.rb +4 -0
  6. data/.cody/google/project.rb +4 -0
  7. data/.cody/none/project.rb +4 -0
  8. data/.cody/shared/script/install/infracost.sh +6 -0
  9. data/.cody/shared/script/install/terraform.sh +2 -2
  10. data/.cody/shared/script/install.sh +1 -0
  11. data/.github/FUNDING.yml +1 -0
  12. data/.pipedream/README.md +1 -1
  13. data/.pipedream/pipeline.rb +15 -8
  14. data/CHANGELOG.md +16 -0
  15. data/lib/templates/base/project/Gemfile.tt +5 -0
  16. data/lib/templates/base/project/config/app.rb +6 -2
  17. data/lib/templates/plugin/ci/CHANGELOG.md.tt +1 -1
  18. data/lib/templates/plugin/ci/lib/%gem_name%/vars.rb.tt +1 -1
  19. data/lib/terraspace/app.rb +16 -0
  20. data/lib/terraspace/cli/base.rb +1 -0
  21. data/lib/terraspace/cli/commander.rb +2 -1
  22. data/lib/terraspace/cli/concerns/plan_path.rb +1 -1
  23. data/lib/terraspace/cli/down.rb +42 -6
  24. data/lib/terraspace/cli/logs/concern.rb +1 -1
  25. data/lib/terraspace/cli/new/plugin/ci.rb +1 -4
  26. data/lib/terraspace/cli/plan.rb +66 -2
  27. data/lib/terraspace/cli/up.rb +65 -11
  28. data/lib/terraspace/cloud/api/cani.rb +15 -9
  29. data/lib/terraspace/cloud/api/concern.rb +0 -1
  30. data/lib/terraspace/cloud/api/http_methods.rb +7 -2
  31. data/lib/terraspace/cloud/api.rb +29 -5
  32. data/lib/terraspace/cloud/base.rb +16 -29
  33. data/lib/terraspace/cloud/ci.rb +1 -8
  34. data/lib/terraspace/cloud/comment.rb +28 -0
  35. data/lib/terraspace/cloud/context.rb +1 -0
  36. data/lib/terraspace/cloud/cost/infracost.rb +80 -0
  37. data/lib/terraspace/cloud/cost.rb +68 -0
  38. data/lib/terraspace/cloud/git.rb +0 -0
  39. data/lib/terraspace/cloud/plan.rb +33 -15
  40. data/lib/terraspace/cloud/stream.rb +113 -0
  41. data/lib/terraspace/cloud/streamer.rb +9 -0
  42. data/lib/terraspace/cloud/update.rb +19 -19
  43. data/lib/terraspace/cloud/{folder → upload}/base.rb +2 -2
  44. data/lib/terraspace/cloud/{folder → upload}/package.rb +2 -2
  45. data/lib/terraspace/cloud/{folder → upload}/tidy.rb +1 -1
  46. data/lib/terraspace/cloud/upload.rb +53 -0
  47. data/lib/terraspace/cloud/vcs/base.rb +6 -0
  48. data/lib/terraspace/cloud/vcs/ci_env.rb +15 -0
  49. data/lib/terraspace/cloud/vcs/commenter.rb +75 -0
  50. data/lib/terraspace/cloud/vcs/interface.rb +14 -0
  51. data/lib/terraspace/cloud/vcs/local_env.rb +25 -0
  52. data/lib/terraspace/cloud/{ci/vcs → vcs/local_git}/base.rb +6 -3
  53. data/lib/terraspace/cloud/vcs/local_git/bitbucket.rb +17 -0
  54. data/lib/terraspace/cloud/vcs/local_git/github.rb +17 -0
  55. data/lib/terraspace/cloud/vcs/local_git/gitlab.rb +17 -0
  56. data/lib/terraspace/cloud/{ci/manual.rb → vcs/local_git.rb} +18 -10
  57. data/lib/terraspace/cloud/vcs.rb +21 -0
  58. data/lib/terraspace/compiler/strategy/tfvar/layer.rb +1 -1
  59. data/lib/terraspace/core.rb +8 -0
  60. data/lib/terraspace/logger.rb +3 -2
  61. data/lib/terraspace/plugin/expander/interface.rb +5 -8
  62. data/lib/terraspace/shell/error.rb +1 -1
  63. data/lib/terraspace/terraform/runner.rb +4 -22
  64. data/lib/terraspace/util/popen.rb +67 -0
  65. data/lib/terraspace/version.rb +1 -1
  66. metadata +26 -23
  67. data/lib/templates/plugin/ci/lib/%gem_name%/pr.rb.tt +0 -15
  68. data/lib/terraspace/cloud/api/concern/record.rb +0 -18
  69. data/lib/terraspace/cloud/ci/generic.rb +0 -25
  70. data/lib/terraspace/cloud/ci/vcs/bitbucket.rb +0 -11
  71. data/lib/terraspace/cloud/ci/vcs/github.rb +0 -11
  72. data/lib/terraspace/cloud/ci/vcs/gitlab.rb +0 -11
  73. data/lib/terraspace/cloud/ci/vcs.rb +0 -18
  74. data/lib/terraspace/cloud/folder/uploader.rb +0 -37
  75. data/lib/terraspace/cloud/folder.rb +0 -11
  76. data/lib/terraspace/terraform/ihooks/after/apply.rb +0 -8
  77. data/lib/terraspace/terraform/ihooks/after/destroy.rb +0 -8
  78. data/lib/terraspace/terraform/ihooks/after/plan.rb +0 -46
  79. data/lib/terraspace/terraform/ihooks/base.rb +0 -17
  80. data/lib/terraspace/terraform/ihooks/before/apply.rb +0 -8
  81. data/lib/terraspace/terraform/ihooks/before/destroy.rb +0 -8
  82. data/lib/terraspace/terraform/ihooks/before/plan.rb +0 -20
@@ -0,0 +1,53 @@
1
+ module Terraspace::Cloud
2
+ class Upload < Base
3
+ def create(data) # data: {stream_id:, type: }
4
+ zip_path = Package.new(@options.merge(data)).build
5
+ upload = create_upload(data)
6
+ upload_project(upload, zip_path)
7
+ upload
8
+ end
9
+
10
+ private
11
+ def create_upload(params)
12
+ upload = api.create_upload(params)
13
+ if errors?(upload)
14
+ error_message(upload)
15
+ exit 1 # Consider: raise exception can rescue higher up
16
+ else
17
+ upload
18
+ end
19
+ end
20
+
21
+ def upload_project(upload, path, retries=0)
22
+ url = upload['data']['attributes']['url']
23
+ uri = URI.parse(url)
24
+ object_content = IO.read(path)
25
+ sleep 2
26
+ resp = Net::HTTP.start(uri.host) do |http|
27
+ http.send_request(
28
+ 'PUT',
29
+ uri.request_uri,
30
+ object_content,
31
+ 'content-type' => ''
32
+ )
33
+ end
34
+ return if resp.code =~ /^20/
35
+
36
+ log_errors(resp.body, :debug)
37
+ if resp.body.include?('expired')
38
+ if retries >= 10 # 15m * 10 = 150m = 2.5h
39
+ log_errors(resp.body, :info)
40
+ exit 1
41
+ end
42
+ logger.debug("Retrying upload")
43
+ upload = create_upload(upload_id: upload['data']['id'])
44
+ upload_project(upload, path, retries+1)
45
+ end
46
+ end
47
+
48
+ def log_errors(body, level=:debug)
49
+ logger.send(level, "ERROR: Uploader uploading code")
50
+ logger.send(level, "resp body #{body}")
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,6 @@
1
+ class Terraspace::Cloud::Vcs
2
+ class Base
3
+ extend Memoist
4
+ include Terraspace::Util::Logging
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ class Terraspace::Cloud::Vcs
2
+ class CiEnv
3
+ extend Memoist
4
+ include Terraspace::Util::Logging
5
+
6
+ def vars
7
+ klass = Terraspace::Cloud::Ci.detect
8
+ if klass
9
+ klass.new.vars.compact # remove items with nil values
10
+ else
11
+ {}
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,75 @@
1
+ class Terraspace::Cloud::Vcs
2
+ module Commenter
3
+ extend Memoist
4
+
5
+ # record is plan or update
6
+ def pr_comment(record, cost)
7
+ return unless able_to_comment?
8
+
9
+ resp = cloud_comment.get(record, cost)
10
+ body = resp['data']['attributes']['body'] if resp
11
+ if body
12
+ vcs.comment(body)
13
+ else
14
+ logger.info "WARN: Unable to post a PR comment"
15
+ end
16
+ end
17
+
18
+ def cloud_comment
19
+ Terraspace::Cloud::Comment.new(@options.merge(stack: @mod.name, kind: kind))
20
+ end
21
+ memoize :cloud_comment
22
+
23
+ def vcs
24
+ # IE: TerraspaceVcsGithub::Interface.new
25
+ Terraspace::Cloud::Vcs.detect(full_repo: vcs_vars[:full_repo], pr_number: vcs_vars[:pr_number])
26
+ end
27
+ memoize :vcs
28
+
29
+ #
30
+ # full_repo # env or .git * min required for pr url
31
+ # host # env or .git * min required for pr url
32
+ # branch_name # env or .git
33
+ # sha # env or .git
34
+ # dirty # env or .git
35
+ # pr_number # env * min required for pr url
36
+ #
37
+ # commit_message # env
38
+ # build_system # env
39
+ # build_id # env
40
+ # build_number # env
41
+ # build_type # env
42
+ #
43
+ # build_url
44
+ # commit_url
45
+ # branch_url
46
+ # pr_url
47
+ #
48
+ def vcs_vars
49
+ ci_env = CiEnv.new
50
+ local_git = LocalGit.new
51
+ local_env = LocalEnv.new
52
+ vars = local_git.vars.merge(ci_env.vars).merge(local_env.vars)
53
+ finalize_vars(local_git, vars)
54
+ end
55
+ memoize :vcs_vars
56
+
57
+ # finalize branch_url since info is set from multiple layers
58
+ def finalize_vars(local_git, vars)
59
+ if local_git.vcs_class # IE: LocalGit::Github
60
+ vars[:branch_url] ||= local_git.vcs_class.new(vars).branch_url # IE: LocalGit::Github#branch_url
61
+ end
62
+ vars
63
+ end
64
+
65
+ def able_to_comment?
66
+ !!(vcs && vcs_vars[:full_repo] && vcs_vars[:pr_number])
67
+ end
68
+
69
+ # stored on cloud: kind can be apply or destroy. its extra info
70
+ def kind
71
+ is_destroy = Terraspace.command?("down") || @options[:args]&.include?('--destroy') || @options[:destroy]
72
+ is_destroy ? "destroy" : "apply"
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,14 @@
1
+ class Terraspace::Cloud::Vcs
2
+ module Interface
3
+ extend Memoist
4
+ include Terraspace::Util::Logging
5
+
6
+ MARKER = "<!-- terraspace marker -->"
7
+
8
+ attr_reader :full_repo, :pr_number
9
+ def initialize(options={})
10
+ @full_repo = options[:full_repo]
11
+ @pr_number = options[:pr_number]
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ class Terraspace::Cloud::Vcs
2
+ class LocalEnv < Base
3
+ def vars
4
+ # Do not set any default values. These take highest precedence and will override LocalGit and CiVars
5
+ {
6
+ host: ENV['TS_VCS_HOST'] || ENV['VCS_HOST'] || ENV['GIT_HOST'],
7
+ full_repo: ENV['TS_VCS_REPO'] || ENV['VCS_REPO'] || ENV['GIT_REPO'],
8
+ branch_name: ENV['TS_VCS_BRANCH'],
9
+ # urls
10
+ commit_url: ENV['TS_VCS_COMMIT_URL'],
11
+ branch_url: ENV['TS_VCS_BRANCH_URL'],
12
+ pr_url: ENV['TS_VCS_PR_URL'],
13
+ build_url: ENV['TS_VCS_BUILD_URL'],
14
+ # additional properties
15
+ build_type: ENV['TS_VCS_BUILD_TYPE'],
16
+ # pr_number: ENV['TS_VCS_PR_NUMBER'] || ENV['PR_NUMBER'] || ENV['MR_NUMBER'], # handle in LocalGit::Base so can compute pr_url
17
+ sha: ENV['TS_VCS_SHA'],
18
+ # additional properties
19
+ commit_message: ENV['TS_VCS_COMMIT_MESSAGE'],
20
+ build_id: ENV['TS_VCS_BUILD_ID'],
21
+ build_number: ENV['TS_VCS_BUILD_NUMBER'],
22
+ }.compact # remove items with nil values
23
+ end
24
+ end
25
+ end
@@ -1,4 +1,4 @@
1
- class Terraspace::Cloud::Ci::Vcs
1
+ class Terraspace::Cloud::Vcs::LocalGit
2
2
  class Base
3
3
  extend Memoist
4
4
 
@@ -10,11 +10,14 @@ class Terraspace::Cloud::Ci::Vcs
10
10
  {
11
11
  commit_url: commit_url, # implemented by subclass
12
12
  branch_url: branch_url, # implemented by subclass
13
+ # pr_url handled when PR_NUMBER set by user outside of ci env. ci plugin pr_url takes higher precedence though
14
+ pr_number: pr_number,
15
+ pr_url: pr_url,
13
16
  }
14
17
  end
15
18
 
16
- def merged_vars
17
- @vars.merge(vars)
19
+ def pr_number
20
+ ENV['TS_VCS_PR_NUMBER'] || ENV['PR_NUMBER'] || ENV['MR_NUMBER']
18
21
  end
19
22
 
20
23
  class << self
@@ -0,0 +1,17 @@
1
+ class Terraspace::Cloud::Vcs::LocalGit
2
+ class Bitbucket < Base
3
+ def commit_url
4
+ "#{host}/#{full_repo}/commits/#{sha}" if sha
5
+ end
6
+
7
+ def branch_url
8
+ "#{host}/#{full_repo}/branch/#{branch_name}" if branch_name
9
+ end
10
+
11
+ # Also computed in ci plugins which detects it from the ci env.
12
+ # Also handling here for case when user provides PR_NUMBER and GIT_REPO outside of normal CI env.
13
+ def pr_url
14
+ "#{host}/#{full_repo}/pull-requests/#{pr_number}" if pr_number
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ class Terraspace::Cloud::Vcs::LocalGit
2
+ class Github < Base
3
+ def commit_url
4
+ "#{host}/#{full_repo}/commits/#{sha}" if sha
5
+ end
6
+
7
+ def branch_url
8
+ "#{host}/#{full_repo}/tree/#{branch_name}" if branch_name
9
+ end
10
+
11
+ # Also computed in ci plugins which detects it from the ci env.
12
+ # Also handling here for case when user provides PR_NUMBER and GIT_REPO outside of normal CI env.
13
+ def pr_url
14
+ "#{host}/#{full_repo}/pull/#{pr_number}" if pr_number
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ class Terraspace::Cloud::Vcs::LocalGit
2
+ class Gitlab < Base
3
+ def commit_url
4
+ "#{host}/#{full_repo}/-/commits/#{sha}" if sha
5
+ end
6
+
7
+ def branch_url
8
+ "#{host}/#{full_repo}/-/tree/#{branch_name}" if branch_name
9
+ end
10
+
11
+ # Also computed in ci plugins which detects it from the ci env.
12
+ # Also handling here for case when user provides PR_NUMBER and GIT_REPO outside of normal CI env.
13
+ def pr_url
14
+ "#{host}/#{full_repo}/-/merge_requests/#{pr_number}" if pr_number
15
+ end
16
+ end
17
+ end
@@ -1,17 +1,23 @@
1
- class Terraspace::Cloud::Ci
2
- class Manual
3
- extend Memoist
4
- include Terraspace::Util::Logging
5
-
1
+ class Terraspace::Cloud::Vcs
2
+ class LocalGit < Base
6
3
  def vars
7
4
  if git_repo? && git_installed?
8
- vars_data
5
+ provider_vars = vcs_class ? vcs_class.new(base_vars).vars : {}
6
+ base_vars.merge(provider_vars).compact # remove items with nil values
9
7
  else
10
8
  { build_system: "manual" }
11
9
  end
12
10
  end
13
11
 
14
- def vars_data
12
+ def vcs_class
13
+ case host
14
+ when /github/ then Github
15
+ when /gitlab/ then Gitlab
16
+ when /bitbucket/ then Bitbucket
17
+ end
18
+ end
19
+
20
+ def base_vars
15
21
  {
16
22
  build_system: "manual", # required
17
23
  host: host,
@@ -19,8 +25,8 @@ class Terraspace::Cloud::Ci
19
25
  branch_name: branch_name,
20
26
  sha: sha,
21
27
  dirty: dirty?,
22
- # commit_url: commit_url, # provided by core
23
- # branch_url: branch_url, # provided by core
28
+ # commit_url: commit_url, # provided by provider vars
29
+ # branch_url: branch_url, # provided by provider vars
24
30
  }
25
31
  end
26
32
 
@@ -46,7 +52,9 @@ class Terraspace::Cloud::Ci
46
52
  # git@bitbucket.org: => https://bitbucket.org/
47
53
  # git@gitlab.com: => https://gitlab.com/
48
54
  def git_url
49
- out = git "config --get remote.origin.url"
55
+ remotes = git("remote").strip.split("\n")
56
+ remote_name = remotes.size == 1 ? remotes[0] : "origin"
57
+ out = git "config --get remote.#{remote_name}.url"
50
58
  out.sub(/\.git/,'').sub(/^git@/,'https://').sub(/\.(.*):/,'.\1/')
51
59
  end
52
60
 
@@ -0,0 +1,21 @@
1
+ module Terraspace::Cloud
2
+ class Vcs
3
+ class << self
4
+ @@name = nil
5
+ def register(options={})
6
+ @@name = options[:name]
7
+ end
8
+
9
+ # IE: TerraspaceVcsGithub::Interface.new
10
+ def detect(options)
11
+ name = detect_name
12
+ "TerraspaceVcs#{name.camelize}::Interface".constantize.new(options) if name
13
+ end
14
+
15
+ def detect_name
16
+ # allow user to override vcs.name
17
+ Terraspace.config.cloud.vcs.name || @@name
18
+ end
19
+ end
20
+ end
21
+ end
@@ -41,7 +41,7 @@ class Terraspace::Compiler::Strategy::Tfvar
41
41
  def paths
42
42
  project_paths = full_paths(project_tfvars_dir)
43
43
  stack_paths = full_paths(stack_tfvars_dir)
44
- paths = project_paths + stack_paths
44
+ paths = (project_paths + stack_paths).uniq
45
45
  show_layers(paths)
46
46
  paths.select do |path|
47
47
  File.exist?(path)
@@ -18,6 +18,14 @@ module Terraspace
18
18
  ENV['TS_EXTRA'] unless ENV['TS_EXTRA'].blank?
19
19
  end
20
20
 
21
+ def project
22
+ if ENV['TS_PROJECT'].blank?
23
+ config.cloud.project
24
+ else
25
+ ENV['TS_PROJECT']
26
+ end
27
+ end
28
+
21
29
  @@root = nil
22
30
  def root
23
31
  @@root ||= ENV['TS_ROOT'] || Dir.pwd
@@ -14,7 +14,7 @@ module Terraspace
14
14
  else
15
15
  super # use the configured formatter
16
16
  end
17
- out = line =~ /\n$/ ? line : "#{line}\n"
17
+ out = line.force_encoding('UTF-8') =~ /\n$/ ? line : "#{line}\n"
18
18
  @@buffer << out
19
19
  out
20
20
  end
@@ -45,7 +45,8 @@ module Terraspace
45
45
  end
46
46
 
47
47
  def logs
48
- @@buffer.join('')
48
+ # force_encoding https://jch.github.io/posts/2013-03-05-ruby-incompatible-encoding.html
49
+ @@buffer.map { |s| s.force_encoding('UTF-8') }.join('')
49
50
  end
50
51
 
51
52
  # for test framework
@@ -96,10 +96,11 @@ module Terraspace::Plugin::Expander
96
96
  @mod.name
97
97
  end
98
98
 
99
- def app; Terraspace.app ; end
100
- def role; Terraspace.role ; end
101
- def env; Terraspace.env ; end
102
- def extra; Terraspace.extra ; end
99
+ def app; Terraspace.app ; end
100
+ def env; Terraspace.env ; end
101
+ def extra; Terraspace.extra ; end
102
+ def project; Terraspace.project ; end
103
+ def role; Terraspace.role ; end
103
104
 
104
105
  def type_instance
105
106
  [type, instance].reject { |s| s.blank? }.join('-')
@@ -114,10 +115,6 @@ module Terraspace::Plugin::Expander
114
115
  Terraspace.cache_root
115
116
  end
116
117
 
117
- def project
118
- Terraspace.config.cloud.project
119
- end
120
-
121
118
  # So default config works:
122
119
  # config.cache_dir = ":REGION/:ENV/:BUILD_DIR"
123
120
  # For when folks configure it with the http backend for non-cloud providers
@@ -35,7 +35,7 @@ class Terraspace::Shell
35
35
 
36
36
  def message
37
37
  # For error messages, terraform lines from buffer do not contain newlines. So join with newline
38
- @lines.join("\n")
38
+ @lines.map { |l| l.force_encoding('UTF-8') }.join("\n")
39
39
  end
40
40
 
41
41
  def shared_cache_error?
@@ -4,7 +4,7 @@ module Terraspace::Terraform
4
4
  include Terraspace::Hooks::Concern
5
5
  include Terraspace::Util
6
6
 
7
- attr_reader :name
7
+ attr_reader :name, :shell_exception
8
8
  def initialize(name, options={})
9
9
  @name = name
10
10
  super(options)
@@ -14,12 +14,7 @@ module Terraspace::Terraform
14
14
  time_took do
15
15
  terraform(name, args)
16
16
  end
17
-
18
- run_internal_hook(:after, name) # always run so plan and apply get saved to tsc
19
- if @shell_error
20
- logger.error @shell_error.message.color(:red)
21
- exit 1 if name == "plan" && Terraspace.command?("up")
22
- end
17
+ @success
23
18
  end
24
19
 
25
20
  # default at end in case of redirection. IE: terraform output > /path
@@ -51,15 +46,14 @@ module Terraspace::Terraform
51
46
 
52
47
  params = args.flatten.join(' ')
53
48
  command = "terraform #{name} #{params}".squish
54
- @shell_error = nil
49
+ @shell_exception = nil
55
50
  run_hooks("terraform.rb", name) do
56
51
  Backend.new(@mod).create
57
- run_internal_hook(:before, name)
58
52
  begin
59
53
  Terraspace::Shell.new(@mod, command, @options.merge(env: custom.env_vars)).run
60
54
  @success = true
61
55
  rescue Terraspace::ShellError => exception
62
- @shell_error = exception
56
+ @shell_exception = exception
63
57
  @success = false
64
58
  end
65
59
  end
@@ -73,18 +67,6 @@ module Terraspace::Terraform
73
67
  end
74
68
  end
75
69
 
76
- def run_internal_hook(type, name)
77
- begin
78
- class_name = "Terraspace::Terraform::Ihooks::#{type.to_s.classify}::#{name.classify}"
79
- klass = class_name.constantize
80
- rescue NameError => e
81
- logger.debug "DEBUG: #{e.class} #{e.message}".color(:red)
82
- return
83
- end
84
- ihook = klass.new(name, @options.merge(success: @success))
85
- ihook.run
86
- end
87
-
88
70
  @@current_dir_message_shown = false
89
71
  def current_dir_message
90
72
  return if @@current_dir_message_shown
@@ -0,0 +1,67 @@
1
+ require 'open3'
2
+
3
+ module Terraspace::Util
4
+ module Popen
5
+ include Logging
6
+
7
+ # Similar to Terraspace::Shell#popen3
8
+ # More generalized. Useful for plugins
9
+ def popen(command, options={})
10
+ Open3.popen3(command) do |stdin, stdout, stderr, wait_thread|
11
+ handle_streams(stdin, stdout, stderr, options)
12
+ status = wait_thread.value.exitstatus
13
+ unless status == 0
14
+ logger.error "Error running command #{command}".color(:red)
15
+ exit 1
16
+ end
17
+ end
18
+ end
19
+
20
+ BLOCK_SIZE = Integer(ENV['TS_BUFFER_BLOCK_SIZE'] || 102400)
21
+ def handle_streams(stdin, stdout, stderr, options)
22
+ files = [stdout, stderr]
23
+ until all_eof?(files) do
24
+ ready = IO.select(files)
25
+ next unless ready
26
+
27
+ readable = ready[0]
28
+ readable.each do |f|
29
+ buffer = f.read_nonblock(BLOCK_SIZE, exception: false)
30
+ next unless buffer
31
+
32
+ lines = buffer.split("\n")
33
+ lines.each do |line|
34
+ if f.fileno == stdout.fileno
35
+ handle_stdout(line, options)
36
+ else
37
+ handle_stderr(line, options)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def handle_stdout(line, options={})
45
+ newline = options[:newline].nil? ? true : options[:newline]
46
+ filter = options[:filter]
47
+
48
+ # Terraspace logger has special stdout method so original terraform output
49
+ # can be piped to jq. IE:
50
+ # terraspace show demo --json | jq
51
+ if logger.respond_to?(:stdout) && !options[:log_to_stderr]
52
+ logger.stdout(line, newline: newline) unless line.include?(filter)
53
+ else
54
+ logger.info(line) unless line.include?(filter)
55
+ end
56
+ end
57
+
58
+ def handle_stderr(line, options={})
59
+ logger.error(line) unless line.include?(options[:filter])
60
+ end
61
+
62
+ def all_eof?(files)
63
+ files.find { |f| !f.eof }.nil?
64
+ end
65
+
66
+ end
67
+ end
@@ -1,3 +1,3 @@
1
1
  module Terraspace
2
- VERSION = "2.0.1"
2
+ VERSION = "2.1.0"
3
3
  end
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: 2.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-06-14 00:00:00.000000000 Z
11
+ date: 2022-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -382,12 +382,14 @@ files:
382
382
  - ".cody/none/iam_role.rb"
383
383
  - ".cody/none/project.rb"
384
384
  - ".cody/shared/script/install.sh"
385
+ - ".cody/shared/script/install/infracost.sh"
385
386
  - ".cody/shared/script/install/terraform.sh"
386
387
  - ".cody/shared/script/install/terraspace.sh"
387
388
  - ".cody/shared/script/update/gemfile.sh"
388
389
  - ".cody/unit/bin/build.sh"
389
390
  - ".cody/unit/buildspec.yml"
390
391
  - ".cody/unit/project.rb"
392
+ - ".github/FUNDING.yml"
391
393
  - ".github/ISSUE_TEMPLATE.md"
392
394
  - ".github/ISSUE_TEMPLATE/bug_report.md"
393
395
  - ".github/ISSUE_TEMPLATE/documentation.md"
@@ -450,7 +452,6 @@ files:
450
452
  - lib/templates/plugin/ci/lib/%gem_name%.rb.tt
451
453
  - lib/templates/plugin/ci/lib/%gem_name%/autoloader.rb.tt
452
454
  - lib/templates/plugin/ci/lib/%gem_name%/interface.rb.tt
453
- - lib/templates/plugin/ci/lib/%gem_name%/pr.rb.tt
454
455
  - lib/templates/plugin/ci/lib/%gem_name%/vars.rb.tt
455
456
  - lib/templates/plugin/ci/lib/%gem_name%/version.rb.tt
456
457
  - lib/templates/plugin/ci/spec/%gem_name%_spec.rb.tt
@@ -645,26 +646,34 @@ files:
645
646
  - lib/terraspace/cloud/api/cani.rb
646
647
  - lib/terraspace/cloud/api/concern.rb
647
648
  - lib/terraspace/cloud/api/concern/errors.rb
648
- - lib/terraspace/cloud/api/concern/record.rb
649
649
  - lib/terraspace/cloud/api/http_methods.rb
650
650
  - lib/terraspace/cloud/api/validate.rb
651
651
  - lib/terraspace/cloud/base.rb
652
652
  - lib/terraspace/cloud/ci.rb
653
- - lib/terraspace/cloud/ci/generic.rb
654
- - lib/terraspace/cloud/ci/manual.rb
655
- - lib/terraspace/cloud/ci/vcs.rb
656
- - lib/terraspace/cloud/ci/vcs/base.rb
657
- - lib/terraspace/cloud/ci/vcs/bitbucket.rb
658
- - lib/terraspace/cloud/ci/vcs/github.rb
659
- - lib/terraspace/cloud/ci/vcs/gitlab.rb
653
+ - lib/terraspace/cloud/comment.rb
660
654
  - lib/terraspace/cloud/context.rb
661
- - lib/terraspace/cloud/folder.rb
662
- - lib/terraspace/cloud/folder/base.rb
663
- - lib/terraspace/cloud/folder/package.rb
664
- - lib/terraspace/cloud/folder/tidy.rb
665
- - lib/terraspace/cloud/folder/uploader.rb
655
+ - lib/terraspace/cloud/cost.rb
656
+ - lib/terraspace/cloud/cost/infracost.rb
657
+ - lib/terraspace/cloud/git.rb
666
658
  - lib/terraspace/cloud/plan.rb
659
+ - lib/terraspace/cloud/stream.rb
660
+ - lib/terraspace/cloud/streamer.rb
667
661
  - lib/terraspace/cloud/update.rb
662
+ - lib/terraspace/cloud/upload.rb
663
+ - lib/terraspace/cloud/upload/base.rb
664
+ - lib/terraspace/cloud/upload/package.rb
665
+ - lib/terraspace/cloud/upload/tidy.rb
666
+ - lib/terraspace/cloud/vcs.rb
667
+ - lib/terraspace/cloud/vcs/base.rb
668
+ - lib/terraspace/cloud/vcs/ci_env.rb
669
+ - lib/terraspace/cloud/vcs/commenter.rb
670
+ - lib/terraspace/cloud/vcs/interface.rb
671
+ - lib/terraspace/cloud/vcs/local_env.rb
672
+ - lib/terraspace/cloud/vcs/local_git.rb
673
+ - lib/terraspace/cloud/vcs/local_git/base.rb
674
+ - lib/terraspace/cloud/vcs/local_git/bitbucket.rb
675
+ - lib/terraspace/cloud/vcs/local_git/github.rb
676
+ - lib/terraspace/cloud/vcs/local_git/gitlab.rb
668
677
  - lib/terraspace/command.rb
669
678
  - lib/terraspace/compiler/basename.rb
670
679
  - lib/terraspace/compiler/cleaner.rb
@@ -773,13 +782,6 @@ files:
773
782
  - lib/terraspace/terraform/args/pass.rb
774
783
  - lib/terraspace/terraform/args/shorthands.rb
775
784
  - lib/terraspace/terraform/args/thor.rb
776
- - lib/terraspace/terraform/ihooks/after/apply.rb
777
- - lib/terraspace/terraform/ihooks/after/destroy.rb
778
- - lib/terraspace/terraform/ihooks/after/plan.rb
779
- - lib/terraspace/terraform/ihooks/base.rb
780
- - lib/terraspace/terraform/ihooks/before/apply.rb
781
- - lib/terraspace/terraform/ihooks/before/destroy.rb
782
- - lib/terraspace/terraform/ihooks/before/plan.rb
783
785
  - lib/terraspace/terraform/remote_state/fetcher.rb
784
786
  - lib/terraspace/terraform/remote_state/marker/output.rb
785
787
  - lib/terraspace/terraform/remote_state/marker/pretty_tracer.rb
@@ -802,6 +804,7 @@ files:
802
804
  - lib/terraspace/tester/meta.rb
803
805
  - lib/terraspace/util.rb
804
806
  - lib/terraspace/util/logging.rb
807
+ - lib/terraspace/util/popen.rb
805
808
  - lib/terraspace/util/pretty.rb
806
809
  - lib/terraspace/util/sure.rb
807
810
  - lib/terraspace/version.rb