capistrano-soa 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|