rest_connection 0.1.10 → 0.1.11
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/LICENSE +10 -22
- data/README.rdoc +1 -1
- data/VERSION +1 -1
- data/config/rest_api_config.yaml.sample +6 -3
- data/lib/rest_connection.rb +7 -0
- data/lib/rest_connection/rightscale/mc_server.rb +56 -1
- data/lib/rest_connection/rightscale/server.rb +21 -0
- data/log_api_call_parser +92 -0
- metadata +6 -5
data/LICENSE
CHANGED
@@ -1,22 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be
|
13
|
-
# included in all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
#++
|
1
|
+
Copyright (c) 2012 RightScale, Inc, All Rights Reserved Worldwide.
|
2
|
+
|
3
|
+
THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
4
|
+
AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
5
|
+
reproduction, modification, or disclosure of this program is
|
6
|
+
strictly prohibited. Any use of this program by an authorized
|
7
|
+
licensee is strictly subject to the terms and conditions,
|
8
|
+
including confidentiality obligations, set forth in the applicable
|
9
|
+
License Agreement between RightScale, Inc. and
|
10
|
+
the licensee.
|
data/README.rdoc
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
|
14
14
|
You must setup ~/.rest_connection/rest_api_config.yaml or /etc/rest_connection/rest_api_config.yaml
|
15
15
|
|
16
|
-
Copy the example from GEMHOME/rest_connection/
|
16
|
+
Copy the example from GEMHOME/rest_connection/config/rest_api_config.yaml.sample and fill in your connection info.
|
17
17
|
|
18
18
|
Pro Tip: to find a GEMHOME, use gemedit
|
19
19
|
"gem install gemedit"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.11
|
@@ -1,10 +1,13 @@
|
|
1
|
-
---
|
2
|
-
:ssh_keys:
|
1
|
+
---
|
2
|
+
:ssh_keys:
|
3
3
|
- ~/.ssh/my_server_key
|
4
4
|
- ~/.ssh/my_server_key-eu
|
5
5
|
- ~/.ssh/my_server_key-west
|
6
6
|
:pass: myUltraSecurePasswordz
|
7
7
|
:user: myUserEmail@MyMailDomain.com
|
8
8
|
:api_url: https://my.rightscale.com/api/acct/00000000
|
9
|
-
:common_headers:
|
9
|
+
:common_headers:
|
10
10
|
X_API_VERSION: "1.0"
|
11
|
+
:azure_hack_on: true
|
12
|
+
:azure_hack_retry_count: 5
|
13
|
+
:azure_hack_sleep_seconds: 60
|
data/lib/rest_connection.rb
CHANGED
@@ -81,6 +81,9 @@ module RestConnection
|
|
81
81
|
@@pass = ask("Password:") { |q| q.echo = false } unless @@pass
|
82
82
|
@settings[:pass] = @@pass
|
83
83
|
end
|
84
|
+
@settings[:azure_hack_on] ||= true
|
85
|
+
@settings[:azure_hack_retry_count] ||= 5
|
86
|
+
@settings[:azure_hack_sleep_seconds] ||= 60
|
84
87
|
end
|
85
88
|
|
86
89
|
# Main HTTP connection loop. Common settings are set here, then we yield(BASE_URI, OPTIONAL_HEADERS) to other methods for each type of HTTP request: GET, PUT, POST, DELETE
|
@@ -151,6 +154,7 @@ module RestConnection
|
|
151
154
|
def get(href, additional_parameters = "")
|
152
155
|
rest_connect do |base_uri,headers|
|
153
156
|
new_href = (href =~ /^\// ? href : "#{base_uri}/#{href}")
|
157
|
+
puts("DEBUG: new_href get : #{new_href.inspect}")
|
154
158
|
params = requestify(additional_parameters) || ""
|
155
159
|
new_path = URI.escape(new_href + @settings[:extension] + "?") + params
|
156
160
|
Net::HTTP::Get.new(new_path, headers)
|
@@ -165,6 +169,7 @@ module RestConnection
|
|
165
169
|
def post(href, additional_parameters = {})
|
166
170
|
rest_connect do |base_uri, headers|
|
167
171
|
new_href = (href =~ /^\// ? href : "#{base_uri}/#{href}")
|
172
|
+
puts("DEBUG: new_href post : #{new_href.inspect}")
|
168
173
|
res = Net::HTTP::Post.new(new_href , headers)
|
169
174
|
unless additional_parameters.empty?
|
170
175
|
res.set_content_type('application/json')
|
@@ -184,7 +189,9 @@ module RestConnection
|
|
184
189
|
rest_connect do |base_uri, headers|
|
185
190
|
new_href = (href =~ /^\// ? href : "#{base_uri}/#{href}")
|
186
191
|
new_path = URI.escape(new_href)
|
192
|
+
puts("DEBUG: new_href put : #{new_href.inspect}")
|
187
193
|
req = Net::HTTP::Put.new(new_path, headers)
|
194
|
+
puts("DEBUG: req put : #{req.inspect}")
|
188
195
|
req.set_content_type('application/json')
|
189
196
|
req.body = additional_parameters.to_json
|
190
197
|
req
|
@@ -57,7 +57,62 @@ class McServer < Server
|
|
57
57
|
def launch
|
58
58
|
if actions.include?("launch")
|
59
59
|
t = URI.parse(self.href)
|
60
|
-
|
60
|
+
begin
|
61
|
+
connection.post(t.path + '/launch')
|
62
|
+
rescue Exception => e
|
63
|
+
puts "************* McServer.launch(): Caught exception #{e.inspect}"
|
64
|
+
puts "************* McServer.launch(): connection.settings[:azure_hack_on] = #{connection.settings[:azure_hack_on]}"
|
65
|
+
puts "************* McServer.launch(): connection.settings[:azure_hack_retry_count] = #{connection.settings[:azure_hack_retry_count]}"
|
66
|
+
puts "************* McServer.launch(): connection.settings[:azure_hack_sleep_seconds] = #{connection.settings[:azure_hack_sleep_seconds]}"
|
67
|
+
# THIS IS A TEMPORARY HACK TO GET AROUND AZURE SERVER LAUNCH PROBLEMS AND SHOULD BE REMOVED ONCE MICROSOFT
|
68
|
+
# FIXES THIS BUG ON THEIR END!
|
69
|
+
|
70
|
+
# Retry on 422 conflict exception (ONLY MS AZURE WILL GENERATE THIS EXCEPTION)
|
71
|
+
target_422_conflict_error_message = "Invalid response HTTP code: 422: CloudException: ConflictError:"
|
72
|
+
target_504_gateway_timeout_error_message = "504 Gateway Time-out"
|
73
|
+
if e.message =~ /#{target_504_gateway_timeout_error_message}/
|
74
|
+
exception_matched_message = "McServer.launch(): Caught #{e.message}, treating as a successful launch..."
|
75
|
+
puts(exception_matched_message)
|
76
|
+
connection.logger(exception_matched_message)
|
77
|
+
true
|
78
|
+
elsif e.message =~ /#{target_422_conflict_error_message}/
|
79
|
+
if connection.settings[:azure_hack_on]
|
80
|
+
azure_hack_retry_count = connection.settings[:azure_hack_retry_count]
|
81
|
+
exception_matched_message = "************* McServer.launch(): Matched Azure exception: \"#{target_422_conflict_error_message}\""
|
82
|
+
puts(exception_matched_message)
|
83
|
+
connection.logger(exception_matched_message)
|
84
|
+
|
85
|
+
retry_count = 1
|
86
|
+
loop do
|
87
|
+
# sleep for azure_hack_sleep_seconds seconds
|
88
|
+
sleep_message = "************* McServer.launch(): Sleeping for #{connection.settings[:azure_hack_sleep_seconds]} seconds and then retrying (#{retry_count}) launch..."
|
89
|
+
puts(sleep_message)
|
90
|
+
connection.logger(sleep_message)
|
91
|
+
sleep(connection.settings[:azure_hack_sleep_seconds])
|
92
|
+
|
93
|
+
# retry the launch
|
94
|
+
begin
|
95
|
+
connection.post(t.path + '/launch')
|
96
|
+
rescue Exception => e2
|
97
|
+
if e2.message =~ /#{target_422_conflict_error_message}/
|
98
|
+
azure_hack_retry_count -= 1
|
99
|
+
if azure_hack_retry_count > 0
|
100
|
+
retry_count += 1
|
101
|
+
next
|
102
|
+
else
|
103
|
+
raise
|
104
|
+
end
|
105
|
+
else
|
106
|
+
raise
|
107
|
+
end
|
108
|
+
end
|
109
|
+
break
|
110
|
+
end
|
111
|
+
else
|
112
|
+
raise
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
61
116
|
elsif self.state == "inactive"
|
62
117
|
raise "FATAL: Server is in an unlaunchable state!"
|
63
118
|
else
|
@@ -455,4 +455,25 @@ class Server
|
|
455
455
|
tags = tags.select { |tag| tag.start_with?("#{namespace}:") } if namespace
|
456
456
|
self.remove_tags(*tags)
|
457
457
|
end
|
458
|
+
|
459
|
+
def lock
|
460
|
+
unless self.settings['locked']
|
461
|
+
serv_href = URI.parse(self.href)
|
462
|
+
res = connection.put(serv_href.path, :server => {:lock => 'true'})
|
463
|
+
res.is_a?(Net::HTTPSuccess) ? true : false
|
464
|
+
else
|
465
|
+
connection.logger("Server is already locked")
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
def unlock
|
470
|
+
if self.settings['locked']
|
471
|
+
serv_href = URI.parse(self.href)
|
472
|
+
res = connection.put(serv_href.path, :server => {:lock => 'false'})
|
473
|
+
res.is_a?(Net::HTTPSuccess) ? true : false
|
474
|
+
else
|
475
|
+
connection.logger("Server is already unlocked")
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
458
479
|
end
|
data/log_api_call_parser
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2012 RightScale, Inc, All Rights Reserved Worldwide.
|
5
|
+
#
|
6
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
7
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
8
|
+
# reproduction, modification, or disclosure of this program is
|
9
|
+
# strictly prohibited. Any use of this program by an authorized
|
10
|
+
# licensee is strictly subject to the terms and conditions,
|
11
|
+
# including confidentiality obligations, set forth in the applicable
|
12
|
+
# License Agreement between RightScale, Inc. and
|
13
|
+
# the licensee.
|
14
|
+
#++
|
15
|
+
|
16
|
+
########################################################################################################################
|
17
|
+
# rest_connection API Call Parser Main program
|
18
|
+
#
|
19
|
+
# This program will parse a rest_connection.log produced from any given monkey run and display the:
|
20
|
+
# - API version
|
21
|
+
# - Request Type
|
22
|
+
# - Request
|
23
|
+
# in tabular format on STDOUT. It will also generate the csv file odf the same information.
|
24
|
+
########################################################################################################################
|
25
|
+
|
26
|
+
# Third party requires
|
27
|
+
require 'rubygems'
|
28
|
+
require 'trollop'
|
29
|
+
require 'terminal-table'
|
30
|
+
require 'tempfile'
|
31
|
+
require 'csv'
|
32
|
+
|
33
|
+
#
|
34
|
+
# Parse and validate command line arguments
|
35
|
+
#
|
36
|
+
opts = Trollop::options do
|
37
|
+
banner <<-EOS
|
38
|
+
Usage:
|
39
|
+
log_api_call_parser [options]
|
40
|
+
where [options] are:
|
41
|
+
EOS
|
42
|
+
opt :input, "Path to the input file in standard rest_connection logger format", :short => "-i", :type => String, :required => true
|
43
|
+
opt :csv_file, "Path to the csv output file", :short => "-o", :type => String, :required => true
|
44
|
+
end
|
45
|
+
|
46
|
+
# Open the input file and read it into an array
|
47
|
+
input_file = File.open(opts[:input])
|
48
|
+
log_file_array = input_file.readlines
|
49
|
+
input_file.close
|
50
|
+
|
51
|
+
# Loop over the array and for each row, parse out the api version, request type and the request
|
52
|
+
# and add them to output_array for later sorting and writing.
|
53
|
+
output_array = []
|
54
|
+
search_string = "INFO -- :"
|
55
|
+
log_file_array.each { |element|
|
56
|
+
if element[0..2] == "I, "
|
57
|
+
# Find the API version start column as this can vary at least per log file and maybe even per line
|
58
|
+
api_version_start_column = element.index(search_string)
|
59
|
+
api_version_start_column = api_version_start_column + search_string.length + 1
|
60
|
+
|
61
|
+
# Get the elements
|
62
|
+
element = element[api_version_start_column..-1]
|
63
|
+
version = element[5..8]
|
64
|
+
request_type = element[11..13]
|
65
|
+
if request_type == "GET" || request_type == "PUT"
|
66
|
+
request = element[16..-1]
|
67
|
+
output_array.push "#{version},#{request_type},#{request}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
}
|
71
|
+
|
72
|
+
# Sort the output array by API version
|
73
|
+
output_array.sort! {|a,b| a <=> b}
|
74
|
+
|
75
|
+
# Remove duplicates
|
76
|
+
output_array.uniq!
|
77
|
+
|
78
|
+
# Write out the CSV file
|
79
|
+
csv_file = File.open(opts[:csv_file], "w")
|
80
|
+
csv_file_name = csv_file.path()
|
81
|
+
output_array.each { |element| csv_file.puts element }
|
82
|
+
csv_file.close
|
83
|
+
|
84
|
+
# Generate a table version and write that out to STDOUT
|
85
|
+
csv_array = CSV.read(csv_file_name)
|
86
|
+
table = Terminal::Table.new
|
87
|
+
csv_array.collect do |line|
|
88
|
+
table << line
|
89
|
+
table << :separator
|
90
|
+
end
|
91
|
+
puts table
|
92
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest_connection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 11
|
10
|
+
version: 0.1.11
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeremy Deininger
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-
|
19
|
+
date: 2012-08-28 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: activesupport
|
@@ -210,6 +210,7 @@ files:
|
|
210
210
|
- lib/rest_connection/rightscale/user.rb
|
211
211
|
- lib/rest_connection/rightscale/vpc_dhcp_option.rb
|
212
212
|
- lib/rest_connection/ssh_hax.rb
|
213
|
+
- log_api_call_parser
|
213
214
|
- spec/ec2_server_array_spec.rb
|
214
215
|
- spec/ec2_ssh_key_internal_spec.rb
|
215
216
|
- spec/image_jockey.rb
|
@@ -253,7 +254,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
253
254
|
requirements: []
|
254
255
|
|
255
256
|
rubyforge_project:
|
256
|
-
rubygems_version: 1.8.
|
257
|
+
rubygems_version: 1.8.24
|
257
258
|
signing_key:
|
258
259
|
specification_version: 3
|
259
260
|
summary: Modular RESTful API library
|