cloudspin-stack 0.1.19 → 0.1.20
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/lib/cloudspin/cli.rb +7 -4
- data/lib/cloudspin/stack/instance.rb +83 -47
- data/lib/cloudspin/stack/instance_configuration.rb +61 -15
- data/lib/cloudspin/stack/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7367da5398e58437223ee59141a3acfde89306c4
|
4
|
+
data.tar.gz: c7d4175e095df03cbd6e51bb8ba81a7cb9e9bef4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8677124654c9c41f12a14c60d825d565d2574ae98ae07bc6fba1fdb86d9b60c0aefadc392dde3e54ceae77260519e05f7bb8b17fe633c3c0e23eb85f88a84732
|
7
|
+
data.tar.gz: c6f53cae6e58db92b63b72a32d869a5a40557affbc5d6c78d17387953c8235a442fbc3321432e2494f753959791c6fa12976c425922c01e02b8f64dea17e702b
|
data/lib/cloudspin/cli.rb
CHANGED
@@ -20,13 +20,15 @@ module Cloudspin
|
|
20
20
|
|
21
21
|
class_option :environment,
|
22
22
|
:aliases => '-e',
|
23
|
-
:banner => '
|
24
|
-
:desc => 'An environment instance to manage.'
|
23
|
+
:banner => 'environment_id',
|
24
|
+
:desc => 'An environment instance to manage. File ./environments/stack-instance-ENVIRONMENT_ID.yaml must exist.'
|
25
25
|
|
26
26
|
desc 'up', 'Create or update the stack instance'
|
27
27
|
option :dry, :type => :boolean, :default => false
|
28
28
|
option :plan, :type => :boolean, :default => false
|
29
|
+
option :'show-init', :type => :boolean, :default => true
|
29
30
|
def up
|
31
|
+
puts instance.init_dry if options[:'show-init']
|
30
32
|
if options[:plan] && options[:dry]
|
31
33
|
puts instance.plan_dry
|
32
34
|
elsif options[:plan] && ! options[:dry]
|
@@ -41,7 +43,9 @@ module Cloudspin
|
|
41
43
|
desc 'down', 'Destroy the stack instance'
|
42
44
|
option :dry, :type => :boolean, :default => false
|
43
45
|
option :plan, :type => :boolean, :default => false
|
46
|
+
option :'show-init', :type => :boolean, :default => true
|
44
47
|
def down
|
48
|
+
puts instance.init_dry if options[:'show-init']
|
45
49
|
if options[:plan] && options[:dry]
|
46
50
|
puts instance.plan_dry(plan_destroy: true)
|
47
51
|
elsif options[:plan] && ! options[:dry]
|
@@ -69,8 +73,7 @@ module Cloudspin
|
|
69
73
|
Cloudspin::Stack::Instance.from_files(
|
70
74
|
instance_configuration_files,
|
71
75
|
stack_definition: stack_definition,
|
72
|
-
base_working_folder: './work'
|
73
|
-
base_statefile_folder: './state'
|
76
|
+
base_working_folder: './work'
|
74
77
|
)
|
75
78
|
end
|
76
79
|
|
@@ -9,51 +9,50 @@ module Cloudspin
|
|
9
9
|
|
10
10
|
attr_reader :id,
|
11
11
|
:working_folder,
|
12
|
-
:statefile_folder,
|
13
12
|
:configuration
|
14
13
|
|
15
14
|
def initialize(
|
16
15
|
id:,
|
17
16
|
stack_definition:,
|
18
17
|
working_folder:,
|
19
|
-
statefile_folder:,
|
20
18
|
configuration:
|
21
19
|
)
|
22
20
|
validate_id(id)
|
23
21
|
@id = id
|
24
22
|
@stack_definition = stack_definition
|
25
|
-
@working_folder
|
26
|
-
@
|
27
|
-
@configuration = configuration
|
28
|
-
@backend_config = {}
|
23
|
+
@working_folder = working_folder
|
24
|
+
@configuration = configuration
|
29
25
|
end
|
30
26
|
|
31
27
|
def self.from_folder(
|
32
28
|
*instance_configuration_files,
|
33
29
|
definition_folder:,
|
34
|
-
|
35
|
-
|
30
|
+
base_folder: '.',
|
31
|
+
base_working_folder:
|
36
32
|
)
|
37
33
|
self.from_files(
|
38
34
|
instance_configuration_files,
|
39
35
|
stack_definition: Definition.from_folder(definition_folder),
|
40
|
-
|
41
|
-
|
36
|
+
base_folder: base_folder,
|
37
|
+
base_working_folder: base_working_folder
|
42
38
|
)
|
43
39
|
end
|
44
40
|
|
45
41
|
def self.from_files(
|
46
42
|
*instance_configuration_files,
|
47
43
|
stack_definition:,
|
48
|
-
|
49
|
-
|
44
|
+
base_folder: '.',
|
45
|
+
base_working_folder:
|
50
46
|
)
|
51
|
-
instance_configuration = InstanceConfiguration.from_files(
|
47
|
+
instance_configuration = InstanceConfiguration.from_files(
|
48
|
+
instance_configuration_files,
|
49
|
+
stack_definition: stack_definition,
|
50
|
+
base_folder: base_folder
|
51
|
+
)
|
52
52
|
self.new(
|
53
53
|
id: instance_configuration.instance_identifier,
|
54
54
|
stack_definition: stack_definition,
|
55
55
|
working_folder: ensure_folder("#{base_working_folder}/#{instance_configuration.instance_identifier}"),
|
56
|
-
statefile_folder: ensure_folder("#{base_statefile_folder}/#{instance_configuration.instance_identifier}"),
|
57
56
|
configuration: instance_configuration
|
58
57
|
)
|
59
58
|
end
|
@@ -81,24 +80,20 @@ module Cloudspin
|
|
81
80
|
RubyTerraform.clean(directory: working_folder)
|
82
81
|
mkdir_p File.dirname(working_folder)
|
83
82
|
cp_r @stack_definition.source_path, working_folder
|
83
|
+
ensure_state_folder
|
84
84
|
Dir.chdir(working_folder) do
|
85
|
-
|
86
|
-
RubyTerraform.plan(
|
87
|
-
destroy: plan_destroy,
|
88
|
-
state: terraform_statefile,
|
89
|
-
vars: terraform_variables
|
90
|
-
)
|
85
|
+
terraform_init
|
86
|
+
RubyTerraform.plan(terraform_command_parameters(destroy: plan_destroy))
|
91
87
|
end
|
92
88
|
end
|
93
89
|
|
94
90
|
def plan_dry(plan_destroy: false)
|
95
91
|
plan_command = RubyTerraform::Commands::Plan.new
|
96
92
|
command_line_builder = plan_command.instantiate_builder
|
97
|
-
configured_command = plan_command.configure_command(
|
98
|
-
|
99
|
-
:
|
100
|
-
|
101
|
-
})
|
93
|
+
configured_command = plan_command.configure_command(
|
94
|
+
command_line_builder,
|
95
|
+
terraform_command_parameters(:destroy => plan_destroy)
|
96
|
+
)
|
102
97
|
built_command = configured_command.build
|
103
98
|
"cd #{working_folder} && #{built_command.to_s}"
|
104
99
|
end
|
@@ -107,23 +102,17 @@ module Cloudspin
|
|
107
102
|
RubyTerraform.clean(directory: working_folder)
|
108
103
|
mkdir_p File.dirname(working_folder)
|
109
104
|
cp_r @stack_definition.source_path, working_folder
|
105
|
+
ensure_state_folder
|
110
106
|
Dir.chdir(working_folder) do
|
111
|
-
|
112
|
-
RubyTerraform.apply(
|
113
|
-
auto_approve: true,
|
114
|
-
state: terraform_statefile,
|
115
|
-
vars: terraform_variables
|
116
|
-
)
|
107
|
+
terraform_init
|
108
|
+
RubyTerraform.apply(terraform_command_parameters(auto_approve: true))
|
117
109
|
end
|
118
110
|
end
|
119
111
|
|
120
112
|
def up_dry
|
121
113
|
up_command = RubyTerraform::Commands::Apply.new
|
122
114
|
command_line_builder = up_command.instantiate_builder
|
123
|
-
configured_command = up_command.configure_command(command_line_builder,
|
124
|
-
:state => terraform_statefile,
|
125
|
-
:vars => terraform_variables
|
126
|
-
})
|
115
|
+
configured_command = up_command.configure_command(command_line_builder, terraform_command_parameters)
|
127
116
|
built_command = configured_command.build
|
128
117
|
"cd #{working_folder} && #{built_command.to_s}"
|
129
118
|
end
|
@@ -132,35 +121,82 @@ module Cloudspin
|
|
132
121
|
RubyTerraform.clean(directory: working_folder)
|
133
122
|
mkdir_p File.dirname(working_folder)
|
134
123
|
cp_r @stack_definition.source_path, working_folder
|
124
|
+
ensure_state_folder
|
135
125
|
Dir.chdir(working_folder) do
|
136
|
-
|
137
|
-
RubyTerraform.destroy(
|
138
|
-
force: true,
|
139
|
-
state: terraform_statefile,
|
140
|
-
vars: terraform_variables
|
141
|
-
)
|
126
|
+
terraform_init
|
127
|
+
RubyTerraform.destroy(terraform_command_parameters(force: true))
|
142
128
|
end
|
143
129
|
end
|
144
130
|
|
145
131
|
def down_dry
|
146
132
|
down_command = RubyTerraform::Commands::Destroy.new
|
147
133
|
command_line_builder = down_command.instantiate_builder
|
148
|
-
configured_command = down_command.configure_command(command_line_builder,
|
149
|
-
:state => terraform_statefile,
|
150
|
-
:vars => terraform_variables
|
151
|
-
})
|
134
|
+
configured_command = down_command.configure_command(command_line_builder, terraform_command_parameters)
|
152
135
|
built_command = configured_command.build
|
153
136
|
"cd #{working_folder} && #{built_command.to_s}"
|
154
137
|
end
|
155
138
|
|
139
|
+
def terraform_init
|
140
|
+
RubyTerraform.init(terraform_init_params)
|
141
|
+
end
|
142
|
+
|
143
|
+
def init_dry
|
144
|
+
init_command = RubyTerraform::Commands::Init.new
|
145
|
+
command_line_builder = init_command.instantiate_builder
|
146
|
+
configured_command = init_command.configure_command(
|
147
|
+
command_line_builder,
|
148
|
+
terraform_init_params
|
149
|
+
)
|
150
|
+
built_command = configured_command.build
|
151
|
+
"cd #{working_folder} && #{built_command.to_s}"
|
152
|
+
end
|
153
|
+
|
154
|
+
def terraform_init_params
|
155
|
+
if configuration.has_remote_state_configuration?
|
156
|
+
{
|
157
|
+
backend: 's3',
|
158
|
+
backend_config: backend_parameters
|
159
|
+
}
|
160
|
+
else
|
161
|
+
{}
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def ensure_state_folder
|
166
|
+
if configuration.has_local_state_configuration?
|
167
|
+
Instance.ensure_folder(configuration.terraform_backend['statefile_folder'])
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def terraform_command_parameters(added_parameters = {})
|
172
|
+
{
|
173
|
+
vars: terraform_variables
|
174
|
+
}.merge(local_state_parameters).merge(added_parameters)
|
175
|
+
end
|
176
|
+
|
156
177
|
def terraform_variables
|
157
178
|
parameter_values.merge(resource_values) { |key, oldval, newval|
|
158
179
|
raise "Duplicate values for terraform variable '#{key}' ('#{oldval}' and '#{newval}')"
|
159
180
|
}.merge({ 'instance_identifier' => id })
|
160
181
|
end
|
161
182
|
|
162
|
-
def
|
163
|
-
|
183
|
+
def local_state_parameters
|
184
|
+
if configuration.has_local_state_configuration?
|
185
|
+
{ state: configuration.local_statefile }
|
186
|
+
else
|
187
|
+
{}
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def backend_parameters
|
192
|
+
if configuration.has_remote_state_configuration?
|
193
|
+
{
|
194
|
+
'bucket' => configuration.terraform_backend['bucket'],
|
195
|
+
'key' => configuration.terraform_backend['key']
|
196
|
+
}
|
197
|
+
else
|
198
|
+
{}
|
199
|
+
end
|
164
200
|
end
|
165
201
|
|
166
202
|
end
|
@@ -7,28 +7,52 @@ module Cloudspin
|
|
7
7
|
|
8
8
|
attr_reader :stack_definition
|
9
9
|
attr_reader :stack_name
|
10
|
+
attr_reader :base_folder
|
10
11
|
|
11
12
|
attr_reader :instance_values
|
12
13
|
attr_reader :parameter_values
|
13
14
|
attr_reader :resource_values
|
14
15
|
|
15
|
-
|
16
|
+
attr_reader :terraform_backend
|
17
|
+
|
18
|
+
def initialize(
|
19
|
+
configuration_values: {},
|
20
|
+
stack_definition:,
|
21
|
+
base_folder: '.'
|
22
|
+
)
|
16
23
|
@stack_definition = stack_definition
|
17
24
|
@stack_name = stack_definition.name
|
18
|
-
@
|
19
|
-
|
20
|
-
@
|
25
|
+
@base_folder = base_folder
|
26
|
+
|
27
|
+
@instance_values = configuration_values['instance'] || {}
|
28
|
+
@parameter_values = configuration_values['parameters'] || {}
|
29
|
+
@resource_values = configuration_values['resources'] || {}
|
30
|
+
|
31
|
+
@terraform_backend = configuration_values['terraform_backend'] || {}
|
32
|
+
if @terraform_backend.empty?
|
33
|
+
@terraform_backend['statefile_folder'] = default_state_folder
|
34
|
+
else
|
35
|
+
@terraform_backend['key'] = default_state_key
|
36
|
+
end
|
21
37
|
end
|
22
38
|
|
23
|
-
def self.from_files(
|
24
|
-
|
39
|
+
def self.from_files(
|
40
|
+
*configuration_files,
|
41
|
+
stack_definition:,
|
42
|
+
base_folder: '.'
|
43
|
+
)
|
44
|
+
configuration_values = {}
|
25
45
|
configuration_files.flatten.each { |config_file|
|
26
|
-
|
46
|
+
configuration_values = configuration_values.deep_merge(yaml_file_to_hash(config_file))
|
27
47
|
}
|
28
|
-
|
48
|
+
self.new(
|
49
|
+
stack_definition: stack_definition,
|
50
|
+
base_folder: base_folder,
|
51
|
+
configuration_values: configuration_values
|
52
|
+
)
|
29
53
|
end
|
30
54
|
|
31
|
-
def self.
|
55
|
+
def self.yaml_file_to_hash(yaml_file)
|
32
56
|
if File.exists?(yaml_file)
|
33
57
|
YAML.load_file(yaml_file) || {}
|
34
58
|
else
|
@@ -36,11 +60,24 @@ module Cloudspin
|
|
36
60
|
end
|
37
61
|
end
|
38
62
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
63
|
+
def has_local_state_configuration?
|
64
|
+
! @terraform_backend['statefile_folder'].nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
def local_statefile
|
68
|
+
"#{@terraform_backend['statefile_folder']}/#{instance_identifier}.tfstate"
|
69
|
+
end
|
70
|
+
|
71
|
+
def has_remote_state_configuration?
|
72
|
+
! @terraform_backend['key'].nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
def default_state_folder
|
76
|
+
Pathname.new("#{base_folder}/state/#{instance_identifier}").realdirpath.to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
def default_state_key
|
80
|
+
"/#{instance_identifier}.tfstate"
|
44
81
|
end
|
45
82
|
|
46
83
|
def instance_identifier
|
@@ -55,9 +92,11 @@ module Cloudspin
|
|
55
92
|
|
56
93
|
def to_s
|
57
94
|
{
|
95
|
+
'instance_identifier' => instance_identifier,
|
58
96
|
'instance' => instance_values,
|
59
97
|
'parameters' => parameter_values,
|
60
|
-
'resources' => resource_values
|
98
|
+
'resources' => resource_values,
|
99
|
+
'terraform_backend' => terraform_backend
|
61
100
|
}.to_s
|
62
101
|
end
|
63
102
|
|
@@ -66,3 +105,10 @@ module Cloudspin
|
|
66
105
|
end
|
67
106
|
end
|
68
107
|
|
108
|
+
# hat tip: https://stackoverflow.com/questions/9381553/ruby-merge-nested-hash
|
109
|
+
class ::Hash
|
110
|
+
def deep_merge(second)
|
111
|
+
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
|
112
|
+
self.merge(second.to_h, &merger)
|
113
|
+
end
|
114
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudspin-stack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.20
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 'kief '
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-09-
|
11
|
+
date: 2018-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-terraform
|