houcho 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module Houcho
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,27 @@
1
+ module Houcho
2
+ module YamlHandle
3
+ class Loader
4
+ attr_reader :data
5
+
6
+ def initialize(yaml_file)
7
+ @data = YAML.load_file(yaml_file)
8
+ @data ||= {}
9
+ end
10
+ end
11
+
12
+ class Editor < Loader
13
+ attr_accessor :data
14
+
15
+ def initialize(yaml_file)
16
+ super
17
+ @yaml_file = yaml_file
18
+ end
19
+
20
+ def save_to_file
21
+ open(@yaml_file, 'w') do |f|
22
+ YAML.dump(@data, f)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,10 @@
1
+ ---
2
+ ukigumo:
3
+ host:
4
+ port:
5
+ ikachan:
6
+ host:
7
+ port:
8
+ channel: []
9
+ git:
10
+ uri:
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ require 'yaml'
3
+ File.write('./conf', {
4
+ 'ukigumo' => {
5
+ 'host' => nil,
6
+ 'port' => nil,
7
+ },
8
+ 'ikachan' => {
9
+ 'host' => nil,
10
+ 'port' => nil,
11
+ 'channel' => [],
12
+ },
13
+ 'git' => {'uri' => nil}
14
+ }.to_yaml)
@@ -0,0 +1 @@
1
+ --format documentation
@@ -0,0 +1,94 @@
1
+ module Houcho
2
+ module Initialize
3
+ %W{conf role/cloudforecast spec}.each do |d|
4
+ FileUtils.mkdir_p d if ! Dir.exists? d
5
+ end
6
+
7
+ File.write('./role/cloudforecast/houcho_sample.yaml', <<EOH
8
+ --- #houcho
9
+ servers:
10
+ - label: author
11
+ config: studio3104
12
+ hosts:
13
+ - studio3104.test
14
+ - studio3105.test
15
+ - studio3106.test
16
+ - studio3107.test
17
+ - studio3108.test
18
+ - studio3109.test
19
+ - studio3110.test
20
+ EOH
21
+ ) if ! File.exists? './role/cloudforecast/houcho_sample.yaml'
22
+
23
+ File.write('./spec/spec_helper.rb', <<EOH
24
+ require 'serverspec'
25
+ require 'pathname'
26
+ require 'net/ssh'
27
+
28
+ include Serverspec::Helper::Ssh
29
+ include Serverspec::Helper::DetectOS
30
+
31
+ RSpec.configure do |c|
32
+ if ENV['ASK_SUDO_PASSWORD']
33
+ require 'highline/import'
34
+ c.sudo_password = ask("Enter sudo password: ") { |q| q.echo = false }
35
+ else
36
+ c.sudo_password = ENV['SUDO_PASSWORD']
37
+ end
38
+ c.before :all do
39
+ block = self.class.metadata[:example_group_block]
40
+ if RUBY_VERSION.start_with?('1.8')
41
+ file = block.to_s.match(/.*@(.*):[0-9]+>/)[1]
42
+ else
43
+ file = block.source_location.first
44
+ end
45
+ c.ssh.close if c.ssh
46
+ c.host = ENV['TARGET_HOST']
47
+ options = Net::SSH::Config.for(c.host)
48
+ user = options[:user] || Etc.getlogin
49
+ c.ssh = Net::SSH.start(c.host, user, options)
50
+ c.os = backend(Serverspec::Commands::Base).check_os
51
+ end
52
+ end
53
+ EOH
54
+ ) if ! File.exists? './spec/spec_helper.rb'
55
+
56
+ File.write('./spec/houcho_sample_spec.rb', <<EOH
57
+ require 'spec_helper'
58
+
59
+ describe user('studio3104') do
60
+ it { should exist }
61
+ it { should have_uid 3104 }
62
+ it { should have_home_directory '/home/studio3104' }
63
+ it { should have_login_shell '/bin/zsh' }
64
+ it { should belong_to_group 'studio3104' }
65
+ end
66
+ describe group('studio3104') do
67
+ it { should exist }
68
+ it { should have_gid 3104 }
69
+ end
70
+ EOH
71
+ ) if ! File.exists? './spec/houcho_sample_spec.rb'
72
+
73
+ File.write('./conf/houcho.conf', {
74
+ 'ukigumo' => {'host' => nil, 'port' => nil,},
75
+ 'ikachan' => {'host' => nil, 'port' => nil, 'channel' => [nil],},
76
+ 'git' => {'uri' => nil,},
77
+ }.to_yaml) if ! File.exists? './conf/houcho.conf'
78
+
79
+ File.write('./conf/rspec.conf', '--format documentation') if ! File.exists? './conf/rspec.conf'
80
+ File.symlink('./conf/rspec.conf', './.rspec') if ! File.exists? './.rspec'
81
+
82
+ %w{
83
+ runlists.yaml
84
+ roles.yaml
85
+ hosts.yaml
86
+ specs.yaml
87
+ cf_roles.yaml
88
+ hosts_ignored.yaml
89
+ cloudforecast.yaml
90
+ }.each do |f|
91
+ f = 'role/' + f
92
+ File.write(f, '') if ! File.exists? f
93
+ end
94
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe user('studio3104') do
4
+ it { should exist }
5
+ it { should have_uid 3104 }
6
+ it { should have_home_directory '/home/studio3104' }
7
+ it { should have_login_shell '/bin/zsh' }
8
+ it { should belong_to_group 'studio3104' }
9
+ end
10
+ describe group('studio3104') do
11
+ it { should exist }
12
+ it { should have_gid 3104 }
13
+ end
@@ -0,0 +1,29 @@
1
+ require 'serverspec'
2
+ require 'pathname'
3
+ require 'net/ssh'
4
+
5
+ include Serverspec::Helper::Ssh
6
+ include Serverspec::Helper::DetectOS
7
+
8
+ RSpec.configure do |c|
9
+ if ENV['ASK_SUDO_PASSWORD']
10
+ require 'highline/import'
11
+ c.sudo_password = ask("Enter sudo password: ") { |q| q.echo = false }
12
+ else
13
+ c.sudo_password = ENV['SUDO_PASSWORD']
14
+ end
15
+ c.before :all do
16
+ block = self.class.metadata[:example_group_block]
17
+ if RUBY_VERSION.start_with?('1.8')
18
+ file = block.to_s.match(/.*@(.*):[0-9]+>/)[1]
19
+ else
20
+ file = block.source_location.first
21
+ end
22
+ c.ssh.close if c.ssh
23
+ c.host = ENV['TARGET_HOST']
24
+ options = Net::SSH::Config.for(c.host)
25
+ user = options[:user] || Etc.getlogin
26
+ c.ssh = Net::SSH.start(c.host, user, options)
27
+ c.os = backend(Serverspec::Commands::Base).check_os
28
+ end
29
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: houcho
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Satoshi SUZUKI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-12 00:00:00.000000000 Z
11
+ date: 2013-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rainbow
@@ -109,13 +109,33 @@ files:
109
109
  - Rakefile
