houcho 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +6 -14
- data/README.md +4 -2
- data/bin/houcho +26 -15
- data/houcho.gemspec +3 -0
- data/lib/houcho.rb +14 -3
- data/lib/houcho/cloudforecast.rb +2 -2
- data/lib/houcho/cloudforecast/host.rb +17 -15
- data/lib/houcho/cloudforecast/role.rb +2 -1
- data/lib/houcho/element.rb +2 -2
- data/lib/houcho/host.rb +1 -1
- data/lib/houcho/role.rb +4 -4
- data/lib/houcho/spec/runner.rb +20 -11
- data/lib/houcho/version.rb +1 -1
- data/lib/houcho/yamlhandle.rb +5 -1
- data/spec/houcho_spec.rb +160 -3
- data/spec/spec_helper.rb +3 -0
- data/templates/role/cloudforecast/.gitkeep +0 -0
- metadata +58 -16
- data/lib/houcho/initialize.rb +0 -15
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
YjMwMWI2NGNkMDE0OWRlNDViYjEwNjc2Y2E4MjhkZTc1OGM3NWFmMDVkZWUx
|
10
|
-
NTUwZjRmNjk3MDBkMzg2YjFiN2YxNmJkMGEwYzFhZTUyYWVlYjM1MTVjNjRh
|
11
|
-
ZjFkYjc2N2E2ZTJiNWY3NTQ4YmU3ZmRhZmE0OGU1NTgwMzA5OGY=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
M2IyNTQ4ZmZmYTY4MThlN2YwMzM1MDhhZDMzOThlNTgzNDc3NjJjYmQwZDI5
|
14
|
-
YzNlZTBiZDJhYjJjMzcxNzZhNzFlMWRhYzFlNGNhZmY3NzViMTVmMTE0MjBk
|
15
|
-
MzZhNTYxNTkwN2M5NTg1MDNhM2E4OWNhYjFiYjNjOGNmYjViOWU=
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: df80b6d9b4a0a338d66374bb5e501e4d0fa31500
|
4
|
+
data.tar.gz: bcaeec04d22f9a472d19777fcc607e27c84d42ad
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 59f8a36ce57a130e0f5f7c5614ca6642e4e3b2c31207960e8dfe7f1c2a5d1d23ec5959955df843a63d412eec6b5568b0451dda4f267d4a0c2cde8f0ba49e2a1f
|
7
|
+
data.tar.gz: daaf4b414679b21c6d61a0ceb27f0d475d6262afd4073eede9e1e4453499dace3ad0ffd73b07a3e7a3e629b3eff4f6ce25f5e1004d821a225e54b21ba2016934
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Houcho
|
2
2
|
- wrapping to execute serverspec
|
3
|
-
- depends on ruby 1.9 later.
|
3
|
+
- depends on ruby 1.9 later(recommended: 2.0 later).
|
4
4
|
|
5
5
|
## Install and Initialize
|
6
6
|
- install houcho from ruby gems
|
@@ -142,4 +142,6 @@ $ houcho role exec studio3104::www --exclude-hosts studio3104.test
|
|
142
142
|
```
|
143
143
|
|
144
144
|
## TODO
|
145
|
-
-
|
145
|
+
- write more tests
|
146
|
+
- `Houcho::Logger`
|
147
|
+
- LTSV
|
data/bin/houcho
CHANGED
@@ -54,21 +54,24 @@ class SpecConduct < Thor::MyHelper
|
|
54
54
|
option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
|
55
55
|
def attach(*args)
|
56
56
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
57
|
-
Spec.attach(args, options[:roles])
|
57
|
+
Spec.attach(args, options[:roles]) rescue puts $!.message; exit!
|
58
58
|
end
|
59
59
|
|
60
60
|
desc 'detach [spec1 spec2 spec3...] --roles [role1 role2...]', 'detach spec from spec'
|
61
61
|
option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
|
62
62
|
def detach(*args)
|
63
63
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
64
|
-
Spec.detach(args, options[:roles])
|
64
|
+
Spec.detach(args, options[:roles]) rescue puts $!.message; exit!
|
65
65
|
end
|
66
66
|
|
67
67
|
desc 'check [options]', 'run the spec sampled appropriately to the associated host'
|
68
68
|
option :sample_host_count, :type => :numeric, :default => 5, :desc => 'number of sample hosts'
|
69
69
|
def check(*args)
|
70
70
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
71
|
-
Spec::Runner.check(args, options[:sample_host_count])
|
71
|
+
messages = Spec::Runner.check(args, options[:sample_host_count]) rescue puts $!.message; exit!
|
72
|
+
messages.each do |msg|
|
73
|
+
puts msg
|
74
|
+
end
|
72
75
|
end
|
73
76
|
|
74
77
|
desc 'exec (spec1 spec2..) [options]', 'run serverspec manually'
|
@@ -79,14 +82,18 @@ class SpecConduct < Thor::MyHelper
|
|
79
82
|
def exec(*args)
|
80
83
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
81
84
|
|
82
|
-
Spec::Runner.exec(
|
85
|
+
messages = Spec::Runner.exec(
|
83
86
|
[], [], options[:hosts], args,
|
84
87
|
{
|
85
88
|
ukigumo: options[:ukigumo],
|
86
89
|
ikachan: options[:ikachan],
|
87
90
|
},
|
88
91
|
options[:dry_run],
|
89
|
-
)
|
92
|
+
) rescue puts $!.message; exit!
|
93
|
+
|
94
|
+
messages.each do |msg|
|
95
|
+
puts msg
|
96
|
+
end
|
90
97
|
end
|
91
98
|
end
|
92
99
|
|
@@ -109,14 +116,14 @@ class HostConduct < Thor::MyHelper
|
|
109
116
|
option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
|
110
117
|
def attach(*args)
|
111
118
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
112
|
-
Host.attach(args, options[:roles])
|
119
|
+
Host.attach(args, options[:roles]) rescue puts $!.message; exit!
|
113
120
|
end
|
114
121
|
|
115
122
|
desc 'detach [host1 host2 host3...] --roles [role1 role2...]', 'detach host from role'
|
116
123
|
option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
|
117
124
|
def detach(*args)
|
118
125
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
119
|
-
Host.detach(args, options[:roles])
|
126
|
+
Host.detach(args, options[:roles]) rescue puts $!.message; exit!
|
120
127
|
end
|
121
128
|
end
|
122
129
|
|
@@ -127,18 +134,18 @@ class RoleConduct < Thor::MyHelper
|
|
127
134
|
desc 'create [role1 role2 role3...]', 'cretate role'
|
128
135
|
def create(*args)
|
129
136
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
130
|
-
Role.create(args)
|
137
|
+
Role.create(args) rescue puts $!.message; exit!
|
131
138
|
end
|
132
139
|
|
133
140
|
desc 'delete [role1 role2 role3...]', 'delete a role'
|
134
141
|
def delete(*args)
|
135
142
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
136
|
-
Role.delete(args)
|
143
|
+
Role.delete(args) rescue puts $!.message; exit!
|
137
144
|
end
|
138
145
|
|
139
146
|
desc 'rename [exist role] [name]', 'rename a role'
|
140
147
|
def rename(role, rename)
|
141
|
-
Role.rename(role, rename)
|
148
|
+
Role.rename(role, rename) rescue puts $!.message; exit!
|
142
149
|
end
|
143
150
|
|
144
151
|
desc 'details [role1 role2...]', 'show details about role'
|
@@ -160,14 +167,18 @@ class RoleConduct < Thor::MyHelper
|
|
160
167
|
def exec(*args)
|
161
168
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
162
169
|
|
163
|
-
Spec::Runner.exec(
|
170
|
+
messages = Spec::Runner.exec(
|
164
171
|
args, (options[:exclude_hosts]||[]), [], [],
|
165
172
|
{
|
166
173
|
ukigumo: options[:ukigumo],
|
167
174
|
ikachan: options[:ikachan],
|
168
175
|
},
|
169
176
|
options[:dry_run],
|
170
|
-
)
|
177
|
+
) rescue puts $!.message; exit!
|
178
|
+
|
179
|
+
messages.each do |msg|
|
180
|
+
puts msg
|
181
|
+
end
|
171
182
|
end
|
172
183
|
end
|
173
184
|
|
@@ -190,14 +201,14 @@ class CFConduct < Thor::MyHelper
|
|
190
201
|
option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
|
191
202
|
def attach(*args)
|
192
203
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
193
|
-
CloudForecast::Role.attach(args, options[:roles])
|
204
|
+
CloudForecast::Role.attach(args, options[:roles]) rescue puts $!.message; exit!
|
194
205
|
end
|
195
206
|
|
196
207
|
desc 'detach [cf1 cf2 cf3...] --roles [role1 role2...]', "detach cloudforecast's role from role"
|
197
208
|
option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
|
198
209
|
def detach(*args)
|
199
210
|
Helper.empty_args(self, shell, __method__) if args.empty?
|
200
|
-
CloudForecast::Role.detach(args, options[:roles])
|
211
|
+
CloudForecast::Role.detach(args, options[:roles]) rescue puts $!.message; exit!
|
201
212
|
end
|
202
213
|
|
203
214
|
desc 'load', '(re)loading yamls of cloudforecast'
|
@@ -226,7 +237,7 @@ class Main < Thor
|
|
226
237
|
|
227
238
|
desc 'init', 'set houcho repository on current directory'
|
228
239
|
def init
|
229
|
-
|
240
|
+
init_repo
|
230
241
|
end
|
231
242
|
|
232
243
|
end
|
data/houcho.gemspec
CHANGED
@@ -18,10 +18,13 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.add_runtime_dependency 'thor'
|
21
22
|
spec.add_runtime_dependency 'rainbow'
|
22
23
|
spec.add_runtime_dependency 'parallel_tests'
|
23
24
|
spec.add_runtime_dependency 'systemu'
|
24
25
|
spec.add_runtime_dependency 'serverspec'
|
25
26
|
spec.add_development_dependency "bundler", "~> 1.3"
|
26
27
|
spec.add_development_dependency "rake"
|
28
|
+
spec.add_development_dependency "tmpdir"
|
29
|
+
spec.add_development_dependency "tempfile"
|
27
30
|
end
|
data/lib/houcho.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'fileutils'
|
3
3
|
require 'rainbow'
|
4
|
-
require 'parallel'
|
5
4
|
require 'systemu'
|
6
5
|
require 'tempfile'
|
7
6
|
require 'find'
|
8
7
|
require 'yaml'
|
9
8
|
require 'json'
|
10
|
-
require 'houcho/initialize'
|
11
9
|
require 'houcho/yamlhandle'
|
12
10
|
require 'houcho/element'
|
13
11
|
require 'houcho/role'
|
@@ -20,6 +18,19 @@ require 'houcho/cloudforecast/host'
|
|
20
18
|
require 'houcho/ci'
|
21
19
|
|
22
20
|
module Houcho
|
21
|
+
def init_repo
|
22
|
+
templates = File.expand_path("#{File.dirname(__FILE__)}/../templates")
|
23
|
+
|
24
|
+
%W{conf role spec}.each do |d|
|
25
|
+
FileUtils.cp_r("#{templates}/#{d}", d) if ! Dir.exist?(d)
|
26
|
+
end
|
27
|
+
|
28
|
+
File.symlink('./conf/rspec.conf', './.rspec') if ! File.exists? '.rspec'
|
29
|
+
|
30
|
+
`git init; git add .; git commit -a -m 'initialized houcho repository'` if ! Dir.exist?('.git')
|
31
|
+
end
|
32
|
+
|
33
|
+
|
23
34
|
def puts_details(e, indentsize = 0, cnt = 1)
|
24
35
|
case e
|
25
36
|
when Array
|
data/lib/houcho/cloudforecast.rb
CHANGED
@@ -1,23 +1,25 @@
|
|
1
1
|
module Houcho
|
2
|
-
module CloudForecast
|
3
|
-
|
2
|
+
module CloudForecast
|
3
|
+
class Host
|
4
|
+
def initialize
|
5
|
+
@cf = YamlHandle::Loader.new('./role/cloudforecast.yaml')
|
6
|
+
end
|
4
7
|
|
5
|
-
|
8
|
+
def roles(host)
|
9
|
+
@cf.data.select {|cfrole, cfhosts|cfhosts.include?(host)}.keys
|
10
|
+
end
|
6
11
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def hosts(role)
|
12
|
-
@cfdata[role] || []
|
13
|
-
end
|
12
|
+
def hosts(role)
|
13
|
+
@cf.data[role] || []
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def details(host)
|
17
|
+
CloudForecast::Role.details(roles(host))
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
20
|
+
def all
|
21
|
+
@cf.data.values.flatten.uniq
|
22
|
+
end
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
@@ -7,12 +7,13 @@ module Houcho
|
|
7
7
|
def self.details(cfroles)
|
8
8
|
result = {}
|
9
9
|
cfroles.each do |cfrole|
|
10
|
-
hosts = CloudForecast::Host.hosts(cfrole)
|
10
|
+
hosts = CloudForecast::Host.new.hosts(cfrole)
|
11
11
|
if ! hosts.empty?
|
12
12
|
result[cfrole] = {}
|
13
13
|
result[cfrole]['host'] = hosts
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
16
17
|
result
|
17
18
|
end
|
18
19
|
|
data/lib/houcho/element.rb
CHANGED
@@ -24,7 +24,7 @@ module Houcho
|
|
24
24
|
end
|
25
25
|
|
26
26
|
@elements.save_to_file
|
27
|
-
|
27
|
+
raise("role(#{invalid_roles.join(',')}) does not exist") if ! invalid_roles.size.zero?
|
28
28
|
end
|
29
29
|
|
30
30
|
|
@@ -41,7 +41,7 @@ module Houcho
|
|
41
41
|
end
|
42
42
|
|
43
43
|
@elements.save_to_file
|
44
|
-
|
44
|
+
raise("role(#{invalid_roles.join(',')}) does not exist") if ! invalid_roles.size.zero?
|
45
45
|
end
|
46
46
|
|
47
47
|
|
data/lib/houcho/host.rb
CHANGED
@@ -8,7 +8,7 @@ module Houcho
|
|
8
8
|
|
9
9
|
hosts.each do |host|
|
10
10
|
roles = self.indexes(host).map {|index|Role.name(index)}
|
11
|
-
cfroles = CloudForecast::Host.roles(host)
|
11
|
+
cfroles = CloudForecast::Host.new.roles(host)
|
12
12
|
|
13
13
|
result[host] = {}
|
14
14
|
result[host]['role'] = roles if ! roles.empty?
|
data/lib/houcho/role.rb
CHANGED
@@ -15,7 +15,7 @@ module Houcho
|
|
15
15
|
|
16
16
|
if role.size == 0
|
17
17
|
@roles.save_to_file
|
18
|
-
|
18
|
+
raise("role(#{exists.join(',')}) already exist.") if exists.size != 0
|
19
19
|
else
|
20
20
|
self.create(role, exists)
|
21
21
|
end
|
@@ -49,7 +49,7 @@ module Houcho
|
|
49
49
|
e << "detach host from #{errors[:hosts].join(',')} before delete" if ! errors[:hosts].size.zero?
|
50
50
|
e << "detach spec from #{errors[:specs].join(',')} before delete" if ! errors[:specs].size.zero?
|
51
51
|
e << "detach cloudforecast's role from #{errors[:cf].join(',')} before delete" if ! errors[:cf].size.zero?
|
52
|
-
|
52
|
+
raise("#{e.join(', ')}.") if ! e.size.zero?
|
53
53
|
else
|
54
54
|
self.delete(role, errors)
|
55
55
|
end
|
@@ -58,8 +58,8 @@ module Houcho
|
|
58
58
|
|
59
59
|
def rename(role, name)
|
60
60
|
index = self.index(role)
|
61
|
-
|
62
|
-
|
61
|
+
raise("#{role} does not exist") if ! index
|
62
|
+
raise("#{name} already exist") if self.index(name)
|
63
63
|
|
64
64
|
@roles.data[index] = name
|
65
65
|
@roles.save_to_file
|
data/lib/houcho/spec/runner.rb
CHANGED
@@ -26,27 +26,27 @@ module Houcho
|
|
26
26
|
end
|
27
27
|
|
28
28
|
m = {}
|
29
|
-
m['host'] = hosts
|
30
|
-
m['spec'] = spec_check.call(specs)
|
29
|
+
m['host'] = hosts if ! hosts.empty?
|
30
|
+
m['spec'] = spec_check.call(specs) if ! specs.empty?
|
31
31
|
|
32
32
|
runlist[:'run manually'] = m if m != {}
|
33
33
|
|
34
34
|
if ! spec_not_exist.empty?
|
35
|
-
|
36
|
-
puts "spec(#{spec_not_exist.join(',')}) file not exist in ./spec directory."
|
35
|
+
raise "spec(#{spec_not_exist.join(',')}) file not exist in ./spec directory."
|
37
36
|
end
|
38
37
|
runlist
|
39
38
|
end
|
40
39
|
|
41
40
|
|
42
41
|
def exec(roles, ex_hosts, hosts, specs, ci = {}, dryrun = nil)
|
42
|
+
messages = []
|
43
43
|
self.prepare(roles, ex_hosts, hosts, specs).each do |role, v|
|
44
44
|
next if v['spec'].empty?
|
45
45
|
command = "parallel_rspec #{v['spec'].sort.uniq.join(' ')}"
|
46
46
|
|
47
47
|
if dryrun
|
48
48
|
v['host'].each do |host|
|
49
|
-
|
49
|
+
messages << "TARGET_HOST=#{host} #{command}"
|
50
50
|
end
|
51
51
|
next
|
52
52
|
end
|
@@ -54,12 +54,13 @@ module Houcho
|
|
54
54
|
v['host'].each do |host|
|
55
55
|
ENV['TARGET_HOST'] = host
|
56
56
|
result = systemu command
|
57
|
-
|
57
|
+
messages << result[1].scan(/\d* examples?, \d* failures?\n/).first.chomp + "\t#{host}, #{command}\n"
|
58
58
|
|
59
59
|
post_result(result, role, host, command, ci) if ci != {}
|
60
60
|
$houcho_fail = true if result[0] != 0
|
61
61
|
end
|
62
62
|
end
|
63
|
+
messages
|
63
64
|
end
|
64
65
|
|
65
66
|
|
@@ -91,25 +92,33 @@ module Houcho
|
|
91
92
|
end
|
92
93
|
|
93
94
|
|
94
|
-
def check(specs, host_count)
|
95
|
-
specs
|
95
|
+
def check(specs, host_count, dryrun = false) # dryrun is for test
|
96
|
+
specs = specs.flatten
|
97
|
+
error = []
|
98
|
+
messages = []
|
96
99
|
|
97
100
|
specs.each do |spec|
|
98
101
|
hosts = []
|
99
102
|
indexes = Spec.indexes(spec)
|
100
103
|
|
101
104
|
if indexes.empty?
|
102
|
-
|
105
|
+
error << spec
|
103
106
|
next
|
104
107
|
end
|
105
108
|
|
106
109
|
indexes.each do |index|
|
107
110
|
hosts += Host.elements(index)
|
108
111
|
CloudForecast::Role.elements(index).each do |cfrole|
|
109
|
-
hosts += CloudForecast::Host(cfrole)
|
112
|
+
hosts += CloudForecast::Host.new.hosts(cfrole)
|
110
113
|
end
|
111
114
|
end
|
112
|
-
hosts.sample(host_count).each {|host| exec([], [], [host], [spec])}
|
115
|
+
hosts.sample(host_count).each {|host| messages += exec([], [], [host], [spec], {}, dryrun)}
|
116
|
+
end
|
117
|
+
|
118
|
+
if error.empty?
|
119
|
+
messages
|
120
|
+
else
|
121
|
+
raise("role(#{error.join(',')}) has not attached to any roles")
|
113
122
|
end
|
114
123
|
end
|
115
124
|
end
|
data/lib/houcho/version.rb
CHANGED
data/lib/houcho/yamlhandle.rb
CHANGED
@@ -4,7 +4,11 @@ module Houcho
|
|
4
4
|
attr_reader :data
|
5
5
|
|
6
6
|
def initialize(yaml_file)
|
7
|
-
|
7
|
+
begin
|
8
|
+
@data = YAML.load_file(yaml_file)
|
9
|
+
rescue
|
10
|
+
# I think it should describe the process when current directory has not ready for houcho
|
11
|
+
end
|
8
12
|
@data ||= {}
|
9
13
|
end
|
10
14
|
end
|
data/spec/houcho_spec.rb
CHANGED
@@ -1,7 +1,164 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
spectmp = Dir.mktmpdir('spec')
|
4
|
+
include Houcho
|
5
|
+
|
6
|
+
describe Houcho do
|
7
|
+
before :all do
|
8
|
+
Dir.chdir(spectmp)
|
9
|
+
init_repo
|
10
|
+
Role.create(['studio3104', 'studio3105'])
|
11
|
+
Host.attach(['hostA'], ['studio3104'])
|
12
|
+
|
13
|
+
File.write('spec/specA_spec.rb',' ')
|
14
|
+
Spec.attach(['specA'], ['studio3104'])
|
15
|
+
|
16
|
+
File.write('./role/cloudforecast/cf.yaml', <<EOD
|
17
|
+
--- #houcho
|
18
|
+
servers:
|
19
|
+
- label: rspec
|
20
|
+
config: studio3104
|
21
|
+
hosts:
|
22
|
+
- test1.studio3104.com
|
23
|
+
- test2.studio3104.com
|
24
|
+
EOD
|
25
|
+
)
|
26
|
+
CloudForecast.load_yaml
|
27
|
+
CloudForecast::Role.attach(['houcho::rspec::studio3104'], ['studio3104'])
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
describe Role do
|
32
|
+
context 'create and delete a role' do
|
33
|
+
it { Role.create(['www']) }
|
34
|
+
it { expect { Role.create(['www']) }.to raise_error }
|
35
|
+
it { Role.delete(['www']) }
|
36
|
+
it { expect { Role.delete(['web']) }.to raise_error }
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'create and delete two roles' do
|
40
|
+
it { Role.create(['studio3104::www', 'studio3104::database']) }
|
41
|
+
it { expect { Role.create(['studio3104::www', 'studio3104::database']) }.to raise_error }
|
42
|
+
it { Role.delete(['studio3104::www', 'studio3104::database']) }
|
43
|
+
it { expect { Role.delete(['studio3104::www', 'studio3104::database']) }.to raise_error }
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'rename a role' do
|
47
|
+
it { Role.rename('studio3105', 'studio3106') }
|
48
|
+
it { expect { Role.rename('invalid_role', 'studio3106') }.to raise_error }
|
49
|
+
it { expect { Role.rename('studio3106', 'studio3104') }.to raise_error }
|
50
|
+
it { Role.rename('studio3106', 'studio3105') }
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'get all roles' do
|
54
|
+
it { Role.all.should eq ['studio3104', 'studio3105'] }
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'get details of a role' do
|
58
|
+
it do
|
59
|
+
expect(Role.details(['studio3104'])).to eq(
|
60
|
+
{
|
61
|
+
'studio3104' => {
|
62
|
+
'host' => [ 'hostA' ],
|
63
|
+
'spec' => [ 'specA' ],
|
64
|
+
'cf' => { 'houcho::rspec::studio3104' => { 'host' => [ 'test1.studio3104.com', 'test2.studio3104.com', ] } }
|
65
|
+
}
|
66
|
+
}
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it { expect(Role.index('studio3104')).to be(1)}
|
72
|
+
it { expect(Role.indexes_regexp(/studio310\d/)).to eq([1,2])}
|
73
|
+
it { expect(Role.name(1)).to eq('studio3104')}
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
describe Houcho::Host do
|
78
|
+
context 'attach and detach hosts to roles' do
|
79
|
+
it { Host.attach(['host1', 'host2'], ['studio3104', 'studio3105']) }
|
80
|
+
it { expect { Host.attach(['host1'], ['invalid_role']) }.to raise_error }
|
81
|
+
it { Host.detach(['host1', 'host2'], ['studio3104', 'studio3105']) }
|
82
|
+
it { expect { Host.detach(['host1'], ['invalid_role']) }.to raise_error }
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'get details of a host' do
|
86
|
+
it 'host from original defined' do
|
87
|
+
expect(Host.details(['hostA'])).to eq(
|
88
|
+
{ 'hostA' => { 'role' => [ 'studio3104' ] } }
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'host from cf defined' do
|
93
|
+
expect(Host.details(['test1.studio3104.com'])).to eq(
|
94
|
+
{ 'test1.studio3104.com' => { 'cf' => [ 'houcho::rspec::studio3104' ] } }
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'both' do
|
99
|
+
expect(Host.details(['hostA', 'test1.studio3104.com'])).to eq(
|
100
|
+
{
|
101
|
+
'hostA' => { 'role' => [ 'studio3104' ] },
|
102
|
+
'test1.studio3104.com' => { 'cf' => [ 'houcho::rspec::studio3104' ] },
|
103
|
+
}
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'get host list attached or defined cf' do
|
108
|
+
it 'all of hosts' do
|
109
|
+
expect(Host.elements).to eq(["hostA"])
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'hosts of one of role' do
|
113
|
+
expect(Host.elements(1)).to eq(["hostA"])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
describe Houcho::Spec::Runner do
|
121
|
+
context 'run role' do
|
122
|
+
it do
|
123
|
+
expect(Spec::Runner.exec(['studio3104'],[],[],[],{},true)).to eq([
|
124
|
+
'TARGET_HOST=hostA parallel_rspec spec/specA_spec.rb',
|
125
|
+
'TARGET_HOST=test1.studio3104.com parallel_rspec spec/specA_spec.rb',
|
126
|
+
'TARGET_HOST=test2.studio3104.com parallel_rspec spec/specA_spec.rb'
|
127
|
+
])
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'with exclude host' do
|
131
|
+
expect(Spec::Runner.exec(['studio3104'],['test1.studio3104.com'],[],[],{},true)).to eq([
|
132
|
+
'TARGET_HOST=hostA parallel_rspec spec/specA_spec.rb',
|
133
|
+
'TARGET_HOST=test2.studio3104.com parallel_rspec spec/specA_spec.rb'
|
134
|
+
])
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'run manually' do
|
139
|
+
it do
|
140
|
+
expect(Spec::Runner.exec([],[],['test3.studio3104.com', 'test4.studio3104.com'],['specA'],{},true)).to eq([
|
141
|
+
'TARGET_HOST=test3.studio3104.com parallel_rspec spec/specA_spec.rb',
|
142
|
+
'TARGET_HOST=test4.studio3104.com parallel_rspec spec/specA_spec.rb'
|
143
|
+
])
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'case of spec not exist' do
|
147
|
+
expect { Spec::Runner.exec([],[],['test5.studio3104.com'],['specA', 'specX'],{},true) }.to raise_error
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'check spec' do
|
152
|
+
it { expect(Spec::Runner.check(['specA'], 2, true).size).to be(2) }
|
153
|
+
it 'case of spec not exist' do
|
154
|
+
expect { Spec::Runner.check(['specX'], 2, true) }.to raise_error
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
after :all do
|
161
|
+
Dir.chdir('/')
|
162
|
+
FileUtils.rm_rf(spectmp)
|
6
163
|
end
|
7
164
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,9 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
2
2
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
3
|
require 'rspec'
|
4
4
|
require 'houcho'
|
5
|
+
require 'tmpdir'
|
6
|
+
require 'tempfile'
|
7
|
+
require 'fileutils'
|
5
8
|
|
6
9
|
# Requires supporting files with custom matchers and macros, etc,
|
7
10
|
# in ./support/ and its subdirectories.
|
File without changes
|
metadata
CHANGED
@@ -1,69 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: houcho
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
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-
|
11
|
+
date: 2013-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rainbow
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
|
-
- -
|
31
|
+
- - '>='
|
18
32
|
- !ruby/object:Gem::Version
|
19
33
|
version: '0'
|
20
34
|
type: :runtime
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
|
-
- -
|
38
|
+
- - '>='
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: parallel_tests
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- -
|
45
|
+
- - '>='
|
32
46
|
- !ruby/object:Gem::Version
|
33
47
|
version: '0'
|
34
48
|
type: :runtime
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
|
-
- -
|
52
|
+
- - '>='
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: systemu
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- -
|
59
|
+
- - '>='
|
46
60
|
- !ruby/object:Gem::Version
|
47
61
|
version: '0'
|
48
62
|
type: :runtime
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- -
|
66
|
+
- - '>='
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: serverspec
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- -
|
73
|
+
- - '>='
|
60
74
|
- !ruby/object:Gem::Version
|
61
75
|
version: '0'
|
62
76
|
type: :runtime
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- -
|
80
|
+
- - '>='
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
@@ -84,14 +98,42 @@ dependencies:
|
|
84
98
|
name: rake
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- -
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: tmpdir
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: tempfile
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
88
130
|
- !ruby/object:Gem::Version
|
89
131
|
version: '0'
|
90
132
|
type: :development
|
91
133
|
prerelease: false
|
92
134
|
version_requirements: !ruby/object:Gem::Requirement
|
93
135
|
requirements:
|
94
|
-
- -
|
136
|
+
- - '>='
|
95
137
|
- !ruby/object:Gem::Version
|
96
138
|
version: '0'
|
97
139
|
description: covering to run serverspec
|
@@ -116,7 +158,6 @@ files:
|
|
116
158
|
- lib/houcho/cloudforecast/role.rb
|
117
159
|
- lib/houcho/element.rb
|
118
160
|
- lib/houcho/host.rb
|
119
|
-
- lib/houcho/initialize.rb
|
120
161
|
- lib/houcho/role.rb
|
121
162
|
- lib/houcho/spec.rb
|
122
163
|
- lib/houcho/spec/runner.rb
|
@@ -130,6 +171,7 @@ files:
|
|
130
171
|
- templates/master
|
131
172
|
- templates/role/cf_roles.yaml
|
132
173
|
- templates/role/cloudforecast.yaml
|
174
|
+
- templates/role/cloudforecast/.gitkeep
|
133
175
|
- templates/role/hosts.yaml
|
134
176
|
- templates/role/hosts_ignored.yaml
|
135
177
|
- templates/role/roles.yaml
|
@@ -146,17 +188,17 @@ require_paths:
|
|
146
188
|
- lib
|
147
189
|
required_ruby_version: !ruby/object:Gem::Requirement
|
148
190
|
requirements:
|
149
|
-
- -
|
191
|
+
- - '>='
|
150
192
|
- !ruby/object:Gem::Version
|
151
193
|
version: '0'
|
152
194
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
195
|
requirements:
|
154
|
-
- -
|
196
|
+
- - '>='
|
155
197
|
- !ruby/object:Gem::Version
|
156
198
|
version: '0'
|
157
199
|
requirements: []
|
158
200
|
rubyforge_project:
|
159
|
-
rubygems_version: 2.0.
|
201
|
+
rubygems_version: 2.0.2
|
160
202
|
signing_key:
|
161
203
|
specification_version: 4
|
162
204
|
summary: covering to run serverspec
|
data/lib/houcho/initialize.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
module Houcho
|
4
|
-
module Initialize
|
5
|
-
templates = File.expand_path("#{File.dirname(__FILE__)}/../../templates")
|
6
|
-
|
7
|
-
%W{conf role spec}.each do |d|
|
8
|
-
FileUtils.cp_r("#{templates}/#{d}", d) if ! Dir.exist?(d)
|
9
|
-
end
|
10
|
-
|
11
|
-
File.symlink('./conf/rspec.conf', './.rspec') if ! File.exists? '.rspec'
|
12
|
-
|
13
|
-
`git init; git add .; git commit -a -m 'initialized houcho repository'` if ! Dir.exist?('.git')
|
14
|
-
end
|
15
|
-
end
|