houcho 0.0.6 → 0.0.8

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/Gemfile.lock +32 -0
  4. data/bin/houcho +3 -262
  5. data/houcho.gemspec +2 -1
  6. data/lib/houcho/attribute.rb +99 -0
  7. data/lib/houcho/ci.rb +18 -13
  8. data/lib/houcho/cli/attribute.rb +70 -0
  9. data/lib/houcho/cli/host.rb +46 -0
  10. data/lib/houcho/cli/outerrole.rb +53 -0
  11. data/lib/houcho/cli/role.rb +69 -0
  12. data/lib/houcho/cli/spec.rb +103 -0
  13. data/lib/houcho/cli.rb +52 -0
  14. data/lib/houcho/config.rb +28 -0
  15. data/lib/houcho/database.rb +99 -0
  16. data/lib/houcho/element.rb +79 -50
  17. data/lib/houcho/host.rb +30 -9
  18. data/lib/houcho/outerrole/cloudforecast.rb +94 -0
  19. data/{templates/role/cf_roles.yaml → lib/houcho/outerrole/yabitz.rb} +0 -0
  20. data/lib/houcho/outerrole.rb +52 -0
  21. data/lib/houcho/repository.rb +59 -0
  22. data/lib/houcho/role.rb +78 -91
  23. data/lib/houcho/spec/runner.rb +156 -85
  24. data/lib/houcho/spec.rb +72 -3
  25. data/lib/houcho/version.rb +1 -1
  26. data/lib/houcho.rb +10 -52
  27. data/spec/houcho_spec.rb +334 -91
  28. metadata +31 -22
  29. data/lib/houcho/cloudforecast/host.rb +0 -25
  30. data/lib/houcho/cloudforecast/role.rb +0 -25
  31. data/lib/houcho/cloudforecast.rb +0 -59
  32. data/lib/houcho/yamlhandle.rb +0 -31
  33. data/spec/spec_helper.rb +0 -15
  34. data/templates/conf/houcho.conf +0 -10
  35. data/templates/conf/kk.rb +0 -14
  36. data/templates/conf/rspec.conf +0 -1
  37. data/templates/master +0 -94
  38. data/templates/role/cloudforecast/.gitkeep +0 -0
  39. data/templates/role/cloudforecast.yaml +0 -0
  40. data/templates/role/hosts.yaml +0 -0
  41. data/templates/role/hosts_ignored.yaml +0 -0
  42. data/templates/role/roles.yaml +0 -0
  43. data/templates/role/specs.yaml +0 -0
  44. data/templates/spec/sample_spec.rb +0 -13
  45. data/templates/spec/spec_helper.rb +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3dfa40a671511626f2a5665f70339de35d40004c
4
- data.tar.gz: 63d63e7aa834a00738aab1d6550b532149dd8100
3
+ metadata.gz: 0d83d0e90621526a1a46014365dc3a97deb67f9a
4
+ data.tar.gz: cc2c9dc65df3b0b5145d9c3f02769f2b2c555fb6
5
5
  SHA512:
6
- metadata.gz: 20f31de24421b105522f7bc2e089c6d21fc3e96cb6c67649c4321b82cd9baf1b4e9318f42969b0d7a14b9f9571359ea2891212df9d29efe153e12a03ae25ba12
7
- data.tar.gz: cb9831aa6687b2a89c3104bda38b65fb58e487e3b815c32772f724a6cb3d6911eb24ae87e2eb451ac2d3659f2ef46404577bf0f43f613acd2562a311b9e43a20
6
+ metadata.gz: f6fa79952eacf76bc3ba07ce6b9b8007a51d4ca7b5fe9d3b679f7d909fa8844fe3c01acc95e213ba60fe06bdc74212d3223ff36d5551920c04337a7494f5b1ef
7
+ data.tar.gz: 07aece03104359e42827386d89869fc6229cfeb283c45bf66cbea6de42db114151728bdca051593e41b5ba43d5ccf18f985ab899b08849fbdf8f21309ba6dd16
data/.gitignore CHANGED
@@ -5,4 +5,4 @@ coverage.data
5
5
  rdoc