110
110
  - bin/houcho
111
111
  - houcho.gemspec
112
- - lib/CI.rb
113
- - lib/Conductor.rb
114
- - lib/RoleHandle.rb
115
112
  - lib/houcho.rb
113
+ - lib/houcho/ci.rb
114
+ - lib/houcho/cloudforecast.rb
115
+ - lib/houcho/cloudforecast/host.rb
116
+ - lib/houcho/cloudforecast/role.rb
117
+ - lib/houcho/element.rb
118
+ - lib/houcho/host.rb
119
+ - lib/houcho/initialize.rb
120
+ - lib/houcho/role.rb
121
+ - lib/houcho/spec.rb
122
+ - lib/houcho/spec/runner.rb
116
123
  - lib/houcho/version.rb
124
+ - lib/houcho/yamlhandle.rb
117
125
  - spec/houcho_spec.rb
118
126
  - spec/spec_helper.rb
127
+ - templates/conf/houcho.conf
128
+ - templates/conf/kk.rb
129
+ - templates/conf/rspec.conf
130
+ - templates/master
131
+ - templates/role/cf_roles.yaml
132
+ - templates/role/cloudforecast.yaml
133
+ - templates/role/hosts.yaml
134
+ - templates/role/hosts_ignored.yaml
135
+ - templates/role/roles.yaml
136
+ - templates/role/specs.yaml
137
+ - templates/spec/sample_spec.rb
138
+ - templates/spec/spec_helper.rb
119
139
  homepage: https://github.com/studio3104/houcho
120
140
  licenses:
121
141
  - MIT
