startapp 0.1.6

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 (156) hide show
  1. checksums.yaml +7 -0
  2. data/COPYRIGHT +1 -0
  3. data/LICENSE +11 -0
  4. data/README.md +95 -0
  5. data/Rakefile +6 -0
  6. data/autocomplete/rhc_bash +1672 -0
  7. data/bin/app +37 -0
  8. data/conf/express.conf +8 -0
  9. data/features/assets/deploy.tar.gz +0 -0
  10. data/features/core_feature.rb +191 -0
  11. data/features/deployments_feature.rb +129 -0
  12. data/features/domains_feature.rb +58 -0
  13. data/features/keys_feature.rb +37 -0
  14. data/features/members_feature.rb +166 -0
  15. data/lib/rhc/auth/basic.rb +64 -0
  16. data/lib/rhc/auth/token.rb +102 -0
  17. data/lib/rhc/auth/token_store.rb +53 -0
  18. data/lib/rhc/auth.rb +5 -0
  19. data/lib/rhc/autocomplete.rb +66 -0
  20. data/lib/rhc/autocomplete_templates/bash.erb +39 -0
  21. data/lib/rhc/cartridge_helpers.rb +118 -0
  22. data/lib/rhc/cli.rb +40 -0
  23. data/lib/rhc/command_runner.rb +185 -0
  24. data/lib/rhc/commands/account.rb +25 -0
  25. data/lib/rhc/commands/alias.rb +124 -0
  26. data/lib/rhc/commands/app.rb +726 -0
  27. data/lib/rhc/commands/apps.rb +20 -0
  28. data/lib/rhc/commands/authorization.rb +115 -0
  29. data/lib/rhc/commands/base.rb +174 -0
  30. data/lib/rhc/commands/cartridge.rb +329 -0
  31. data/lib/rhc/commands/clone.rb +66 -0
  32. data/lib/rhc/commands/configure.rb +20 -0
  33. data/lib/rhc/commands/create.rb +100 -0
  34. data/lib/rhc/commands/delete.rb +19 -0
  35. data/lib/rhc/commands/deploy.rb +32 -0
  36. data/lib/rhc/commands/deployment.rb +82 -0
  37. data/lib/rhc/commands/domain.rb +172 -0
  38. data/lib/rhc/commands/env.rb +142 -0
  39. data/lib/rhc/commands/force_stop.rb +17 -0
  40. data/lib/rhc/commands/git_clone.rb +34 -0
  41. data/lib/rhc/commands/logout.rb +51 -0
  42. data/lib/rhc/commands/logs.rb +21 -0
  43. data/lib/rhc/commands/member.rb +148 -0
  44. data/lib/rhc/commands/port_forward.rb +197 -0
  45. data/lib/rhc/commands/reload.rb +17 -0
  46. data/lib/rhc/commands/restart.rb +17 -0
  47. data/lib/rhc/commands/scp.rb +54 -0
  48. data/lib/rhc/commands/server.rb +40 -0
  49. data/lib/rhc/commands/setup.rb +60 -0
  50. data/lib/rhc/commands/show.rb +43 -0
  51. data/lib/rhc/commands/snapshot.rb +137 -0
  52. data/lib/rhc/commands/ssh.rb +51 -0
  53. data/lib/rhc/commands/sshkey.rb +97 -0
  54. data/lib/rhc/commands/start.rb +17 -0
  55. data/lib/rhc/commands/stop.rb +17 -0
  56. data/lib/rhc/commands/tail.rb +47 -0
  57. data/lib/rhc/commands/threaddump.rb +14 -0
  58. data/lib/rhc/commands/tidy.rb +17 -0
  59. data/lib/rhc/commands.rb +396 -0
  60. data/lib/rhc/config.rb +321 -0
  61. data/lib/rhc/context_helper.rb +121 -0
  62. data/lib/rhc/core_ext.rb +202 -0
  63. data/lib/rhc/coverage_helper.rb +33 -0
  64. data/lib/rhc/deployment_helpers.rb +111 -0
  65. data/lib/rhc/exceptions.rb +256 -0
  66. data/lib/rhc/git_helpers.rb +106 -0
  67. data/lib/rhc/help_formatter.rb +55 -0
  68. data/lib/rhc/helpers.rb +481 -0
  69. data/lib/rhc/highline_extensions.rb +479 -0
  70. data/lib/rhc/json.rb +51 -0
  71. data/lib/rhc/output_helpers.rb +260 -0
  72. data/lib/rhc/rest/activation.rb +11 -0
  73. data/lib/rhc/rest/alias.rb +42 -0
  74. data/lib/rhc/rest/api.rb +87 -0
  75. data/lib/rhc/rest/application.rb +348 -0
  76. data/lib/rhc/rest/attributes.rb +36 -0
  77. data/lib/rhc/rest/authorization.rb +8 -0
  78. data/lib/rhc/rest/base.rb +79 -0
  79. data/lib/rhc/rest/cartridge.rb +162 -0
  80. data/lib/rhc/rest/client.rb +650 -0
  81. data/lib/rhc/rest/deployment.rb +18 -0
  82. data/lib/rhc/rest/domain.rb +98 -0
  83. data/lib/rhc/rest/environment_variable.rb +15 -0
  84. data/lib/rhc/rest/gear_group.rb +16 -0
  85. data/lib/rhc/rest/httpclient.rb +145 -0
  86. data/lib/rhc/rest/key.rb +44 -0
  87. data/lib/rhc/rest/membership.rb +105 -0
  88. data/lib/rhc/rest/mock.rb +1042 -0
  89. data/lib/rhc/rest/user.rb +32 -0
  90. data/lib/rhc/rest.rb +148 -0
  91. data/lib/rhc/scp_helpers.rb +27 -0
  92. data/lib/rhc/ssh_helpers.rb +380 -0
  93. data/lib/rhc/tar_gz.rb +51 -0
  94. data/lib/rhc/usage_templates/command_help.erb +51 -0
  95. data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
  96. data/lib/rhc/usage_templates/help.erb +61 -0
  97. data/lib/rhc/usage_templates/missing_help.erb +1 -0
  98. data/lib/rhc/usage_templates/options_help.erb +12 -0
  99. data/lib/rhc/vendor/okjson.rb +600 -0
  100. data/lib/rhc/vendor/parseconfig.rb +178 -0
  101. data/lib/rhc/vendor/sshkey.rb +253 -0
  102. data/lib/rhc/vendor/zliby.rb +628 -0
  103. data/lib/rhc/version.rb +5 -0
  104. data/lib/rhc/wizard.rb +637 -0
  105. data/lib/rhc.rb +34 -0
  106. data/spec/coverage_helper.rb +82 -0
  107. data/spec/direct_execution_helper.rb +339 -0
  108. data/spec/keys/example.pem +23 -0
  109. data/spec/keys/example_private.pem +27 -0
  110. data/spec/keys/server.pem +19 -0
  111. data/spec/rest_spec_helper.rb +31 -0
  112. data/spec/rhc/assets/cert.crt +22 -0
  113. data/spec/rhc/assets/cert_key_rsa +27 -0
  114. data/spec/rhc/assets/empty.txt +0 -0
  115. data/spec/rhc/assets/env_vars.txt +7 -0
  116. data/spec/rhc/assets/env_vars_2.txt +1 -0
  117. data/spec/rhc/assets/foo.txt +1 -0
  118. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  119. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  120. data/spec/rhc/auth_spec.rb +442 -0
  121. data/spec/rhc/cli_spec.rb +186 -0
  122. data/spec/rhc/command_spec.rb +435 -0
  123. data/spec/rhc/commands/account_spec.rb +42 -0
  124. data/spec/rhc/commands/alias_spec.rb +333 -0
  125. data/spec/rhc/commands/app_spec.rb +777 -0
  126. data/spec/rhc/commands/apps_spec.rb +39 -0
  127. data/spec/rhc/commands/authorization_spec.rb +157 -0
  128. data/spec/rhc/commands/cartridge_spec.rb +665 -0
  129. data/spec/rhc/commands/clone_spec.rb +41 -0
  130. data/spec/rhc/commands/deployment_spec.rb +327 -0
  131. data/spec/rhc/commands/domain_spec.rb +401 -0
  132. data/spec/rhc/commands/env_spec.rb +493 -0
  133. data/spec/rhc/commands/git_clone_spec.rb +102 -0
  134. data/spec/rhc/commands/logout_spec.rb +86 -0
  135. data/spec/rhc/commands/member_spec.rb +247 -0
  136. data/spec/rhc/commands/port_forward_spec.rb +217 -0
  137. data/spec/rhc/commands/scp_spec.rb +77 -0
  138. data/spec/rhc/commands/server_spec.rb +69 -0
  139. data/spec/rhc/commands/setup_spec.rb +118 -0
  140. data/spec/rhc/commands/snapshot_spec.rb +179 -0
  141. data/spec/rhc/commands/ssh_spec.rb +163 -0
  142. data/spec/rhc/commands/sshkey_spec.rb +188 -0
  143. data/spec/rhc/commands/tail_spec.rb +81 -0
  144. data/spec/rhc/commands/threaddump_spec.rb +84 -0
  145. data/spec/rhc/config_spec.rb +407 -0
  146. data/spec/rhc/helpers_spec.rb +531 -0
  147. data/spec/rhc/highline_extensions_spec.rb +314 -0
  148. data/spec/rhc/json_spec.rb +30 -0
  149. data/spec/rhc/rest_application_spec.rb +258 -0
  150. data/spec/rhc/rest_client_spec.rb +752 -0
  151. data/spec/rhc/rest_spec.rb +740 -0
  152. data/spec/rhc/targz_spec.rb +55 -0
  153. data/spec/rhc/wizard_spec.rb +756 -0
  154. data/spec/spec_helper.rb +575 -0
  155. data/spec/wizard_spec_helper.rb +330 -0
  156. metadata +469 -0