6
6
  .yardoc
7
7
  .bundle
8
-
8
+ *.db
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.2.4)
5
+ highline (1.6.19)
6
+ net-ssh (2.6.8)
7
+ parallel (0.7.1)
8
+ parallel_tests (0.15.0)
9
+ parallel
10
+ rainbow (1.1.4)
11
+ rspec (2.13.0)
12
+ rspec-core (~> 2.13.0)
13
+ rspec-expectations (~> 2.13.0)
14
+ rspec-mocks (~> 2.13.0)
15
+ rspec-core (2.13.1)
16
+ rspec-expectations (2.13.0)
17
+ diff-lcs (>= 1.1.3, < 2.0)
18
+ rspec-mocks (2.13.1)
19
+ serverspec (0.7.0)
20
+ highline
21
+ net-ssh
22
+ rspec (~> 2.13.0)
23
+ systemu (2.5.2)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ parallel_tests
30
+ rainbow
31
+ serverspec
32
+ systemu
data/bin/houcho CHANGED
@@ -1,263 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- # -*- encoding: utf-8 -*-
3
- $LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
-
5
- require 'rubygems'
6
- require 'thor'
7
- require 'houcho'
8
-
9
- include Houcho
10
-
11
- module Helper
12
- module_function
13
-
14
- def empty_args(klass, chell, mesod)
15
- klass.class.task_help(chell, mesod)
16
- exit
17
- end
18
- end
19
-
20
- class Thor::MyHelper < Thor
21
- class_option :help, :type => :boolean, :aliases => '-h', :desc => 'Help message.'
22
-
23
- no_tasks do
24
- def invoke_task(task, *args)
25
- if options[:help] && task.name != 'help'
26
- self.class.task_help(shell, task.name)
27
- else
28
- super
29
- end
30
- end
31
- end
32
-
33
- def self.banner(task, namespace = false, subcommand = true)
34
- super
35
- end
36
- end
37
-
38
-
39
- class SpecConduct < Thor::MyHelper
40
- namespace :spec
41
-
42
- desc 'details [spec1 spec2 spec3...]', 'show details about spec'
43
- def details(*args)
44
- Helper.empty_args(self, shell, __method__) if args.empty?
45
- puts_details(Spec.details(args))
46
- end
47
-
48
- desc 'show', 'show all of specs'
49
- def show
50
- puts Spec.elements.sort.join("\n")
51
- end
52
-
53
- desc 'attach [spec1 spec2 spec3...] --roles [role1 role2...]', 'attach spec to role'
54
- option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
55
- def attach(*args)
56
- Helper.empty_args(self, shell, __method__) if args.empty?
57
- Spec.attach(args, options[:roles]) rescue puts $!.message; exit!
58
- end
59
-
60
- desc 'detach [spec1 spec2 spec3...] --roles [role1 role2...]', 'detach spec from spec'
61
- option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
62
- def detach(*args)
63
- Helper.empty_args(self, shell, __method__) if args.empty?
64
- Spec.detach(args, options[:roles]) rescue puts $!.message; exit!
65
- end
66
-
67
- desc 'check [options]', 'run the spec sampled appropriately to the associated host'
68
- option :sample_host_count, :type => :numeric, :default => 5, :desc => 'number of sample hosts'
69
- def check(*args)
70
- Helper.empty_args(self, shell, __method__) if args.empty?
71
-
72
- begin
73
- messages = Spec::Runner.check(args, options[:sample_host_count])
74
- rescue
75
- puts $!.message
76
- exit!
77
- end
78
-
79
- messages.each do |msg|
80
- puts msg
81
- end
82
- end
83
-
84
- desc 'exec (spec1 spec2..) [options]', 'run serverspec manually'
85
- option :hosts, :type => :array, :desc => '--hosts host1 host2 host3...', :required => true
86
- option :ukigumo, :type => :boolean, :desc => 'post results to UkigumoServer'
87
- option :ikachan, :type => :boolean, :desc => 'post fail results to Ikachan'
88
- option :dry_run, :type => :boolean, :desc => 'show commands that may exexute'
89
- def exec(*args)
90
- Helper.empty_args(self, shell, __method__) if args.empty?
91
-
92
- begin
93
- messages = Spec::Runner.exec(
94
- [], [], options[:hosts], args,
95
- {
96
- ukigumo: options[:ukigumo],
97
- ikachan: options[:ikachan],
98
- },
99
- options[:dry_run],
100
- )
101
- rescue
102
- puts $!.message
103
- exit!
104
- end
105
-
106
- messages.each do |msg|
107
- puts msg
108
- end
109
- end
110
- end
111
-
112
-
113
- class HostConduct < Thor::MyHelper
114
- namespace :host
115
-
116
- desc 'details [host1 host2 host3...]', 'show details about host'
117
- def details(*args)
118
- Helper.empty_args(self, shell, __method__) if args.empty?
119
- puts_details(Host.details(args))
120
- end
121
-
122
- desc 'show', 'show all of hosts'
123
- def show
124
- puts (Host.elements + CloudForecast::Host.all).join("\n")
125
- end
126
-
127
- desc 'attach [host1 host2 host3...] --roles [role1 role2...]', 'attach host to role'
128
- option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
129
- def attach(*args)
130
- Helper.empty_args(self, shell, __method__) if args.empty?
131
- Host.attach(args, options[:roles]) rescue puts $!.message; exit!
132
- end
133
-
134
- desc 'detach [host1 host2 host3...] --roles [role1 role2...]', 'detach host from role'
135
- option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
136
- def detach(*args)
137
- Helper.empty_args(self, shell, __method__) if args.empty?
138
- Host.detach(args, options[:roles]) rescue puts $!.message; exit!
139
- end
140
- end
141
-
142
-
143
- class RoleConduct < Thor::MyHelper
144
- namespace :role
145
-
146
- desc 'create [role1 role2 role3...]', 'cretate role'
147
- def create(*args)
148
- Helper.empty_args(self, shell, __method__) if args.empty?
149
- Role.create(args) rescue puts $!.message; exit!
150
- end
151
-
152
- desc 'delete [role1 role2 role3...]', 'delete a role'
153
- def delete(*args)
154
- Helper.empty_args(self, shell, __method__) if args.empty?
155
- Role.delete(args) rescue puts $!.message; exit!
156
- end
157
-
158
- desc 'rename [exist role] [name]', 'rename a role'
159
- def rename(role, rename)
160
- Role.rename(role, rename) rescue puts $!.message; exit!
161
- end
162
-
163
- desc 'details [role1 role2...]', 'show details about role'
164
- def details(*args)
165
- Helper.empty_args(self, shell, __method__) if args.empty?
166
- puts_details(Role.details(args))
167
- end
168
-
169
- desc 'show', 'show all of roles'
170
- def show
171
- puts Role.all.join("\n")
172
- end
173
-
174
- desc 'exec (role1 role2..) [options]', 'run role'
175
- option :exclude_hosts, :type => :array, :desc => '--exclude-hosts host1 host2 host3...'
176
- option :ukigumo, :type => :boolean, :desc => 'post results to UkigumoServer'
177
- option :ikachan, :type => :boolean, :desc => 'post fail results to Ikachan'
178
- option :dry_run, :type => :boolean, :desc => 'show commands that may exexute'
179
- def exec(*args)
180
- Helper.empty_args(self, shell, __method__) if args.empty?
181
-
182
- begin
183
- messages = Spec::Runner.exec(
184
- args, (options[:exclude_hosts]||[]), [], [],
185
- {
186
- ukigumo: options[:ukigumo],
187
- ikachan: options[:ikachan],
188
- },
189
- options[:dry_run],
190
- )
191
- rescue
192
- puts $!.message
193
- exit!
194
- end
195
-
196
- messages.each do |msg|
197
- puts msg
198
- end
199
- end
200
- end
201
-
202
-
203
- class CFConduct < Thor::MyHelper
204
- namespace :cf
205
-
206
- desc "details [cf1 cf2 cf3...]", "show details about cloudforecast's role"
207
- def details(*args)
208
- Helper.empty_args(self, shell, __method__) if args.empty?
209
- puts_details(CloudForecast::Role.details(args))
210
- end
211
-
212
- desc 'show', "show all of cloudforecast's roles"
213
- def show
214
- puts CloudForecast::Role.all.sort.join("\n")
215
- end
216
-
217
- desc 'attach [cf1 cf2 cf3...] --roles [role1 role2...]', "attach cloudforecast's role to role"
218
- option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
219
- def attach(*args)
220
- Helper.empty_args(self, shell, __method__) if args.empty?
221
- CloudForecast::Role.attach(args, options[:roles]) rescue puts $!.message; exit!
222
- end
223
-
224
- desc 'detach [cf1 cf2 cf3...] --roles [role1 role2...]', "detach cloudforecast's role from role"
225
- option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
226
- def detach(*args)
227
- Helper.empty_args(self, shell, __method__) if args.empty?
228
- CloudForecast::Role.detach(args, options[:roles]) rescue puts $!.message; exit!
229
- end
230
-
231
- desc 'load', '(re)loading yamls of cloudforecast'
232
- def load
233
- CloudForecast.load_yaml
234
- end
235
- end
236
-
237
-
238
- class Main < Thor
239
- register(CFConduct, 'cf', 'cf [attach|detach|show|details|load]', 'operate relevant to CloudForecast')
240
- register(RoleConduct, 'role', 'role [create|delete|rename|show|details|exec]', 'operate roles')
241
- register(HostConduct, 'host', 'host [attach|detach|show|details]', 'operate hosts')
242
- register(SpecConduct, 'spec', 'spec [attach|detach|show|details|exec|check]', 'operate specs')
243
-
244
- class_option :help, :type => :boolean, :aliases => '-h', :desc => 'Help message.'
245
- no_tasks do
246
- def invoke_task(task, *args)
247
- if options[:help] && ! %w{role host spec cf help}.include?(task.name)
248
- Houcho.task_help(shell, task.name)
249
- else
250
- super
251
- end
252
- end
253
- end
254
-
255
- desc 'init', 'set houcho repository on current directory'
256
- def init
257
- init_repo
258
- end
259
-
260
- end
261
-
262
- Main.start
263
- exit! if $houcho_fail
2
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+ require 'houcho/cli'
4
+ Houcho::CLI::Main.start
data/houcho.gemspec CHANGED
@@ -20,9 +20,10 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_runtime_dependency 'thor'
22
22
  spec.add_runtime_dependency 'rainbow'
