capistrano-soa 0.0.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.
- data/README.md +31 -0
- data/capistrano-soa.gemspec +22 -0
- data/lib/capistrano/ext/soa.rb +372 -0
- data/lib/capistrano/version.rb +0 -0
- data/spec/recipes/fake_recipe.rb +46 -0
- data/spec/soa_spec.rb +150 -0
- data/spec/spec_helper.rb +21 -0
- metadata +57 -0
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Capistrano SOA
|
2
|
+
- An extension for Capistrano supporting SOA Services Deployment
|
3
|
+
|
4
|
+
Capistrano SOA let you management services group in SOA architecuture with multi-stage support.
|
5
|
+
|
6
|
+
## Usage
|
7
|
+
|
8
|
+
project/
|
9
|
+
|- config/
|
10
|
+
|- deploy.rb
|
11
|
+
|- deploy/
|
12
|
+
|- sub_project_a/
|
13
|
+
| |- service_a/
|
14
|
+
| | |- development.rb
|
15
|
+
| | |- production.rb
|
16
|
+
| |- service_b
|
17
|
+
| |- development.rb
|
18
|
+
| |- production.rb
|
19
|
+
|- sub_project_b/
|
20
|
+
|- service_c/
|
21
|
+
| |- development.rb
|
22
|
+
| |- production.rb
|
23
|
+
|- service_d
|
24
|
+
|- development.rb
|
25
|
+
|- production.rb
|
26
|
+
|
27
|
+
cap production sub_project_a:service_a deploy
|
28
|
+
|
29
|
+
cap sub_project_a:service_a:production deploy
|
30
|
+
|
31
|
+
cap production sub_project_a:service_a sub_project_a:service_b deploy
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "capistrano/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
|
7
|
+
s.name = "capistrano-soa"
|
8
|
+
s.version = "0.0.6"
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Ben Wu"]
|
11
|
+
s.email = ["wucheokman@gmail.com"]
|
12
|
+
s.homepage = "http://github.com/capistrano/capistrano-soa"
|
13
|
+
s.summary = %q{An extension for Capistrano supporting SOA Services Deployment}
|
14
|
+
s.description = %q{Capistrano SOA let you management services group in SOA architecuture with multi-stage support.}
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.extra_rdoc_files = [
|
20
|
+
"README.md"
|
21
|
+
]
|
22
|
+
end
|
@@ -0,0 +1,372 @@
|
|
1
|
+
require 'capistrano'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'colored'
|
4
|
+
|
5
|
+
module Capistrano::Ext
|
6
|
+
module SOA
|
7
|
+
def get_config_files(config_root)
|
8
|
+
config_files = Dir["#{config_root}/**/*.rb"]
|
9
|
+
config_files.reject! do |config_file|
|
10
|
+
config_dir = config_file.gsub(/\.rb$/, '/')
|
11
|
+
config_files.any? { |file| file[0, config_dir.size] == config_dir }
|
12
|
+
end
|
13
|
+
config_files
|
14
|
+
end
|
15
|
+
|
16
|
+
def collect_stages(config_files)
|
17
|
+
config_files.map {|f| File.basename(f, ".rb")}.uniq
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_config_names(config_files, config_root)
|
21
|
+
config_names = config_files.map do |config_file|
|
22
|
+
config_file.sub("#{config_root}/", '').sub(/\.rb$/, '').gsub('/', ':')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_services_name(config_names)
|
27
|
+
services_name = []
|
28
|
+
config_names.each do |config_name|
|
29
|
+
services_name << extract_service_name(config_name)
|
30
|
+
end
|
31
|
+
services_name
|
32
|
+
end
|
33
|
+
|
34
|
+
def extract_service_name(config_name)
|
35
|
+
segments = config_name.split(':')
|
36
|
+
segments[0, segments.size - 1].join(':')
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_service_name(config_name, services)
|
40
|
+
if services.include?(config_name)
|
41
|
+
config_name
|
42
|
+
else
|
43
|
+
segments = config_name.split(':')
|
44
|
+
if segments.size > 1
|
45
|
+
possible_service_name = (segments[0, segments.size - 1].join(':'))
|
46
|
+
else
|
47
|
+
possible_service_name = segments[0]
|
48
|
+
end
|
49
|
+
if services.include?(possible_service_name)
|
50
|
+
possible_service_name
|
51
|
+
elsif possible_service_name == "world"
|
52
|
+
services.dup
|
53
|
+
else
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_stage_name(config_name, stages)
|
60
|
+
possible_stage_name = config_name.split(':').last
|
61
|
+
stages.include?(possible_stage_name) ? possible_stage_name : nil
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# One Environment with different applications deployment
|
66
|
+
# cap integration prj0:subprj0:app0 prj1:subprj0:app1 deploy
|
67
|
+
# cap prj0:subprj0:app0:integration prj0:subprj0:app0:integration deploy
|
68
|
+
#
|
69
|
+
# One environment with one application
|
70
|
+
# cap prj0:subprj0:app0:integration deploy
|
71
|
+
#
|
72
|
+
# Different Environments with different applications deployment
|
73
|
+
# cap prj0:subprj0:app0:integration prj0:subprj0:app0:staging deploy
|
74
|
+
#
|
75
|
+
|
76
|
+
def parse_args(args, stages, services)
|
77
|
+
args = args.dup
|
78
|
+
selected_services = []
|
79
|
+
task = nil
|
80
|
+
selected_stage = nil
|
81
|
+
|
82
|
+
selected_stage = if stages.include?(args.first)
|
83
|
+
args.shift
|
84
|
+
elsif !get_stage_name(args.first, stages).nil?
|
85
|
+
arg = args.shift
|
86
|
+
selected_services << get_service_name(arg, services)
|
87
|
+
get_stage_name(arg, stages)
|
88
|
+
else
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
args.each do |a|
|
92
|
+
if selected_stage.nil? && !get_stage_name(a, stages).nil?
|
93
|
+
selected_stage = get_stage_name(a, stages)
|
94
|
+
_service = get_service_name(a, services)
|
95
|
+
selected_services << _service unless selected_services.include?(_service)
|
96
|
+
elsif !get_service_name(a, services).nil?
|
97
|
+
_service = get_service_name(a, services)
|
98
|
+
selected_services << _service unless selected_services.include?(_service)
|
99
|
+
else
|
100
|
+
task = a
|
101
|
+
break
|
102
|
+
end
|
103
|
+
end
|
104
|
+
[selected_stage, selected_services.flatten.uniq, task]
|
105
|
+
end
|
106
|
+
|
107
|
+
def build_task(stage, services, this_task)
|
108
|
+
|
109
|
+
if services.size > 1
|
110
|
+
segments = this_task.split(':')
|
111
|
+
if segments.size > 1
|
112
|
+
namespace_names = segments[0, segments.size-1]
|
113
|
+
task_name = segments.last
|
114
|
+
else
|
115
|
+
namespace_names = [segments[0]]
|
116
|
+
task_name = "default"
|
117
|
+
end
|
118
|
+
|
119
|
+
block = lambda do |parent|
|
120
|
+
alias_task "_#{task_name}".to_sym, task_name.to_sym
|
121
|
+
|
122
|
+
task(task_name) do
|
123
|
+
services.each do |service|
|
124
|
+
system("cap #{stage} #{service} #{this_task}")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
block = namespace_names.reverse.inject(block) do |child, name|
|
130
|
+
lambda do |parent|
|
131
|
+
parent.namespace(name, &child)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
block.call(top)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.load_into(configuration)
|
139
|
+
configuration.extend self
|
140
|
+
|
141
|
+
configuration.load do
|
142
|
+
config_root = File.expand_path(fetch(:config_root, "config/deploy"))
|
143
|
+
|
144
|
+
#config_files = Dir["#{config_root}/**/*.rb"]
|
145
|
+
config_files = get_config_files(config_root)
|
146
|
+
|
147
|
+
set :stages, collect_stages(config_files) unless exists?(:stages)
|
148
|
+
|
149
|
+
# build configuration names list
|
150
|
+
config_names = get_config_names(config_files,config_root)
|
151
|
+
|
152
|
+
config_names.each do |config_name|
|
153
|
+
config_name.split(':').each do |segment|
|
154
|
+
if all_methods.any? { |m| m == segment }
|
155
|
+
raise ArgumentError, "Config task #{config_name} name overrides #{segment.inspect} (method|task|namespace)"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
stages.each do |s|
|
161
|
+
desc "Set the target stage to `#{s}'."
|
162
|
+
|
163
|
+
task(s.to_sym) do
|
164
|
+
top.set :stage, s.to_sym
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# create configuration task for each configuration name
|
169
|
+
config_names.each do |config_name|
|
170
|
+
segments = config_name.split(':')
|
171
|
+
namespace_names = segments[0, segments.size - 1]
|
172
|
+
task_name = segments.last
|
173
|
+
|
174
|
+
# create configuration task block.
|
175
|
+
# NOTE: Capistrano 'namespace' DSL invokes instance_eval that
|
176
|
+
# that pass evaluable object as argument to block.
|
177
|
+
block = lambda do |parent|
|
178
|
+
task(:default) do
|
179
|
+
default_segment = segments[0, segments.size - 1]
|
180
|
+
default_segment << fetch(:stage)
|
181
|
+
default_segment.size.times do |i|
|
182
|
+
path = ([config_root] + default_segment[0..i]).join('/') + '.rb'
|
183
|
+
top.load(:file => path) if File.exists?(path)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
desc "Load #{config_name} configuration"
|
188
|
+
task(task_name) do
|
189
|
+
# set configuration name as :config_name variable
|
190
|
+
top.set :config_name, config_name
|
191
|
+
|
192
|
+
#set :stage, task_name.to_sym
|
193
|
+
# recursively load configurations
|
194
|
+
segments.size.times do |i|
|
195
|
+
path = ([config_root] + segments[0..i]).join('/') + '.rb'
|
196
|
+
top.load(:file => path) if File.exists?(path)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# wrap task block into namespace blocks
|
202
|
+
#
|
203
|
+
# namespace_names = [nsN, ..., ns2, ns1]
|
204
|
+
#
|
205
|
+
# block = block0 = lambda do |parent|
|
206
|
+
# desc "DESC"
|
207
|
+
# task(:task_name) { TASK }
|
208
|
+
# end
|
209
|
+
# block = block1 = lambda { |parent| parent.namespace(:ns1, &block0) }
|
210
|
+
# block = block2 = lambda { |parent| parent.namespace(:ns2, &block1) }
|
211
|
+
# ...
|
212
|
+
# block = blockN = lambda { |parent| parent.namespace(:nsN, &blockN-1) }
|
213
|
+
#
|
214
|
+
block = namespace_names.reverse.inject(block) do |child, name|
|
215
|
+
lambda do |parent|
|
216
|
+
parent.namespace(name, &child)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# create namespaced configuration task
|
221
|
+
#
|
222
|
+
# block = lambda do
|
223
|
+
# namespace :nsN do
|
224
|
+
# ...
|
225
|
+
# namespace :ns2 do
|
226
|
+
# namespace :ns1 do
|
227
|
+
# desc "DESC"
|
228
|
+
# task(:task_name) { TASK }
|
229
|
+
# end
|
230
|
+
# end
|
231
|
+
# ...
|
232
|
+
# end
|
233
|
+
# end
|
234
|
+
block.call(top)
|
235
|
+
end
|
236
|
+
|
237
|
+
STDOUT.sync
|
238
|
+
before "deploy:update_code" do
|
239
|
+
print "Updating Code........ "
|
240
|
+
start_spinner()
|
241
|
+
end
|
242
|
+
|
243
|
+
after "deploy:update_code" do
|
244
|
+
stop_spinner()
|
245
|
+
puts "Done.".green
|
246
|
+
end
|
247
|
+
|
248
|
+
before "deploy:cleanup" do
|
249
|
+
print "Cleaning Up.......... "
|
250
|
+
start_spinner()
|
251
|
+
end
|
252
|
+
|
253
|
+
after "deploy:restart" do
|
254
|
+
stop_spinner()
|
255
|
+
puts "Done.".green
|
256
|
+
end
|
257
|
+
|
258
|
+
before "deploy:restart" do
|
259
|
+
print "Restarting .......... "
|
260
|
+
start_spinner()
|
261
|
+
end
|
262
|
+
|
263
|
+
after "deploy:cleanup" do
|
264
|
+
stop_spinner()
|
265
|
+
puts "Done.".green
|
266
|
+
end
|
267
|
+
# spinner stuff
|
268
|
+
@spinner_running = false
|
269
|
+
@chars = ['|', '/', '-', '\\']
|
270
|
+
@spinner = Thread.new do
|
271
|
+
loop do
|
272
|
+
unless @spinner_running
|
273
|
+
Thread.stop
|
274
|
+
end
|
275
|
+
print @chars[0]
|
276
|
+
sleep(0.1)
|
277
|
+
print "\b"
|
278
|
+
@chars.push @chars.shift
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def start_spinner
|
283
|
+
@spinner_running = true
|
284
|
+
@spinner.wakeup
|
285
|
+
end
|
286
|
+
|
287
|
+
# stops the spinner and backspaces over last displayed character
|
288
|
+
def stop_spinner
|
289
|
+
@spinner_running = false
|
290
|
+
print "\b"
|
291
|
+
end
|
292
|
+
|
293
|
+
on :load do
|
294
|
+
services_name = get_services_name(config_names)
|
295
|
+
|
296
|
+
selected_stage, selected_services, selected_task = parse_args(ARGV, stages, services_name)
|
297
|
+
|
298
|
+
set :stage, selected_stage
|
299
|
+
set :services, selected_services
|
300
|
+
build_task(selected_stage, selected_services, selected_task)
|
301
|
+
|
302
|
+
if stages.include?(stage)
|
303
|
+
# Execute the specified stage so that recipes required in stage can contribute to task list
|
304
|
+
tsk = stage
|
305
|
+
tsk = "#{services.first}:#{tsk}" if services.first
|
306
|
+
find_and_execute_task(tsk)# if ARGV.any?{ |option| option =~ /-T|--tasks|-e|--explain/ }
|
307
|
+
else
|
308
|
+
# Execute the default stage so that recipes required in stage can contribute tasks
|
309
|
+
if exists?(:default_stage)
|
310
|
+
tsk = default_stage
|
311
|
+
tsk = "#{services.first}:#{tsk}" if services.first
|
312
|
+
find_and_execute_task(tsk)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
namespace :soa do
|
318
|
+
desc "[internal] Ensure that a stage has been selected."
|
319
|
+
task :ensure do
|
320
|
+
if !exists?(:stage)
|
321
|
+
if exists?(:default_stage)
|
322
|
+
logger.important "Defaulting to `#{default_stage}'"
|
323
|
+
find_and_execute_task("#{ARGV.first}:#{default_stage}")
|
324
|
+
else
|
325
|
+
abort "No stage specified. Please specify one of: #{stages.join(', ')} (e.g. `cap #{stages.first} #{ARGV.last}')"
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
set(:config_names, config_names)
|
332
|
+
|
333
|
+
on :start, "soa:ensure"
|
334
|
+
|
335
|
+
def service_list_from(services)
|
336
|
+
services = services.split(',') if String == services
|
337
|
+
services.reject {|s| !services_name.include?(s)}
|
338
|
+
end
|
339
|
+
|
340
|
+
def find_soa_stages(stage)
|
341
|
+
unless ENV["SRVS"].nil?
|
342
|
+
services = services_list_from(ENV["SRVS"])
|
343
|
+
else
|
344
|
+
services = services_name
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
task(:world) do
|
349
|
+
end
|
350
|
+
|
351
|
+
# namespace :world do
|
352
|
+
# stages.each do |stage|
|
353
|
+
# namespace stage.to_sym do
|
354
|
+
# task :deploy do
|
355
|
+
# end
|
356
|
+
# end
|
357
|
+
# end
|
358
|
+
# end
|
359
|
+
end
|
360
|
+
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
unless Capistrano::Configuration.respond_to?(:instance)
|
367
|
+
abort "capistrano/ext/soa require Capistrano 2"
|
368
|
+
end
|
369
|
+
|
370
|
+
if Capistrano::Configuration.instance
|
371
|
+
Capistrano::Ext::SOA.load_into(Capistrano::Configuration.instance)
|
372
|
+
end
|
File without changes
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'capistrano'
|
2
|
+
module Capistrano
|
3
|
+
module Fakerecipe
|
4
|
+
def self.load_into(configuration)
|
5
|
+
configuration.load do
|
6
|
+
before "fake:before_this_execute_thing", "fake:thing"
|
7
|
+
before "fake:before_this_also_execute_thing", "fake:thing"
|
8
|
+
after "fake:after_this_execute_thing", "fake:thing"
|
9
|
+
after "fake:after_this_also_execute_thing", "fake:thing"
|
10
|
+
namespace :fake do
|
11
|
+
namespace :inner_fake do
|
12
|
+
task :inner_thing do
|
13
|
+
run ('do inner some stuff')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
desc "thing and run fake manifests"
|
17
|
+
task :thing do
|
18
|
+
set :bar, "baz"
|
19
|
+
run('do some stuff')
|
20
|
+
upload("foo", "/tmp/foo")
|
21
|
+
get('/tmp/baz', 'baz')
|
22
|
+
put('fake content', '/tmp/put')
|
23
|
+
end
|
24
|
+
desc "More fake tasks!"
|
25
|
+
task :before_this_execute_thing do
|
26
|
+
#
|
27
|
+
end
|
28
|
+
desc "You get the picture..."
|
29
|
+
task :before_this_also_execute_thing do
|
30
|
+
#
|
31
|
+
end
|
32
|
+
task :after_this_execute_thing do
|
33
|
+
#
|
34
|
+
end
|
35
|
+
task :after_this_also_execute_thing do
|
36
|
+
#
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
if Capistrano::Configuration.instance
|
45
|
+
Capistrano::FakeRecipe.load_into(Capistrano::Configuration.instance)
|
46
|
+
end
|
data/spec/soa_spec.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
2
|
+
require File.expand_path('../recipes/fake_recipe', __FILE__)
|
3
|
+
describe Capistrano::Ext::SOA, "loaded into a configuration" do
|
4
|
+
before do
|
5
|
+
@configuration = Capistrano::Configuration.new
|
6
|
+
|
7
|
+
@configuration.extend(Capistrano::Spec::ConfigurationExtension)
|
8
|
+
config_root = "/opt/deploy"
|
9
|
+
|
10
|
+
File.stub!(:expand_path) {config_root}
|
11
|
+
@project_dir = ["a/b/production.rb", "a/b/staging.rb", "a/b.rb", "a/c/staging.rb"]
|
12
|
+
|
13
|
+
Dir.stub!(:[]) {@project_dir.map {|dir| "#{config_root}/#{dir}"}}
|
14
|
+
@configuration.extend(Capistrano::Fakerecipe)
|
15
|
+
Capistrano::Fakerecipe.load_into(@configuration)
|
16
|
+
Capistrano::Ext::SOA.load_into(@configuration)
|
17
|
+
@stages = ["production", "staging"]
|
18
|
+
@services = ["a:b", "a:c"]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should define correct tasks" do
|
22
|
+
@configuration.find_task('a:b:production').should_not == nil
|
23
|
+
@configuration.find_task('a:b:staging').should_not == nil
|
24
|
+
@configuration.find_task('a:c:staging').should_not == nil
|
25
|
+
@configuration.find_task('a:c:production').should == nil
|
26
|
+
@configuration.find_task('soa:ensure').should_not == nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should use default stage if not stage define" do
|
30
|
+
@configuration.set :default_stage, 'staging'
|
31
|
+
@configuration.find_task('a:c').should_not == nil
|
32
|
+
@configuration.find_task('world:staging:deploy')
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should parse with stage only args" do
|
36
|
+
args = ["staging"]
|
37
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
38
|
+
selected_services.should be_empty
|
39
|
+
selected_stage.should == "staging"
|
40
|
+
task.should == nil
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should parse single stage with one or more services" do
|
44
|
+
args = ["staging", "a:b", "a:b:production"]
|
45
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
46
|
+
selected_services.should == ["a:b"]
|
47
|
+
selected_stage.should == "staging"
|
48
|
+
task.should == nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should parse single stage with one or more services" do
|
52
|
+
args = ["a:b", "a:c"]
|
53
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
54
|
+
selected_services.should == ["a:b", "a:c"]
|
55
|
+
selected_stage.should == nil
|
56
|
+
task.should == nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should parse single stage with one or more services" do
|
60
|
+
args = ["a:b:integration", "a:c"]
|
61
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
62
|
+
selected_services.should == ["a:b", "a:c"]
|
63
|
+
selected_stage.should == nil
|
64
|
+
task.should == nil
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should parse single stage with one or more services" do
|
68
|
+
args = ["staging", "a:b", "a:c:production"]
|
69
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
70
|
+
selected_services.should == ["a:b", "a:c"]
|
71
|
+
selected_stage.should == "staging"
|
72
|
+
task.should == nil
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should parse single stage with one or more services" do
|
76
|
+
args = ["a:b:staging", "a:c:production"]
|
77
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
78
|
+
selected_services.should == ["a:b", "a:c"]
|
79
|
+
selected_stage.should == "staging"
|
80
|
+
task.should == nil
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should parse single stage with one or more services" do
|
84
|
+
args = ["a:b", "a:c:production"]
|
85
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
86
|
+
selected_services.should == ["a:b", "a:c"]
|
87
|
+
selected_stage.should == "production"
|
88
|
+
task.should == nil
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should parse single stage with one or more services" do
|
92
|
+
args = ["staging","a:b", "deploy:start"]
|
93
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
94
|
+
selected_services.should == ["a:b"]
|
95
|
+
selected_stage.should == "staging"
|
96
|
+
task.should == "deploy:start"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should parse single stage with one or more services" do
|
100
|
+
args = ["staging","a:b", "deploy:start", "a:d"]
|
101
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
102
|
+
selected_services.should == ["a:b"]
|
103
|
+
selected_stage.should == "staging"
|
104
|
+
task.should == "deploy:start"
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should parse single stage with one or more services" do
|
108
|
+
args = ["staging","a:b", "a:d", "deploy:start"]
|
109
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
110
|
+
selected_services.should == ["a:b"]
|
111
|
+
selected_stage.should == "staging"
|
112
|
+
task.should == "a:d"
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should parse single stage with one or more services" do
|
116
|
+
args = ["staging","world", "deploy:start"]
|
117
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
118
|
+
selected_services.should == ["a:b", "a:c"]
|
119
|
+
selected_stage.should == "staging"
|
120
|
+
task.should == "deploy:start"
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should parse single stage with one or more services" do
|
124
|
+
args = ["world:staging", "deploy:start"]
|
125
|
+
selected_stage, selected_services, task = @configuration.parse_args(args, @stages, @services)
|
126
|
+
selected_services.should == ["a:b", "a:c"]
|
127
|
+
selected_stage.should == "staging"
|
128
|
+
task.should == "deploy:start"
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should run one stage and service on load" do
|
132
|
+
args = ["staging"]
|
133
|
+
ARGV = args
|
134
|
+
@configuration.trigger(:load)
|
135
|
+
@configuration.fetch(:stage).should == "staging"
|
136
|
+
@configuration.fetch(:services).should == []
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should build a task for services" do
|
140
|
+
@configuration.stub!(:services).and_return(["a:b", "a:c"])
|
141
|
+
|
142
|
+
@configuration.build_task("staging", ["a:b", "a:c"],"fake:thing")
|
143
|
+
|
144
|
+
@configuration.find_task("fake:_thing").should_not == nil
|
145
|
+
@configuration.find_task("fake:thing").should_not == nil
|
146
|
+
|
147
|
+
@configuration.find_and_execute_task("fake:thing")
|
148
|
+
@configuration.fetch(:bar).should == "baz"
|
149
|
+
end
|
150
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
|
4
|
+
|
5
|
+
require 'rspec'
|
6
|
+
require 'capistrano'
|
7
|
+
require 'capistrano-spec'
|
8
|
+
require 'rspec'
|
9
|
+
require 'rspec/autorun'
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
# Add capistrano-spec matchers and helpers to RSpec
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.include Capistrano::Spec::Matchers
|
17
|
+
config.include Capistrano::Spec::Helpers
|
18
|
+
end
|
19
|
+
|
20
|
+
# Require your lib here
|
21
|
+
require 'capistrano/ext/soa'
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: capistrano-soa
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.6
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ben Wu
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-09-06 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Capistrano SOA let you management services group in SOA architecuture
|
15
|
+
with multi-stage support.
|
16
|
+
email:
|
17
|
+
- wucheokman@gmail.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files:
|
21
|
+
- README.md
|
22
|
+
files:
|
23
|
+
- README.md
|
24
|
+
- capistrano-soa.gemspec
|
25
|
+
- lib/capistrano/ext/soa.rb
|
26
|
+
- lib/capistrano/version.rb
|
27
|
+
- spec/recipes/fake_recipe.rb
|
28
|
+
- spec/soa_spec.rb
|
29
|
+
- spec/spec_helper.rb
|
30
|
+
homepage: http://github.com/capistrano/capistrano-soa
|
31
|
+
licenses: []
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements: []
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 1.8.25
|
51
|
+
signing_key:
|
52
|
+
specification_version: 3
|
53
|
+
summary: An extension for Capistrano supporting SOA Services Deployment
|
54
|
+
test_files:
|
55
|
+
- spec/recipes/fake_recipe.rb
|
56
|
+
- spec/soa_spec.rb
|
57
|
+
- spec/spec_helper.rb
|