terraspace 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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