terraspace 0.1.2 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/lib/templates/base/git_hook/hook.sh +5 -0
- data/lib/templates/base/project/.gitignore +0 -1
- data/lib/templates/base/shim/terraspace +7 -0
- data/lib/templates/hcl/project/config/terraform/backend.tf.tt +3 -3
- data/lib/templates/plugin/lib/templates/hcl/project/config/terraform/backend.tf.tt +2 -2
- data/lib/terraspace/app.rb +6 -0
- data/lib/terraspace/builder.rb +2 -46
- data/lib/terraspace/cli.rb +34 -18
- data/lib/terraspace/cli/build/placeholder.rb +40 -0
- data/lib/terraspace/cli/cloud.rb +24 -0
- data/lib/terraspace/cli/commander.rb +8 -1
- data/lib/terraspace/cli/init.rb +67 -0
- data/lib/terraspace/cli/list.rb +13 -0
- data/lib/terraspace/cli/new.rb +8 -0
- data/lib/terraspace/cli/new/git_hook.rb +33 -0
- data/lib/terraspace/cli/new/shim.rb +58 -0
- data/lib/terraspace/cli/summary.rb +9 -12
- data/lib/terraspace/compiler/backend.rb +9 -37
- data/lib/terraspace/compiler/backend/parser.rb +42 -0
- data/lib/terraspace/compiler/builder.rb +6 -2
- data/lib/terraspace/compiler/cleaner.rb +19 -2
- data/lib/terraspace/compiler/cleaner/backend_change.rb +1 -1
- data/lib/terraspace/compiler/dsl/syntax/mod.rb +1 -0
- data/lib/terraspace/compiler/dsl/syntax/mod/backend.rb +16 -3
- data/lib/terraspace/compiler/expander.rb +28 -1
- data/lib/terraspace/compiler/writer.rb +1 -1
- data/lib/terraspace/core.rb +7 -1
- data/lib/terraspace/mod.rb +37 -12
- data/lib/terraspace/mod/remote.rb +1 -1
- data/lib/terraspace/plugin/expander/interface.rb +48 -5
- data/lib/terraspace/plugin/infer_provider.rb +15 -0
- data/lib/terraspace/plugin/layer/interface.rb +5 -0
- data/lib/terraspace/seeder.rb +4 -4
- data/lib/terraspace/terraform/api.rb +53 -0
- data/lib/terraspace/terraform/api/client.rb +10 -0
- data/lib/terraspace/terraform/api/http.rb +106 -0
- data/lib/terraspace/terraform/api/var.rb +72 -0
- data/lib/terraspace/terraform/api/vars.rb +38 -0
- data/lib/terraspace/terraform/api/vars/base.rb +7 -0
- data/lib/terraspace/terraform/api/vars/json.rb +14 -0
- data/lib/terraspace/terraform/api/vars/rb.rb +21 -0
- data/lib/terraspace/terraform/args/custom.rb +1 -1
- data/lib/terraspace/terraform/args/default.rb +16 -2
- data/lib/terraspace/terraform/cloud.rb +25 -0
- data/lib/terraspace/terraform/cloud/workspace.rb +95 -0
- data/lib/terraspace/terraform/runner.rb +1 -1
- data/lib/terraspace/util/sh.rb +1 -1
- data/lib/terraspace/version.rb +1 -1
- data/spec/fixtures/{cache_build_dir → cache_dir}/variables.tf +0 -0
- data/spec/fixtures/projects/hcl/aws/config/backend.tf +1 -1
- data/spec/fixtures/projects/hcl/google/config/backend.tf +1 -1
- data/spec/terraspace/seeder_spec.rb +1 -1
- data/spec/terraspace/terraform/hooks/builder_spec.rb +1 -1
- data/terraspace.gemspec +3 -3
- metadata +37 -17
- data/lib/terraspace/cli/build.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6cfa0c4e6aa1aa9871bc8b1902b283f2b91f5392738a066fdc58efb56153bed1
|
|
4
|
+
data.tar.gz: 2219a5bbbd4dbad228e406d7ce586cf5bfdb8392868478e59e3adbd6dc4adda5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f3bb558668074f2e278359a887e369c5182c95fd306973a9cae6c4bd7f95d9be653ce41b923e41e5470350c35234443a0ae3d4e16d5c8b35763feab9393a9c12
|
|
7
|
+
data.tar.gz: 24acaffec5e568152133e014697404cc9d80a2bd79d54b700584db93a5884ca184508544519d349e833a17f84ac1cc4f2d095a787ed5cdb5216f25b37f04fb50
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,27 @@
|
|
|
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.2.0]
|
|
7
|
+
* #34 Terraform Cloud and Terraform Enterprise support added.
|
|
8
|
+
* TFC Vars support: JSON and DSL. config.overwrite and config.overwrite_sensitive configs
|
|
9
|
+
* Build all stacks with config/terraform files. Designed to support the TFC VCS-driven workflow.
|
|
10
|
+
* Layer Interface module added. All latest provider plugins like terraspace\_plugin_aws make use of this module.
|
|
11
|
+
* Backend pattern expansion auto-detects the provider bakcend. The `expansion` method replaces the `backend_expand` method. `backend_expand` is deprecated.
|
|
12
|
+
* New expander variables: TYPE_INSTANCE, INSTANCE, CACHE_ROOT. Also added strip trailing - and / behavior.
|
|
13
|
+
* Timeout for terraform init. The default timeout is 10m and will then print out the terraform init log.
|
|
14
|
+
* Terraspace 0.2.x is compatible with terraspace\_plugin_aws 0.2.x, terraspace\_plugin_google 0.2.x, and terraspace\_plugin_azurerm 0.2.x
|
|
15
|
+
* New commands: terraspace list, terraspace cloud list, terraspace cloud setup, terraspace cloud destroy, terraspace new shim, terraspace new git_hook
|
|
16
|
+
* terraspace list: list of modules and stacks
|
|
17
|
+
* terraspace cloud list: shows list of TFC workspaces
|
|
18
|
+
* terraspace cloud setup: setups up TFC workspace for VCS-driven workflow. This automatically happens for the TFC CLI-driven workflow.
|
|
19
|
+
* terraspace cloud destroy: destroys the TFC workspace associated with the stack. Can also use the `terraspace down demo --destroy-workspace` option.
|
|
20
|
+
* terraspace new shim: An quick way to generate a terraspace shim.
|
|
21
|
+
* terraspace new git_hook: An quick way to set up a git pre-push hook for the TFC VCS-driven workflow.
|
|
22
|
+
* terraspace down: works even if there's no app/stacks folder. A fake stack is built.
|
|
23
|
+
* terraspace build: terraspace build placeholder concept.
|
|
24
|
+
* terraspace build: only builds now. auto bucket backend creation and terraform init is is still automatically called by terraform up, etc.
|
|
25
|
+
* terraspace up: --reconfigure option. This is useful if upgrading Terraform version.
|
|
26
|
+
|
|
6
27
|
## [0.1.2]
|
|
7
28
|
- #33 rspec-terraspace dependency added
|
|
8
29
|
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
# terraform {
|
|
4
4
|
# backend "s3" {
|
|
5
5
|
# bucket = "<%= options[:bucket] || "terraform-state-:ACCOUNT-:REGION-:ENV" %>"
|
|
6
|
-
# key = "<%%= "
|
|
7
|
-
# region = "<%%= "
|
|
6
|
+
# key = "<%%= expansion(":REGION/:ENV/:BUILD_DIR/terraform.tfstate") %> # IE: us-west-2/dev/ec2/modules/vpc/terraform.tfstate
|
|
7
|
+
# region = "<%%= expansion(":REGION") %>"
|
|
8
8
|
# encrypt = true
|
|
9
9
|
# dynamodb_table = "terraform_locks"
|
|
10
10
|
# }
|
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
# terraform {
|
|
14
14
|
# backend "gcs" {
|
|
15
15
|
# bucket = "<%= options[:bucket] || "terraform-state-:PROJECT-:REGION-:ENV" %>"
|
|
16
|
-
# prefix = "<%%=
|
|
16
|
+
# prefix = "<%%= expansion(":REGION/:ENV/:BUILD_DIR") %>" # IE: us-central1/dev/modules/vm
|
|
17
17
|
# }
|
|
18
18
|
# }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
terraform {
|
|
2
2
|
backend "PROVIDER_BACKEND" {
|
|
3
|
-
bucket = "<%%=
|
|
4
|
-
prefix = "<%%=
|
|
3
|
+
bucket = "<%%= expansion("terraform-state-REPLACE_ME-REPLACE_ME-:ENV") %>" # expanded by terraspace
|
|
4
|
+
prefix = "<%%= expansion("REPLACE_ME/:ENV/:BUILD_DIR") %>" # expanded by terraspace
|
|
5
5
|
}
|
|
6
6
|
}
|
data/lib/terraspace/app.rb
CHANGED
|
@@ -14,6 +14,12 @@ module Terraspace
|
|
|
14
14
|
config.logger = Logger.new($stdout)
|
|
15
15
|
config.logger.level = :info
|
|
16
16
|
config.hooks = Hooks.new
|
|
17
|
+
config.cloud = ActiveSupport::OrderedOptions.new
|
|
18
|
+
config.cloud.overwrite = true
|
|
19
|
+
config.cloud.overwrite_sensitive = true
|
|
20
|
+
config.build = ActiveSupport::OrderedOptions.new
|
|
21
|
+
config.build.cache_root = nil # defaults to .terraspace-cache
|
|
22
|
+
config.build.cache_dir = ":CACHE_ROOT/:REGION/:ENV/:BUILD_DIR"
|
|
17
23
|
config
|
|
18
24
|
end
|
|
19
25
|
|
data/lib/terraspace/builder.rb
CHANGED
|
@@ -4,24 +4,15 @@ module Terraspace
|
|
|
4
4
|
Terraspace::CLI::CheckSetup.check!
|
|
5
5
|
@mod.root_module = true
|
|
6
6
|
Compiler::Cleaner.new(@mod, @options).clean
|
|
7
|
-
build_dir = Util.pretty_path(@mod.
|
|
7
|
+
build_dir = Util.pretty_path(@mod.cache_dir)
|
|
8
8
|
logger.info "Building #{build_dir}"
|
|
9
9
|
|
|
10
10
|
build_all("modules") # build all modules and stacks as dependencies
|
|
11
11
|
build_all("stacks")
|
|
12
|
-
build_root_module
|
|
13
|
-
|
|
14
|
-
auto_create_backend
|
|
15
|
-
Terraform::Runner.new("init", @options).run if !auto? && @options[:init] != false # will run on @options[:init].nil?
|
|
16
|
-
build_remote_dependencies # runs after terraform init, which downloads remote modules
|
|
12
|
+
build_root_module
|
|
17
13
|
logger.info "Built in #{build_dir}"
|
|
18
14
|
end
|
|
19
15
|
|
|
20
|
-
def auto?
|
|
21
|
-
# command is only passed from CLI in the update specifically for this check
|
|
22
|
-
@options[:auto] && @options[:command] == "update"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
16
|
def build_root_module
|
|
26
17
|
Compiler::Builder.new(@mod).build
|
|
27
18
|
end
|
|
@@ -35,22 +26,12 @@ module Terraspace
|
|
|
35
26
|
|
|
36
27
|
consider_stacks = type_dir == "stacks"
|
|
37
28
|
mod = Mod.new(mod_name, consider_stacks: consider_stacks)
|
|
38
|
-
next if root?(mod) # will build root module at the end
|
|
39
29
|
|
|
40
30
|
Compiler::Builder.new(mod).build
|
|
41
31
|
built << mod_name
|
|
42
32
|
end
|
|
43
33
|
end
|
|
44
34
|
|
|
45
|
-
def root?(mod)
|
|
46
|
-
mod.name == @mod.name && mod.type == @mod.type
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def auto_create_backend
|
|
50
|
-
return unless @options[:command] == "update"
|
|
51
|
-
Compiler::Backend.new(@mod).create
|
|
52
|
-
end
|
|
53
|
-
|
|
54
35
|
def local_paths(type_dir)
|
|
55
36
|
dirs("app/#{type_dir}/*") + dirs("vendor/#{type_dir}/*")
|
|
56
37
|
end
|
|
@@ -58,30 +39,5 @@ module Terraspace
|
|
|
58
39
|
def dirs(path)
|
|
59
40
|
Dir.glob("#{Terraspace.root}/#{path}")
|
|
60
41
|
end
|
|
61
|
-
|
|
62
|
-
# Currently only handles remote modules only one-level deep.
|
|
63
|
-
def build_remote_dependencies
|
|
64
|
-
modules_json_path = "#{@mod.cache_build_dir}/.terraform/modules/modules.json"
|
|
65
|
-
return unless File.exist?(modules_json_path)
|
|
66
|
-
|
|
67
|
-
initialized_modules = JSON.load(IO.read(modules_json_path))
|
|
68
|
-
# For example of structure see spec/fixtures/initialized/modules.json
|
|
69
|
-
initialized_modules["Modules"].each do |meta|
|
|
70
|
-
build_remote_mod(meta)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def build_remote_mod(meta)
|
|
75
|
-
return if local_source?(meta["Source"])
|
|
76
|
-
return if meta['Dir'] == '.' # root is already built
|
|
77
|
-
|
|
78
|
-
remote_mod = Mod::Remote.new(meta, @mod)
|
|
79
|
-
Compiler::Builder.new(remote_mod).build
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
private
|
|
83
|
-
def local_source?(s)
|
|
84
|
-
s =~ %r{^\.} || s =~ %r{^/}
|
|
85
|
-
end
|
|
86
42
|
end
|
|
87
43
|
end
|
data/lib/terraspace/cli.rb
CHANGED
|
@@ -24,20 +24,25 @@ module Terraspace
|
|
|
24
24
|
init_option = Proc.new {
|
|
25
25
|
option :init, type: :boolean, default: true, desc: "Instance of stack"
|
|
26
26
|
}
|
|
27
|
+
reconfigure_option = Proc.new {
|
|
28
|
+
option :reconfigure, type: :boolean, desc: "Add terraform -reconfigure option"
|
|
29
|
+
}
|
|
27
30
|
|
|
28
31
|
desc "new SUBCOMMAND", "new subcommands"
|
|
29
32
|
long_desc Help.text(:new)
|
|
30
33
|
subcommand "new", New
|
|
31
34
|
|
|
32
|
-
desc "
|
|
35
|
+
desc "cloud SUBCOMMAND", "cloud subcommands"
|
|
36
|
+
long_desc Help.text(:cloud)
|
|
37
|
+
subcommand "cloud", Cloud
|
|
38
|
+
|
|
39
|
+
desc "build STACK", "build"
|
|
33
40
|
long_desc Help.text(:build)
|
|
34
41
|
option :quiet, type: :boolean, default: true, desc: "quiet output"
|
|
35
|
-
auto_option.call
|
|
36
|
-
init_option.call
|
|
37
|
-
input_option.call
|
|
38
42
|
instance_option.call
|
|
43
|
+
yes_option.call
|
|
39
44
|
def build(mod)
|
|
40
|
-
|
|
45
|
+
Terraspace::Builder.new(@options.merge(mod: mod)).run
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
desc "bundle", "bundle"
|
|
@@ -58,22 +63,25 @@ module Terraspace
|
|
|
58
63
|
Clean.new(options).run
|
|
59
64
|
end
|
|
60
65
|
|
|
61
|
-
desc "console", "console .terraspace-cache dir"
|
|
66
|
+
desc "console STACK", "console .terraspace-cache dir"
|
|
62
67
|
long_desc Help.text(:console)
|
|
63
68
|
instance_option.call
|
|
64
69
|
def console(mod)
|
|
65
70
|
Commander.new("console", options.merge(mod: mod)).run
|
|
66
71
|
end
|
|
67
72
|
|
|
68
|
-
desc "down
|
|
73
|
+
desc "down STACK", "down"
|
|
69
74
|
long_desc Help.text(:down)
|
|
70
75
|
instance_option.call
|
|
71
76
|
yes_option.call
|
|
77
|
+
reconfigure_option.call
|
|
78
|
+
option :destroy_workspace, type: :boolean, desc: "Also destroy the Cloud workspace. Only applies when using Terraform Cloud remote backend."
|
|
72
79
|
def down(mod)
|
|
73
|
-
Commander.new("destroy", options.merge(mod: mod)).run
|
|
80
|
+
Commander.new("destroy", options.merge(mod: mod, command: "down")).run
|
|
81
|
+
Terraspace::Terraform::Cloud::Workspace.new(options.merge(mod: mod)).destroy if @options[:destroy_workspace]
|
|
74
82
|
end
|
|
75
83
|
|
|
76
|
-
desc "info
|
|
84
|
+
desc "info STACK", "info"
|
|
77
85
|
long_desc Help.text(:info)
|
|
78
86
|
format_option.call
|
|
79
87
|
instance_option.call
|
|
@@ -81,31 +89,38 @@ module Terraspace
|
|
|
81
89
|
Info.new(options.merge(mod: mod)).run
|
|
82
90
|
end
|
|
83
91
|
|
|
84
|
-
desc "
|
|
92
|
+
desc "list", "list stacks and modules"
|
|
93
|
+
long_desc Help.text(:list)
|
|
94
|
+
def list
|
|
95
|
+
List.new(options).run
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
desc "plan STACK", "plan stack"
|
|
85
99
|
long_desc Help.text(:plan)
|
|
86
100
|
auto_option.call
|
|
87
101
|
input_option.call
|
|
88
102
|
instance_option.call
|
|
89
103
|
out_option.call
|
|
104
|
+
reconfigure_option.call
|
|
90
105
|
def plan(mod)
|
|
91
106
|
Commander.new("plan", options.merge(mod: mod)).run
|
|
92
107
|
end
|
|
93
108
|
|
|
94
|
-
desc "providers
|
|
109
|
+
desc "providers STACK", "providers"
|
|
95
110
|
long_desc Help.text(:providers)
|
|
96
111
|
instance_option.call
|
|
97
112
|
def providers(mod)
|
|
98
113
|
Commander.new("providers", options.merge(mod: mod)).run
|
|
99
114
|
end
|
|
100
115
|
|
|
101
|
-
desc "refresh", "refresh"
|
|
116
|
+
desc "refresh STACK", "refresh"
|
|
102
117
|
long_desc Help.text(:refresh)
|
|
103
118
|
instance_option.call
|
|
104
119
|
def refresh(mod)
|
|
105
120
|
Commander.new("refresh", options.merge(mod: mod)).run
|
|
106
121
|
end
|
|
107
122
|
|
|
108
|
-
desc "seed
|
|
123
|
+
desc "seed STACK", "seed"
|
|
109
124
|
long_desc Help.text(:seed)
|
|
110
125
|
option :yes, aliases: :y, type: :boolean, desc: "bypass prompts and force overwrite files"
|
|
111
126
|
option :where, desc: "where to create file. either under app or seed folder structure. values: app or stack"
|
|
@@ -124,7 +139,7 @@ module Terraspace
|
|
|
124
139
|
Summary.new(options).run
|
|
125
140
|
end
|
|
126
141
|
|
|
127
|
-
desc "show
|
|
142
|
+
desc "show STACK", "show"
|
|
128
143
|
long_desc Help.text(:show)
|
|
129
144
|
instance_option.call
|
|
130
145
|
def show(mod)
|
|
@@ -137,7 +152,7 @@ module Terraspace
|
|
|
137
152
|
Test.new(options).run
|
|
138
153
|
end
|
|
139
154
|
|
|
140
|
-
desc "output
|
|
155
|
+
desc "output STACK", "output"
|
|
141
156
|
long_desc Help.text(:output)
|
|
142
157
|
format_option.call
|
|
143
158
|
instance_option.call
|
|
@@ -146,20 +161,21 @@ module Terraspace
|
|
|
146
161
|
Commander.new("output", options.merge(mod: mod)).run
|
|
147
162
|
end
|
|
148
163
|
|
|
149
|
-
desc "update
|
|
164
|
+
desc "update STACK", "Update infrasturcture. IE: apply plan"
|
|
150
165
|
long_desc Help.text(:update)
|
|
151
166
|
auto_option.call
|
|
152
167
|
init_option.call
|
|
153
168
|
input_option.call
|
|
154
169
|
instance_option.call
|
|
155
170
|
yes_option.call
|
|
171
|
+
reconfigure_option.call
|
|
156
172
|
option :plan, desc: "Execution plan that can be used to only execute a pre-determined set of actions."
|
|
157
173
|
option :var_files, type: :array, desc: "list of var files"
|
|
158
174
|
def update(mod)
|
|
159
|
-
Commander.new("apply", options.merge(mod: mod
|
|
175
|
+
Commander.new("apply", options.merge(mod: mod)).run
|
|
160
176
|
end
|
|
161
177
|
|
|
162
|
-
desc "validate
|
|
178
|
+
desc "validate STACK", "validate"
|
|
163
179
|
long_desc Help.text(:validate)
|
|
164
180
|
instance_option.call
|
|
165
181
|
def validate(mod)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# The placeholder stack is a special stack that is useful in case there are no app/stacks.
|
|
2
|
+
# We build a placeholder back just so we have backend.tf to be used to grab info.
|
|
3
|
+
# It's useful for the summary command.
|
|
4
|
+
module Terraspace::CLI::Build
|
|
5
|
+
class Placeholder
|
|
6
|
+
include Terraspace::Util::Logging
|
|
7
|
+
|
|
8
|
+
def initialize(options={})
|
|
9
|
+
@options = options
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Grab the last module and build that.
|
|
13
|
+
# Assume the backend key has the same prefix
|
|
14
|
+
# Note: Tried building a empty "null" stack but with TFC a null space workspace is created, which is undesired.
|
|
15
|
+
def build
|
|
16
|
+
return if ENV['TS_SUMMARY_BUILD'] == '0'
|
|
17
|
+
|
|
18
|
+
mod = @options[:mod]
|
|
19
|
+
if !mod or mod == "placeholder"
|
|
20
|
+
logger.info "Building one of the modules to get backend.tf info"
|
|
21
|
+
mod = find_mod
|
|
22
|
+
end
|
|
23
|
+
Terraspace::Builder.new(@options.merge(mod: mod, init: false)).run # generate and init
|
|
24
|
+
Terraspace::Mod.new(mod, @options) # mod metadata
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Used by: terraspace build placeholder
|
|
28
|
+
def find_mod
|
|
29
|
+
mod_path = Dir.glob("{app,vendor}/{modules,stacks}/*").last
|
|
30
|
+
unless mod_path
|
|
31
|
+
logger.info <<~EOL
|
|
32
|
+
No modules or stacks found.
|
|
33
|
+
Unable to determine the backend state path without at least one module.
|
|
34
|
+
EOL
|
|
35
|
+
exit 0
|
|
36
|
+
end
|
|
37
|
+
File.basename(mod_path) # mod name
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class Terraspace::CLI
|
|
2
|
+
class Cloud < Terraspace::Command
|
|
3
|
+
Workspace = Terraspace::Terraform::Cloud::Workspace
|
|
4
|
+
|
|
5
|
+
desc "list", "List workspaces"
|
|
6
|
+
long_desc Help.text("cloud:list")
|
|
7
|
+
def list
|
|
8
|
+
Workspace.new(options).list
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
desc "destroy", "Destroy workspace"
|
|
12
|
+
long_desc Help.text("cloud:destroy")
|
|
13
|
+
option :yes, aliases: :y, type: :boolean, desc: "bypass are you sure prompt"
|
|
14
|
+
def destroy(mod)
|
|
15
|
+
Workspace.new(options.merge(mod: mod)).destroy
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
desc "setup", "Setup workspace"
|
|
19
|
+
long_desc Help.text("cloud:setup")
|
|
20
|
+
def setup(mod)
|
|
21
|
+
Workspace.new(options.merge(mod: mod)).setup
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -7,8 +7,15 @@ class Terraspace::CLI
|
|
|
7
7
|
|
|
8
8
|
# Commander always runs Build#run
|
|
9
9
|
def run
|
|
10
|
-
|
|
10
|
+
Terraspace::Builder.new(@options).run # generate and init
|
|
11
|
+
auto_create_backend
|
|
12
|
+
Init.new(@options.merge(calling_command: @name)).run
|
|
11
13
|
Terraspace::Terraform::Runner.new(@name, @options).run
|
|
12
14
|
end
|
|
15
|
+
|
|
16
|
+
def auto_create_backend
|
|
17
|
+
return unless @name == "apply"
|
|
18
|
+
Terraspace::Compiler::Backend.new(@mod).create
|
|
19
|
+
end
|
|
13
20
|
end
|
|
14
21
|
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'timeout'
|
|
2
|
+
|
|
3
|
+
class Terraspace::CLI
|
|
4
|
+
class Init < Base
|
|
5
|
+
def initialize(options={})
|
|
6
|
+
# Original calling command. Can be from Commander which is a terraform command. IE: terraform apply
|
|
7
|
+
# Or can be from terraspace cloud setup. Which will be cloud-setup.
|
|
8
|
+
@calling_command = options[:calling_command]
|
|
9
|
+
super(options)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run
|
|
13
|
+
init if init?
|
|
14
|
+
build_remote_dependencies # runs after terraform init, which downloads remote modules
|
|
15
|
+
sync_cloud
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Note the init will always create the Terraform Cloud Workspace
|
|
19
|
+
def init
|
|
20
|
+
# default init timeout is pretty generous in case of slow internet to download the provider plugins
|
|
21
|
+
init_timeout = Integer(ENV['TS_INIT_TIMEOUT'] || 600)
|
|
22
|
+
Timeout::timeout(init_timeout) do
|
|
23
|
+
Terraspace::Terraform::Runner.new("init", @options).run if !auto? && @options[:init] != false # will run on @options[:init].nil?
|
|
24
|
+
end
|
|
25
|
+
rescue Timeout::Error
|
|
26
|
+
logger.error "ERROR: It took too long to run terraform init. Here is the output logs of terraform init:".color(:red)
|
|
27
|
+
logger.error IO.read(Terraspace::Terraform::Args::Default.terraform_init_log)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def sync_cloud
|
|
31
|
+
Terraspace::Terraform::Cloud.new(@options).run if %w[apply plan destroy cloud-setup].include?(@calling_command)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Currently only handles remote modules only one-level deep.
|
|
35
|
+
def build_remote_dependencies
|
|
36
|
+
modules_json_path = "#{@mod.cache_dir}/.terraform/modules/modules.json"
|
|
37
|
+
return unless File.exist?(modules_json_path)
|
|
38
|
+
|
|
39
|
+
initialized_modules = JSON.load(IO.read(modules_json_path))
|
|
40
|
+
# For example of structure see spec/fixtures/initialized/modules.json
|
|
41
|
+
initialized_modules["Modules"].each do |meta|
|
|
42
|
+
build_remote_mod(meta)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def build_remote_mod(meta)
|
|
47
|
+
return if local_source?(meta["Source"])
|
|
48
|
+
return if meta['Dir'] == '.' # root is already built
|
|
49
|
+
|
|
50
|
+
remote_mod = Mod::Remote.new(meta, @mod)
|
|
51
|
+
Compiler::Builder.new(remote_mod).build
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def auto?
|
|
55
|
+
# command is only passed from CLI in the update specifically for this check
|
|
56
|
+
@options[:auto] && @calling_command == "apply"
|
|
57
|
+
end
|
|
58
|
+
private
|
|
59
|
+
def local_source?(s)
|
|
60
|
+
s =~ %r{^\.} || s =~ %r{^/}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def init?
|
|
64
|
+
%w[apply console destroy output plan providers refresh show validate cloud-setup].include?(@calling_command)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|