rest_connection 0.1.10 → 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|