terraspace 0.2.3 → 0.3.3
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 +14 -1
- 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 +5 -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 +31 -9
- data/lib/terraspace/booter.rb +9 -0
- data/lib/terraspace/builder.rb +59 -22
- 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 +18 -2
- 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 +46 -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/backend.rb +10 -0
- data/lib/terraspace/compiler/builder.rb +5 -4
- data/lib/terraspace/compiler/cleaner.rb +1 -1
- data/lib/terraspace/compiler/cleaner/backend_change.rb +21 -7
- data/lib/terraspace/compiler/commands_concern.rb +18 -0
- 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 +97 -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 +143 -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 +138 -5
- data/lib/terraspace/terraform/cloud.rb +0 -25
- data/lib/terraspace/util/sh.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4501185815eeebafbdadd49e8afac52af4fc1c6b8d6d297269614482a38df47
|
4
|
+
data.tar.gz: b532e32f8c4a2a34e14b528649ff313041610adb7fc89349f7f97336a4c767d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8e949cadb19e163b961bebc40cc8e31bfba8e6ccefb07e28cdabb88a6cf0696a7a8a62b7f4c5f73ab1ae420c9b1956f38d2916f65ad0bfae3ee4e64ba885de5
|
7
|
+
data.tar.gz: 0f0ef1edc6432743dc6f3535449c880615057038a4e097ca03227660d7dd39270da8186675c26315f86636344635017d16f4c60fef580dfb6188bd0c785e92ab
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,37 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
|
5
5
|
|
6
|
+
## [0.3.3]
|
7
|
+
* #41 fix `terraspace build` and `terraspace seed` when bucket doesnt exist yet and there are dependenices defined.
|
8
|
+
|
9
|
+
## [0.3.2]
|
10
|
+
* #40 fix backend auto creation
|
11
|
+
|
12
|
+
## [0.3.1]
|
13
|
+
* #39 fix backend auto creation
|
14
|
+
|
15
|
+
## [0.3.0]
|
16
|
+
* All commands: Dependency graph calculated and deployed in proper order
|
17
|
+
* All commands: `terraspace all up`, `terraspace all build`, `terraspace all down`, etc. `terraspace all -h`
|
18
|
+
* Terraspace log: view and tail log files
|
19
|
+
* Terraspace logs management commands: `terraspace logs truncate` and `terraspace logs remove`
|
20
|
+
* TFC/TFE: Improve support. `config.cloud.vars`, `config.cloud.workspace.attrs`
|
21
|
+
* TFC commands: terraspace cloud runs list, terraspace cloud runs prune
|
22
|
+
* TFC VCS also sync as part of deploy. Also separate `terraspace cloud sync` command
|
23
|
+
* Logger improvements: configurable formatter, log to stderr by default
|
24
|
+
* Rename: `cloud.relative_root` to `cloud.working_dir_prefix`
|
25
|
+
* Run a plan to capture the diff as part of `-y` option. IE: `terraspace up demo -y`
|
26
|
+
* Run plan -destroy as part of down -y
|
27
|
+
* Rename update cli to up. Only support the shorthand.
|
28
|
+
* Config options: config.all.concurrency, config.all.exit_on_fail, etc
|
29
|
+
* TFC: cloud.auto_sync option
|
30
|
+
* Improve terraform version check
|
31
|
+
* Terraform init: auto mode will retry initializing up to 3 times
|
32
|
+
* Terraspace seed: fix instance option
|
33
|
+
|
34
|
+
## [0.2.4]
|
35
|
+
* fix version check for some versions of terraform
|
36
|
+
|
6
37
|
## [0.2.3]
|
7
38
|
* #37 config.clean_cache option
|
8
39
|
|
data/README.md
CHANGED
@@ -71,13 +71,26 @@ Destroy infrastructure:
|
|
71
71
|
Destroy complete! Resources: 2 destroyed.
|
72
72
|
$
|
73
73
|
|
74
|
+
## Deploy Multiple Stacks
|
75
|
+
|
76
|
+
To deploy all the infrastructure stacks:
|
77
|
+
|
78
|
+
terraspace all up
|
79
|
+
|
80
|
+
To choose multiple stacks to deploy
|
81
|
+
|
82
|
+
terraspace all up instance vpc
|
83
|
+
|
84
|
+
When you use the all command, the dependency graph is calculated and the stacks are deployed in the right order. To learn more: [Deploy Multiple Stacks](https://terraspace.cloud/docs/dependencies/deploy-all/).
|
85
|
+
|
74
86
|
## Features
|
75
87
|
|
76
88
|
* [Config Structure](https://terraspace.cloud/docs/config/): A common config structure that gets materializes with the deployed module. Configs can be dynamically controlled to keep your code DRY. You can override the settings if needed, like for using existing backends. See: [Existing Backends](https://terraspace.cloud/docs/state/existing/).
|
77
89
|
* [Generators](https://terraspace.cloud/docs/generators/): Built-in generators to quickly create the starter module. Focus on code instead of boilerplate structure.
|
78
90
|
* [Tfvars](https://terraspace.cloud/docs/tfvars/) & [Layering](https://terraspace.cloud/docs/tfvars/layering/): Use the same code with different tfvars to create multiple environments. Terraspace conventionally loads tfvars from the `tfvars` folder. Rich layering support allows you to build different environments like dev and prod with the same code. Examples are in [Full Layering](https://terraspace.cloud/docs/tfvars/full-layering/).
|
79
|
-
* [
|
91
|
+
* [Deploy Multiple Stacks](https://terraspace.cloud/docs/intro/deploy-all/): The ability to deploy multiple stacks with a single command. Terraspace calculates the [dependency graph](https://terraspace.cloud/docs/dependencies/) and deploys stacks in the right order. You can also target specific stacks and deploy [subgraphs](https://terraspace.cloud/docs/dependencies/subgraphs/).
|
80
92
|
* [Configurable CLI](https://terraspace.cloud/docs/cli/): Configurable [CLI Hooks](https://terraspace.cloud/docs/cli/hooks/) and [CLI Args](https://terraspace.cloud/docs/cli/args/) allow you to adjust the underlying terraform command.
|
93
|
+
* [Testing](https://terraspace.cloud/docs/testing/): A testing framework that allows you to create test harnesses, deploy real-resources, and have higher confidence that your code works.
|
81
94
|
* [Terraform Cloud and Terraform Enterprise Support](https://terraspace.cloud/docs/cloud/): TFC and TFE are both supported. Terraspace adds additional conveniences to make working with Terraform Cloud Workspaces easier.
|
82
95
|
|
83
96
|
For more info: [terraspace.cloud](https://terraspace.cloud)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Terraspace Project
|
2
|
+
|
3
|
+
This is a Terraspace project. It contains code to provision Cloud infrastructure built with [Terraform](https://www.terraform.io/) and the [Terraspace Framework](https://terraspace.cloud/).
|
4
|
+
|
5
|
+
## Deploy
|
6
|
+
|
7
|
+
To deploy all the infrastructure stacks:
|
8
|
+
|
9
|
+
terraspace all up
|
10
|
+
|
11
|
+
To deploy individual stacks:
|
12
|
+
|
13
|
+
terraspace up demo # where demo is app/stacks/demo
|
14
|
+
|
15
|
+
## Terrafile
|
16
|
+
|
17
|
+
To add more modules for use, you can add them to the [Terrafile](https://terraspace.cloud/docs/terrafile/).
|
data/lib/terraspace.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
$stdout.sync = true unless ENV["TS_STDOUT_SYNC"] == "0"
|
2
2
|
|
3
3
|
$:.unshift(File.expand_path("../", __FILE__))
|
4
|
+
require "active_support/concern"
|
4
5
|
require "active_support/core_ext/class"
|
5
6
|
require "active_support/core_ext/hash"
|
6
7
|
require "active_support/core_ext/string"
|
7
8
|
require "active_support/ordered_options"
|
9
|
+
require "deep_merge/rails_compat"
|
8
10
|
require "dsl_evaluator"
|
9
11
|
require "fileutils"
|
10
12
|
require "json"
|
11
13
|
require "memoist"
|
12
14
|
require "rainbow/ext/string"
|
13
15
|
require "render_me_pretty"
|
16
|
+
require "set"
|
14
17
|
require "terraspace/ext"
|
15
18
|
require "terraspace/version"
|
16
19
|
|
@@ -22,6 +25,8 @@ DslEvaluator.backtrace_reject = "lib/terraspace"
|
|
22
25
|
module Terraspace
|
23
26
|
extend Core # for Terraspace.root
|
24
27
|
class Error < StandardError; end
|
28
|
+
class InitRequiredError < Error; end
|
29
|
+
class BucketNotFoundError < Error; end
|
25
30
|
end
|
26
31
|
|
27
32
|
Terraspace::Booter.boot
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require "graph"
|
2
|
+
require "tty-tree"
|
3
|
+
|
4
|
+
module Terraspace::All
|
5
|
+
class Grapher < Base
|
6
|
+
include Terraspace::Util::Logging
|
7
|
+
|
8
|
+
def run
|
9
|
+
check_graphviz!
|
10
|
+
logger.info "Building graph..."
|
11
|
+
builder = Terraspace::Builder.new(@options.merge(mod: "placeholder", quiet: true, draw_full_graph: draw_full_graph))
|
12
|
+
builder.run
|
13
|
+
graph = builder.graph
|
14
|
+
if @options[:format] == "text"
|
15
|
+
text(graph.top_nodes)
|
16
|
+
else
|
17
|
+
draw(graph.nodes)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def text(nodes)
|
22
|
+
Rainbow.enabled = false unless @options[:full]
|
23
|
+
data = build_tree_data(nodes)
|
24
|
+
Rainbow.enabled = true unless @options[:full]
|
25
|
+
tree = TTY::Tree.new(data)
|
26
|
+
logger.info tree.render
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_tree_data(nodes)
|
30
|
+
if nodes.size == 1
|
31
|
+
tree_data(nodes.first)
|
32
|
+
else
|
33
|
+
root = Terraspace::Dependency::Node.new('.')
|
34
|
+
nodes.each { |node| node.parent!(root) }
|
35
|
+
tree_data(root)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def tree_data(parent, data={})
|
40
|
+
parent_name = text_name(parent)
|
41
|
+
data[parent_name] ||= []
|
42
|
+
parent.children.each do |child|
|
43
|
+
child_name = text_name(child)
|
44
|
+
if child.children.empty? # leaf node
|
45
|
+
data[parent_name] << child_name
|
46
|
+
else
|
47
|
+
next_data = { child_name => [] }
|
48
|
+
data[parent_name] << tree_data(child, next_data)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
data
|
52
|
+
end
|
53
|
+
|
54
|
+
def text_name(node)
|
55
|
+
node.highlighted? ? node.name.bright : node.name
|
56
|
+
end
|
57
|
+
|
58
|
+
def draw(nodes)
|
59
|
+
path, filename = nil, filename() # outside block to capture value
|
60
|
+
digraph do
|
61
|
+
node_attribs << color('"#b6d7a8"') << filled << fontcolor("white")
|
62
|
+
edge_attribs << color('"#999999"') << filled
|
63
|
+
nodes.each do |parent|
|
64
|
+
if parent.highlighted?
|
65
|
+
node(parent.name)
|
66
|
+
else
|
67
|
+
node(parent.name).attributes << color('"#A4C2F4"')
|
68
|
+
end
|
69
|
+
parent.children.each do |child|
|
70
|
+
edge(parent.name, child.name)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
74
|
+
save(filename, "png")
|
75
|
+
path = "#{filename}.png"
|
76
|
+
end
|
77
|
+
|
78
|
+
logger.info "Graph saved to #{Terraspace::Util.pretty_path(path)}"
|
79
|
+
open(path)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
def draw_full_graph
|
84
|
+
if @options[:format] == "text"
|
85
|
+
@options[:full].nil? ? false : @options[:full]
|
86
|
+
else
|
87
|
+
@options[:full].nil? ? true : @options[:full]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def filename
|
93
|
+
name = "#{Terraspace.cache_root}/graph/dependencies" # dont include extension
|
94
|
+
unless ENV['TS_GRAPH_TS'] == '0'
|
95
|
+
@@timestamp ||= Time.now.utc.strftime("%Y%m%d%H%M%S")
|
96
|
+
name += "-#{@@timestamp}"
|
97
|
+
end
|
98
|
+
name
|
99
|
+
end
|
100
|
+
|
101
|
+
def open(path)
|
102
|
+
command = command("c9") || command("open")
|
103
|
+
system("#{command} #{path}") if command
|
104
|
+
end
|
105
|
+
|
106
|
+
def command(name)
|
107
|
+
name if system("type #{name} > /dev/null 2>&1") # c9 = cloud9, open = macosx
|
108
|
+
end
|
109
|
+
|
110
|
+
# Check if Graphiz is installed and prints a user friendly message if it is not installed.
|
111
|
+
def check_graphviz!
|
112
|
+
installed = system("type dot > /dev/null 2>&1") # dot is a command that is part of the graphviz package
|
113
|
+
return if installed
|
114
|
+
logger.error "ERROR: It appears that the Graphviz is not installed. Please install it to use the graph command.".color(:red)
|
115
|
+
if RUBY_PLATFORM =~ /darwin/
|
116
|
+
logger.error "You can install Graphviz with homebrew:"
|
117
|
+
logger.error " brew install graphviz"
|
118
|
+
end
|
119
|
+
logger.info <<~EOL
|
120
|
+
Also consider:
|
121
|
+
|
122
|
+
terraspace all graph --format text
|
123
|
+
|
124
|
+
Which will print out the graph in text form.
|
125
|
+
EOL
|
126
|
+
exit 1
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Terraspace::All
|
2
|
+
class Preview
|
3
|
+
extend Memoist
|
4
|
+
include Terraspace::Util::Logging
|
5
|
+
include Terraspace::Compiler::DirsConcern
|
6
|
+
|
7
|
+
def initialize(command, batches, options={})
|
8
|
+
@command, @batches, @options = command, batches, options
|
9
|
+
end
|
10
|
+
|
11
|
+
def show
|
12
|
+
logger.info header
|
13
|
+
logger.info preview
|
14
|
+
end
|
15
|
+
|
16
|
+
def header
|
17
|
+
%w[up down].include?(@command) && !@options[:yes] ? "Will run:" : "Running:"
|
18
|
+
end
|
19
|
+
|
20
|
+
def preview
|
21
|
+
i = 0
|
22
|
+
@batches.map do |batch|
|
23
|
+
i += 1
|
24
|
+
batch.map do |stack|
|
25
|
+
command = " terraspace #{@command}"
|
26
|
+
ljust = command.size + max_name_size + 1
|
27
|
+
command = "#{command} #{stack.name}"
|
28
|
+
command.ljust(ljust, ' ') + " # batch #{i}"
|
29
|
+
end
|
30
|
+
end.join("\n")
|
31
|
+
end
|
32
|
+
|
33
|
+
def max_name_size
|
34
|
+
@batches.inject(0) do |max,batch|
|
35
|
+
batch.each do |node|
|
36
|
+
max = node.name.size if node.name.size > max
|
37
|
+
end
|
38
|
+
max
|
39
|
+
end
|
40
|
+
end
|
41
|
+
memoize :max_name_size
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module Terraspace::All
|
2
|
+
class Runner < Base
|
3
|
+
include Terraspace::Util
|
4
|
+
|
5
|
+
def initialize(command, options={})
|
6
|
+
@command, @options = command, options
|
7
|
+
super(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
time_took do
|
12
|
+
@batches = build_batches
|
13
|
+
preview
|
14
|
+
are_you_sure?
|
15
|
+
deploy_batches
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def preview
|
20
|
+
Preview.new(@command, @batches, @options).show
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_batches
|
24
|
+
@batches = run_builder(quiet: false)
|
25
|
+
@batches.reverse! if @command == "down"
|
26
|
+
@batches
|
27
|
+
end
|
28
|
+
|
29
|
+
def deploy_batches
|
30
|
+
truncate_logs if ENV['TS_TRUNCATE_LOGS']
|
31
|
+
@batches.each_with_index do |batch,i|
|
32
|
+
logger.info "Batch Run #{i+1}:"
|
33
|
+
run_builder unless i == 0 # already handled by build_batches the first time
|
34
|
+
deploy_batch(batch)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Should run after each batch run. run_builder also calls replace_outputs.
|
39
|
+
# Important: rebuild from source so placeholders are in place.
|
40
|
+
def run_builder(quiet: true)
|
41
|
+
Terraspace::Builder.new(@options.merge(mod: "placeholder", quiet: quiet)).run
|
42
|
+
end
|
43
|
+
|
44
|
+
def deploy_batch(batch)
|
45
|
+
@pids = {} # stores child processes pids. map of pid to mod_name, reset this list on each batch run
|
46
|
+
concurrency = Terraspace.config.all.concurrency
|
47
|
+
batch.sort_by(&:name).each_slice(concurrency) do |slice|
|
48
|
+
slice.each do |node|
|
49
|
+
pid = fork do
|
50
|
+
run_terraspace(node.name)
|
51
|
+
end
|
52
|
+
@pids[pid] = node.name # store mod_name mapping
|
53
|
+
end
|
54
|
+
end
|
55
|
+
wait_for_child_proccess
|
56
|
+
summarize # also reports lower-level error info
|
57
|
+
report_errors # reports finall errors and possibly exit
|
58
|
+
end
|
59
|
+
|
60
|
+
def wait_for_child_proccess
|
61
|
+
@errors = [] # stores child processes pids that errored
|
62
|
+
@pids.each do |pid, _|
|
63
|
+
pid, status = Process.wait2(pid)
|
64
|
+
success = status.exitstatus == 0
|
65
|
+
@errors << pid unless success
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def report_errors
|
70
|
+
@errors.each do |pid|
|
71
|
+
mod_name = @pids[pid]
|
72
|
+
terraspace_command = terraspace_command(mod_name)
|
73
|
+
logger.error "Error running: #{terraspace_command}. Check logs and fix the error.".color(:red)
|
74
|
+
end
|
75
|
+
unless @errors.empty?
|
76
|
+
exit 2 if exit_on_fail?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Precendence:
|
81
|
+
# 1. env var
|
82
|
+
# 2. cli
|
83
|
+
# 3. config/app.rb setting
|
84
|
+
def exit_on_fail?
|
85
|
+
return false if ENV['TS_EXIT_ON_FAIL'] == '0'
|
86
|
+
if @options[:exit_on_fail].nil?
|
87
|
+
Terraspace.config.all.exit_on_fail[@command]
|
88
|
+
else
|
89
|
+
@options[:exit_on_fail]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def summarize
|
94
|
+
@pids.each do |_, mod_name|
|
95
|
+
data = {
|
96
|
+
command: @command,
|
97
|
+
log_path: log_path(mod_name),
|
98
|
+
terraspace_command: terraspace_command(mod_name),
|
99
|
+
}
|
100
|
+
Summary.new(data).run
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def run_terraspace(mod_name)
|
105
|
+
set_log_path!(mod_name)
|
106
|
+
name = command_map(@command)
|
107
|
+
o = @options.merge(mod: mod_name, yes: true, build: false, input: false)
|
108
|
+
case @command
|
109
|
+
when "up"
|
110
|
+
Terraspace::CLI::Up.new(o).run
|
111
|
+
when "down"
|
112
|
+
Terraspace::CLI::Down.new(o).run
|
113
|
+
else
|
114
|
+
Terraspace::CLI::Commander.new(name, o).run
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def set_log_path!(mod_name)
|
119
|
+
command = terraspace_command(mod_name)
|
120
|
+
path = log_path(mod_name)
|
121
|
+
pretty_path = Terraspace::Util.pretty_path(path)
|
122
|
+
logger.info "Running: #{command.bright} Logs: #{pretty_path}"
|
123
|
+
|
124
|
+
FileUtils.mkdir_p(File.dirname(path))
|
125
|
+
logger = Terraspace::Logger.new(path)
|
126
|
+
logger.level = Terraspace.config.logger.level # match the level that user configured
|
127
|
+
logger.formatter = Terraspace.config.logger.formatter # match the level that user configured
|
128
|
+
logger.progname = command
|
129
|
+
Terraspace.logger = logger
|
130
|
+
end
|
131
|
+
|
132
|
+
def log_path(mod_name)
|
133
|
+
"#{Terraspace.config.log.root}/#{@command}/#{mod_name}.log"
|
134
|
+
end
|
135
|
+
|
136
|
+
def truncate_logs
|
137
|
+
logs = Terraspace::CLI::Log::Tasks.new(mute: true)
|
138
|
+
logs.truncate
|
139
|
+
end
|
140
|
+
|
141
|
+
def terraspace_command(name)
|
142
|
+
"terraspace #{@command} #{name}"
|
143
|
+
end
|
144
|
+
|
145
|
+
def command_map(name)
|
146
|
+
map = {
|
147
|
+
up: "apply",
|
148
|
+
down: "destroy",
|
149
|
+
}.stringify_keys
|
150
|
+
map[name] || name
|
151
|
+
end
|
152
|
+
|
153
|
+
def are_you_sure?
|
154
|
+
return true unless sure_command?
|
155
|
+
sure? # from Util
|
156
|
+
end
|
157
|
+
|
158
|
+
def sure_command?
|
159
|
+
%w[up down].include?(@command)
|
160
|
+
end
|
161
|
+
|
162
|
+
def time_took
|
163
|
+
t1 = Time.now
|
164
|
+
yield
|
165
|
+
t2 = Time.now
|
166
|
+
logger.info "Time took: #{pretty_time(t2-t1)}"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|