terraspace 0.2.2 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/README.md +34 -13
- data/lib/templates/base/git_hook/hook.sh +1 -1
- data/lib/templates/base/project/.gitignore +1 -0
- data/lib/templates/base/project/README.md +17 -0
- data/lib/terraspace.rb +4 -0
- data/lib/terraspace/all/base.rb +8 -0
- data/lib/terraspace/all/grapher.rb +129 -0
- data/lib/terraspace/all/preview.rb +43 -0
- data/lib/terraspace/all/runner.rb +169 -0
- data/lib/terraspace/all/summary.rb +99 -0
- data/lib/terraspace/app.rb +32 -9
- data/lib/terraspace/booter.rb +9 -0
- data/lib/terraspace/builder.rb +67 -20
- data/lib/terraspace/cli.rb +39 -12
- data/lib/terraspace/cli/all.rb +63 -0
- data/lib/terraspace/cli/build/placeholder.rb +2 -5
- data/lib/terraspace/cli/bundle.rb +1 -1
- data/lib/terraspace/cli/check_setup.rb +17 -5
- data/lib/terraspace/cli/cloud.rb +19 -3
- data/lib/terraspace/cli/cloud/runs.rb +24 -0
- data/lib/terraspace/cli/commander.rb +1 -8
- data/lib/terraspace/cli/down.rb +20 -0
- data/lib/terraspace/cli/help/cloud/runs/list.md +36 -0
- data/lib/terraspace/cli/help/cloud/runs/prune.md +25 -0
- data/lib/terraspace/cli/help/cloud/sync.md +19 -0
- data/lib/terraspace/cli/help/log.md +42 -0
- data/lib/terraspace/cli/init.rb +35 -7
- data/lib/terraspace/cli/list.rb +14 -1
- data/lib/terraspace/cli/log.rb +112 -0
- data/lib/terraspace/cli/log/concern.rb +24 -0
- data/lib/terraspace/cli/logs.rb +15 -0
- data/lib/terraspace/cli/logs/tasks.rb +32 -0
- data/lib/terraspace/cli/new/git_hook.rb +1 -1
- data/lib/terraspace/cli/tfc_concern.rb +14 -0
- data/lib/terraspace/cli/up.rb +32 -0
- data/lib/terraspace/compiler/builder.rb +3 -3
- data/lib/terraspace/compiler/cleaner.rb +1 -1
- data/lib/terraspace/compiler/cleaner/backend_change.rb +21 -7
- data/lib/terraspace/compiler/dirs_concern.rb +47 -0
- data/lib/terraspace/compiler/dsl/syntax/helpers/common.rb +26 -1
- data/lib/terraspace/core.rb +11 -2
- data/lib/terraspace/dependency/graph.rb +139 -0
- data/lib/terraspace/dependency/node.rb +38 -0
- data/lib/terraspace/dependency/registry.rb +11 -0
- data/lib/terraspace/logger.rb +6 -18
- data/lib/terraspace/logger/formatter.rb +13 -0
- data/lib/terraspace/mod.rb +7 -1
- data/lib/terraspace/seeder/where.rb +6 -2
- data/lib/terraspace/shell.rb +79 -0
- data/lib/terraspace/terraform/api.rb +7 -45
- data/lib/terraspace/terraform/api/base.rb +7 -0
- data/lib/terraspace/terraform/api/client.rb +23 -3
- data/lib/terraspace/terraform/api/http.rb +14 -34
- data/lib/terraspace/terraform/api/http/concern.rb +10 -0
- data/lib/terraspace/terraform/api/runs.rb +28 -0
- data/lib/terraspace/terraform/api/token.rb +65 -0
- data/lib/terraspace/terraform/api/var.rb +20 -6
- data/lib/terraspace/terraform/api/vars.rb +2 -1
- data/lib/terraspace/terraform/api/workspace.rb +98 -0
- data/lib/terraspace/terraform/args/default.rb +48 -21
- data/lib/terraspace/terraform/cloud/runs.rb +13 -0
- data/lib/terraspace/terraform/cloud/runs/base.rb +33 -0
- data/lib/terraspace/terraform/cloud/runs/item_presenter.rb +37 -0
- data/lib/terraspace/terraform/cloud/runs/lister.rb +22 -0
- data/lib/terraspace/terraform/cloud/runs/pruner.rb +109 -0
- data/lib/terraspace/terraform/cloud/sync.rb +41 -0
- data/lib/terraspace/terraform/cloud/syncer.rb +52 -0
- data/lib/terraspace/terraform/cloud/workspace.rb +10 -21
- data/lib/terraspace/terraform/hooks/builder.rb +1 -1
- data/lib/terraspace/terraform/remote_state/fetcher.rb +122 -0
- data/lib/terraspace/terraform/remote_state/marker/output.rb +39 -0
- data/lib/terraspace/terraform/remote_state/marker/pretty_tracer.rb +37 -0
- data/lib/terraspace/terraform/remote_state/output_proxy.rb +29 -0
- data/lib/terraspace/terraform/runner.rb +24 -14
- data/lib/terraspace/util.rb +1 -5
- data/lib/terraspace/util/pretty.rb +18 -0
- data/lib/terraspace/version.rb +1 -1
- data/spec/fixtures/fetcher/c1.json +37 -0
- data/spec/fixtures/parser/cache_dirs/all/01-test.auto.tfvars +5 -0
- data/spec/fixtures/parser/cache_dirs/depends_on/01-test.auto.tfvars +2 -0
- data/spec/fixtures/parser/cache_dirs/output/01-test.auto.tfvars +2 -0
- data/spec/fixtures/summary/down.log +12 -0
- data/spec/fixtures/summary/output.log +5 -0
- data/spec/fixtures/summary/plan/error.log +20 -0
- data/spec/fixtures/summary/plan/success.log +17 -0
- data/spec/fixtures/summary/show.log +22 -0
- data/spec/fixtures/summary/up/error.log +13 -0
- data/spec/fixtures/summary/up/success.log +63 -0
- data/spec/fixtures/summary/validate/error.log +13 -0
- data/spec/fixtures/summary/validate/success.log +5 -0
- data/spec/terraspace/all/grapher_spec.rb +38 -0
- data/spec/terraspace/all/runner_spec.rb +48 -0
- data/spec/terraspace/all/summary_spec.rb +93 -0
- data/spec/terraspace/dependency/graph_spec.rb +162 -0
- data/spec/terraspace/seeder_spec.rb +0 -1
- data/spec/terraspace/terraform/remote_state/fetcher_spec.rb +52 -0
- data/terraspace.gemspec +5 -1
- metadata +137 -5
- data/lib/terraspace/terraform/cloud.rb +0 -25
- data/lib/terraspace/util/sh.rb +0 -19
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'cli-format'
|
2
|
+
|
3
|
+
class Terraspace::Terraform::Cloud::Runs
|
4
|
+
class Lister < Base
|
5
|
+
def run
|
6
|
+
build_project
|
7
|
+
if runs.empty?
|
8
|
+
logger.info "No runs found"
|
9
|
+
return
|
10
|
+
end
|
11
|
+
|
12
|
+
presenter = CliFormat::Presenter.new(@options)
|
13
|
+
presenter.header = ["Id", "Status", "Message", "Created At"]
|
14
|
+
runs.each do |item|
|
15
|
+
p = ItemPresenter.new(item)
|
16
|
+
row = [p.id, p.status, p.message, p.created_at]
|
17
|
+
presenter.rows << row
|
18
|
+
end
|
19
|
+
presenter.show
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
class Terraspace::Terraform::Cloud::Runs
|
2
|
+
class Pruner < Base
|
3
|
+
include Terraspace::Terraform::Api::Client
|
4
|
+
|
5
|
+
# @mod required for Api::Client
|
6
|
+
def initialize(mod, options={})
|
7
|
+
super
|
8
|
+
@queue, @kept, @needs_pruning = [], nil, false
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
build_project
|
13
|
+
build_queue
|
14
|
+
are_you_sure?
|
15
|
+
process_queue
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def build_queue
|
20
|
+
runs.each do |item|
|
21
|
+
next unless actionable?(item)
|
22
|
+
unless @kept
|
23
|
+
@kept = item
|
24
|
+
next
|
25
|
+
end
|
26
|
+
queue(item)
|
27
|
+
@needs_pruning = true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def are_you_sure?
|
32
|
+
unless @needs_pruning
|
33
|
+
logger.info "Nothing to prune"
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
keeping = item_message(@kept)
|
38
|
+
items = @queue.map { |i| item_message(i) }.join("\n")
|
39
|
+
message =<<~EOL
|
40
|
+
Will keep:
|
41
|
+
|
42
|
+
#{keeping}
|
43
|
+
|
44
|
+
Will prune:
|
45
|
+
|
46
|
+
#{items}
|
47
|
+
|
48
|
+
Are you sure?
|
49
|
+
EOL
|
50
|
+
sure?(message.chop)
|
51
|
+
end
|
52
|
+
|
53
|
+
def item_message(item)
|
54
|
+
p = ItemPresenter.new(item)
|
55
|
+
" #{p.id} #{p.status} #{p.message} #{p.created_at}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def process_queue
|
59
|
+
@queue.each do |item|
|
60
|
+
process(item)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def process(item)
|
65
|
+
id = item['id']
|
66
|
+
action = discardable?(item) ? "Discarded" : "Cancelled"
|
67
|
+
p = ItemPresenter.new(item)
|
68
|
+
msg = "#{action} #{p.id} #{p.message}" # note id is named run-xxx
|
69
|
+
logger.info("NOOP: #{msg}") && return if @options[:noop]
|
70
|
+
|
71
|
+
if discardable?(item)
|
72
|
+
api.runs.discard(id)
|
73
|
+
elsif cancelable?(item)
|
74
|
+
api.runs.cancel(id)
|
75
|
+
end
|
76
|
+
logger.info msg
|
77
|
+
end
|
78
|
+
|
79
|
+
def queue(item)
|
80
|
+
if discardable?(item)
|
81
|
+
@queue << item
|
82
|
+
elsif cancelable?(item)
|
83
|
+
@queue << item
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Docs seem to be off: https://www.terraform.io/docs/cloud/api/run.html#apply-a-run
|
88
|
+
#
|
89
|
+
# This includes runs in the "pending," "needs confirmation," "policy checked," and "policy override" states.
|
90
|
+
#
|
91
|
+
# Cant really discard a "pending" status, but can discard a "planned" status.
|
92
|
+
#
|
93
|
+
def actionable?(item)
|
94
|
+
discardable?(item) || cancelable?(item)
|
95
|
+
end
|
96
|
+
|
97
|
+
def discardable?(item)
|
98
|
+
%w[planned].include?(status(item))
|
99
|
+
end
|
100
|
+
|
101
|
+
def cancelable?(item)
|
102
|
+
%w[pending].include?(status(item))
|
103
|
+
end
|
104
|
+
|
105
|
+
def status(item)
|
106
|
+
item['attributes']['status']
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Terraspace::Terraform::Cloud
|
2
|
+
class Sync < Terraspace::CLI::Base
|
3
|
+
extend Memoist
|
4
|
+
include Terraspace::Terraform::Api::Client
|
5
|
+
|
6
|
+
# Note about why workspace.create is called:
|
7
|
+
#
|
8
|
+
# CLI::Init#run
|
9
|
+
# init => runs `terraform init`
|
10
|
+
# build_remote_dependencies
|
11
|
+
# sync_cloud => leads to create_workspace
|
12
|
+
#
|
13
|
+
# The `terraform init` will auto-create the TFC workspace
|
14
|
+
# If there is a .terraform folder the config.init.mode == "auto" though,
|
15
|
+
# then the workspace won't be created.
|
16
|
+
# So we check and create the workspace if necessary.
|
17
|
+
def run
|
18
|
+
# Note: workspace still gets created by `terraform init` However, variables wont be sync if returns early
|
19
|
+
return unless Terraspace.config.cloud.auto_sync || @options[:override_auto_sync]
|
20
|
+
return unless workspaces_backend?
|
21
|
+
logger.info "Syncing to Terraform Cloud: #{@mod.name} => #{workspace_name}"
|
22
|
+
@api = Terraspace::Terraform::Api.new(@mod, remote)
|
23
|
+
workspace.create_or_update
|
24
|
+
workspace.set_working_dir
|
25
|
+
workspace.set_env_vars
|
26
|
+
end
|
27
|
+
|
28
|
+
def workspace
|
29
|
+
@api.workspace
|
30
|
+
end
|
31
|
+
|
32
|
+
def workspaces_backend?
|
33
|
+
remote && remote['workspaces']
|
34
|
+
end
|
35
|
+
|
36
|
+
# already memoized in Api::Client
|
37
|
+
def backend
|
38
|
+
Terraspace::Compiler::Backend::Parser.new(@mod).result
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Terraspace::Terraform::Cloud
|
2
|
+
class Syncer < Terraspace::CLI::Base
|
3
|
+
extend Memoist
|
4
|
+
include Terraspace::Compiler::DirsConcern
|
5
|
+
include Terraspace::Util::Sure
|
6
|
+
|
7
|
+
def run
|
8
|
+
are_you_sure?
|
9
|
+
mods.each do |mod|
|
10
|
+
run_sync(mod)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def mods
|
15
|
+
mod = @options[:mod]
|
16
|
+
mod ? [mod] : stack_names
|
17
|
+
end
|
18
|
+
|
19
|
+
def run_sync(mod)
|
20
|
+
sync(mod).run
|
21
|
+
end
|
22
|
+
|
23
|
+
def sync(mod)
|
24
|
+
Sync.new(@options.merge(mod: mod))
|
25
|
+
end
|
26
|
+
memoize :sync
|
27
|
+
|
28
|
+
def are_you_sure?
|
29
|
+
message =<<~EOL
|
30
|
+
About to sync these project stacks with Terraform Cloud workspaces:
|
31
|
+
|
32
|
+
Stack => Workspace
|
33
|
+
EOL
|
34
|
+
|
35
|
+
mods.each do |mod|
|
36
|
+
sync = sync(mod)
|
37
|
+
message << " #{mod} => #{sync.workspace_name}\n"
|
38
|
+
end
|
39
|
+
message << <<~EOL
|
40
|
+
|
41
|
+
A sync does the following for each workspace:
|
42
|
+
|
43
|
+
1. Create or update workspace, including the VCS settings.
|
44
|
+
2. Set the working dir.
|
45
|
+
3. Set env and terraform variables.
|
46
|
+
|
47
|
+
Are you sure?
|
48
|
+
EOL
|
49
|
+
sure?(message.chop)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,8 +1,9 @@
|
|
1
|
-
|
1
|
+
module Terraspace::Terraform::Cloud
|
2
2
|
class Workspace < Terraspace::CLI::Base
|
3
3
|
extend Memoist
|
4
4
|
include Terraspace::Util::Logging
|
5
5
|
include Terraspace::Terraform::Api::Client
|
6
|
+
include Terraspace::Terraform::Api::Http::Concern
|
6
7
|
|
7
8
|
# List will not have @mod set.
|
8
9
|
def list
|
@@ -32,10 +33,15 @@ class Terraspace::Terraform::Cloud
|
|
32
33
|
Terraspace::CLI::Init.new(@options.merge(calling_command: "cloud-setup")).run
|
33
34
|
end
|
34
35
|
|
36
|
+
def create
|
37
|
+
build
|
38
|
+
return unless api
|
39
|
+
api.workspace.create
|
40
|
+
end
|
41
|
+
|
35
42
|
def destroy
|
36
43
|
build
|
37
|
-
return unless
|
38
|
-
api = Terraspace::Terraform::Api.new(@mod, remote)
|
44
|
+
return unless api
|
39
45
|
workspace = api.workspace(exit_on_fail: false)
|
40
46
|
unless workspace
|
41
47
|
logger.info "Workspace #{workspace_name} not found for #{@mod.type}: #{@mod.name}"
|
@@ -43,25 +49,8 @@ class Terraspace::Terraform::Cloud
|
|
43
49
|
end
|
44
50
|
sure?
|
45
51
|
logger.info "Destroying workspace #{workspace_name}"
|
46
|
-
api.
|
47
|
-
end
|
48
|
-
|
49
|
-
def build
|
50
|
-
Terraspace::Builder.new(@options).run
|
51
|
-
end
|
52
|
-
|
53
|
-
def workspace_name
|
54
|
-
remote['workspaces']['name']
|
55
|
-
end
|
56
|
-
|
57
|
-
def remote
|
58
|
-
backend["remote"]
|
59
|
-
end
|
60
|
-
|
61
|
-
def backend
|
62
|
-
Terraspace::Compiler::Backend::Parser.new(@mod).result
|
52
|
+
api.workspace.destroy
|
63
53
|
end
|
64
|
-
memoize :backend
|
65
54
|
|
66
55
|
def sure?
|
67
56
|
message = <<~EOL.chop + " " # chop to remove newline
|
@@ -34,7 +34,7 @@ module Terraspace::Terraform::Hooks
|
|
34
34
|
exit_on_fail = exit_on_fail.nil? ? true : exit_on_fail
|
35
35
|
|
36
36
|
logger.info "Running #{type} hook"
|
37
|
-
|
37
|
+
Terraspace::Shell.new(@mod, execute, exit_on_fail: exit_on_fail).run
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module Terraspace::Terraform::RemoteState
|
2
|
+
class Fetcher
|
3
|
+
extend Memoist
|
4
|
+
include Terraspace::Util::Logging
|
5
|
+
|
6
|
+
def initialize(parent, identifier, options={})
|
7
|
+
@parent, @identifier, @options = parent, identifier, options
|
8
|
+
child_name, @output_key = identifier.split('.')
|
9
|
+
@child = Terraspace::Mod.new(child_name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
validate!
|
14
|
+
pull
|
15
|
+
load
|
16
|
+
end
|
17
|
+
|
18
|
+
def output
|
19
|
+
run
|
20
|
+
if pull_success?
|
21
|
+
value = output_value
|
22
|
+
error = output_error(:key_not_found) unless @outputs.key?(@output_key)
|
23
|
+
OutputProxy.new(value, @options.merge(error: error))
|
24
|
+
else
|
25
|
+
error = output_error(:state_not_found)
|
26
|
+
OutputProxy.new(nil, @options.merge(error: error))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def output_value
|
31
|
+
return unless @outputs.key?(@output_key)
|
32
|
+
result = @outputs.dig(@output_key)
|
33
|
+
result.dig("value") if result
|
34
|
+
end
|
35
|
+
|
36
|
+
def output_error(type)
|
37
|
+
msg = case type
|
38
|
+
when :key_not_found
|
39
|
+
"Output #{@output_key} was not found for the #{@parent.name} tfvars file. Either #{@child.name} stack has not been deployed yet or it does not have this output: #{@output_key}"
|
40
|
+
when :state_not_found
|
41
|
+
"Output #{@output_key} could not be looked up for the #{@parent.name} tfvars file. #{@child.name} stack needs to be deployed"
|
42
|
+
end
|
43
|
+
msg = "(#{msg})"
|
44
|
+
log_message(msg)
|
45
|
+
msg
|
46
|
+
end
|
47
|
+
|
48
|
+
@@pull_successes = {}
|
49
|
+
@@download_shown = false
|
50
|
+
def pull
|
51
|
+
return if @@pull_successes[cache_key]
|
52
|
+
logger.info "Downloading tfstate files for dependencies defined in tfvars..." unless @@download_shown || @options[:quiet]
|
53
|
+
@@download_shown = true
|
54
|
+
logger.debug "Downloading tfstate for stack: #{@child.name}"
|
55
|
+
Terraspace::CLI::Init.new(mod: @child.name, calling_command: "apply", quiet: true).init # init not run, so only init
|
56
|
+
FileUtils.mkdir_p(File.dirname(state_path))
|
57
|
+
command = "cd #{@child.cache_dir} && terraform state pull > #{state_path}"
|
58
|
+
logger.debug "=> #{command}"
|
59
|
+
success = system(command)
|
60
|
+
# Can error if using a old terraform version and the statefile was created with a newer version of terraform
|
61
|
+
# IE: Failed to refresh state: state snapshot was created by Terraform v0.13.2, which is newer than current v0.12.29;
|
62
|
+
# upgrade to Terraform v0.13.2 or greater to work with this state
|
63
|
+
unless success
|
64
|
+
logger.info "Error running: #{command}".color(:red)
|
65
|
+
logger.info "Please fix the error before continuing"
|
66
|
+
end
|
67
|
+
@@pull_successes[cache_key] = success
|
68
|
+
end
|
69
|
+
|
70
|
+
def load
|
71
|
+
return self unless pull_success?
|
72
|
+
|
73
|
+
# use or set cache
|
74
|
+
if @@cache[cache_key]
|
75
|
+
@outputs = @@cache[cache_key]
|
76
|
+
else
|
77
|
+
@outputs = @@cache[cache_key] = read_statefile_outputs
|
78
|
+
end
|
79
|
+
|
80
|
+
self
|
81
|
+
end
|
82
|
+
memoize :load
|
83
|
+
|
84
|
+
def cache_key
|
85
|
+
@child.name
|
86
|
+
end
|
87
|
+
|
88
|
+
def read_statefile_outputs
|
89
|
+
data = JSON.load(IO.read(state_path))
|
90
|
+
data ? data['outputs'] : {}
|
91
|
+
end
|
92
|
+
|
93
|
+
def pull_success?
|
94
|
+
@@pull_successes[cache_key]
|
95
|
+
end
|
96
|
+
|
97
|
+
def state_path
|
98
|
+
"#{Terraspace.tmp_root}/remote_state/#{@child.build_dir}/state.json"
|
99
|
+
end
|
100
|
+
|
101
|
+
# Note we already validate mod exist at the terraform_output helper. This is just in case that logic changes.
|
102
|
+
def validate!
|
103
|
+
return if @child.exist?
|
104
|
+
logger.error "ERROR: stack #{@child.name} not found".color(:red)
|
105
|
+
exit 1
|
106
|
+
end
|
107
|
+
|
108
|
+
# Using debug level because all the tfvar files always get evaluated.
|
109
|
+
# So dont want these messages to show up and be noisy unless debugging.
|
110
|
+
def log_message(msg)
|
111
|
+
logger.debug "DEBUG: #{msg}".color(:yellow)
|
112
|
+
end
|
113
|
+
|
114
|
+
cattr_accessor :cache, default: {}
|
115
|
+
class << self
|
116
|
+
def flush!
|
117
|
+
@@pull_successes = {}
|
118
|
+
@@cache = {}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Terraspace::Terraform::RemoteState::Marker
|
2
|
+
class Output
|
3
|
+
include Terraspace::Util::Logging
|
4
|
+
|
5
|
+
def initialize(mod, identifier, options={})
|
6
|
+
@mod, @identifier, @options = mod, identifier, options
|
7
|
+
@parent_name = @mod.name
|
8
|
+
@child_name, @output_key = @identifier.split('.')
|
9
|
+
end
|
10
|
+
|
11
|
+
def build
|
12
|
+
if valid?
|
13
|
+
Terraspace::Dependency::Registry.register(@parent_name, @child_name)
|
14
|
+
else
|
15
|
+
warning
|
16
|
+
end
|
17
|
+
# MARKER for debugging. Only appears on 1st pass. Will not see unless changing Terraspace code for debugging.
|
18
|
+
marker = "MARKER:terraform_output('#{@identifier}')"
|
19
|
+
Terraspace::Terraform::RemoteState::OutputProxy.new(marker, @options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid?
|
23
|
+
self.class.stack_names.include?(@child_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def warning
|
27
|
+
logger.warn "WARN: The #{@child_name} stack does not exist".color(:yellow)
|
28
|
+
caller_line = caller.find { |l| l.include?('.tfvars') }
|
29
|
+
source_code = PrettyTracer.new(caller_line).source_code
|
30
|
+
logger.info source_code
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
extend Memoist
|
35
|
+
# Marker::Output uses DirsConcern stack_names to check if stacks are valid
|
36
|
+
include Terraspace::Compiler::DirsConcern
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|