23
- spec.add_runtime_dependency 'parallel_tests'
23
+ spec.add_runtime_dependency 'parallel'
24
24
  spec.add_runtime_dependency 'systemu'
25
25
  spec.add_runtime_dependency 'serverspec'
26
+ spec.add_runtime_dependency 'sqlite3-ruby'
26
27
  spec.add_development_dependency "bundler", "~> 1.3"
27
28
  spec.add_development_dependency "rake"
28
29
  spec.add_development_dependency "tmpdir"
@@ -0,0 +1,99 @@
1
+ require "houcho/database"
2
+
3
+ module Houcho
4
+ class AttributeExceptiotn < Exception; end
5
+
6
+ module Attribute
7
+ def attr_id(attr_name)
8
+ id = @db.execute("SELECT id FROM attribute WHERE name = ?", attr_name)
9
+ raise AttributeExceptiotn, "attribute does not exist - #{attr_name}" unless id
10
+ id.flatten.first
11
+ end
12
+
13
+
14
+ def set_attr!(target, attr)
15
+ set_attr(target, attr, true)
16
+ end
17
+
18
+ def set_attr(target, attr, force = false)
19
+ target_id = id(target)
20
+ raise_target_does_not_exist(target) if target_id.nil?
21
+ @db.transaction do
22
+
23
+ attr.each do |name, attr_value|
24
+ attr_name = name.to_s
25
+
26
+ begin
27
+ @db.execute("INSERT INTO attribute(name) VALUES(?)", attr_name)
28
+ rescue SQLite3::ConstraintException, "column name is not unique"
29
+ end
30
+
31
+ begin
32
+ @db.execute(
33
+ "INSERT INTO attribute_value(attr_id, element_type, element_id, value) VALUES(?,?,?,?)",
34
+ attr_id(attr_name),
35
+ @type_id,
36
+ target_id,
37
+ attr_value
38
+ )
39
+ rescue SQLite3::ConstraintException, "columns attr_id, element_type, element_id are not unique"
40
+ if force
41
+ @db.execute("
42
+ UPDATE attribute_value SET value = ?
43
+ WHERE attr_id = ? AND element_type = ? AND element_id = ?
44
+ ", attr_value, attr_id(attr_name), @type_id, target_id)
45
+ else
46
+ raise AttributeExceptiotn, "attribute has already defined value in #{@type} - #{attr_name}"
47
+ end
48
+ end
49
+ end
50
+
51
+ end #end of transaction
52
+ end
53
+
54
+
55
+ def get_attr_json(target, name = nil)
56
+ get_attr(target, name, true)
57
+ end
58
+
59
+
60
+ def get_attr(target, attr_name = nil, json = false)
61
+ target_id = id(target)
62
+ return json ? "{}" : {} if target_id.nil?
63
+ attr = {}
64
+
65
+ id_value = @db.execute("
66
+ SELECT attr_id, value FROM attribute_value
67
+ WHERE element_type = ? AND element_id = ?
68
+ ", @type_id, target_id)
69
+
70
+ id_value.each do |iv|
71
+ name = @db.execute("SELECT name FROM attribute WHERE id = ?", iv[0]).first.first
72
+ attr[name.to_sym] = iv[1]
73
+ end
74
+
75
+ attr = attr.select { |k,v| k == attr_name.to_sym } if attr_name
76
+ attr = JSON.generate(attr) if json
77
+ attr
78
+ end
79
+
80
+
81
+ def del_attr(target, attr_name = nil)
82
+ before_delete = get_attr(target, attr_name)
83
+ sql = "DELETE FROM attribute_value WHERE element_type = ? AND element_id = ?"
84
+
85
+ @db.transaction do
86
+
87
+ if attr_name
88
+ sql += " AND attr_id = ?"
89
+ @db.execute(sql, @type_id, id(target), attr_id(attr_name))
90
+ else
91
+ @db.execute(sql, @type_id, id(target))
92
+ end
93
+
94
+ end #end of transaction
95
+
96
+ before_delete
97
+ end
98
+ end
99
+ end
data/lib/houcho/ci.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding: utf-8 -*-
1
2
  require 'net/http'
2
3
  require 'uri'
3
4
 
@@ -9,17 +10,18 @@ end
9
10
  module Houcho::CI
10
11
  class UkigumoClient
11
12
  def initialize(server, port = 80, url = "http://#{server}:#{port}")
12
- @ukigumo_server = server
13
+ @ukigumo_server = server
13
14
  @ukigumo_listen_port = port
14
- @ukigumo_base_url = url
15
+ @ukigumo_base_url = url
15
16
  end
16
17
 
17
18
  def search(elements, limit = 1)
18
- query_string =
19
- URI.encode("project") + "=" + URI.encode(elements[:project].to_s) + "&" +
20
- URI.encode("branch") + "=" + URI.encode(elements[:branch].to_s) + "&" +
21
- URI.encode("revision") + "=" + URI.encode(elements[:revision].to_s) + "&" +
22
- URI.encode("limit") + "=" + URI.encode(limit.to_s)
19
+ query_string = URI.encode_www_form({
20
+ :project => elements[:project].to_s,
21
+ :branch => elements[:branch].to_s,
22
+ :revision => elements[:revision].to_s,
23
+ :limit => limit.to_s,
24
+ })
23
25
 
24
26
  Net::HTTP.start(@ukigumo_server, @ukigumo_listen_port) do |http|
25
27
  responce = http.get("/api/v1/report/search?#{query_string}")
@@ -28,7 +30,7 @@ module Houcho::CI
28
30
  end
29
31
 
30
32
  def post(elements)
31
- Net::HTTP.post_form(
33
+ response = Net::HTTP.post_form(
32
34
  URI.parse("#{@ukigumo_base_url}/api/v1/report/add"),
33
35
  {
34
36
  :status => elements[:status],
@@ -39,26 +41,29 @@ module Houcho::CI
39
41
  :vc_log => elements[:vc_log],
40
42
  :body => elements[:body],
41
43
  }
42
- ).body
44
+ )
45
+ response.body
43
46
  end
44
47
  end
45
48
 
46
49
  class IkachanClient
47
50
  def initialize(channel, server, port = 4979)
48
- @ikachan_server = server
51
+ @ikachan_server = server
49
52
  @ikachan_listen_port = port
50
- @ikachan_channels = channel.instance_of?(Array) ? channel : [channel]
53
+ @ikachan_channels = channel.is_a?(Array) ? channel : [channel]
51
54
  end
52
55
 
56
+ # return が @ikachan_channels の最後の要素だけになってるからどうにかする
53
57
  def post(message)
54
58
  @ikachan_channels.each do |channel|
55
- Net::HTTP.post_form(
59
+ response = Net::HTTP.post_form(
56
60
  URI.parse("http://#{@ikachan_server}:#{@ikachan_listen_port}/notice"),
57
61
  {
58
62
  :channel => channel,
59
63
  :message => message,
60
64
  }
61
- ).body
65
+ )
66
+ response.body
62
67
  end
63
68
  end
64
69
  end
@@ -0,0 +1,70 @@
1
+ require "thor"
2
+ require "houcho/attribute"
3
+
4
+ module Houcho
5
+ module CLI
6
+ class Attribute < Thor
7
+ namespace :attr
8
+
9
+
10
+ def self.target_type_obj(target_type)
11
+ case target_type
12
+ when "role"
13
+ Houcho::Role.new
14
+ when "outerrole"
15
+ Houcho::OuterRole.new
16
+ when "host"
17
+ Houcho::Host.new
18
+ else
19
+ Houcho::CLI::Main.empty_args(self, shell, __method__)
20
+ # puts helps and exit(1)
21
+ end
22
+ end
23
+
24
+
25
+ desc "set", "set attribute"
26
+ option :target, :type => :hash, :required => true, :desc => "assign target of hash"
27
+ option :value, :type => :hash, :required => true, :desc => "assign attribute of hash"
28
+ option :force, :type => :boolean, :desc => "update attribute if defined already"
29
+ def set
30
+ options[:target].each do |target_type, target_name|
31
+ obj = Houcho::CLI::Attribute.target_type_obj(target_type)
32
+ begin
33
+ if options[:force]
34
+ obj.set_attr!(target_name, options[:value])
35
+ else
36
+ obj.set_attr(target_name, options[:value])
37
+ end
38
+ rescue Houcho::AttributeExceptiotn=> e
39
+ puts e.message
40
+ exit!
41
+ end
42
+ end
43
+ end
44
+
45
+
46
+ desc "get [attr name](optional)", "get attribute"
47
+ option :target, :type => :hash, :required => true, :desc => "assign target of hash"
48
+ def get(attr_name = nil)
49
+ options[:target].each do |target_type, target_name|
50
+ obj = Houcho::CLI::Attribute.target_type_obj(target_type)
51
+ obj.get_attr(target_name, attr_name).each do |k,v|
52
+ puts "#{k.to_s.color(:red)}:#{v}"
53
+ end
54
+ end
55
+ end
56
+
57
+
58
+ desc "delete [attr name](optional)", "delete attribute of host"
59
+ option :target, :type => :hash, :required => true, :desc => "assign target of hash"
60
+ def delete(attr_name = nil)
61
+ options[:target].each do |target_type, target_name|
62
+ obj = Houcho::CLI::Attribute.target_type_obj(target_type)
63
+ obj.del_attr(target_name, attr_name).each do |k,v|
64
+ print "#{k}:#{v} "
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,46 @@
1
+ require 'thor'
2
+ require 'houcho/host'
3
+
4
+ module Houcho
5
+ module CLI
6
+ class Host < Thor
7
+ namespace :host
8
+
9
+ @@h = Houcho::Host.new
10
+
11
+ desc 'list', 'show all of host list'
12
+ def list
13
+ puts @@h.list.sort.join("\n")
14
+ end
15
+
16
+
17
+ desc 'attach [host1 host2 host3...] --roles [role1 role2...]', 'attach host to role'
18
+ option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
19
+ def attach(*args)
20
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
21
+ @@h.attach(args, options[:roles])
22
+ rescue RoleExistenceException, SpecFileException, SQLite3::ConstraintException => e
23
+ puts e.message
24
+ exit!
25
+ end
26
+
27
+
28
+ desc 'detach [spec1 spec2 spec3...] --roles [role1 role2...]', 'detach spec from spec'
29
+ option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
30
+ def detach(*args)
31
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
32
+ @@h.detach(args, options[:roles])
33
+ rescue RoleExistenceException, SQLite3::ConstraintException => e
34
+ puts e.message
35
+ exit!
36
+ end
37
+
38
+
39
+ desc 'details [spec1 spec2 spec3...]', 'show details about spec'
40
+ def details(*args)
41
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
42
+ Houcho::CLI::Main.puts_details(@@h.details(args))
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,53 @@
1
+ require 'thor'
2
+ require 'houcho/outerrole'
3
+ require 'houcho/outerrole/cloudforecast'
4
+
5
+ module Houcho
6
+ module CLI
7
+ class OuterRole < Thor
8
+ namespace :host
9
+
10
+ @@or = Houcho::OuterRole.new
11
+
12
+ desc 'list', 'show all of host list'
13
+ def list
14
+ puts @@or.list.sort.join("\n")
15
+ end
16
+
17
+
18
+ desc 'attach [outerrole1 outerrole2 outerrole3...] --roles [role1 role2...]', 'attach outer role to role'
19
+ option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
20
+ def attach(*args)
21
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
22
+ @@or.attach(args, options[:roles])
23
+ rescue RoleExistenceException, SpecFileException, SQLite3::ConstraintException => e
24
+ puts e.message
25
+ exit!
26
+ end
27
+
28
+
29
+ desc 'detach [outerrole1 outerrole2 outerrole3...] --roles [role1 role2...]', 'detach outer role from role'
30
+ option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
31
+ def detach(*args)
32
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
33
+ @@or.detach(args, options[:roles])
34
+ rescue RoleExistenceException, SQLite3::ConstraintException => e
35
+ puts e.message
36
+ exit!
37
+ end
38
+
39
+
40
+ desc 'details [outerrole1 outerrole2 outerrole3...]', 'show details about outerrole'
41
+ def details(*args)
42
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
43
+ Houcho::CLI::Main.puts_details(@@or.details(args))
44
+ end
45
+
46
+
47
+ desc 'load', 'load role data from outer system'
48
+ def load
49
+ Houcho::OuterRole::CloudForecast.load
50
+ end
51
+ end
52
+ end
53
+ end