cm 0.1.4 → 0.1.6
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/.gitmodules +3 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +5 -0
- data/VERSION +1 -1
- data/bootstrap/lib/bash/LICENSE.txt +674 -0
- data/cm.gemspec +19 -12
- data/lib/CM/batch/celluloid.rb +4 -4
- data/lib/CM/configuration/file.rb +0 -4
- data/lib/CM/{job → resource}/AWS.rb +11 -3
- data/lib/CM/{job → resource}/BOSH.rb +11 -3
- data/lib/CM/resource/MicroBOSH.rb +46 -0
- data/lib/CM/{job → resource}/concourse.rb +11 -3
- data/lib/CM/{job → resource}/keypair.rb +11 -3
- data/lib/CM/{job/MicroBOSH.rb → resource/variables.rb} +11 -7
- data/lib/CM/sequence/default.rb +10 -10
- data/lib/cm.rb +1 -1
- data/lib/core/facade.rb +4 -4
- data/lib/core/mixin/action/registration.rb +8 -8
- data/lib/core/plugin/auth_docker_resource.rb +52 -0
- data/lib/core/plugin/batch.rb +25 -29
- data/lib/core/plugin/configuration.rb +1 -5
- data/lib/core/plugin/docker_resource.rb +315 -0
- data/lib/core/plugin/plan.rb +125 -54
- data/lib/core/plugin/plan_action.rb +47 -18
- data/lib/core/plugin/{job.rb → resource.rb} +33 -14
- data/lib/core/plugin/sequence.rb +26 -109
- data/lib/nucleon/action/resource/run.rb +53 -0
- data/locales/en.yml +9 -3
- metadata +39 -21
- data/lib/CM/job/variables.rb +0 -34
- data/lib/core/plugin/docker_job.rb +0 -52
data/lib/core/plugin/batch.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
|
2
|
-
nucleon_require(File.dirname(__FILE__), :parallel_base)
|
3
|
-
|
4
|
-
#---
|
5
|
-
|
6
2
|
module CM
|
7
3
|
module Plugin
|
8
|
-
class Batch < Nucleon.plugin_class(:nucleon, :
|
4
|
+
class Batch < Nucleon.plugin_class(:nucleon, :base)
|
9
5
|
|
10
6
|
#-----------------------------------------------------------------------------
|
11
7
|
# Plugin interface
|
@@ -13,24 +9,24 @@ class Batch < Nucleon.plugin_class(:nucleon, :parallel_base)
|
|
13
9
|
def normalize(reload)
|
14
10
|
super
|
15
11
|
|
16
|
-
@
|
12
|
+
@plan = delete(:plan, nil) unless reload
|
17
13
|
|
18
|
-
|
14
|
+
init_resources
|
19
15
|
yield if block_given?
|
20
16
|
end
|
21
17
|
|
22
18
|
#---
|
23
19
|
|
24
|
-
def
|
25
|
-
@
|
26
|
-
get_array(:
|
27
|
-
if
|
28
|
-
@
|
20
|
+
def init_resources
|
21
|
+
@resources = []
|
22
|
+
get_array(:resources).each do |resource_config|
|
23
|
+
if resource_config.has_key?(:sequence) # Array
|
24
|
+
@resources << plan.create_sequence(resource_config[:sequence])
|
29
25
|
else # Atomic
|
30
|
-
@
|
26
|
+
@resources << plan.create_resource(resource_config)
|
31
27
|
end
|
32
28
|
end
|
33
|
-
@
|
29
|
+
@resources
|
34
30
|
end
|
35
31
|
|
36
32
|
#-----------------------------------------------------------------------------
|
@@ -43,30 +39,30 @@ class Batch < Nucleon.plugin_class(:nucleon, :parallel_base)
|
|
43
39
|
#-----------------------------------------------------------------------------
|
44
40
|
# Property accessors / modifiers
|
45
41
|
|
46
|
-
def
|
47
|
-
@
|
42
|
+
def plan
|
43
|
+
@plan
|
48
44
|
end
|
49
45
|
|
50
46
|
#---
|
51
47
|
|
52
|
-
def
|
53
|
-
@
|
48
|
+
def resources
|
49
|
+
@resources
|
54
50
|
end
|
55
51
|
|
56
|
-
def
|
57
|
-
set(:
|
58
|
-
|
52
|
+
def resources=resources
|
53
|
+
set(:resources, array(resources))
|
54
|
+
init_resources
|
59
55
|
end
|
60
56
|
|
61
57
|
#-----------------------------------------------------------------------------
|
62
58
|
# Operations
|
63
59
|
|
64
|
-
def execute
|
60
|
+
def execute(operation)
|
65
61
|
if initialized?
|
66
62
|
if Nucleon.parallel?
|
67
|
-
success = execute_parallel
|
63
|
+
success = execute_parallel(operation)
|
68
64
|
else
|
69
|
-
success = execute_sequence
|
65
|
+
success = execute_sequence(operation)
|
70
66
|
end
|
71
67
|
else
|
72
68
|
success = false
|
@@ -77,17 +73,17 @@ class Batch < Nucleon.plugin_class(:nucleon, :parallel_base)
|
|
77
73
|
#-----------------------------------------------------------------------------
|
78
74
|
# Utilities
|
79
75
|
|
80
|
-
def execute_parallel
|
76
|
+
def execute_parallel(operation)
|
81
77
|
false # Override me!!
|
82
78
|
end
|
83
79
|
|
84
80
|
#---
|
85
81
|
|
86
|
-
def execute_sequence
|
82
|
+
def execute_sequence(operation)
|
87
83
|
success = true
|
88
|
-
|
89
|
-
success = false unless
|
90
|
-
break if
|
84
|
+
resources.each do |resource|
|
85
|
+
success = false unless resource.execute(operation)
|
86
|
+
break if plan.trap && plan.step
|
91
87
|
end
|
92
88
|
success
|
93
89
|
end
|
@@ -1,11 +1,7 @@
|
|
1
1
|
|
2
|
-
nucleon_require(File.dirname(__FILE__), :parallel_base)
|
3
|
-
|
4
|
-
#---
|
5
|
-
|
6
2
|
module CM
|
7
3
|
module Plugin
|
8
|
-
class Configuration < Nucleon.plugin_class(:nucleon, :
|
4
|
+
class Configuration < Nucleon.plugin_class(:nucleon, :base)
|
9
5
|
|
10
6
|
include Nucleon::Mixin::SubConfig
|
11
7
|
|
@@ -0,0 +1,315 @@
|
|
1
|
+
|
2
|
+
nucleon_require(File.dirname(__FILE__), :resource)
|
3
|
+
|
4
|
+
#---
|
5
|
+
|
6
|
+
module CM
|
7
|
+
module Plugin
|
8
|
+
class DockerResource < Nucleon.plugin_class(:CM, :resource)
|
9
|
+
|
10
|
+
#-----------------------------------------------------------------------------
|
11
|
+
# Plugin interface
|
12
|
+
|
13
|
+
def normalize(reload)
|
14
|
+
require 'docker'
|
15
|
+
super
|
16
|
+
|
17
|
+
codes :docker_exec_failed
|
18
|
+
|
19
|
+
settings[:docker_protocol] ||= 'unix'
|
20
|
+
settings[:docker_sock] ||= '/var/run/docker.sock'
|
21
|
+
settings[:docker_host] ||= nil
|
22
|
+
settings[:docker_port] ||= '127.0.0.1'
|
23
|
+
settings[:docker_image] ||= 'awebb/cm'
|
24
|
+
|
25
|
+
if settings[:docker_host].nil?
|
26
|
+
Docker.url = "#{settings[:docker_protocol]}://#{settings[:docker_sock]}"
|
27
|
+
else
|
28
|
+
Docker.url = "#{settings[:docker_protocol]}://#{settings[:docker_host]}:#{settings[:docker_port]}"
|
29
|
+
end
|
30
|
+
|
31
|
+
yield if block_given?
|
32
|
+
end
|
33
|
+
|
34
|
+
#---
|
35
|
+
|
36
|
+
def remove_plugin
|
37
|
+
destroy_container(plugin_instance_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
#-----------------------------------------------------------------------------
|
41
|
+
# Checks
|
42
|
+
|
43
|
+
def initialized?(options = {})
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
#---
|
48
|
+
|
49
|
+
def internal?
|
50
|
+
File.exist?('/.dockerinit')
|
51
|
+
end
|
52
|
+
|
53
|
+
#-----------------------------------------------------------------------------
|
54
|
+
# Property accessors / modifiers
|
55
|
+
|
56
|
+
def image
|
57
|
+
get(:image, 'awebb/cm').to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
#---
|
61
|
+
|
62
|
+
def startup_commands
|
63
|
+
get(:startup_commands, ['bash'])
|
64
|
+
end
|
65
|
+
|
66
|
+
#---
|
67
|
+
|
68
|
+
def container
|
69
|
+
@container
|
70
|
+
end
|
71
|
+
|
72
|
+
#---
|
73
|
+
|
74
|
+
def plan_directory
|
75
|
+
get(:plan_directory, '/opt/cm/volumes/plan')
|
76
|
+
end
|
77
|
+
|
78
|
+
def key_directory
|
79
|
+
get(:key_directory, '/opt/cm/volumes/keys')
|
80
|
+
end
|
81
|
+
|
82
|
+
#---
|
83
|
+
|
84
|
+
def host_input_directory
|
85
|
+
get(:host_input_directory, "/tmp/cm/input/#{plugin_instance_name}")
|
86
|
+
end
|
87
|
+
|
88
|
+
def input_directory
|
89
|
+
get(:input_directory, '/opt/cm/volumes/input')
|
90
|
+
end
|
91
|
+
|
92
|
+
#---
|
93
|
+
|
94
|
+
def host_output_directory
|
95
|
+
get(:host_output_directory, "/tmp/cm/output/#{plugin_instance_name}")
|
96
|
+
end
|
97
|
+
|
98
|
+
def output_directory
|
99
|
+
get(:output_directory, '/opt/cm/volumes/output')
|
100
|
+
end
|
101
|
+
|
102
|
+
#-----------------------------------------------------------------------------
|
103
|
+
# Operations
|
104
|
+
|
105
|
+
def operation_deploy
|
106
|
+
super do
|
107
|
+
data = nil
|
108
|
+
|
109
|
+
# A fork in the road!
|
110
|
+
if internal?
|
111
|
+
data = yield if block_given?
|
112
|
+
else
|
113
|
+
data = action(plugin_provider, :deploy)
|
114
|
+
myself.status = code.docker_exec_failed unless data
|
115
|
+
end
|
116
|
+
myself.data = data
|
117
|
+
myself.status == code.success
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
#-----------------------------------------------------------------------------
|
122
|
+
# Docker resource operation execution
|
123
|
+
|
124
|
+
def exec(command)
|
125
|
+
data = nil
|
126
|
+
|
127
|
+
create_container
|
128
|
+
|
129
|
+
results = container.exec(['bash', '-l', '-c', command]) do |stream, message|
|
130
|
+
unless message.match(/stdin\:\s+is not a tty/)
|
131
|
+
render_docker_message(stream, message)
|
132
|
+
yield(stream, message) if block_given?
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
if results[2] == 0
|
137
|
+
if output_config = CM.configuration(extended_config(:resource_results, {
|
138
|
+
:provider => get(:resource_result_provider, :directory),
|
139
|
+
:path => host_output_directory
|
140
|
+
}))
|
141
|
+
data = Nucleon::Util::Data.clone(output_config.export)
|
142
|
+
Nucleon.remove_plugin(output_config)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
destroy_container
|
147
|
+
data
|
148
|
+
end
|
149
|
+
|
150
|
+
#---
|
151
|
+
|
152
|
+
def command(command, options = {})
|
153
|
+
config = Nucleon::Config.ensure(options)
|
154
|
+
remove_command = false
|
155
|
+
|
156
|
+
unless command.is_a?(Nucleon::Plugin::Command)
|
157
|
+
command = Nucleon.command(Nucleon::Config.new({ :command => command }, {}, true, false).import(config), :bash)
|
158
|
+
remove_command = true
|
159
|
+
end
|
160
|
+
|
161
|
+
data = exec(command.to_s.strip) do |stream, message|
|
162
|
+
yield(stream, message) if block_given?
|
163
|
+
end
|
164
|
+
|
165
|
+
Nucleon.remove_plugin(command) if remove_command
|
166
|
+
data
|
167
|
+
end
|
168
|
+
|
169
|
+
#---
|
170
|
+
|
171
|
+
def action(provider, operation)
|
172
|
+
FileUtils.mkdir_p(host_input_directory)
|
173
|
+
FileUtils.mkdir_p(host_output_directory)
|
174
|
+
|
175
|
+
action_settings = Nucleon::Util::Data.clean(plan.action_settings)
|
176
|
+
initialize_remote_config(action_settings)
|
177
|
+
|
178
|
+
encoded_config = Nucleon::Util::CLI.encode(action_settings)
|
179
|
+
action_config = extended_config(:action, {
|
180
|
+
:command => 'resource run',
|
181
|
+
:data => { :encoded => encoded_config },
|
182
|
+
:args => [ provider, operation ]
|
183
|
+
})
|
184
|
+
action_config[:data][:log_level] = Nucleon.log_level if Nucleon.log_level
|
185
|
+
|
186
|
+
data = command('cm', Nucleon::Util::Data.clean({
|
187
|
+
:subcommand => action_config,
|
188
|
+
:quiet => Nucleon::Util::Console.quiet
|
189
|
+
})) do |stream, message|
|
190
|
+
yield(stream, message) if block_given?
|
191
|
+
end
|
192
|
+
|
193
|
+
FileUtils.rm_rf(host_input_directory)
|
194
|
+
FileUtils.rm_rf(host_output_directory)
|
195
|
+
data
|
196
|
+
end
|
197
|
+
|
198
|
+
#-----------------------------------------------------------------------------
|
199
|
+
# Utilities
|
200
|
+
|
201
|
+
def create_container
|
202
|
+
container = nil
|
203
|
+
|
204
|
+
destroy_container
|
205
|
+
|
206
|
+
container_env = []
|
207
|
+
container_env << "NUCLEON_NO_PARALLEL=1" unless Nucleon.parallel?
|
208
|
+
container_env << "NUCLEON_NO_COLOR=1" unless Nucleon::Util::Console.use_colors
|
209
|
+
|
210
|
+
@container = Docker::Container.create({
|
211
|
+
'name' => plugin_instance_name,
|
212
|
+
'Image' => image,
|
213
|
+
'Cmd' => array(startup_commands),
|
214
|
+
'Tty' => true,
|
215
|
+
'Env' => container_env,
|
216
|
+
'Volumes' => {
|
217
|
+
plan_directory => {},
|
218
|
+
key_directory => {},
|
219
|
+
input_directory => {},
|
220
|
+
output_directory => {}
|
221
|
+
},
|
222
|
+
'HostConfig' => {
|
223
|
+
'Binds' => [
|
224
|
+
"#{plan.path}:#{plan_directory}:ro",
|
225
|
+
"#{plan.key_directory}:#{key_directory}:rw",
|
226
|
+
"#{host_input_directory}:#{input_directory}:ro", # config.yaml and tokens.json
|
227
|
+
"#{host_output_directory}:#{output_directory}:rw" # ??.yaml and/or ??.json
|
228
|
+
]
|
229
|
+
}
|
230
|
+
})
|
231
|
+
|
232
|
+
if @container
|
233
|
+
@container.start!
|
234
|
+
else
|
235
|
+
error('cm.resource.docker.error.container_failed', {
|
236
|
+
:image => image
|
237
|
+
})
|
238
|
+
end
|
239
|
+
end
|
240
|
+
protected :create_container
|
241
|
+
|
242
|
+
#---
|
243
|
+
|
244
|
+
def initialize_remote_config(action_settings)
|
245
|
+
# Generate action settings file
|
246
|
+
settings = CM.configuration(extended_config(:container_input_settings_data, {
|
247
|
+
:provider => get(:container_input_settings_provider, :file),
|
248
|
+
:path => "#{host_input_directory}/action_settings.json"
|
249
|
+
}))
|
250
|
+
settings.import(action_settings)
|
251
|
+
settings.save
|
252
|
+
|
253
|
+
Nucleon.remove_plugin(settings)
|
254
|
+
|
255
|
+
# Generate and store plan configuration in local input directory
|
256
|
+
config = CM.configuration(extended_config(:container_input_config_data, {
|
257
|
+
:provider => get(:container_input_config_provider, :file),
|
258
|
+
:path => "#{host_input_directory}/config.json"
|
259
|
+
}))
|
260
|
+
config.import(plan.manifest_config)
|
261
|
+
config.save
|
262
|
+
|
263
|
+
Nucleon.remove_plugin(config)
|
264
|
+
|
265
|
+
# Generate and store plan tokens in local input directory
|
266
|
+
tokens = CM.configuration(extended_config(:container_input_token_data, {
|
267
|
+
:provider => get(:container_input_token_provider, :file),
|
268
|
+
:path => "#{host_output_directory}/tokens.json"
|
269
|
+
}))
|
270
|
+
tokens.import(plan.tokens)
|
271
|
+
tokens.save
|
272
|
+
|
273
|
+
Nucleon.remove_plugin(tokens)
|
274
|
+
|
275
|
+
# Customize action settings
|
276
|
+
action_settings[:resource_config] = myself.settings
|
277
|
+
action_settings[:settings_path] = "#{input_directory}/action_settings.json"
|
278
|
+
action_settings[:plan_path] = plan_directory
|
279
|
+
action_settings[:config_provider] = 'file'
|
280
|
+
action_settings[:config_path] = "#{input_directory}/config.json"
|
281
|
+
action_settings[:token_provider] = 'file'
|
282
|
+
action_settings[:token_path] = output_directory
|
283
|
+
action_settings[:token_file] = 'tokens.json'
|
284
|
+
action_settings[:key_path] = key_directory
|
285
|
+
end
|
286
|
+
protected :initialize_remote_config
|
287
|
+
|
288
|
+
|
289
|
+
#---
|
290
|
+
|
291
|
+
def destroy_container
|
292
|
+
containers = Docker::Container.all({ :all => 1 })
|
293
|
+
|
294
|
+
containers.each do |cont|
|
295
|
+
if cont.info.key?('Names') && cont.info['Names'].include?("/#{plugin_instance_name}")
|
296
|
+
cont.kill!
|
297
|
+
cont.remove
|
298
|
+
end
|
299
|
+
end
|
300
|
+
@container = nil
|
301
|
+
end
|
302
|
+
protected :destroy_container
|
303
|
+
|
304
|
+
#---
|
305
|
+
|
306
|
+
def render_docker_message(stream, message)
|
307
|
+
if stream == 'stderr'
|
308
|
+
puts message
|
309
|
+
else
|
310
|
+
puts message
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
data/lib/core/plugin/plan.rb
CHANGED
@@ -7,6 +7,10 @@ module CM
|
|
7
7
|
module Plugin
|
8
8
|
class Plan < Nucleon.plugin_class(:CM, :disk_configuration)
|
9
9
|
|
10
|
+
include Nucleon::Parallel # All sub providers are parallel capable
|
11
|
+
|
12
|
+
#---
|
13
|
+
|
10
14
|
def self.register_ids
|
11
15
|
[ :directory, :revision ]
|
12
16
|
end
|
@@ -17,50 +21,67 @@ class Plan < Nucleon.plugin_class(:CM, :disk_configuration)
|
|
17
21
|
def normalize(reload)
|
18
22
|
super
|
19
23
|
|
20
|
-
|
21
|
-
:provider => _get(:project_provider, Nucleon.type_default(:nucleon, :project)),
|
22
|
-
:directory => _get(:path, Dir.pwd),
|
23
|
-
:url => _get(:url),
|
24
|
-
:revision => _get(:revision, :master),
|
25
|
-
:create => true,
|
26
|
-
:pull => true,
|
27
|
-
:nucleon_resave => false,
|
28
|
-
:nucleon_cache => false,
|
29
|
-
:nucleon_file => false
|
30
|
-
}))
|
31
|
-
|
32
|
-
if project && !reload
|
24
|
+
if !reload
|
33
25
|
@loaded_config = CM.configuration(extended_config(:config_data, {
|
34
26
|
:provider => _get(:config_provider, :directory),
|
35
|
-
:path =>
|
27
|
+
:path => config_path
|
28
|
+
}))
|
29
|
+
|
30
|
+
@tokens = CM.configuration(extended_config(:token_data, {
|
31
|
+
:provider => _get(:token_provider, :file),
|
32
|
+
:path => token_path
|
36
33
|
}))
|
37
34
|
|
38
35
|
yield if block_given?
|
39
36
|
end
|
40
37
|
end
|
41
38
|
|
39
|
+
#---
|
40
|
+
|
41
|
+
def init_tokens
|
42
|
+
clear_tokens
|
43
|
+
|
44
|
+
collect_tokens = lambda do |local_settings, token|
|
45
|
+
local_settings.each do |name, value|
|
46
|
+
setting_token = [ array(token), name ].flatten
|
47
|
+
|
48
|
+
if value.is_a?(Hash)
|
49
|
+
collect_tokens.call(value, setting_token)
|
50
|
+
else
|
51
|
+
token_base = setting_token.shift
|
52
|
+
set_token(token_base, setting_token, value)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Generate config tokens
|
58
|
+
collect_tokens.call(manifest_config, 'config')
|
59
|
+
end
|
60
|
+
|
42
61
|
#-----------------------------------------------------------------------------
|
43
62
|
# Checks
|
44
63
|
|
45
64
|
def initialized?(options = {})
|
46
|
-
|
65
|
+
loaded_config
|
47
66
|
end
|
48
67
|
|
49
68
|
#-----------------------------------------------------------------------------
|
50
69
|
# Property accessors / modifiers
|
51
70
|
|
52
|
-
def project
|
53
|
-
@project
|
54
|
-
end
|
55
|
-
|
56
71
|
def loaded_config
|
57
72
|
@loaded_config
|
58
73
|
end
|
59
74
|
|
60
75
|
#---
|
61
76
|
|
77
|
+
def action_settings
|
78
|
+
_get(:action_settings, {})
|
79
|
+
end
|
80
|
+
|
81
|
+
#---
|
82
|
+
|
62
83
|
def path
|
63
|
-
|
84
|
+
_get(:path, Dir.pwd)
|
64
85
|
end
|
65
86
|
|
66
87
|
def key_directory
|
@@ -85,39 +106,60 @@ class Plan < Nucleon.plugin_class(:CM, :disk_configuration)
|
|
85
106
|
get_hash(:config)
|
86
107
|
end
|
87
108
|
|
88
|
-
def
|
89
|
-
get_array(:
|
109
|
+
def manifest_resources
|
110
|
+
get_array(:resources)
|
111
|
+
end
|
112
|
+
|
113
|
+
#---
|
114
|
+
|
115
|
+
def config_path
|
116
|
+
_get(:config_path, path)
|
90
117
|
end
|
91
118
|
|
92
119
|
#---
|
93
120
|
|
94
|
-
def
|
95
|
-
|
121
|
+
def sequence
|
122
|
+
@sequence
|
96
123
|
end
|
97
124
|
|
98
|
-
|
99
|
-
|
125
|
+
#---
|
126
|
+
|
127
|
+
def token_directory
|
128
|
+
_get(:token_directory, config_path)
|
100
129
|
end
|
101
130
|
|
102
|
-
def
|
103
|
-
|
131
|
+
def token_file
|
132
|
+
_get(:token_file, 'tokens.json')
|
104
133
|
end
|
105
134
|
|
135
|
+
def token_path
|
136
|
+
::File.join(token_directory, token_file)
|
137
|
+
end
|
106
138
|
|
107
139
|
#---
|
108
140
|
|
109
|
-
def
|
110
|
-
|
141
|
+
def tokens
|
142
|
+
@tokens.parse
|
111
143
|
end
|
112
144
|
|
113
|
-
def
|
114
|
-
|
145
|
+
def set_token(id, location, value)
|
146
|
+
@tokens["#{id}:#{array(location).join('.')}"] = value
|
147
|
+
@tokens.save
|
148
|
+
end
|
149
|
+
|
150
|
+
def remove_token(id, location)
|
151
|
+
@tokens.delete("#{id}:#{array(location).join('.')}")
|
152
|
+
@tokens.save
|
153
|
+
end
|
154
|
+
|
155
|
+
def clear_tokens
|
156
|
+
@tokens.wipe
|
115
157
|
end
|
116
158
|
|
117
159
|
#---
|
118
160
|
|
119
|
-
def
|
120
|
-
|
161
|
+
def trap
|
162
|
+
_get(:trap, false)
|
121
163
|
end
|
122
164
|
|
123
165
|
#-----------------------------------------------------------------------------
|
@@ -127,7 +169,7 @@ class Plan < Nucleon.plugin_class(:CM, :disk_configuration)
|
|
127
169
|
success = true
|
128
170
|
|
129
171
|
if initialized?
|
130
|
-
# Initialize plan manifest (default config and
|
172
|
+
# Initialize plan manifest (default config and resources)
|
131
173
|
wipe
|
132
174
|
import(CM.configuration(extended_config(:manifest_data, {
|
133
175
|
:provider => _get(:manifest_provider, :file),
|
@@ -137,12 +179,8 @@ class Plan < Nucleon.plugin_class(:CM, :disk_configuration)
|
|
137
179
|
# Merge in configuration overlay (private config)
|
138
180
|
override(loaded_config.get_hash(:config), :config)
|
139
181
|
|
140
|
-
#
|
141
|
-
@sequence =
|
142
|
-
:jobs => manifest_jobs,
|
143
|
-
:settings => manifest_config,
|
144
|
-
:trap => _get(:trap, false)
|
145
|
-
}, _get(:sequence_provider, :default))
|
182
|
+
# Initializeresource sequence
|
183
|
+
@sequence = create_sequence(manifest_resources)
|
146
184
|
|
147
185
|
yield if block_given?
|
148
186
|
end
|
@@ -151,14 +189,17 @@ class Plan < Nucleon.plugin_class(:CM, :disk_configuration)
|
|
151
189
|
|
152
190
|
#---
|
153
191
|
|
154
|
-
def execute(operation
|
192
|
+
def execute(operation)
|
155
193
|
success = true
|
156
194
|
|
157
195
|
if initialized?
|
158
196
|
if ::File.exist?(manifest_path)
|
159
197
|
method = "operation_#{operation}"
|
160
|
-
|
161
|
-
|
198
|
+
|
199
|
+
if respond_to?(method) && load
|
200
|
+
init_tokens
|
201
|
+
success = send(method)
|
202
|
+
end
|
162
203
|
success
|
163
204
|
else
|
164
205
|
error('manifest_file', { :file => manifest_path })
|
@@ -172,27 +213,57 @@ class Plan < Nucleon.plugin_class(:CM, :disk_configuration)
|
|
172
213
|
|
173
214
|
#---
|
174
215
|
|
175
|
-
def operation_deploy
|
176
|
-
|
177
|
-
sequence.forward(config)
|
216
|
+
def operation_deploy
|
217
|
+
sequence.forward(:deploy)
|
178
218
|
end
|
179
219
|
|
180
220
|
#---
|
181
221
|
|
182
|
-
def operation_destroy
|
183
|
-
|
184
|
-
|
222
|
+
def operation_destroy
|
223
|
+
sequence.reverse(:destroy)
|
224
|
+
end
|
225
|
+
|
226
|
+
#-----------------------------------------------------------------------------
|
227
|
+
# Utilities
|
228
|
+
|
229
|
+
def create_sequence(resources)
|
230
|
+
CM.sequence({
|
231
|
+
:plan => myself,
|
232
|
+
:settings => manifest_config,
|
233
|
+
:resources => resources,
|
234
|
+
:new => true,
|
235
|
+
}, _get(:sequence_provider, :default))
|
185
236
|
end
|
186
237
|
|
187
238
|
#---
|
188
239
|
|
189
|
-
def
|
190
|
-
|
240
|
+
def create_batch(resources)
|
241
|
+
CM.batch({
|
242
|
+
:plan => myself,
|
243
|
+
:resources => resources,
|
244
|
+
:new => true
|
245
|
+
}, _get(:batch_provider, :celluloid))
|
191
246
|
end
|
192
247
|
|
193
|
-
|
194
|
-
# Utilities
|
248
|
+
#---
|
195
249
|
|
250
|
+
def create_resource(settings)
|
251
|
+
settings = Nucleon::Config.ensure(settings)
|
252
|
+
settings[:type] ||= _get(:default_resource_provider, :variables)
|
253
|
+
|
254
|
+
CM.resource({
|
255
|
+
:plan => myself,
|
256
|
+
:settings => settings.export,
|
257
|
+
:id => settings[:name]
|
258
|
+
}, settings[:type])
|
259
|
+
end
|
260
|
+
|
261
|
+
#---
|
262
|
+
|
263
|
+
def step
|
264
|
+
answer = ask('Continue? (yes|no): ', { :i18n => false })
|
265
|
+
answer.match(/^[Yy][Ee][Ss]$/) ? false : true
|
266
|
+
end
|
196
267
|
end
|
197
268
|
end
|
198
269
|
end
|