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
@@ -16,7 +16,7 @@ module Terraspace::CLI::Build
|
|
16
16
|
return if ENV['TS_SUMMARY_BUILD'] == '0'
|
17
17
|
|
18
18
|
mod = @options[:mod]
|
19
|
-
if !mod or mod
|
19
|
+
if !mod or %w[placeholder].include?(mod)
|
20
20
|
logger.info "Building one of the modules to get backend.tf info"
|
21
21
|
mod = find_mod
|
22
22
|
end
|
@@ -28,10 +28,7 @@ module Terraspace::CLI::Build
|
|
28
28
|
def find_mod
|
29
29
|
mod_path = Dir.glob("{app,vendor}/{modules,stacks}/*").last
|
30
30
|
unless mod_path
|
31
|
-
logger.info
|
32
|
-
No modules or stacks found.
|
33
|
-
Unable to determine the backend state path without at least one module.
|
34
|
-
EOL
|
31
|
+
logger.info "No modules or stacks found."
|
35
32
|
exit 0
|
36
33
|
end
|
37
34
|
File.basename(mod_path) # mod name
|
@@ -23,17 +23,27 @@ class Terraspace::CLI
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def check_required_version!
|
26
|
-
puts "Terraspace requires Terraform v#{REQUIRED_TERRAFORM_VERSION}.x"
|
26
|
+
puts "Terraspace requires Terraform v#{REQUIRED_TERRAFORM_VERSION}.x and above"
|
27
27
|
if ok?
|
28
28
|
puts "You're all set!"
|
29
29
|
else
|
30
|
-
puts "The installed version of terraform may not work with terraspace.
|
31
|
-
|
30
|
+
puts "The installed version of terraform may not work with terraspace."
|
31
|
+
puts "Recommend using at least terraform v#{REQUIRED_TERRAFORM_VERSION}.x"
|
32
|
+
puts "If you would like to bypass this check. Use TS_VERSION_CHECK=0" unless check_command?
|
33
|
+
exit 1 unless ENV['TS_VERSION_CHECK'] == '0'
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
37
|
+
def check_command?
|
38
|
+
ARGV[0] == "check_setup"
|
39
|
+
end
|
40
|
+
|
35
41
|
def ok?
|
36
42
|
version = terraform_version_message.sub(/.*v/,'') # => 0.12.24
|
43
|
+
unless version.match(/\d+\.\d+\.\d+/) # just parse did not find the version number
|
44
|
+
puts "WARN: Unable to get the terraform version".color(:yellow)
|
45
|
+
return true
|
46
|
+
end
|
37
47
|
major, minor, _ = version.split('.')
|
38
48
|
required_major, required_minor = REQUIRED_TERRAFORM_VERSION.split('.')
|
39
49
|
x = major.to_i >= required_major.to_i
|
@@ -47,7 +57,8 @@ class Terraspace::CLI
|
|
47
57
|
end
|
48
58
|
memoize :terraform_bin
|
49
59
|
|
50
|
-
#
|
60
|
+
# Sometimes Terraform shows the version info on the first line and sometimes on the bottom line.
|
61
|
+
# Account for that by finding the line.
|
51
62
|
#
|
52
63
|
# $ terraform --version
|
53
64
|
# Terraform v0.12.24
|
@@ -55,8 +66,9 @@ class Terraspace::CLI
|
|
55
66
|
# Your version of Terraform is out of date! The latest version
|
56
67
|
# is 0.12.26. You can update by downloading from https://www.terraform.io/downloads.html
|
57
68
|
#
|
69
|
+
# Note: The -json option is only available in v0.13+
|
58
70
|
def terraform_version_message
|
59
|
-
`terraform --version`.split("\n").
|
71
|
+
`terraform --version`.split("\n").find { |l| l =~ /^Terraform / }.strip
|
60
72
|
end
|
61
73
|
memoize :terraform_version_message
|
62
74
|
|
data/lib/terraspace/cli/cloud.rb
CHANGED
@@ -1,24 +1,40 @@
|
|
1
1
|
class Terraspace::CLI
|
2
2
|
class Cloud < Terraspace::Command
|
3
|
+
Syncer = Terraspace::Terraform::Cloud::Syncer
|
3
4
|
Workspace = Terraspace::Terraform::Cloud::Workspace
|
4
5
|
|
6
|
+
yes_option = Proc.new {
|
7
|
+
option :yes, aliases: :y, type: :boolean, desc: "bypass are you sure prompt"
|
8
|
+
}
|
9
|
+
|
5
10
|
desc "list", "List workspaces"
|
6
11
|
long_desc Help.text("cloud:list")
|
12
|
+
yes_option.call
|
7
13
|
def list
|
8
14
|
Workspace.new(options).list
|
9
15
|
end
|
10
16
|
|
11
|
-
desc "destroy", "Destroy workspace"
|
17
|
+
desc "destroy STACK", "Destroy workspace by specifying the stack"
|
12
18
|
long_desc Help.text("cloud:destroy")
|
13
|
-
option :yes, aliases: :y, type: :boolean, desc: "bypass are you sure prompt"
|
14
19
|
def destroy(mod)
|
15
20
|
Workspace.new(options.merge(mod: mod)).destroy
|
16
21
|
end
|
17
22
|
|
18
|
-
desc "setup", "Setup workspace"
|
23
|
+
desc "setup STACK", "Setup workspace"
|
19
24
|
long_desc Help.text("cloud:setup")
|
20
25
|
def setup(mod)
|
21
26
|
Workspace.new(options.merge(mod: mod)).setup
|
22
27
|
end
|
28
|
+
|
29
|
+
desc "sync [STACK]", "sync workspace"
|
30
|
+
long_desc Help.text("cloud:sync")
|
31
|
+
yes_option.call
|
32
|
+
def sync(mod=nil)
|
33
|
+
Syncer.new(options.merge(mod: mod, override_auto_sync: true)).run
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "runs SUBCOMMAND", "runs subcommands"
|
37
|
+
long_desc Help.text(:runs)
|
38
|
+
subcommand "runs", Runs
|
23
39
|
end
|
24
40
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'cli-format'
|
2
|
+
|
3
|
+
class Terraspace::CLI::Cloud
|
4
|
+
class Runs < Terraspace::Command
|
5
|
+
Help = Terraspace::CLI::Help
|
6
|
+
Runs = Terraspace::Terraform::Cloud::Runs
|
7
|
+
|
8
|
+
desc "list STACK", "List runs."
|
9
|
+
long_desc Help.text("cloud:runs:list")
|
10
|
+
option :format, desc: "Output formats: #{CliFormat.formats.join(', ')}"
|
11
|
+
option :status, default: %w[pending planned], type: :array, desc: "Filter by statuses: pending, planned, all"
|
12
|
+
def list(mod)
|
13
|
+
Runs.new(options.merge(mod: mod)).list
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "prune STACK", "Prune runs that are possible to cancel or discard."
|
17
|
+
long_desc Help.text("cloud:runs:prune")
|
18
|
+
option :noop, type: :boolean, desc: "Shows what would be cancelled/discarded."
|
19
|
+
option :yes, aliases: :y, type: :boolean, desc: "bypass are you sure prompt"
|
20
|
+
def prune(mod)
|
21
|
+
Runs.new(options.merge(mod: mod)).prune
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -5,17 +5,10 @@ class Terraspace::CLI
|
|
5
5
|
super(options)
|
6
6
|
end
|
7
7
|
|
8
|
-
# Commander always runs Build#run
|
9
8
|
def run
|
10
|
-
Terraspace::Builder.new(@options).run #
|
11
|
-
auto_create_backend
|
9
|
+
Terraspace::Builder.new(@options).run unless @options[:build] # Up already ran build
|
12
10
|
Init.new(@options.merge(calling_command: @name)).run
|
13
11
|
Terraspace::Terraform::Runner.new(@name, @options).run
|
14
12
|
end
|
15
|
-
|
16
|
-
def auto_create_backend
|
17
|
-
return unless @name == "apply"
|
18
|
-
Terraspace::Compiler::Backend.new(@mod).create
|
19
|
-
end
|
20
13
|
end
|
21
14
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Terraspace::CLI
|
2
|
+
class Down < Base
|
3
|
+
include TfcConcern
|
4
|
+
|
5
|
+
def run
|
6
|
+
plan if @options[:yes] && !tfc?
|
7
|
+
destroy
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
def plan
|
12
|
+
Commander.new("plan", @options.merge(destroy: true)).run
|
13
|
+
end
|
14
|
+
|
15
|
+
def destroy
|
16
|
+
Commander.new("destroy", @options.merge(command: "down")).run
|
17
|
+
Terraspace::Terraform::Cloud::Workspace.new(@options).destroy if @options[:destroy_workspace]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
## Example
|
2
|
+
|
3
|
+
Statuses of pending and planned are shown by default.
|
4
|
+
|
5
|
+
$ terraspace cloud runs list pet
|
6
|
+
+----------------------+---------+---------------------------------+---------------------+
|
7
|
+
| Id | Status | Message | Created At |
|
8
|
+
+----------------------+---------+---------------------------------+---------------------+
|
9
|
+
| run-AuTXsYU1svQEzQVg | pending | Queued manually using Terraform | 2020-09-18T11:30:41 |
|
10
|
+
| run-LuwMibh3ebiG7KQZ | planned | test | 2020-09-17T23:16:36 |
|
11
|
+
+----------------------+---------+---------------------------------+---------------------+
|
12
|
+
$
|
13
|
+
|
14
|
+
To see all most recent runs, use `--status all`.
|
15
|
+
|
16
|
+
$ terraspace cloud runs list pet --status all
|
17
|
+
+----------------------+-----------+--------------------------------+---------------------+
|
18
|
+
| Id | Status | Message | Created At |
|
19
|
+
+----------------------+-----------+--------------------------------+---------------------+
|
20
|
+
| run-LuwMibh3ebiG7KQZ | planned | test 3 | 2020-09-17T23:16:36 |
|
21
|
+
| run-z9f67TNMRamZiGMR | canceled | test 2 | 2020-09-17T23:15:55 |
|
22
|
+
| run-cN3CKT5po29p35Ta | discarded | test | 2020-09-17T22:24:31 |
|
23
|
+
| run-rXMd7dm3fHvVsA36 | discarded | Queued from Terraform Cloud UI | 2020-09-17T20:00:20 |
|
24
|
+
+----------------------+-----------+--------------------------------+---------------------+
|
25
|
+
$
|
26
|
+
|
27
|
+
You can provide a list of statuses to the `--status` filter option.
|
28
|
+
|
29
|
+
$ terraspace cloud runs list pet --status canceled discarded
|
30
|
+
+----------------------+-----------+--------------------------------+---------------------+
|
31
|
+
| Id | Status | Message | Created At |
|
32
|
+
+----------------------+-----------+--------------------------------+---------------------+
|
33
|
+
| run-gS2m1avc3U4j1fip | canceled | test | 2020-09-17T23:15:43 |
|
34
|
+
| run-ojwQ4r7MxuzyK3d9 | discarded | test | 2020-09-17T22:33:00 |
|
35
|
+
| run-dczeLQsMc3ya4XnY | canceled | test | 2020-09-17T22:32:55 |
|
36
|
+
+----------------------+-----------+--------------------------------+---------------------+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
This leaves the to most recent run alone. The top run will immediately start planning. Runs that are also in "Needs Confirmation" will be cancelled.
|
2
|
+
|
3
|
+
## Examples
|
4
|
+
|
5
|
+
terraspace cloud runs prune demo --noop
|
6
|
+
terraspace cloud runs prune demo # live run
|
7
|
+
|
8
|
+
## Example with Output
|
9
|
+
|
10
|
+
$ terraspace cloud runs prune pet
|
11
|
+
Will keep:
|
12
|
+
|
13
|
+
run-9muMrjrd22vhsP4u pending test 2020-09-18T12:47:11
|
14
|
+
|
15
|
+
Will prune:
|
16
|
+
|
17
|
+
run-fYTDzmKfCQf558UN pending test 2020-09-18T12:46:34
|
18
|
+
run-6bgSTattJGpaRn9X pending test 2020-09-18T12:46:28
|
19
|
+
run-jDHEtZb3vuFnuXqJ planned test 2020-09-18T12:38:35
|
20
|
+
|
21
|
+
Are you sure? (y/N) y
|
22
|
+
Cancelled run-fYTDzmKfCQf558UN test
|
23
|
+
Cancelled run-6bgSTattJGpaRn9X test
|
24
|
+
Discarded run-jDHEtZb3vuFnuXqJ test
|
25
|
+
$
|
@@ -0,0 +1,19 @@
|
|
1
|
+
## Example
|
2
|
+
|
3
|
+
$ terraspace cloud sync
|
4
|
+
About to sync these project stacks with Terraform Cloud workspaces:
|
5
|
+
|
6
|
+
Stack => Workspace
|
7
|
+
demo => demo-dev-us-west-2
|
8
|
+
demo2 => demo2-dev-us-west-2
|
9
|
+
|
10
|
+
A sync does the following for each workspace:
|
11
|
+
|
12
|
+
1. Create or update workspace, including the VCS settings.
|
13
|
+
2. Set the working dir.
|
14
|
+
3. Set env and terraform variables.
|
15
|
+
|
16
|
+
Are you sure? (y/N) y
|
17
|
+
Syncing to Terraform Cloud: demo => demo-dev-us-west-2
|
18
|
+
Syncing to Terraform Cloud: demo2 => demo2-dev-us-west-2
|
19
|
+
$
|
@@ -0,0 +1,42 @@
|
|
1
|
+
The log commands will filter out the logs for the last ran terraspace command. It does this by filtering for the last found PID in the log files.
|
2
|
+
|
3
|
+
## Quick Start
|
4
|
+
|
5
|
+
Follow all the logs as you're running `terraspace all up`:
|
6
|
+
|
7
|
+
terraspace log -f
|
8
|
+
|
9
|
+
## View Logs
|
10
|
+
|
11
|
+
View last 10 lines of each log file.
|
12
|
+
|
13
|
+
terraspace log up network # view up log on specific stack
|
14
|
+
terraspace log up # view all up logs
|
15
|
+
terraspace log down # view all down logs
|
16
|
+
terraspace log # view all logs: up, down, etc
|
17
|
+
|
18
|
+
By default, the log command shows the last 10 lines of the logs for each log file. You can use the `-n` option to adjust this.
|
19
|
+
|
20
|
+
terraspace log -n 2 # view last 2 lines of all logs: up, down, etc
|
21
|
+
|
22
|
+
To show all logs, use the `-a` option.
|
23
|
+
|
24
|
+
terraspace log up -a
|
25
|
+
|
26
|
+
Note, if both an action and stack is specified, then it defaults to showing all logs. If you want to not show all logs in thta case, then you can use `--no-all`.
|
27
|
+
|
28
|
+
## Tail Logs
|
29
|
+
|
30
|
+
To tail logs, use the `-f` option.
|
31
|
+
|
32
|
+
terraspace log up network -f # view up log on specific stack
|
33
|
+
terraspace log up -f # view all up logs
|
34
|
+
terraspace log down -f # view all down logs
|
35
|
+
terraspace log -f # view all logs: up, down, etc
|
36
|
+
|
37
|
+
## Timestamps
|
38
|
+
|
39
|
+
The timestamps are shown by default when you are looking for multiple files. When you specify a both the action and stack for a single log file, then timestamps are not shown.
|
40
|
+
|
41
|
+
terraspace log up # timestamps will be shown in this case
|
42
|
+
terraspace log up network # timestamps not be shown in this case
|
data/lib/terraspace/cli/init.rb
CHANGED
@@ -10,13 +10,14 @@ class Terraspace::CLI
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def run
|
13
|
-
init
|
14
|
-
build_remote_dependencies # runs after terraform init, which downloads remote modules
|
13
|
+
init
|
14
|
+
# build_remote_dependencies # runs after terraform init, which downloads remote modules
|
15
15
|
sync_cloud
|
16
16
|
end
|
17
17
|
|
18
18
|
# Note the init will always create the Terraform Cloud Workspace
|
19
19
|
def init
|
20
|
+
return unless run_init? # check here because RemoteState::Fetcher#pull calls init directly
|
20
21
|
# default init timeout is pretty generous in case of slow internet to download the provider plugins
|
21
22
|
init_timeout = Integer(ENV['TS_INIT_TIMEOUT'] || 600)
|
22
23
|
Timeout::timeout(init_timeout) do
|
@@ -28,7 +29,7 @@ class Terraspace::CLI
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def sync_cloud
|
31
|
-
Terraspace::Terraform::Cloud.new(@options).run if %w[apply plan destroy cloud-setup].include?(@calling_command)
|
32
|
+
Terraspace::Terraform::Cloud::Sync.new(@options).run if %w[apply plan destroy cloud-setup].include?(@calling_command)
|
32
33
|
end
|
33
34
|
|
34
35
|
# Currently only handles remote modules only one-level deep.
|
@@ -47,8 +48,8 @@ class Terraspace::CLI
|
|
47
48
|
return if local_source?(meta["Source"])
|
48
49
|
return if meta['Dir'] == '.' # root is already built
|
49
50
|
|
50
|
-
remote_mod = Mod::Remote.new(meta, @mod)
|
51
|
-
Compiler::Builder.new(remote_mod).build
|
51
|
+
remote_mod = Terraspace::Mod::Remote.new(meta, @mod)
|
52
|
+
Terraspace::Compiler::Builder.new(remote_mod).build
|
52
53
|
end
|
53
54
|
|
54
55
|
def auto?
|
@@ -60,8 +61,35 @@ class Terraspace::CLI
|
|
60
61
|
s =~ %r{^\.} || s =~ %r{^/}
|
61
62
|
end
|
62
63
|
|
63
|
-
def
|
64
|
-
%w[apply console destroy output plan providers refresh show validate cloud-setup]
|
64
|
+
def run_init?
|
65
|
+
commands = %w[apply console destroy output plan providers refresh show validate cloud-setup]
|
66
|
+
return false unless commands.include?(@calling_command)
|
67
|
+
mode = ENV['TS_INIT_MODE'] || Terraspace.config.init.mode
|
68
|
+
case mode.to_sym
|
69
|
+
when :auto
|
70
|
+
!already_initialized?
|
71
|
+
when :always
|
72
|
+
true
|
73
|
+
when :never
|
74
|
+
false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Would like to improve this detection
|
79
|
+
#
|
80
|
+
# Traverse symlink dirs also: linux_amd64 is a symlink
|
81
|
+
# plugins/registry.terraform.io/hashicorp/google/3.39.0/linux_amd64/terraform-provider-google_v3.39.0_x5
|
82
|
+
#
|
83
|
+
# Check modules/modules.json also because during the tfvars dependency pass main.tf modules are not built.
|
84
|
+
# So init happens again during the second pass.
|
85
|
+
#
|
86
|
+
def already_initialized?
|
87
|
+
terraform = "#{@mod.cache_dir}/.terraform"
|
88
|
+
provider = Dir.glob("#{terraform}/**{,/*/**}/*").find do |path|
|
89
|
+
path.include?("terraform-provider-")
|
90
|
+
end
|
91
|
+
modules = File.exist?("#{terraform}/modules/modules.json")
|
92
|
+
!!(provider && modules)
|
65
93
|
end
|
66
94
|
end
|
67
95
|
end
|
data/lib/terraspace/cli/list.rb
CHANGED
@@ -2,11 +2,24 @@ class Terraspace::CLI
|
|
2
2
|
class List
|
3
3
|
def initialize(options={})
|
4
4
|
@options = options
|
5
|
+
@type_dir = normalized_type
|
5
6
|
end
|
6
7
|
|
7
8
|
def run
|
8
9
|
Dir.glob("{app,vendor}/{modules,stacks}/*").sort.each do |path|
|
9
|
-
|
10
|
+
if @type_dir
|
11
|
+
puts path if path.include?("/#{@type_dir}/")
|
12
|
+
else
|
13
|
+
puts path
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def normalized_type
|
20
|
+
type = @options[:type]
|
21
|
+
if %w[stack module].include?(type)
|
22
|
+
type.pluralize
|
10
23
|
end
|
11
24
|
end
|
12
25
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "eventmachine"
|
2
|
+
require "eventmachine-tail"
|
3
|
+
|
4
|
+
class Terraspace::CLI
|
5
|
+
class Log < Base
|
6
|
+
include Log::Concern
|
7
|
+
|
8
|
+
def initialize(options={})
|
9
|
+
super
|
10
|
+
@action, @stack = options[:action], options[:stack]
|
11
|
+
@action ||= '**'
|
12
|
+
@stack ||= '*'
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
check_logs!
|
17
|
+
if @options[:follow]
|
18
|
+
follow_logs
|
19
|
+
else
|
20
|
+
all_log_paths.each { |path| show_log(path) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def follow_logs
|
25
|
+
glob_path = "#{Terraspace.log_root}/#{@action}/#{@stack}.log"
|
26
|
+
Dir.glob(glob_path).each do |path|
|
27
|
+
puts "Following #{pretty(path)}".color(:purple)
|
28
|
+
end
|
29
|
+
EventMachine.run do
|
30
|
+
interval = Integer(ENV['TS_LOG_GLOB_INTERNAL'] || 1)
|
31
|
+
EventMachine::FileGlobWatchTail.new(glob_path, nil, interval) do |filetail, line|
|
32
|
+
puts line # always show timestamp in follow mode
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def show_log(path)
|
38
|
+
report_log(path)
|
39
|
+
lines = readlines(path)
|
40
|
+
lines = apply_limit(lines)
|
41
|
+
lines.each do |line|
|
42
|
+
puts format(line)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def report_log(path)
|
47
|
+
pretty_path = pretty(path)
|
48
|
+
if File.exist?(path)
|
49
|
+
puts "Showing: #{pretty_path}".color(:purple)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def format(line)
|
54
|
+
if timestamps
|
55
|
+
line
|
56
|
+
else
|
57
|
+
line.sub(/.*\]: /,'')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def all_log_paths
|
62
|
+
Dir.glob("#{Terraspace.log_root}/#{@action}/#{@stack}.log")
|
63
|
+
end
|
64
|
+
|
65
|
+
def check_logs!
|
66
|
+
return unless all_log_paths.empty?
|
67
|
+
puts "WARN: No logs found".color(:yellow)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Only need to check if both action and stack are provided. Otherwise the Dir.globs are used to discover the files
|
71
|
+
def check_log!
|
72
|
+
return unless single_log?
|
73
|
+
path = "#{Terraspace.log_root}/#{@action}/#{@stack}.log"
|
74
|
+
return if File.exist?(path)
|
75
|
+
puts "ERROR: Log file was not found: #{pretty(path)}".color(:red)
|
76
|
+
exit 1
|
77
|
+
end
|
78
|
+
|
79
|
+
def single_log?
|
80
|
+
@action != '**' && @stack != '*'
|
81
|
+
end
|
82
|
+
|
83
|
+
def apply_limit(lines)
|
84
|
+
return lines if all
|
85
|
+
left = limit * -1
|
86
|
+
lines[left..-1] || []
|
87
|
+
end
|
88
|
+
|
89
|
+
def all
|
90
|
+
if single_log?
|
91
|
+
@options[:all].nil? ? true : @options[:all]
|
92
|
+
else # multiple
|
93
|
+
@options[:all].nil? ? false : @options[:all]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def limit
|
98
|
+
@options[:limit].nil? ? 10 : @options[:limit]
|
99
|
+
end
|
100
|
+
|
101
|
+
def timestamps
|
102
|
+
if single_log?
|
103
|
+
@options[:timestamps].nil? ? false : @options[:timestamps]
|
104
|
+
else
|
105
|
+
@options[:timestamps].nil? ? true : @options[:timestamps]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
def pretty(path)
|
109
|
+
Terraspace::Util.pretty_path(path)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|