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.
- checksums.yaml +7 -0
- data/COPYRIGHT +1 -0
- data/LICENSE +11 -0
- data/README.md +95 -0
- data/Rakefile +6 -0
- data/autocomplete/rhc_bash +1672 -0
- data/bin/app +37 -0
- data/conf/express.conf +8 -0
- data/features/assets/deploy.tar.gz +0 -0
- data/features/core_feature.rb +191 -0
- data/features/deployments_feature.rb +129 -0
- data/features/domains_feature.rb +58 -0
- data/features/keys_feature.rb +37 -0
- data/features/members_feature.rb +166 -0
- data/lib/rhc/auth/basic.rb +64 -0
- data/lib/rhc/auth/token.rb +102 -0
- data/lib/rhc/auth/token_store.rb +53 -0
- data/lib/rhc/auth.rb +5 -0
- data/lib/rhc/autocomplete.rb +66 -0
- data/lib/rhc/autocomplete_templates/bash.erb +39 -0
- data/lib/rhc/cartridge_helpers.rb +118 -0
- data/lib/rhc/cli.rb +40 -0
- data/lib/rhc/command_runner.rb +185 -0
- data/lib/rhc/commands/account.rb +25 -0
- data/lib/rhc/commands/alias.rb +124 -0
- data/lib/rhc/commands/app.rb +726 -0
- data/lib/rhc/commands/apps.rb +20 -0
- data/lib/rhc/commands/authorization.rb +115 -0
- data/lib/rhc/commands/base.rb +174 -0
- data/lib/rhc/commands/cartridge.rb +329 -0
- data/lib/rhc/commands/clone.rb +66 -0
- data/lib/rhc/commands/configure.rb +20 -0
- data/lib/rhc/commands/create.rb +100 -0
- data/lib/rhc/commands/delete.rb +19 -0
- data/lib/rhc/commands/deploy.rb +32 -0
- data/lib/rhc/commands/deployment.rb +82 -0
- data/lib/rhc/commands/domain.rb +172 -0
- data/lib/rhc/commands/env.rb +142 -0
- data/lib/rhc/commands/force_stop.rb +17 -0
- data/lib/rhc/commands/git_clone.rb +34 -0
- data/lib/rhc/commands/logout.rb +51 -0
- data/lib/rhc/commands/logs.rb +21 -0
- data/lib/rhc/commands/member.rb +148 -0
- data/lib/rhc/commands/port_forward.rb +197 -0
- data/lib/rhc/commands/reload.rb +17 -0
- data/lib/rhc/commands/restart.rb +17 -0
- data/lib/rhc/commands/scp.rb +54 -0
- data/lib/rhc/commands/server.rb +40 -0
- data/lib/rhc/commands/setup.rb +60 -0
- data/lib/rhc/commands/show.rb +43 -0
- data/lib/rhc/commands/snapshot.rb +137 -0
- data/lib/rhc/commands/ssh.rb +51 -0
- data/lib/rhc/commands/sshkey.rb +97 -0
- data/lib/rhc/commands/start.rb +17 -0
- data/lib/rhc/commands/stop.rb +17 -0
- data/lib/rhc/commands/tail.rb +47 -0
- data/lib/rhc/commands/threaddump.rb +14 -0
- data/lib/rhc/commands/tidy.rb +17 -0
- data/lib/rhc/commands.rb +396 -0
- data/lib/rhc/config.rb +321 -0
- data/lib/rhc/context_helper.rb +121 -0
- data/lib/rhc/core_ext.rb +202 -0
- data/lib/rhc/coverage_helper.rb +33 -0
- data/lib/rhc/deployment_helpers.rb +111 -0
- data/lib/rhc/exceptions.rb +256 -0
- data/lib/rhc/git_helpers.rb +106 -0
- data/lib/rhc/help_formatter.rb +55 -0
- data/lib/rhc/helpers.rb +481 -0
- data/lib/rhc/highline_extensions.rb +479 -0
- data/lib/rhc/json.rb +51 -0
- data/lib/rhc/output_helpers.rb +260 -0
- data/lib/rhc/rest/activation.rb +11 -0
- data/lib/rhc/rest/alias.rb +42 -0
- data/lib/rhc/rest/api.rb +87 -0
- data/lib/rhc/rest/application.rb +348 -0
- data/lib/rhc/rest/attributes.rb +36 -0
- data/lib/rhc/rest/authorization.rb +8 -0
- data/lib/rhc/rest/base.rb +79 -0
- data/lib/rhc/rest/cartridge.rb +162 -0
- data/lib/rhc/rest/client.rb +650 -0
- data/lib/rhc/rest/deployment.rb +18 -0
- data/lib/rhc/rest/domain.rb +98 -0
- data/lib/rhc/rest/environment_variable.rb +15 -0
- data/lib/rhc/rest/gear_group.rb +16 -0
- data/lib/rhc/rest/httpclient.rb +145 -0
- data/lib/rhc/rest/key.rb +44 -0
- data/lib/rhc/rest/membership.rb +105 -0
- data/lib/rhc/rest/mock.rb +1042 -0
- data/lib/rhc/rest/user.rb +32 -0
- data/lib/rhc/rest.rb +148 -0
- data/lib/rhc/scp_helpers.rb +27 -0
- data/lib/rhc/ssh_helpers.rb +380 -0
- data/lib/rhc/tar_gz.rb +51 -0
- data/lib/rhc/usage_templates/command_help.erb +51 -0
- data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
- data/lib/rhc/usage_templates/help.erb +61 -0
- data/lib/rhc/usage_templates/missing_help.erb +1 -0
- data/lib/rhc/usage_templates/options_help.erb +12 -0
- data/lib/rhc/vendor/okjson.rb +600 -0
- data/lib/rhc/vendor/parseconfig.rb +178 -0
- data/lib/rhc/vendor/sshkey.rb +253 -0
- data/lib/rhc/vendor/zliby.rb +628 -0
- data/lib/rhc/version.rb +5 -0
- data/lib/rhc/wizard.rb +637 -0
- data/lib/rhc.rb +34 -0
- data/spec/coverage_helper.rb +82 -0
- data/spec/direct_execution_helper.rb +339 -0
- data/spec/keys/example.pem +23 -0
- data/spec/keys/example_private.pem +27 -0
- data/spec/keys/server.pem +19 -0
- data/spec/rest_spec_helper.rb +31 -0
- data/spec/rhc/assets/cert.crt +22 -0
- data/spec/rhc/assets/cert_key_rsa +27 -0
- data/spec/rhc/assets/empty.txt +0 -0
- data/spec/rhc/assets/env_vars.txt +7 -0
- data/spec/rhc/assets/env_vars_2.txt +1 -0
- data/spec/rhc/assets/foo.txt +1 -0
- data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
- data/spec/rhc/assets/targz_sample.tar.gz +0 -0
- data/spec/rhc/auth_spec.rb +442 -0
- data/spec/rhc/cli_spec.rb +186 -0
- data/spec/rhc/command_spec.rb +435 -0
- data/spec/rhc/commands/account_spec.rb +42 -0
- data/spec/rhc/commands/alias_spec.rb +333 -0
- data/spec/rhc/commands/app_spec.rb +777 -0
- data/spec/rhc/commands/apps_spec.rb +39 -0
- data/spec/rhc/commands/authorization_spec.rb +157 -0
- data/spec/rhc/commands/cartridge_spec.rb +665 -0
- data/spec/rhc/commands/clone_spec.rb +41 -0
- data/spec/rhc/commands/deployment_spec.rb +327 -0
- data/spec/rhc/commands/domain_spec.rb +401 -0
- data/spec/rhc/commands/env_spec.rb +493 -0
- data/spec/rhc/commands/git_clone_spec.rb +102 -0
- data/spec/rhc/commands/logout_spec.rb +86 -0
- data/spec/rhc/commands/member_spec.rb +247 -0
- data/spec/rhc/commands/port_forward_spec.rb +217 -0
- data/spec/rhc/commands/scp_spec.rb +77 -0
- data/spec/rhc/commands/server_spec.rb +69 -0
- data/spec/rhc/commands/setup_spec.rb +118 -0
- data/spec/rhc/commands/snapshot_spec.rb +179 -0
- data/spec/rhc/commands/ssh_spec.rb +163 -0
- data/spec/rhc/commands/sshkey_spec.rb +188 -0
- data/spec/rhc/commands/tail_spec.rb +81 -0
- data/spec/rhc/commands/threaddump_spec.rb +84 -0
- data/spec/rhc/config_spec.rb +407 -0
- data/spec/rhc/helpers_spec.rb +531 -0
- data/spec/rhc/highline_extensions_spec.rb +314 -0
- data/spec/rhc/json_spec.rb +30 -0
- data/spec/rhc/rest_application_spec.rb +258 -0
- data/spec/rhc/rest_client_spec.rb +752 -0
- data/spec/rhc/rest_spec.rb +740 -0
- data/spec/rhc/targz_spec.rb +55 -0
- data/spec/rhc/wizard_spec.rb +756 -0
- data/spec/spec_helper.rb +575 -0
- data/spec/wizard_spec_helper.rb +330 -0
- 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,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
|