right_api_helper 0.0.1
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/.gitignore +25 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE +13 -0
- data/README.md +66 -0
- data/Rakefile +7 -0
- data/bin/organize +193 -0
- data/demo/deployments.json +44 -0
- data/demo/index.html +83 -0
- data/demo/logo.png +0 -0
- data/demo/start_server.sh +12 -0
- data/demo/tree.jquery.js +2947 -0
- data/lib/right_api_helper/api15.rb +357 -0
- data/lib/right_api_helper/base.rb +54 -0
- data/lib/right_api_helper/cache.rb +53 -0
- data/lib/right_api_helper/deployments.rb +39 -0
- data/lib/right_api_helper/instances.rb +46 -0
- data/lib/right_api_helper/scripts/deployments_creator.rb +44 -0
- data/lib/right_api_helper/session.rb +76 -0
- data/lib/right_api_helper/version.rb +3 -0
- data/lib/right_api_helper.rb +32 -0
- data/right_api_helper.gemspec +30 -0
- data/spec/api15_spec.rb +280 -0
- data/spec/cache_spec.rb +57 -0
- data/spec/data/deployments.json +44 -0
- data/spec/deployments_spec.rb +57 -0
- data/spec/instances_spec.rb +41 -0
- data/spec/scripts/deployments_creator_spec.rb +59 -0
- data/spec/session_spec.rb +46 -0
- data/spec/spec_helper.rb +50 -0
- metadata +214 -0
@@ -0,0 +1,357 @@
|
|
1
|
+
#
|
2
|
+
# Author: cary@rightscale.com
|
3
|
+
# Copyright 2014 RightScale, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
# This contains a bunch or random helper shims
|
19
|
+
# Probably should be broken out into separate classes
|
20
|
+
#
|
21
|
+
module RightApiHelper
|
22
|
+
class API15 < Base
|
23
|
+
|
24
|
+
# If the cloud reports ssh keys, then we assume it requires them to launch
|
25
|
+
# servers.
|
26
|
+
def requires_ssh_keys?(cloud)
|
27
|
+
begin
|
28
|
+
cloud.show.ssh_keys
|
29
|
+
true
|
30
|
+
rescue RightApi::ApiError => e
|
31
|
+
false # assume cloud does not require them
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Find SSH key
|
36
|
+
#
|
37
|
+
# EC2 and Eucalyptus require an SSH key to launch a server. RightScale
|
38
|
+
# manages SSH keys for each user so just grabbing the first one is fine,
|
39
|
+
# however older configurations might relay on specific keys. You will
|
40
|
+
# need to grab the resource UUID from the RightScale dashboard for the key
|
41
|
+
# that you want to use.
|
42
|
+
def find_ssh_key_by_uuid_or_first(cloud, ssh_uuid = nil)
|
43
|
+
ssh_key = nil
|
44
|
+
if ssh_uuid
|
45
|
+
# grab specific ssh key
|
46
|
+
sshkey = find_resource(:ssh_keys, :by_resource_uid, uuid)
|
47
|
+
else
|
48
|
+
# grab first key found
|
49
|
+
keys = cloud.show.ssh_keys
|
50
|
+
ssh_key = keys.index.first if keys
|
51
|
+
end
|
52
|
+
ssh_key
|
53
|
+
end
|
54
|
+
|
55
|
+
# If the cloud reports security groups then we assume it requires them to launch
|
56
|
+
# servers.
|
57
|
+
def requires_security_groups?(cloud)
|
58
|
+
begin
|
59
|
+
cloud.show.security_groups
|
60
|
+
true
|
61
|
+
rescue RightApi::ApiError => e
|
62
|
+
false # assume cloud does not require them
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def user_data(server)
|
67
|
+
@user_data ||= server.show.current_instance(:view=>"extended").show.user_data
|
68
|
+
end
|
69
|
+
|
70
|
+
def data_request_url(userdata)
|
71
|
+
data_hash = {}
|
72
|
+
entry = userdata.split('&').select { |entry| entry =~ /RS_rn_auth/i }
|
73
|
+
raise "ERROR: user data token not found. " +
|
74
|
+
"Does your MCI have a provides:rs_agent_type=right_link tag?" unless entry
|
75
|
+
token = entry.first.split('=')[1]
|
76
|
+
"#{api_url}/servers/data_injection_payload/#{token}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def delete_server(name)
|
80
|
+
server = find_server_by_name(name)
|
81
|
+
server.terminate
|
82
|
+
begin
|
83
|
+
server_wait_for_state(server, "terminated")
|
84
|
+
rescue Exception => e
|
85
|
+
|
86
|
+
end
|
87
|
+
server.destroy
|
88
|
+
end
|
89
|
+
|
90
|
+
def list_servers(filter_by, filter_value)
|
91
|
+
list_resources(:servers, filter_by, filter_value)
|
92
|
+
end
|
93
|
+
|
94
|
+
def list_deployments(filter_by=nil, filter_value=nil)
|
95
|
+
list_resources(:deployments, filter_by, filter_value)
|
96
|
+
end
|
97
|
+
|
98
|
+
def list_clouds(filter_by=nil, filter_value=nil)
|
99
|
+
list_resources(:clouds, filter_by, filter_value)
|
100
|
+
end
|
101
|
+
|
102
|
+
def list_servertemplates(filter_by, filter_value)
|
103
|
+
list_resources(:server_templates, filter_by, filter_value)
|
104
|
+
end
|
105
|
+
|
106
|
+
def list_security_groups(cloud, filter_by, filter_value)
|
107
|
+
list_subresources(cloud, :security_groups, filter_by, filter_value)
|
108
|
+
end
|
109
|
+
|
110
|
+
def list_multi_cloud_images(server_template, filter_by, filter_value)
|
111
|
+
list_subresources(server_template, :multi_cloud_images, filter_by, filter_value)
|
112
|
+
end
|
113
|
+
|
114
|
+
def find_security_group_by_name(cloud, security_group_name)
|
115
|
+
find_cloud_resource(cloud, :security_groups, :by_name, security_group_name)
|
116
|
+
end
|
117
|
+
|
118
|
+
def find_server_by_name(name)
|
119
|
+
find_resource(:servers, :by_name, name)
|
120
|
+
end
|
121
|
+
|
122
|
+
def find_deployment_by_name(name)
|
123
|
+
find_resource(:deployments, :by_name, name)
|
124
|
+
end
|
125
|
+
|
126
|
+
# returns:: String if cloud is found, nil if not found
|
127
|
+
def find_cloud_by_name(name)
|
128
|
+
find_resource(:clouds, :by_name, name)
|
129
|
+
end
|
130
|
+
|
131
|
+
def find_mci_by_name(name)
|
132
|
+
find_resource(:multi_cloud_images, :by_name, name)
|
133
|
+
end
|
134
|
+
|
135
|
+
def find_servertemplate(name_or_id)
|
136
|
+
server_template = nil; id = nil; name = nil
|
137
|
+
|
138
|
+
# detect if user passed in a name or an id
|
139
|
+
# there is probably a cleaner way to do this, but I am lazy ATM.
|
140
|
+
begin
|
141
|
+
id = Integer(name_or_id)
|
142
|
+
rescue Exception => e
|
143
|
+
name = name_or_id # Cannot be case to integer, assume a name was passed
|
144
|
+
end
|
145
|
+
|
146
|
+
if name
|
147
|
+
# find ServerTemplate by name
|
148
|
+
st_list = list_resources(:server_templates, :by_name, name)
|
149
|
+
revisions = st_list.map { |st| st.revision }
|
150
|
+
|
151
|
+
# check for duplicate revisions
|
152
|
+
duplicates = (revisions.size != revisions.uniq.size)
|
153
|
+
raise "ERROR: Duplicate ServerTemplate with the name of '#{name}' detected " +
|
154
|
+
"in account -- there can be only one. Please fix via the RightScale dashboard and retry." if duplicates
|
155
|
+
|
156
|
+
# always use latest revision
|
157
|
+
latest_rev = revisions.sort.last
|
158
|
+
server_template = st_list.select { |st| st.revision == latest_rev}.first
|
159
|
+
raise "ERROR: Unable to find ServerTemplate with the name of '#{name}' found " unless server_template
|
160
|
+
else
|
161
|
+
# find ServerTemplate by id
|
162
|
+
server_template = @client.server_templates.index(:id => id)
|
163
|
+
end
|
164
|
+
|
165
|
+
server_template
|
166
|
+
end
|
167
|
+
|
168
|
+
def create_deployment(name)
|
169
|
+
@client.deployments.create(:deployment => { :name => name, :decription => "Created by the Vagrant"})
|
170
|
+
end
|
171
|
+
|
172
|
+
def destroy_deployment(deployment)
|
173
|
+
deployment.destroy
|
174
|
+
end
|
175
|
+
|
176
|
+
def create_server(deployment, server_template, mci, cloud, name, ssh_key = nil, groups = nil)
|
177
|
+
|
178
|
+
# check params
|
179
|
+
unless st_href = server_template.show.href
|
180
|
+
raise "ERROR: ServerTemplate parameter not initialized properly"
|
181
|
+
end
|
182
|
+
|
183
|
+
unless mci.nil?
|
184
|
+
unless mci_href = mci.show.href
|
185
|
+
raise "ERROR: Multi Cloud Image parameter not initialized properly"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
unless d_href = deployment.show.href
|
190
|
+
raise "ERROR: Deployment parameter not initialized properly"
|
191
|
+
end
|
192
|
+
|
193
|
+
unless c_href = cloud.show.href
|
194
|
+
raise "ERROR: Deployment parameter not initialized properly"
|
195
|
+
end
|
196
|
+
|
197
|
+
if ssh_key
|
198
|
+
unless ssh_key_href = ssh_key.show.href
|
199
|
+
raise "ERROR: ssh_key parameter not initialized properly"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
security_group_hrefs = nil
|
204
|
+
if groups
|
205
|
+
security_group_hrefs = []
|
206
|
+
groups.each do |group|
|
207
|
+
unless group_href = group.show.href
|
208
|
+
raise "ERROR: ssh_key parameter not initialized properly"
|
209
|
+
end
|
210
|
+
security_group_hrefs << group_href
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
instance_hash = {
|
215
|
+
:cloud_href => c_href,
|
216
|
+
:server_template_href => st_href
|
217
|
+
}
|
218
|
+
instance_hash[:ssh_key_href] = ssh_key_href if ssh_key
|
219
|
+
instance_hash[:security_group_hrefs] = security_group_hrefs if security_group_hrefs
|
220
|
+
|
221
|
+
# Use the MCI if provided otherwise let the API choose the default MCI
|
222
|
+
# in the ServerTemplate.
|
223
|
+
instance_hash[:multi_cloud_image_href] = mci_href unless mci_href.nil?
|
224
|
+
|
225
|
+
# create server in deployment using specfied ST
|
226
|
+
server =
|
227
|
+
@client.servers.create({
|
228
|
+
:server => {
|
229
|
+
:name => name,
|
230
|
+
:decription => "Created by the right_provision_api", #TODO: pass this as a param
|
231
|
+
:deployment_href => d_href,
|
232
|
+
:instance => instance_hash
|
233
|
+
}
|
234
|
+
})
|
235
|
+
end
|
236
|
+
|
237
|
+
def is_provisioned?(server)
|
238
|
+
server.show.api_methods.include?(:current_instance)
|
239
|
+
end
|
240
|
+
|
241
|
+
# @param(Hash) inputs Hash input name/value pairs i.e. { :name => "text:dummy"}
|
242
|
+
def launch_server(server, inputs = { :name => "text:dummy"})
|
243
|
+
server_name = server.show.name
|
244
|
+
server.launch(inputs) # TODO: parse inputs from Vagrantfile
|
245
|
+
# XXX: need to create a new server object after launch -- why? API bug?
|
246
|
+
find_server_by_name(server_name)
|
247
|
+
end
|
248
|
+
|
249
|
+
def terminate_server(server)
|
250
|
+
server.terminate
|
251
|
+
end
|
252
|
+
|
253
|
+
# Only use this *before* you launch the server
|
254
|
+
def set_server_inputs(server, inputs)
|
255
|
+
server.show.next_instance.show.inputs.multi_update({"inputs" => inputs})
|
256
|
+
end
|
257
|
+
|
258
|
+
def server_wait_for_state(server, target_state, delay = 10)
|
259
|
+
current_state = server_state(server)
|
260
|
+
while current_state != target_state
|
261
|
+
raise "Unexpected sever state: #{current_state}" if is_bad?(current_state)
|
262
|
+
puts "Server #{current_state}. Waiting for instance to be in #{target_state} state..."
|
263
|
+
sleep delay
|
264
|
+
current_state = server_state(server)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def set_bad_states(list_array)
|
269
|
+
@bad_states = list_array
|
270
|
+
end
|
271
|
+
|
272
|
+
def is_bad?(state)
|
273
|
+
@bad_states ||= []
|
274
|
+
@bad_states.select{|s| state =~ /#{s}/}.size > 0
|
275
|
+
end
|
276
|
+
|
277
|
+
def server_ready?(server)
|
278
|
+
server_state(server) == "operational"
|
279
|
+
end
|
280
|
+
|
281
|
+
def server_cloud_name(server)
|
282
|
+
instance = instance_from_server(server)
|
283
|
+
cloud = cloud_from_instance(instance)
|
284
|
+
cloud.show.name
|
285
|
+
end
|
286
|
+
|
287
|
+
def server_info(server)
|
288
|
+
server.show.current_instance.show(:view => 'extended')
|
289
|
+
end
|
290
|
+
|
291
|
+
private
|
292
|
+
|
293
|
+
def server_state(server)
|
294
|
+
instance_from_server(server).show.state
|
295
|
+
end
|
296
|
+
|
297
|
+
def instance_from_server(server)
|
298
|
+
server_data = server.show
|
299
|
+
if is_provisioned?(server)
|
300
|
+
begin
|
301
|
+
server_data.current_instance
|
302
|
+
rescue
|
303
|
+
server_data.next_instance
|
304
|
+
end
|
305
|
+
else
|
306
|
+
server_data.next_instance
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def cloud_from_instance(instance)
|
311
|
+
instance.show.cloud
|
312
|
+
end
|
313
|
+
|
314
|
+
def find_resource(api_resource, filter_key, filter_value)
|
315
|
+
resource = nil
|
316
|
+
list = list_resources(api_resource, filter_key, filter_value)
|
317
|
+
raise "More than one #{api_resource} with the #{filter_key} of '#{filter_value}'. " +
|
318
|
+
"Please resolve via the RightScale dashboard and retry." if list.size > 1
|
319
|
+
resource = list.first unless list.empty?
|
320
|
+
resource
|
321
|
+
end
|
322
|
+
|
323
|
+
def list_resources(api_resource, filter_key=nil, filter_value=nil)
|
324
|
+
raise ArgumentError.new("api_resource must be a symbol") unless api_resource.kind_of?(Symbol)
|
325
|
+
key = filter_key.to_s.delete("by_") # convert :by_name to "name"
|
326
|
+
filter = {}
|
327
|
+
filter = {:filter => ["#{key}==#{filter_value}"]} if filter_value
|
328
|
+
list = @client.send(api_resource).index(filter)
|
329
|
+
list
|
330
|
+
end
|
331
|
+
|
332
|
+
def index_resource(api_resource, index_key, index_value)
|
333
|
+
raise ArgumentError.new("api_resource must be a symbol") unless api_resource.kind_of?(Symbol)
|
334
|
+
arry = @client.send(api_resource).index(index_key => index_value)
|
335
|
+
arry
|
336
|
+
end
|
337
|
+
|
338
|
+
def find_cloud_resource(cloud, api_resource, filter_key, filter_value)
|
339
|
+
resource = nil
|
340
|
+
list = list_subresources(cloud, api_resource, filter_key, filter_value)
|
341
|
+
raise "More than one #{api_resource} with the #{filter_key} of '#{filter_value}'. " +
|
342
|
+
"Please resolve via the RightScale dashboard and retry." if list.size > 1
|
343
|
+
resource = list.first unless list.empty?
|
344
|
+
resource
|
345
|
+
end
|
346
|
+
|
347
|
+
def list_subresources(api_resource, subresource, filter_key, filter_value)
|
348
|
+
raise ArgumentError.new("subresource must be a symbol") unless subresource.kind_of?(Symbol)
|
349
|
+
key = filter_key.to_s.delete("by_") # convert :by_name to "name"
|
350
|
+
filter = {}
|
351
|
+
filter = {:filter => ["#{key}==#{filter_value}"]} if filter_value
|
352
|
+
list = api_resource.show.send(subresource).index(filter)
|
353
|
+
list
|
354
|
+
end
|
355
|
+
|
356
|
+
end
|
357
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#
|
2
|
+
# Author: cary@rightscale.com
|
3
|
+
# Copyright 2014 RightScale, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
require 'logger'
|
18
|
+
|
19
|
+
module RightApiHelper
|
20
|
+
|
21
|
+
# Base helper class
|
22
|
+
#
|
23
|
+
class Base
|
24
|
+
|
25
|
+
def initialize(right_api_client)
|
26
|
+
@client = right_api_client
|
27
|
+
logger
|
28
|
+
end
|
29
|
+
|
30
|
+
def api_url
|
31
|
+
@client.api_url
|
32
|
+
end
|
33
|
+
|
34
|
+
def logger(logger=nil)
|
35
|
+
@log = logger
|
36
|
+
@log ||= default_logger
|
37
|
+
end
|
38
|
+
|
39
|
+
def log_level(level)
|
40
|
+
@log.level = level
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def default_logger
|
46
|
+
logger = Logger.new(STDOUT)
|
47
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
48
|
+
"#{msg}\n"
|
49
|
+
end
|
50
|
+
logger
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#
|
2
|
+
# Author: cary@rightscale.com
|
3
|
+
# Copyright 2014 RightScale, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module RightApiHelper
|
19
|
+
class Cache < Base
|
20
|
+
|
21
|
+
def initialize(cache_uuid, cache_tmp_dir=".")
|
22
|
+
logger
|
23
|
+
@cache_file = File.join(cache_tmp_dir, "#{cache_uuid}.yml")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get all instances for all clouds registered in account
|
27
|
+
def get
|
28
|
+
hash = nil
|
29
|
+
if File.exists?(@cache_file)
|
30
|
+
@log.info "Reading cache from #{@cache_file}"
|
31
|
+
hash = YAML::load(File.open(@cache_file))
|
32
|
+
else
|
33
|
+
@log.info "No cache found at #{@cache_file}"
|
34
|
+
end
|
35
|
+
hash
|
36
|
+
end
|
37
|
+
|
38
|
+
def set(hash)
|
39
|
+
@log.info "Writing cache to #{@cache_file}"
|
40
|
+
File.open(@cache_file, "w") { |f| f.write(YAML.dump(hash)) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def clear
|
44
|
+
if File.exists?(@cache_file)
|
45
|
+
@log.info("removing cache file at #{@cache_file}")
|
46
|
+
File.delete(@cache_file)
|
47
|
+
else
|
48
|
+
@log.info("no cache file to remove at #{@cache_file}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#
|
2
|
+
# Author: cary@rightscale.com
|
3
|
+
# Copyright 2014 RightScale, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module RightApiHelper
|
19
|
+
class Deployments < Base
|
20
|
+
|
21
|
+
def initialize(right_api_client)
|
22
|
+
super(right_api_client)
|
23
|
+
@api_shim = RightApiHelper::API15.new(right_api_client)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return: MediaType : right_api_client deployment
|
27
|
+
def find_or_create(name)
|
28
|
+
@log.info "Looking for deployment: '#{name}'..."
|
29
|
+
deployment = @api_shim.find_deployment_by_name(name)
|
30
|
+
@log.info "Deployment #{deployment.nil? ? "not found" : "found"}."
|
31
|
+
unless deployment
|
32
|
+
deployment = @api_shim.create_deployment(name)
|
33
|
+
@log.info "Deployment created: '#{name}'"
|
34
|
+
end
|
35
|
+
deployment
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#
|
2
|
+
# Author: cary@rightscale.com
|
3
|
+
# Copyright 2014 RightScale, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module RightApiHelper
|
19
|
+
class Instances < Base
|
20
|
+
|
21
|
+
def initialize(right_api_client)
|
22
|
+
super(right_api_client)
|
23
|
+
@api_shim = RightApiHelper::API15.new(right_api_client)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get all instances for all clouds registered in account
|
27
|
+
def get_instances
|
28
|
+
instances = [ ]
|
29
|
+
get_clouds.each do |cloud|
|
30
|
+
instances += cloud.instances.index(:filter => [], :view => 'tiny')
|
31
|
+
end
|
32
|
+
instances
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_unmanaged_instances
|
36
|
+
get_instances.reject { |i| i.respond_to?(:deployment) }
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def get_clouds
|
42
|
+
@client.clouds.index
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#
|
2
|
+
# Author: cary@rightscale.com
|
3
|
+
# Copyright 2014 RightScale, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module RightApiHelper
|
19
|
+
class DeploymentsCreator
|
20
|
+
|
21
|
+
def run(argv)
|
22
|
+
if argv.empty? or argv[0].empty?
|
23
|
+
log_error "FATAL: you must supply path to json file"
|
24
|
+
exit -1
|
25
|
+
end
|
26
|
+
filename = ""
|
27
|
+
filename = argv[0] if argv[0]
|
28
|
+
unless File.exists?(filename)
|
29
|
+
log_error "FATAL: no such file: '#{filename}'"
|
30
|
+
exit -2
|
31
|
+
end
|
32
|
+
|
33
|
+
@json = File.open(filename, "r") { |f| f.read }
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def log_error(message)
|
40
|
+
puts message
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#
|
2
|
+
# Author: cary@rightscale.com
|
3
|
+
# Copyright 2014 RightScale, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module RightApiHelper
|
19
|
+
class Session < Base
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
logger
|
23
|
+
end
|
24
|
+
|
25
|
+
# Create a right_api_client session
|
26
|
+
# See https://github.com/rightscale/right_api_client/blob/master/README.md#usage-instructions
|
27
|
+
#
|
28
|
+
# Returns: handle to right_api_client gem
|
29
|
+
#
|
30
|
+
def create_client(email, password, account_id, api_url=nil)
|
31
|
+
begin
|
32
|
+
args = { :email => email, :password => password, :account_id => account_id }
|
33
|
+
args[:api_url] = api_url if api_url
|
34
|
+
@client ||= RightApi::Client.new(args)
|
35
|
+
setup_client_logging
|
36
|
+
@client
|
37
|
+
rescue Exception => e
|
38
|
+
args.delete(:password) # don't log password
|
39
|
+
puts "ERROR: could not connect to RightScale API. Params: #{args.inspect}"
|
40
|
+
puts e.message
|
41
|
+
puts e.backtrace
|
42
|
+
raise e
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Create a right_api_client session from YAML file
|
47
|
+
# See https://github.com/rightscale/right_api_client/blob/master/README.md#usage-instructions
|
48
|
+
#
|
49
|
+
# Returns: handle to right_api_client gem
|
50
|
+
#
|
51
|
+
def create_client_from_file(filename)
|
52
|
+
begin
|
53
|
+
@client ||= RightApi::Client.new(YAML.load_file(File.expand_path(filename, __FILE__)))
|
54
|
+
setup_client_logging
|
55
|
+
@client
|
56
|
+
rescue Exception => e
|
57
|
+
puts "ERROR: could not connect to RightScale API. filename: '#{filename}'"
|
58
|
+
puts e.message
|
59
|
+
puts e.backtrace
|
60
|
+
raise e
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def setup_client_logging
|
67
|
+
# right_api_client logs too much stuff, throw away unless in debug mode
|
68
|
+
if @log.level == Logger::DEBUG
|
69
|
+
@client.log(STDOUT)
|
70
|
+
else
|
71
|
+
@client.log("/dev/null")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|