@@ -0,0 +1,348 @@
1
+ require 'uri'
2
+
3
+ module RHC
4
+ module Rest
5
+ class Application < Base
6
+ include Membership
7
+
8
+ define_attr :domain_id, :name, :creation_time, :uuid,
9
+ :git_url, :app_url, :gear_profile, :framework,
10
+ :scalable, :health_check_path, :embedded, :gear_count,
11
+ :ssh_url, :building_app, :cartridges, :initial_git_url,
12
+ :auto_deploy, :deployment_branch, :deployment_type, :keep_deployments, :deployments
13
+ alias_method :domain_name, :domain_id
14
+
15
+ # Query helper to say consistent with cartridge
16
+ def scalable?
17
+ scalable
18
+ end
19
+
20
+ def id
21
+ attributes['id'] || uuid
22
+ end
23
+
24
+ def uuid
25
+ if (client.api_version_negotiated >= 1.6)
26
+ attributes['id']
27
+ else
28
+ attributes['uuid']
29
+ end
30
+ end
31
+
32
+ def domain
33
+ domain_id
34
+ end
35
+
36
+ def scalable_carts
37
+ return [] unless scalable?
38
+ carts = cartridges.select(&:scalable?)
39
+ scales_with = carts.map(&:scales_with)
40
+ carts.delete_if{|x| scales_with.include?(x.name)}
41
+ end
42
+
43
+ def add_cartridge(cart, options={})
44
+ debug "Adding cartridge #{name}"
45
+ clear_attribute :cartridges
46
+ cart =
47
+ if cart.is_a? String
48
+ {:name => cart}
49
+ elsif cart.respond_to? :[]
50
+ cart
51
+ else
52
+ c = cart.url ? {:url => cart.url} : {:name => cart.name}
53
+ if cart.respond_to?(:environment_variables) && cart.environment_variables.present?
54
+ c[:environment_variables] = cart.environment_variables
55
+ end
56
+ if cart.respond_to?(:gear_size) && cart.gear_size.present?
57
+ c[:gear_size] = cart.gear_size
58
+ end
59
+ cart = c
60
+ end
61
+
62
+ if cart.respond_to?(:[]) and cart[:url] and !has_param?('ADD_CARTRIDGE', 'url')
63
+ raise RHC::Rest::DownloadingCartridgesNotSupported, "The server does not support downloading cartridges."
64
+ end
65
+
66
+ rest_method(
67
+ "ADD_CARTRIDGE",
68
+ cart,
69
+ options
70
+ )
71
+ end
72
+
73
+ def cartridges
74
+ @cartridges ||=
75
+ unless (carts = attributes['cartridges']).nil?
76
+ carts.map{|x| Cartridge.new(x, client) }
77
+ else
78
+ debug "Getting all cartridges for application #{name}"
79
+ rest_method "LIST_CARTRIDGES"
80
+ end
81
+ end
82
+
83
+ def gear_info
84
+ { :gear_count => gear_count, :gear_profile => gear_profile } unless gear_count.nil?
85
+ end
86
+
87
+ def gear_groups
88
+ debug "Getting all gear groups for application #{name}"
89
+ rest_method "GET_GEAR_GROUPS"
90
+ end
91
+
92
+ def gears
93
+ gear_groups.map{ |group| group.gears }.flatten
94
+ end
95
+
96
+ def gear_ssh_url(gear_id)
97
+ gear = gears.find{ |g| g['id'] == gear_id }
98
+
99
+ raise ArgumentError, "Gear #{gear_id} not found" if gear.nil?
100
+ gear['ssh_url'] or raise NoPerGearOperations
101
+ end
102
+
103
+ def tidy
104
+ debug "Starting application #{name}"
105
+ rest_method 'TIDY', :event => "tidy"
106
+ end
107
+
108
+ def scale_up
109
+ rest_method 'SCALE_UP', :event => "scale-up"
110
+ end
111
+
112
+ def scale_down
113
+ rest_method 'SCALE_DOWN', :event => "scale-down"
114
+ end
115
+
116
+ def start
117
+ debug "Starting application #{name}"
118
+ rest_method 'START', :event => "start"
119
+ end
120
+
121
+ def stop(force=false)
122
+ debug "Stopping application #{name} force-#{force}"
123
+
124
+ if force
125
+ payload = {:event=> "force-stop"}
126
+ else
127
+ payload = {:event=> "stop"}
128
+ end
129
+
130
+ rest_method "STOP", payload
131
+ end
132
+
133
+ def restart
134
+ debug "Restarting application #{name}"
135
+ rest_method "RESTART", :event => "restart"
136
+ end
137
+
138
+ def destroy
139
+ debug "Deleting application #{name}"
140
+ rest_method "DELETE"
141
+ end
142
+ alias :delete :destroy
143
+
144
+ def reload
145
+ debug "Reload application #{name}"
146
+ rest_method "RELOAD", :event => "reload"
147
+ end
148
+
149
+ def threaddump
150
+ debug "Running thread dump for #{name}"
151
+ rest_method "THREAD_DUMP", :event => "thread-dump"
152
+ end
153
+
154
+ def environment_variables
155
+ debug "Getting all environment variables for application #{name}"
156
+ if supports? "LIST_ENVIRONMENT_VARIABLES"
157
+ rest_method "LIST_ENVIRONMENT_VARIABLES"
158
+ else
159
+ raise RHC::EnvironmentVariablesNotSupportedException.new
160
+ end
161
+ end
162
+
163
+ def find_environment_variable(env_var_name)
164
+ find_environment_variables(env_var_name).first
165
+ end
166
+
167
+ def find_environment_variables(env_var_names=nil)
168
+ return environment_variables if env_var_names.nil?
169
+ env_var_names = [env_var_names].flatten
170
+ debug "Finding environment variable(s) #{env_var_names.inspect} in app #{@name}"
171
+ env_vars = environment_variables.select { |item| env_var_names.include? item.name }
172
+ raise RHC::EnvironmentVariableNotFoundException.new("Environment variable(s) #{env_var_names.join(', ')} can't be found in application #{name}.") if env_vars.empty?
173
+ env_vars
174
+ end
175
+
176
+ # @param [Array<RHC::Rest::EnvironmentVariable>] Array of RHC::Rest::EnvironmentVariable to be set
177
+ def set_environment_variables(env_vars=[])
178
+ debug "Adding environment variable(s) #{env_vars.inspect} for #{name}"
179
+ if supports? "SET_UNSET_ENVIRONMENT_VARIABLES"
180
+ rest_method "SET_UNSET_ENVIRONMENT_VARIABLES", :environment_variables => env_vars.map{|item| item.to_hash}
181
+ else
182
+ raise RHC::EnvironmentVariablesNotSupportedException.new
183
+ end
184
+ end
185
+
186
+ # @param [Array<String>] Array of env var names like ['FOO', 'BAR']
187
+ def unset_environment_variables(env_vars=[])
188
+ debug "Removing environment variable(s) #{env_vars.inspect} for #{name}"
189
+ if supports? "SET_UNSET_ENVIRONMENT_VARIABLES"
190
+ rest_method "SET_UNSET_ENVIRONMENT_VARIABLES", :environment_variables => env_vars.map{|item| {:name => item}}
191
+ else
192
+ raise RHC::EnvironmentVariablesNotSupportedException.new
193
+ end
194
+ end
195
+
196
+ def supports_add_cartridge_with_env_vars?
197
+ has_param?('ADD_CARTRIDGE', 'environment_variables')
198
+ end
199
+
200
+ def supports_add_cartridge_with_gear_size?
201
+ has_param?('ADD_CARTRIDGE', 'gear_size')
202
+ end
203
+
204
+ def deployments
205
+ debug "Listing deployments for application #{name}"
206
+ raise RHC::DeploymentsNotSupportedException if !supports? "LIST_DEPLOYMENTS"
207
+ rest_method("LIST_DEPLOYMENTS").sort
208
+ end
209
+
210
+ def deployment_activations
211
+ items = []
212
+
213
+ # building an array of activations with their deployments
214
+ deployments.each do |deployment|
215
+ deployment.activations.each do |activation|
216
+ items << {:activation => activation, :deployment => deployment}
217
+ end
218
+ end
219
+
220
+ items.sort! {|a,b| a[:activation].created_at <=> b[:activation].created_at }
221
+
222
+ first_activation = {}
223
+
224
+ items.each do |item|
225
+ deployment = item[:deployment]
226
+ activation = item[:activation]
227
+
228
+ # set the currently active (last activation by date)
229
+ item[:active] = item == items.last
230
+
231
+ # mark rollbacks (activations whose deployment had previous activations)
232
+ if rollback_to = first_activation[deployment.id]
233
+ item[:rollback] = true
234
+ item[:rollback_to] = rollback_to
235
+ # mark rolled back (all in between a rollback and its original deployment)
236
+ items.each {|i| i[:rolled_back] = true if i[:activation].created_at > rollback_to && i[:activation].created_at < activation.created_at }
237
+ else
238
+ first_activation[deployment.id] = activation.created_at
239
+ end
240
+
241
+ end
242
+
243
+ items
244
+ end
245
+
246
+ def configure(options={})
247
+ debug "Running update for #{name} with options #{options.inspect}"
248
+ if supports? "UPDATE"
249
+ rest_method "UPDATE", options
250
+ else
251
+ raise RHC::DeploymentsNotSupportedException
252
+ end
253
+ end
254
+
255
+ def add_alias(app_alias)
256
+ debug "Running add_alias for #{name}"
257
+ rest_method "ADD_ALIAS", :event => "add-alias", :alias => app_alias
258
+ end
259
+
260
+ def remove_alias(app_alias)
261
+ debug "Running remove_alias for #{name}"
262
+ if (client.api_version_negotiated >= 1.4)
263
+ find_alias(app_alias).destroy
264
+ else
265
+ rest_method "REMOVE_ALIAS", :event => "remove-alias", :alias => app_alias
266
+ end
267
+ end
268
+
269
+ def aliases
270
+ debug "Getting all aliases for application #{name}"
271
+ @aliases ||= begin
272
+ aliases = attributes['aliases']
273
+ if aliases.nil? or not aliases.is_a?(Array)
274
+ supports?('LIST_ALIASES') ? rest_method("LIST_ALIASES") : []
275
+ else
276
+ aliases.map do |a|
277
+ Alias.new(a.is_a?(String) ? {'id' => a} : a, client)
278
+ end
279
+ end
280
+ end
281
+ end
282
+
283
+ def find_alias(name, options={})
284
+ debug "Finding alias #{name} in app #{@name}"
285
+
286
+ if name.is_a?(Hash)
287
+ options = name
288
+ name = options[:name]
289
+ end
290
+ aliases.each { |a| return a if a.is_a?(String) || a.id == name.downcase }
291
+ raise RHC::AliasNotFoundException.new("Alias #{name} can't be found in application #{@name}.")
292
+ end
293
+
294
+ #Find Cartridge by name
295
+ def find_cartridge(sought, options={})
296
+ debug "Finding cartridge #{sought} in app #{name}"
297
+
298
+ type = options[:type]
299
+
300
+ cartridges.each { |cart| return cart if cart.name == sought and (type.nil? or cart.type == type) }
301
+
302
+ suggested_msg = ""
303
+ valid_cartridges = cartridges.select {|c| type.nil? or c.type == type}
304
+ unless valid_cartridges.empty?
305
+ suggested_msg = "\n\nValid cartridges:"
306
+ valid_cartridges.each { |cart| suggested_msg += "\n#{cart.name}" }
307
+ end
308
+ raise RHC::CartridgeNotFoundException.new("Cartridge #{sought} can't be found in application #{name}.#{suggested_msg}")
309
+ end
310
+
311
+ #Find Cartridges by name or regex
312
+ def find_cartridges(name, options={})
313
+ if name.is_a?(Hash)
314
+ options = name
315
+ name = options[:name]
316
+ end
317
+
318
+ type = options[:type]
319
+ regex = options[:regex]
320
+ debug "Finding cartridge #{name || regex} in app #{@name}"
321
+
322
+ filtered = Array.new
323
+ cartridges.each do |cart|
324
+ if regex
325
+ filtered.push(cart) if cart.name.match(/(?i:#{regex})/) and (type.nil? or cart.type == type)
326
+ else
327
+ filtered.push(cart) if cart.name.downcase == name.downcase and (type.nil? or cart.type == type)
328
+ end
329
+ end
330
+ filtered
331
+ end
332
+
333
+ def host
334
+ @host ||= URI.parse(app_url).host rescue nil
335
+ end
336
+
337
+ def ssh_string
338
+ RHC::Helpers.ssh_string(ssh_url)
339
+ end
340
+
341
+ def <=>(other)
342
+ c = name.downcase <=> other.name.downcase
343
+ return c unless c == 0
344
+ domain_id <=> other.domain_id
345
+ end
346
+ end
347
+ end
348
+ end
@@ -0,0 +1,36 @@
1
+ module RHC::Rest::Attributes
2
+ def attributes
3
+ @attributes
4
+ end
5
+
6
+ def attributes=(attr=nil)
7
+ @attributes = (attr || {}).stringify_keys!
8
+ end
9
+
10
+ def attribute(name)
11
+ instance_variable_get("@#{name}") || attributes[name.to_s]
12
+ end
13
+
14
+ def clear_attribute(name)
15
+ v = instance_variable_set("@#{name}", nil)
16
+ attributes.delete(name.to_s) or v
17
+ end
18
+ end
19
+
20
+ module RHC::Rest::AttributesClass
21
+ def define_attr(*names)
22
+ names.map(&:to_sym).each do |name|
23
+ define_method(name) do
24
+ attribute(name)
25
+ end
26
+ define_method("#{name}=") do |value|
27
+ instance_variable_set(:"@#{name}", nil)
28
+ attributes[name.to_s] = value
29
+ end
30
+ end
31
+ end
32
+
33
+ def model_name
34
+ name.split("::").last
35
+ end
36
+ end
@@ -0,0 +1,8 @@
1
+ module RHC
2
+ module Rest
3
+ class Authorization < Base
4
+ define_attr :token, :note, :expires_in, :expires_in_seconds, :scopes, :created_at
5
+ alias_method :creation_time, :created_at
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,79 @@
1
+ require 'cgi'
2
+
3
+ module RHC
4
+ module Rest
5
+ class Base
6
+ include Attributes
7
+ extend AttributesClass
8
+
9
+ define_attr :messages
10
+
11
+ def initialize(attrs=nil, client=nil)
12
+ @attributes = (attrs || {}).stringify_keys!
13
+ @attributes['messages'] ||= []
14
+ @client = client
15
+ end
16
+
17
+ def add_message(msg)
18
+ messages << msg
19
+ end
20
+
21
+ def rest_method(link_name, payload={}, options={})
22
+ link = link(link_name)
23
+ raise "No link defined for #{link_name}" unless link
24
+ url = link['href']
25
+ url = url.gsub(/:\w+/) { |s| CGI.escape(options[:params][s]) || s } if options[:params]
26
+ method = options[:method] || link['method']
27
+
28
+ result = client.request(options.merge({
29
+ :url => url,
30
+ :method => method,
31
+ :payload => payload,
32
+ }))
33
+ if result.is_a?(Hash) && (result['messages'] || result['errors'])
34
+ attributes['messages'] = Array(result['messages'])
35
+ result = self
36
+ end
37
+ result
38
+ end
39
+
40
+ def links
41
+ attributes['links'] || {}
42
+ end
43
+
44
+ def supports?(sym)
45
+ !!link(sym)
46
+ end
47
+
48
+ def has_param?(sym, name)
49
+ if l = link(sym)
50
+ (l['required_params'] || []).any?{ |p| p['name'] == name} or (l['optional_params'] || []).any?{ |p| p['name'] == name}
51
+ end
52
+ end
53
+
54
+ def link_href(sym, params=nil, resource=nil, &block)
55
+ if (l = link(sym)) && (h = l['href'])
56
+ h = h.gsub(/:\w+/){ |s| params[s].nil? ? s : CGI.escape(params[s]) } if params
57
+ h = "#{h}/#{resource}" if resource
58
+ return h
59
+ end
60
+ yield if block_given?
61
+ end
62
+
63
+ protected
64
+ attr_reader :client
65
+
66
+ def link(sym)
67
+ (links[sym.to_s] || links[sym.to_s.upcase])
68
+ end
69
+
70
+ def debug(msg, obj=nil)
71
+ client.debug("#{msg}#{obj ? " #{obj}" : ''}") if client && client.debug?
72
+ end
73
+
74
+ def debug?
75
+ client && client.debug?
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,162 @@
1
+ module RHC
2
+ module Rest
3
+ class Cartridge < Base
4
+ HIDDEN_TAGS = [:framework, :web_framework, :cartridge].map(&:to_s)
5
+
6
+ define_attr :type, :name, :display_name, :properties, :gear_profile, :status_messages, :scales_to, :scales_from, :scales_with,
7
+ :current_scale, :supported_scales_to, :supported_scales_from, :tags, :description, :collocated_with, :base_gear_storage,
8
+ :additional_gear_storage, :url, :environment_variables, :gear_size, :automatic_updates
9
+
10
+ def scalable?
11
+ supported_scales_to != supported_scales_from
12
+ end
13
+
14
+ def custom?
15
+ url.present?
16
+ end
17
+
18
+ def only_in_new?
19
+ type == 'standalone'
20
+ end
21
+
22
+ def only_in_existing?
23
+ type == 'embedded'
24
+ end
25
+
26
+ def automatic_updates?
27
+ v = attribute(:automatic_updates)
28
+ if v.nil?
29
+ v = !(tags.include?('no_updates') || custom?)
30
+ end
31
+ v
32
+ end
33
+
34
+ def shares_gears?
35
+ Array(collocated_with).present?
36
+ end
37
+ def collocated_with
38
+ Array(attribute(:collocated_with))
39
+ end
40
+
41
+ def tags
42
+ Array(attribute(:tags))
43
+ end
44
+
45
+ def gear_storage
46
+ (base_gear_storage + additional_gear_storage) * 1024 * 1024 * 1024
47
+ end
48
+
49
+ def additional_gear_storage
50
+ attribute(:additional_gear_storage).to_i rescue 0
51
+ end
52
+
53
+ def display_name
54
+ attribute(:display_name) || name || url_basename
55
+ end
56
+
57
+ #
58
+ # Use this value when the user should interact with this cart via CLI arguments
59
+ #
60
+ def short_name
61
+ name || url
62
+ end
63
+
64
+ def usage_rate?
65
+ rate = usage_rate
66
+ rate && rate > 0.0
67
+ end
68
+
69
+ def usage_rate
70
+ rate = attribute(:usage_rate_usd)
71
+
72
+ if attribute(:usage_rates)
73
+ rate ||= attribute(:usage_rates).inject(0) { |total, rate| total + rate['usd'].to_f }
74
+ end
75
+
76
+ rate.to_f rescue 0.0
77
+ end
78
+
79
+ def scaling
80
+ {
81
+ :current_scale => current_scale,
82
+ :scales_from => scales_from,
83
+ :scales_to => scales_to,
84
+ :gear_profile => gear_profile,
85
+ } if scalable?
86
+ end
87
+
88
+ def property(type, key)
89
+ key, type = key.to_s, type.to_s
90
+ properties.select{ |p| p['type'] == type }.find{ |p| p['name'] == key }
91
+ end
92
+
93
+ def status
94
+ debug "Getting cartridge #{name}'s status"
95
+ result = rest_method "GET", :include => "status_messages"
96
+ result.status_messages
97
+ end
98
+
99
+ def start
100
+ debug "Starting cartridge #{name}"
101
+ rest_method "START", :event => "start"
102
+ end
103
+
104
+ def stop
105
+ debug "Stopping cartridge #{name}"
106
+ rest_method "STOP", :event => "stop"
107
+ end
108
+
109
+ def restart
110
+ debug "Restarting cartridge #{name}"
111
+ rest_method "RESTART", :event => "restart"
112
+ end
113
+
114
+ def reload
115
+ debug "Reloading cartridge #{name}"
116
+ rest_method "RESTART", :event => "reload"
117
+ end
118
+
119
+ def destroy
120
+ debug "Deleting cartridge #{name}"
121
+ rest_method "DELETE"
122
+ end
123
+ alias :delete :destroy
124
+
125
+ def set_scales(values)
126
+ values.delete_if{|k,v| v.nil? }
127
+ debug "Setting scales = %s" % values.map{|k,v| "#{k}: #{v}"}.join(" ")
128
+ rest_method "UPDATE", values
129
+ end
130
+
131
+ def set_storage(values)
132
+ debug "Setting additional storage: #{values[:additional_gear_storage]}GB"
133
+ rest_method "UPDATE", values
134
+ end
135
+
136
+ def connection_info
137
+ info = property(:cart_data, :connection_url) || property(:cart_data, :job_url) || property(:cart_data, :monitoring_url)
138
+ info ? (info["value"] || '').rstrip : nil
139
+ end
140
+
141
+ def <=>(other)
142
+ return -1 if other.type == 'standalone' && type != 'standalone'
143
+ return 1 if type == 'standalone' && other.type != 'standalone'
144
+ name <=> other.name
145
+ end
146
+
147
+ def url_basename
148
+ uri = URI.parse(url)
149
+ name = uri.fragment
150
+ name = Rack::Utils.parse_nested_query(uri.query)['name'] if name.blank? && uri.query
151
+ name = File.basename(uri.path) if name.blank? && uri.path.present? && uri.path != '/'
152
+ name.presence || url
153
+ rescue
154
+ url
155
+ end
156
+
157
+ def self.for_url(url)
158
+ new 'url' => url
159
+ end
160
+ end
161
+ end
162
+ end