@@ -1,619 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- def app_dir
3
- File.expand_path("#{File.dirname(__FILE__)}/..")
4
- end
5
-
6
- require 'awesome_print'
7
- require 'rainbow'
8
- require 'parallel'
9
- require 'systemu'
10
- require 'tempfile'
11
- require 'find'
12
- require 'yaml'
13
- require 'json'
14
- require app_dir + "/lib/CI"
15
- require app_dir + "/lib/RoleHandle"
16
-
17
- class Conductor
18
- def configure_houcho
19
- cf_yamls = Tempfile.new('yaml')
20
- File.open(cf_yamls,'a') do |t|
21
- Find.find('./role/cloudforecast') do |f|
22
- t.write File.read(f) if f =~ /\.yaml$/
23
- end
24
- end
25
-
26
- cf = RoleHandle::CfLoader.new(cf_yamls)
27
- File.write('./role/cloudforecast.yaml', cf.role_hosts.to_yaml)
28
- end
29
-
30
- def initialize_houcho
31
- # ヒアドキュメントのところ、外部ファイルを置いてそれを参照するようにしたほうがよさそうね
32
- %W{conf role/cloudforecast spec}.each do |d|
33
- FileUtils.mkdir_p d if ! Dir.exists? d
34
- end
35
-
36
- File.write('./role/cloudforecast/houcho_sample.yaml', <<EOH
37
- --- #houcho
38
- servers:
39
- - label: author
40
- config: studio3104
41
- hosts:
42
- - studio3104.test
43
- - studio3105.test
44
- - studio3106.test
45
- - studio3107.test
46
- - studio3108.test
47
- - studio3109.test
48
- - studio3110.test
49
- EOH
50
- ) if ! File.exists? './role/cloudforecast/houcho_sample.yaml'
51
-
52
- File.write('./spec/spec_helper.rb', <<EOH
53
- require 'serverspec'
54
- require 'pathname'
55
- require 'net/ssh'
56
-
57
- include Serverspec::Helper::Ssh
58
- include Serverspec::Helper::DetectOS
59
-
60
- RSpec.configure do |c|
61
- if ENV['ASK_SUDO_PASSWORD']
62
- require 'highline/import'
63
- c.sudo_password = ask("Enter sudo password: ") { |q| q.echo = false }
64
- else
65
- c.sudo_password = ENV['SUDO_PASSWORD']
66
- end
67
- c.before :all do
68
- block = self.class.metadata[:example_group_block]
69
- if RUBY_VERSION.start_with?('1.8')
70
- file = block.to_s.match(/.*@(.*):[0-9]+>/)[1]
71
- else
72
- file = block.source_location.first
73
- end
74
- c.ssh.close if c.ssh
75
- c.host = ENV['TARGET_HOST']
76
- options = Net::SSH::Config.for(c.host)
77
- user = options[:user] || Etc.getlogin
78
- c.ssh = Net::SSH.start(c.host, user, options)
79
- c.os = backend(Serverspec::Commands::Base).check_os
80
- end
81
- end
82
- EOH
83
- ) if ! File.exists? './spec/spec_helper.rb'
84
-
85
- File.write('./spec/houcho_sample_spec.rb', <<EOH
86
- require 'spec_helper'
87
-
88
- describe user('studio3104') do
89
- it { should exist }
90
- it { should have_uid 3104 }
91
- it { should have_home_directory '/home/studio3104' }
92
- it { should have_login_shell '/bin/zsh' }
93
- it { should belong_to_group 'studio3104' }
94
- end
95
- describe group('studio3104') do
96
- it { should exist }
97
- it { should have_gid 3104 }
98
- end
99
- EOH
100
- ) if ! File.exists? './spec/houcho_sample_spec.rb'
101
-
102
- File.write('./conf/houcho.conf', {
103
- 'ukigumo' => {'host' => nil, 'port' => nil,},
104
- 'ikachan' => {'host' => nil, 'port' => nil, 'channel' => [nil],},
105
- 'git' => {'uri' => nil,},
106
- }.to_yaml) if ! File.exists? './conf/houcho.conf'
107
-
108
- File.write('./conf/rspec.conf', '--format documentation') if ! File.exists? './conf/rspec.conf'
109
- File.symlink('./conf/rspec.conf', './.rspec') if ! File.exists? './.rspec'
110
-
111
- %w{
112
- runlists.yaml
113
- roles.yaml
114
- hosts.yaml
115
- specs.yaml
116
- cf_roles.yaml
117
- hosts_ignored.yaml
118
- cloudforecast.yaml
119
- }.each do |f|
120
- f = 'role/' + f
121
- File.write(f, '') if ! File.exists? f
122
- end
123
-
124
- File.open("./.houcho", "w").close()
125
- `git init; git add .; git commit -a -m 'initial commit'` if ! Dir.exists?('./.git')
126
- end
127
-
128
- def show_all_cf_roles
129
- puts cfload.keys.sort.join("\n")
130
- end
131
-
132
- def show_all_roles
133
- puts RoleHandle::YamlLoader.new('./role/roles.yaml').data.values.sort.join("\n")
134
- end
135
-
136
- def show_all_hosts
137
- puts (cfload.values.flatten.uniq + hosthandle.elements).join("\n")
138
- end
139
-
140
- def show_all_specs
141
- puts spechandle.elements.sort.join("\n")
142
- end
143
-
144
-
145
- def show_cf_role_details(cf_role)
146
- rh = cfload
147
- abort("#{cf_role} does not exist in cloudforecast's yaml") if ! rh.keys.include?(cf_role)
148
-
149
- puts '[host(s)]'
150
- puts rh[cf_role].join("\n")
151
-
152
- attached_role_indexes = cfrolehandle.indexes(cf_role)
153
- if ! attached_role_indexes.empty?
154
- r = rolehandle
155
- puts ''
156
- puts '[attached role(s)]'
157
- attached_role_indexes.each do |index|
158
- puts r.name(index)
159
- end
160
- end
161
- end
162
-
163
-
164
- def show_role_details(role)
165
- puts_details(role_details(role))
166
- end
167
-
168
-
169
- def show_host_details(host)
170
- h = hosthandle
171
- r = rolehandle
172
- indexes = h.indexes(host)
173
- cfroles = cfload.select {|role, hosts|hosts.include?(host)}.keys
174
-
175
- abort("#{host} has not attached to any roles") if indexes.empty? && cfroles.empty?
176
-
177
- result = {host => {}}
178
-
179
- if ! indexes.empty?
180
- result[host]['[attached role(s)]'] = []
181
- indexes.each do |index|
182
- result[host]['[attached role(s)]'] << r.name(index)
183
- end
184
- end
185
-
186
- if ! cfroles.empty?
187
- cf = cfrolehandle
188
- ih = ignorehosthandle
189
- result[host]["[cloudforecast's role]"] = {}
190
- cfroles.each do |cfrole|
191
- result[host]["[cloudforecast's role]"][cfrole] = []
192
- cf.indexes(cfrole).each do |index|
193
- res = ih.data.include?(host) ? '<ignored>' + r.name(index) + '</ignored>' : r.name(index)
194
- result[host]["[cloudforecast's role]"][cfrole] << res
195
- end
196
- end
197
- end
198
-
199
- puts_details(result)
200
- end
201
-
202
-
203
- def show_spec_details(spec)
204
- s = spechandle
205
- r = rolehandle
206
- indexes = s.indexes(spec)
207
-
208
- abort("#{spec} has not attached to any roles") if indexes.empty?
209
-
210
- result = {spec => {}}
211
-
212
- if ! indexes.empty?
213
- result[spec]['[attached role(s)]'] = []
214
- indexes.each do |index|
215
- result[spec]['[attached role(s)]'] << r.name(index)
216
- end
217
- end
218
-
219
- puts_details(result)
220
- end
221
-
222
-
223
- def create_runlist(runlist)
224
- rlh = runlisthandle
225
- abort("runlist(#{runlist}) already exist") if rlh.data.has_key?(runlist)
226
- rlh.data[runlist] = []
227
- rlh.save_to_file
228
- end
229
-
230
-
231
- def delete_runlist(runlist)
232
- rlh = runlisthandle
233
- abort("runlist(#{runlist}) does not exist") if ! rlh.data.has_key?(runlist)
234
- abort("exclude role(s) from runlist before delete runlist") if ! rlh.data[runlist].empty?
235
- rlh.data.delete(runlist)
236
- rlh.save_to_file
237
- end
238
-
239
-
240
- def include_role_among_runlist(role, runlist)
241
- rlh = runlisthandle
242
- abort("runlist(#{runlist}) does not exist") if ! rlh.data.has_key?(runlist)
243
- index = validate_role(role)
244
- rlh.data[runlist] << index
245
- rlh.save_to_file
246
- end
247
-
248
-
249
- def exclude_role_from_runlist(role, runlist)
250
- rlh = runlisthandle
251
- abort("runlist(#{runlist}) does not exist") if ! rlh.data.has_key?(runlist)
252
- index = validate_role(role)
253
- rlh.data[runlist].delete(index)
254
- rlh.save_to_file
255
- end
256
-
257
-
258
- def rename_runlist(runlist, rename)
259
- rlh = runlisthandle
260
- abort("runlist(#{runlist}) does not exist") if ! rlh.data.has_key?(runlist)
261
- abort("runlist(#{rename}) already exist") if rlh.data.has_key?(rename)
262
- rlh.data[rename] = rlh.data[runlist]
263
- rlh.data.delete(runlist)
264
- rlh.save_to_file
265
- end
266
-
267
-
268
- def show_runlist_details(runlist)
269
- rlh = runlisthandle
270
- r = rolehandle
271
- abort("runlist(#{runlist}) does not exist") if ! rlh.data.has_key?(runlist)
272
-
273
- roledetails = {}
274
- rlh.data[runlist].each do |roleindex|
275
- roledetails.merge!(role_details(r.name(roleindex)))
276
- end
277
-
278
- puts_details({
279
- runlist => {
280
- '[role]' => roledetails
281
- }
282
- })
283
- end
284
-
285
-
286
- def show_all_runlists
287
- puts runlisthandle.data.keys.sort.join("\n")
288
- end
289
-
290
-
291
- def create_role(role)
292
- abort("#{role} is reserved by houcho") if %w{ManuallyRun}.include?(role)
293
- r = rolehandle
294
- index = r.index(role)
295
- abort("role(#{role}) already exist") if index
296
- r.create(role)
297
- end
298
-
299
-
300
- def delete_role(role)
301
- r = rolehandle
302
- index = r.index(role)
303
- abort("role(#{role}) does not exist") if ! index
304
- abort("detach host(s) from #{role} before delete #{role}") if hosthandle.has_data?(index)
305
- abort("detach spec(s) from #{role} before delete #{role}") if spechandle.has_data?(index)
306
- abort("detach cloudforecast's role(s) from #{role} before delete #{role}") if cfrolehandle.has_data?(index)
307
- r.delete(index)
308
- end
309
-
310
-
311
- def rename_role(role, name)
312
- r = rolehandle
313
- index = r.index(role)
314
- abort("#{role} does not exist") if ! index
315
- abort("#{name} already exist") if r.index(name)
316
- r.rename(index, name)
317
- end
318
-
319
-
320
- def attach_host_to_role(host, role)
321
- index = validate_role(role)
322
- h = hosthandle
323
- abort("#{host} has already attached to #{role}") if h.attached?(index, host)
324
- h.attach(index, host)
325
- end
326
-
327
-
328
- def detach_host_from_role(host, role)
329
- index = validate_role(role)
330
- h = hosthandle
331
- abort("#{host} does not attach to #{role}") if ! h.attached?(index, host)
332
- h.detach(index, host)
333
- end
334
-
335
-
336
- def ignore_host(host)
337
- ih = ignorehosthandle
338
- ih.data = Hash === ih.data ? [] : ih.data
339
- abort("#{host} has already included into ignore list") if ih.data.include?(host)
340
- ih.data << host
341
- ih.save_to_file
342
- end
343
-
344
-
345
- def disignore_host(host)
346
- ih = ignorehosthandle
347
- ih.data = Hash === ih.data ? [] : ih.data
348
- abort("#{host} does not include into ignore list") if ! ih.data.include?(host)
349
- ih.data.delete(host)
350
- ih.save_to_file
351
- end
352
-
353
-
354
- def attach_spec_to_role(spec, role)
355
- index = validate_role(role)
356
- s = spechandle
357
- abort("#{spec} already attach to #{role}") if s.attached?(index, spec)
358
- s.attach(index, spec)
359
- end
360
-
361
-
362
- def detach_spec_from_role(spec, role)
363
- index = validate_role(role)
364
- s = spechandle
365
- abort("#{spec} does not attach to #{role}") if ! s.attached?(index, spec)
366
- s.detach(index, spec)
367
- end
368
-
369
-
370
- def attach_cfrole_to_role(cf_role, role)
371
- index = validate_role(role)
372
- cr = cfrolehandle
373
- abort("#{cf_role} does not exist in cloudforecast's yaml") if ! cfload.has_key?(cf_role)
374
- abort("#{cf_role} already attach to #{role}") if cr.attached?(index, cf_role)
375
- cr.attach(index, cf_role)
376
- end
377
-
378
-
379
- def detach_cfrole_from_role(cf_role, role)
380
- index = validate_role(role)
381
- cr = cfrolehandle
382
- abort("#{cf_role} does not attach to #{role}") if ! cr.attached?(index, cf_role)
383
- cr.detach(index, cf_role)
384
- end
385
-
386
-
387
- def check_specs(*args)
388
- host_count = args.shift
389
- specs = args.flatten
390
- s = spechandle
391
- h = hosthandle
392
- cr = cfrolehandle
393
- rh = cfload
394
-
395
- specs.each do |spec|
396
- hosts = []
397
- indexes = s.indexes(spec)
398
-
399
- if indexes.empty?
400
- puts "#{spec} has not attached to any roles"
401
- next
402
- end
403
-
404
- indexes.each do |index|
405
- hosts += h.elements(index)
406
- cr.elements(index).each do |cfrole|
407
- hosts += rh[cfrole]
408
- end
409
- end
410
- hosts.sample(host_count).each {|host| runspec(nil, host, [spec])}
411
- end
412
- end
413
-
414
-
415
- def runspec_all(ci, dry)
416
- roles = RoleHandle::YamlLoader.new('./role/roles.yaml').data.values.sort
417
- end
418
-
419
-
420
- def runspec_prepare(roles, hosts, specs, ci, dry)
421
- rhs = prepare_list(roles, hosts, specs)
422
-
423
- rhs.each do |role, host_specs|
424
- host_specs.each do |host, specs|
425
- runspec(role, host, specs, ci, dry)
426
- end
427
- end
428
- end
429
-
430
-
431
- private
432
- def prepare_list(roles, hosts, specs)
433
- role_host_specs = { 'ManuallyRun' => {} }
434
-
435
- rh = cfload
436
- r = rolehandle
437
-
438
- hosts.each do |host|
439
- role_host_specs['ManuallyRun'][host] ||= []
440
- role_host_specs['ManuallyRun'][host] = (role_host_specs['ManuallyRun'][host] + specs).uniq
441
- end
442
-
443
- roles.each do |role|
444
- validate_role(Regexp.new(role)).each do |index|
445
- _role = r.name(index)
446
- _hosts = hosthandle.elements(index)
447
- _specs = spechandle.elements(index)
448
-
449
- cfrolehandle.elements(index).each do |cf_role|
450
- if rh[cf_role].nil?
451
- p cf_role
452
- next
453
- end
454
- _hosts += rh[cf_role]
455
- end
456
-
457
- _hosts = (hosts + _hosts).uniq - ignorehosthandle.data.to_a
458
- role_host_specs[_role] = {}
459
-
460
- _hosts.each do |host|
461
- role_host_specs[_role][host] ||= []
462
- role_host_specs[_role][host] = (role_host_specs[_role][host] + _specs).uniq
463
- end
464
- end
465
- end
466
-
467
- role_host_specs
468
- end
469
-
470
- def validate_role(role)
471
- if Regexp === role
472
- indexes = rolehandle.indexes_regexp(role)
473
- abort if indexes.empty?
474
- indexes
475
- else
476
- index = rolehandle.index(role)
477
- abort("role(#{role}) does not exist") if ! index
478
- index
479
- end
480
- end
481
-
482
- def cfload
483
- RoleHandle::YamlLoader.new('./role/cloudforecast.yaml').data
484
- end
485
-
486
- def runlisthandle
487
- RoleHandle::YamlEditor.new('./role/runlists.yaml')
488
- end
489
-
490
- def rolehandle
491
- RoleHandle::RoleHandler.new('./role/roles.yaml')
492
- end
493
-
494
- def cfrolehandle
495
- RoleHandle::ElementHandler.new('./role/cf_roles.yaml')
496
- end
497
-
498
- def hosthandle
499
- RoleHandle::ElementHandler.new('./role/hosts.yaml')
500
- end
501
-
502
- def ignorehosthandle
503
- RoleHandle::YamlEditor.new('./role/hosts_ignored.yaml')
504
- end
505
-
506
- def spechandle
507
- RoleHandle::ElementHandler.new('./role/specs.yaml')
508
- end
509
-
510
- def runspec(role, host, specs, ci = {}, dryrun = nil)
511
- executable_specs = []
512
- specs.each do |spec|
513
- if spec =~ /_spec.rb$/
514
- executable_specs << spec
515
- else
516
- executable_specs << 'spec/' + spec + '_spec.rb'
517
- end
518
- end
519
-
520
- command = "parallel_rspec #{executable_specs.sort.uniq.join(' ')}"
521
-
522
- if dryrun
523
- puts 'TARGET_HOST=' + host + ' ' + command
524
- return
525
- end
526
-
527
- ENV['TARGET_HOST'] = host
528
- result = systemu command
529
- result_status = result[0] == 0 ? 1 : 2
530
- puts result[1].scan(/\d* examples?, \d* failures?\n/).first.chomp + "\t#{host}, #{executable_specs}\n"
531
-
532
- if ci[:ukigumo]
533
- @conf = YAML.load_file('conf/houcho.conf')
534
- ukigumo_report = CI::UkigumoClient.new(@conf['ukigumo']['host'], @conf['ukigumo']['port']).post({
535
- :status => result_status,
536
- :project => role,
537
- :branch => host.gsub(/\./, '-'),
538
- :repo => @conf['git']['uri'],
539
- :revision => `git log spec/| grep '^commit' | head -1 | awk '{print $2}'`.chomp,
540
- :vc_log => command,
541
- :body => result[1],
542
- })
543
- end
544
-
545
- if ci[:ikachan] && result_status != 1
546
- message = "[serverspec fail]\`TARGET_HOST=#{host} #{command}\` "
547
- message += JSON.parse(ukigumo_report)['report']['url'] if ukigumo_report
548
- @conf = YAML.load_file('conf/houcho.conf')
549
- CI::IkachanClient.new(
550
- @conf['ikachan']['channel'],
551
- @conf['ikachan']['host'],
552
- @conf['ikachan']['port']
553
- ).post(message)
554
- end
555
-
556
- $fail_runspec = true if result_status != 1
557
- end
558
-
559
-
560
- def puts_details(e, indentsize = 0, cnt = 1)
561
- case e
562
- when Array
563
- e.sort.each.with_index(1) do |v, i|
564
- (indentsize-1).times {print ' '}
565
- print i != e.size ? '├─ ' : '└─ '
566
- puts v =~ /^<ignored>.*<\/ignored>$/ ? v.color(:red) : v.color(240,230,140)
567
- end
568
- puts ''
569
- when Hash
570
- e.each do |k,v|
571
- if ! indentsize.zero?
572
- (indentsize).times {print ' '}
573
- end
574
- puts k =~ /^\[.*\]$/ ? k : k.color(0,255,0)
575
- puts '' if indentsize.zero?
576
- puts_details(v, indentsize+1, cnt+1)
577
- end
578
- end
579
- end
580
-
581
-
582
- def role_details(role)
583
- index = validate_role(role)
584
-
585
- ih = ignorehosthandle
586
-
587
- hosts = hosthandle.elements(index)
588
- specs = spechandle.elements(index)
589
- cfroles = cfrolehandle.elements(index)
590
-
591
- result = {role => {}}
592
-
593
- if ! hosts.empty?
594
- hosts.each do |h|
595
- host = ih.data.include?(h) ? '<ignored>' + h + '</ignored>' : h
596
- result[role]['[host]'] ||= []
597
- result[role]['[host]'] << host
598
- end
599
- end
600
- result[role]['[spec]'] = specs if ! specs.empty?
601
-
602
- if ! cfroles.empty?
603
- rh = cfload
604
- result[role]["[cloudforecast's]"] = {}
605
- cfroles.each do |cr|
606
- result[role]["[cloudforecast's]"][cr] = {}
607
- if ! (rh[cr]||[]).empty?
608
- result[role]["[cloudforecast's]"][cr]['[host]'] = []
609
- rh[cr].each do |h|
610
- host = ih.data.include?(h) ? '<ignored>' + h + '</ignored>' : h
611
- result[role]["[cloudforecast's]"][cr]['[host]'] << host
612
- end
613
- end
614
- end
615
- end
616
-
617
- result
618
- end
619
- end