cap-rightscale 0.0.12 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -21,6 +21,8 @@ Jeweler::Tasks.new do |gem|
21
21
  gem.authors = ["Satoshi Ohki"]
22
22
  # Include your dependencies below. Runtime dependencies are required when using your gem,
23
23
  # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ gem.add_runtime_dependency 'capistrano', '> 2.5'
25
+ gem.add_runtime_dependency 'rightresource', '> 0.3.4'
24
26
  # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
27
  # gem.add_development_dependency 'rspec', '> 1.2.3'
26
28
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.12
1
+ 0.1.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{cap-rightscale}
8
- s.version = "0.0.12"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Satoshi Ohki"]
12
- s.date = %q{2011-02-02}
12
+ s.date = %q{2011-02-03}
13
13
  s.description = %q{Capistrano extension that maps RightScale parameters to Roles.}
14
14
  s.email = %q{roothybrid7@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -41,7 +41,7 @@ Gem::Specification.new do |s|
41
41
  s.homepage = %q{http://github.com/roothybrid7/cap-rightscale}
42
42
  s.licenses = ["MIT"]
43
43
  s.require_paths = ["lib"]
44
- s.rubygems_version = %q{1.5.0}
44
+ s.rubygems_version = %q{1.3.7}
45
45
  s.summary = %q{Capistrano extension that maps RightScale parameters to Roles}
46
46
  s.test_files = [
47
47
  "spec/cap-rightscale_spec.rb",
@@ -49,6 +49,7 @@ Gem::Specification.new do |s|
49
49
  ]
50
50
 
51
51
  if s.respond_to? :specification_version then
52
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
52
53
  s.specification_version = 3
53
54
 
54
55
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
@@ -57,12 +58,16 @@ Gem::Specification.new do |s|
57
58
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
58
59
  s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
59
60
  s.add_development_dependency(%q<rcov>, [">= 0"])
61
+ s.add_runtime_dependency(%q<capistrano>, ["> 2.5"])
62
+ s.add_runtime_dependency(%q<rightresource>, ["> 0.3.4"])
60
63
  else
61
64
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
62
65
  s.add_dependency(%q<cucumber>, [">= 0"])
63
66
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
64
67
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
65
68
  s.add_dependency(%q<rcov>, [">= 0"])
69
+ s.add_dependency(%q<capistrano>, ["> 2.5"])
70
+ s.add_dependency(%q<rightresource>, ["> 0.3.4"])
66
71
  end
67
72
  else
68
73
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
@@ -70,6 +75,8 @@ Gem::Specification.new do |s|
70
75
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
71
76
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
72
77
  s.add_dependency(%q<rcov>, [">= 0"])
78
+ s.add_dependency(%q<capistrano>, ["> 2.5"])
79
+ s.add_dependency(%q<rightresource>, ["> 0.3.4"])
73
80
  end
74
81
  end
75
82
 
@@ -1,3 +1,6 @@
1
+ require 'cap-rightscale/utils/rs_utils.rb'
2
+ require 'ping'
3
+
1
4
  module Capistrano
2
5
  class Configuration
3
6
  module RightScale
@@ -9,6 +12,14 @@ module Capistrano
9
12
  @rs_confpath = path
10
13
  end
11
14
 
15
+ def rs_cache_lifetime(time)
16
+ @lifetime = time # seconds
17
+ end
18
+
19
+ def validate_echo(bool=false)
20
+ @pingecho = bool
21
+ end
22
+
12
23
  # register deploy host's /etc/hosts OR dns record(replace 's/ #/-000/' to ServerArray name)
13
24
  def use_nickname(bool=false)
14
25
  @use_nick = bool
@@ -18,15 +29,6 @@ module Capistrano
18
29
  @domain = domain
19
30
  end
20
31
 
21
- def connect
22
- @auth ||= open(get_rs_confpath) {|f| YAML.load(f)}
23
- @conn ||= RightResource::Connection.new do |c|
24
- c.login(:username => @auth["username"], :password => @auth["password"], :account => @auth["account"])
25
- end
26
-
27
- RightResource::Base.connection = @conn
28
- end
29
-
30
32
  # Get RightScale Server Array
31
33
  # === Parameters
32
34
  # * _role_ - Capistrano role symbol (ex. :app, :web, :db)
@@ -39,25 +41,46 @@ module Capistrano
39
41
  return [] unless check_role(role)
40
42
  raise ArgumentError, ":array_id is not included in params!![#{params}]" unless params.has_key?(:array_id)
41
43
 
42
- start = Time.now
43
- connect
44
44
  logger.info("SETTING ROLE: #{role}")
45
- array = ServerArray.show(params[:array_id])
46
- logger.info("querying rightscale for server_array #{array.nickname}...")
47
- deployment_name = Deployment.show(array.deployment_href.match(/[0-9]+$/).to_s).nickname
48
- logger.info("Deployment #{deployment_name}:")
45
+
46
+ # Set rightscale's parameters
47
+ _array = params[:array_id]
49
48
 
50
49
  params.delete(:array_id) # remove rightscale's parameters
51
50
 
52
- host_list = ServerArray.instances(array.id).select {|i| i[:state] == "operational"}.map do |instance|
53
- hostname = instance[:nickname].sub(/ #[0-9]+$/, "-%03d" % instance[:nickname].match(/[0-9]+$/).to_s.to_i)
54
- hostname << ".#{_domain}" if _domain
55
- ip = instance[:private_ip_address]
56
- logger.info("Found server: #{hostname}(#{ip})")
57
- enable_hostname ? hostname : ip
58
- end
59
- role(role, params) { host_list } if host_list
51
+ host_list = get_server_cache(role) # Get cache
52
+
53
+ if host_list && host_list.size > 0
54
+ logger.info("restore cache of servers:\n#{host_list.pretty_inspect}")
55
+ role(role, params) { host_list } # set cache to role()
56
+ else
57
+ # Request RightScale API
58
+ start = Time.now
59
+ connect
60
+ array = ServerArray.show(_array)
61
+ logger.info("querying rightscale for server_array #{array.nickname}...")
62
+ deployment_name = Deployment.show(array.deployment_href.match(/[0-9]+$/).to_s).nickname
63
+ logger.info("Deployment #{deployment_name}:")
64
+
65
+ host_list = ServerArray.instances(array.id).select {|i| i[:state] == "operational"}.map do |instance|
66
+ hostname = instance[:nickname].sub(/ #[0-9]+$/, "-%03d" % instance[:nickname].match(/[0-9]+$/).to_s.to_i)
67
+ hostname << ".#{_domain}" if _domain
68
+ ip = instance[:private_ip_address]
69
+ if @pingecho
70
+ next unless Ping.pingecho(ip)
71
+ end
72
+
73
+ logger.info("Found server: #{hostname}(#{ip})")
74
+ enable_hostname ? hostname : ip
75
+ end
76
+ host_list.delete(nil)
60
77
  puts "Time: #{Time.now - start}"
78
+ if host_list && host_list.size > 0
79
+ role(role, params) { host_list }
80
+ dump_server_cache(role, host_list) # Dump cache
81
+ end
82
+ end
83
+
61
84
  host_list || []
62
85
  end
63
86
 
@@ -74,27 +97,48 @@ puts "Time: #{Time.now - start}"
74
97
  return [] unless check_role(role)
75
98
  raise ArgumentError, ":deployment is not included in params!![#{params}]" unless params.has_key?(:deployment)
76
99
 
77
- start = Time.now
78
- connect
79
100
  logger.info("SETTING ROLE: #{role}")
80
- dept = Deployment.show(params[:deployment], :server_settings => 'true')
81
- logger.info("querying rightscale for servers #{params[:name_prefix]} in deployment #{dept.nickname}...")
82
- srvs = dept.servers.select {|s| s[:state] == "operational"}
83
- srvs = srvs.select {|s| /#{params[:name_prefix]}/ =~ s[:nickname]} if params[:name_prefix]
84
101
 
85
- # remove rightscale's parameters
102
+ # Set rightscale's parameters
103
+ _dept = params[:deployment]
104
+ _name_prefix = params[:name_prefix]
105
+
86
106
  params.delete(:deployment)
87
107
  params.delete(:name_prefix) if params.has_key?(:name_prefix)
88
108
 
89
- host_list = srvs.map do |server|
90
- hostname = server[:nickname]
91
- hostname << ".#{_domain}" if _domain
92
- ip = server[:settings][:private_ip_address]
93
- logger.info("Found server: #{hostname}(#{ip})")
94
- enable_hostname ? hostname : ip
95
- end
96
- role(role, params) { host_list } if host_list
109
+ host_list = get_server_cache(role) # Get cache
110
+
111
+ if host_list && host_list.size > 0
112
+ logger.info("restore cache of servers:\n#{host_list.pretty_inspect}")
113
+ role(role, params) { host_list } # set cache to role()
114
+ else
115
+ # Request RightScale API
116
+ start = Time.now
117
+ connect
118
+ dept = Deployment.show(_dept, :server_settings => 'true')
119
+ logger.info("querying rightscale for servers #{_name_prefix} in deployment #{dept.nickname}...")
120
+ srvs = dept.servers.select {|s| s[:state] == "operational"}
121
+ srvs = srvs.select {|s| /#{_name_prefix}/ =~ s[:nickname]} if _name_prefix
122
+
123
+ host_list = srvs.map do |server|
124
+ hostname = server[:nickname]
125
+ hostname << ".#{_domain}" if _domain
126
+ ip = server[:settings][:private_ip_address]
127
+ if @pingecho
128
+ next unless Ping.pingecho(ip)
129
+ end
130
+
131
+ logger.info("Found server: #{hostname}(#{ip})")
132
+ enable_hostname ? hostname : ip
133
+ end
134
+ host_list.delete(nil)
97
135
  puts "Time: #{Time.now - start}"
136
+ if host_list && host_list.size > 0
137
+ role(role, params) { host_list }
138
+ dump_server_cache(role, host_list) # Dump cache
139
+ end
140
+ end
141
+
98
142
  host_list || []
99
143
  end
100
144
 
@@ -112,44 +156,122 @@ puts "Time: #{Time.now - start}"
112
156
  raise ArgumentError, ":tags is not included in params!![#{params}]" unless params.has_key?(:tags)
113
157
  raise ArgumentError, ":deployment is not included in params!![#{params}]" unless params.has_key?(:deployment)
114
158
 
115
- start = Time.now
116
- connect
117
159
  logger.info("SETTING ROLE: #{role}")
118
- dept = Deployment.show(params[:deployment], :server_settings => 'true')
119
- logger.info("querying rightscale for servers matching tags #{params[:tags]} in deployment #{dept.nickname}...")
120
- srvs = dept.servers.select {|s| s[:state] == "operational"}
121
160
 
122
- ts_params = {:resource_type => "ec2_instance", :tags => [params[:tags]]}
123
- ts = Tag.search(ts_params).
124
- select {|s| s.state == "operational"}.
125
- select {|s| s.deployment_href.match(/[0-9]+$/).to_s == params[:deployment].to_s}
161
+ # Set rightscale's parameters
162
+ _dept = params[:deployment]
163
+ _tags = params[:tags]
126
164
 
127
- # diff servers in deployment and servers matching tags in deployment
128
- srvs_ids = srvs.map {|s| s[:href].match(/[0-9]+$/).to_s}
129
- ts_ids = ts.map {|s| s.href.sub("/current", "").match(/[0-9]+$/).to_s}
130
- found_ids = srvs_ids & ts_ids
131
-
132
- # remove rightscale's parameters
133
165
  params.delete(:deployment)
134
166
  params.delete(:tags)
135
167
 
136
- host_list = []
137
- if found_ids.size > 0
138
- host_list = srvs.select {|s| found_ids.include?(s[:href].match(/[0-9]+$/).to_s)}.map do |server|
139
- hostname = server[:nickname]
140
- hostname << ".#{_domain}" if _domain
141
- ip = server[:settings][:private_ip_address]
142
- logger.info("Found server: #{hostname}(#{ip})")
143
- enable_hostname ? hostname : ip
144
- end
168
+ host_list = get_server_cache(role) # Get cache
145
169
 
146
- role(role, params) { host_list } if host_list
147
- end
170
+ if host_list && host_list.size > 0
171
+ logger.info("restore cache of servers:\n#{host_list.pretty_inspect}")
172
+ role(role, params) { host_list } # set cache to role()
173
+ else
174
+ # Request RightScale API
175
+ start = Time.now
176
+ connect
177
+ dept = Deployment.show(_dept, :server_settings => 'true')
178
+ logger.info("querying rightscale for servers matching tags #{_tags} in deployment #{dept.nickname}...")
179
+ srvs = dept.servers.select {|s| s[:state] == "operational"}
180
+
181
+ ts_params = {:resource_type => "ec2_instance", :tags => [_tags]}
182
+ ts = Tag.search(ts_params).
183
+ select {|s| s.state == "operational"}.
184
+ select {|s| s.deployment_href.match(/[0-9]+$/).to_s == _dept.to_s}
185
+
186
+ # diff servers in deployment and servers matching tags in deployment
187
+ srvs_ids = srvs.map {|s| s[:href].match(/[0-9]+$/).to_s}
188
+ ts_ids = ts.map {|s| s.href.sub("/current", "").match(/[0-9]+$/).to_s}
189
+ found_ids = srvs_ids & ts_ids
190
+
191
+ if found_ids.size > 0
192
+ host_list = srvs.select {|s| found_ids.include?(s[:href].match(/[0-9]+$/).to_s)}.map do |server|
193
+ hostname = server[:nickname]
194
+ hostname << ".#{_domain}" if _domain
195
+ ip = server[:settings][:private_ip_address]
196
+ if @pingecho
197
+ next unless Ping.pingecho(ip)
198
+ end
199
+
200
+ logger.info("Found server: #{hostname}(#{ip})")
201
+ enable_hostname ? hostname : ip
202
+ end
203
+ host_list.delete(nil)
204
+ end
148
205
  puts "Time: #{Time.now - start}"
206
+ if host_list && host_list.size > 0
207
+ role(role, params) { host_list }
208
+ dump_server_cache(role, host_list) # Dump cache
209
+ end
210
+ end
211
+
149
212
  host_list || []
150
213
  end
151
214
 
152
215
  private
216
+ def connect
217
+ @auth ||= open(get_rs_confpath) {|f| YAML.load(f)}
218
+ @conn ||= RightResource::Connection.new do |c|
219
+ c.login(:username => @auth["username"], :password => @auth["password"], :account => @auth["account"])
220
+ end
221
+
222
+ RightResource::Base.connection = @conn
223
+ end
224
+
225
+ def get_server_cache(role)
226
+ @lifetime ||= 86400
227
+ @server_cache ||= {}
228
+
229
+ begin
230
+ @cache_files ||= Dir.glob("#{Dir.tmpdir}/cap-rightscale-#{ENV['USER']}-*/#{stage}*")
231
+
232
+ @cache_files.each do |c|
233
+ @server_cache.update(Marshal.load(open(c) {|f| f.read}))
234
+ end if @cache_files.size > 0 && @server_cache.empty?
235
+
236
+ return [] if @server_cache.empty? # No cache entry
237
+
238
+ # get servers
239
+ if Time.now - @server_cache[role][:cache] > @lifetime
240
+ @server_cache.delete(role)
241
+ server_list = []
242
+ elsif @server_cache[role][:servers]
243
+ server_list = @server_cache[role][:servers]
244
+ else
245
+ server_list = []
246
+ end
247
+ rescue => e
248
+ return [] if @server_cache.empty?
249
+ end
250
+ server_list
251
+ end
252
+
253
+ def dump_server_cache(role, servers)
254
+ h = {role => {:servers => servers, :cache => Time.now}}
255
+ cache = @server_cache.update(h) # update servers cache
256
+ obj_dump = Marshal.dump(cache)
257
+
258
+ # Get cache directory
259
+ cache_dir = Dir.glob("#{Dir.tmpdir}/cap-rightscale-#{ENV['USER']}-*").first
260
+ if cache_dir.nil?
261
+ RSUtils.mk_rs_cache_dir
262
+ cache_dir = Dir.glob("#{Dir.tmpdir}/cap-rightscale-#{ENV['USER']}-*").first
263
+ exit if cache_dir.nil?
264
+ end
265
+ cache_file = File.join(cache_dir, stage ? "#{stage}" : "default")
266
+
267
+ begin
268
+ open(cache_file, "w") {|f| f.write(obj_dump)}
269
+ rescue => e
270
+ logger.error("#{e.class}: #{e.pretty_inspect}")
271
+ logger.debug {"Backtrace:\n#{e.backtrace.pretty_inspect}"}
272
+ end
273
+ end
274
+
153
275
  def enable_hostname
154
276
  @use_nick ||= false
155
277
  end
@@ -7,9 +7,10 @@ namespace :rightscale do
7
7
  desc "Clear rightscale's server list cache"
8
8
  namespace :cache do
9
9
  task :clear do
10
- puts "Clear cache all"
11
- pp Dir.glob("#{Dir.tmpdir}/cap-rightscale-*/#{stage}*")
12
- FileUtils.rm(Dir.glob("#{Dir.tmpdir}/cap-rightscale-*/#{stage}*"), {:force => true})
10
+ logger.info("Clear cache all")
11
+ pp Dir.glob("#{Dir.tmpdir}/cap-rightscale-#{ENV['USER']}-*/#{stage}*")
12
+ prefix = stage ? "#{stage}" : "default"
13
+ FileUtils.rm(Dir.glob("#{Dir.tmpdir}/cap-rightscale-#{ENV['USER']}-*/#{prefix}*"), {:force => true})
13
14
  end
14
15
  end
15
16
  end
@@ -1,5 +1,5 @@
1
1
  class RSUtils
2
- def self.mk_rs_cache_dir(prefix)
2
+ def self.mk_rs_cache_dir(prefix=nil)
3
3
  tmpdir = Dir.tmpdir
4
4
  _prefix = prefix || "cap-rightscale"
5
5
  begin
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cap-rightscale
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
5
- prerelease:
4
+ hash: 27
5
+ prerelease: false
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 12
10
- version: 0.0.12
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Satoshi Ohki
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-02 00:00:00 +09:00
18
+ date: 2011-02-03 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: rspec
22
+ prerelease: false
23
23
  version_requirements: &id001 !ruby/object:Gem::Requirement
24
24
  none: false
25
25
  requirements:
@@ -31,11 +31,11 @@ dependencies:
31
31
  - 3
32
32
  - 0
33
33
  version: 2.3.0
34
- prerelease: false
35
- type: :development
34
+ name: rspec
36
35
  requirement: *id001
36
+ type: :development
37
37
  - !ruby/object:Gem::Dependency
38
- name: cucumber
38
+ prerelease: false
39
39
  version_requirements: &id002 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
@@ -45,11 +45,11 @@ dependencies:
45
45
  segments:
46
46
  - 0
47
47
  version: "0"
48
- prerelease: false
49
- type: :development
48
+ name: cucumber
50
49
  requirement: *id002
50
+ type: :development
51
51
  - !ruby/object:Gem::Dependency
52
- name: bundler
52
+ prerelease: false
53
53
  version_requirements: &id003 !ruby/object:Gem::Requirement
54
54
  none: false
55
55
  requirements:
@@ -61,11 +61,11 @@ dependencies:
61
61
  - 0
62
62
  - 0
63
63
  version: 1.0.0
64
- prerelease: false
65
- type: :development
64
+ name: bundler
66
65
  requirement: *id003
66
+ type: :development
67
67
  - !ruby/object:Gem::Dependency
68
- name: jeweler
68
+ prerelease: false
69
69
  version_requirements: &id004 !ruby/object:Gem::Requirement
70
70
  none: false
71
71
  requirements:
@@ -77,11 +77,11 @@ dependencies:
77
77
  - 5
78
78
  - 2
79
79
  version: 1.5.2
80
- prerelease: false
81
- type: :development
80
+ name: jeweler
82
81
  requirement: *id004
82
+ type: :development
83
83
  - !ruby/object:Gem::Dependency
84
- name: rcov
84
+ prerelease: false
85
85
  version_requirements: &id005 !ruby/object:Gem::Requirement
86
86
  none: false
87
87
  requirements:
@@ -91,9 +91,40 @@ dependencies:
91
91
  segments:
92
92
  - 0
93
93
  version: "0"
94
- prerelease: false
95
- type: :development
94
+ name: rcov
96
95
  requirement: *id005
96
+ type: :development
97
+ - !ruby/object:Gem::Dependency
98
+ prerelease: false
99
+ version_requirements: &id006 !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">"
103
+ - !ruby/object:Gem::Version
104
+ hash: 9
105
+ segments:
106
+ - 2
107
+ - 5
108
+ version: "2.5"
109
+ name: capistrano
110
+ requirement: *id006
111
+ type: :runtime
112
+ - !ruby/object:Gem::Dependency
113
+ prerelease: false
114
+ version_requirements: &id007 !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">"
118
+ - !ruby/object:Gem::Version
119
+ hash: 27
120
+ segments:
121
+ - 0
122
+ - 3
123
+ - 4
124
+ version: 0.3.4
125
+ name: rightresource
126
+ requirement: *id007
127
+ type: :runtime
97
128
  description: Capistrano extension that maps RightScale parameters to Roles.
98
129
  email: roothybrid7@gmail.com
99
130
  executables: []
@@ -154,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
185
  requirements: []
155
186
 
156
187
  rubyforge_project:
157
- rubygems_version: 1.5.0
188
+ rubygems_version: 1.3.7
158
189
  signing_key:
159
190
  specification_version: 3
160
191
  summary: Capistrano extension that maps RightScale parameters to Roles