collins_client 0.2.7
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/Gemfile +15 -0
- data/Gemfile.lock +50 -0
- data/README.md +46 -0
- data/Rakefile +66 -0
- data/VERSION +1 -0
- data/collins_client.gemspec +73 -0
- data/lib/collins/address.rb +74 -0
- data/lib/collins/api.rb +119 -0
- data/lib/collins/api/admin.rb +19 -0
- data/lib/collins/api/asset.rb +184 -0
- data/lib/collins/api/asset_state.rb +85 -0
- data/lib/collins/api/attributes.rb +76 -0
- data/lib/collins/api/ip_address.rb +87 -0
- data/lib/collins/api/logging.rb +137 -0
- data/lib/collins/api/management.rb +84 -0
- data/lib/collins/api/tag.rb +46 -0
- data/lib/collins/api/util.rb +28 -0
- data/lib/collins/api/util/errors.rb +45 -0
- data/lib/collins/api/util/parameters.rb +44 -0
- data/lib/collins/api/util/requests.rb +136 -0
- data/lib/collins/api/util/responses.rb +46 -0
- data/lib/collins/asset.rb +311 -0
- data/lib/collins/asset_client.rb +57 -0
- data/lib/collins/client.rb +100 -0
- data/lib/collins/errors.rb +56 -0
- data/lib/collins/ipmi.rb +41 -0
- data/lib/collins/logging.rb +33 -0
- data/lib/collins/monkeypatch.rb +24 -0
- data/lib/collins/option.rb +220 -0
- data/lib/collins/power.rb +99 -0
- data/lib/collins/profile.rb +73 -0
- data/lib/collins/simple_callback.rb +141 -0
- data/lib/collins/state.rb +50 -0
- data/lib/collins/util.rb +145 -0
- data/lib/collins_client.rb +7 -0
- metadata +100 -0
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Collins; module Api
|
4
|
+
|
5
|
+
module Logging
|
6
|
+
|
7
|
+
include Collins::Util
|
8
|
+
|
9
|
+
# @see http://tumblr.github.com/platform/collinsTutorial/out/logapi.html
|
10
|
+
module Severity
|
11
|
+
extend self
|
12
|
+
|
13
|
+
EMERGENCY = "EMERGENCY"
|
14
|
+
ALERT = "ALERT"
|
15
|
+
CRITICAL = "CRITICAL"
|
16
|
+
ERROR = "ERROR"
|
17
|
+
WARNING = "WARNING"
|
18
|
+
NOTICE = "NOTICE"
|
19
|
+
INFORMATIONAL = "INFORMATIONAL"
|
20
|
+
DEBUG = "DEBUG"
|
21
|
+
NOTE = "NOTE"
|
22
|
+
|
23
|
+
# Given a severity level, give back the severity, or nil if not valid
|
24
|
+
# @param [String,Symbol] level Severity level
|
25
|
+
# @return [String] Severity level as string
|
26
|
+
def value_of level
|
27
|
+
level_s = normalize level
|
28
|
+
if valid? level_s then
|
29
|
+
level_s.to_s
|
30
|
+
else
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Convert a level into one appropriate for validating
|
36
|
+
# @param [Symbol,String] level Severity level
|
37
|
+
# @return [Symbol] normalized (not neccesarily valid) severity level
|
38
|
+
def normalize level
|
39
|
+
level.to_s.upcase.to_sym
|
40
|
+
end
|
41
|
+
|
42
|
+
# Check is a level is valid or not
|
43
|
+
# @param [Symbol,String] level Severity level
|
44
|
+
# @return [Boolean] indicate whether valid or not
|
45
|
+
def valid? level
|
46
|
+
level_s = normalize level
|
47
|
+
Collins::Api::Logging::Severity.constants.include?(level_s)
|
48
|
+
end
|
49
|
+
|
50
|
+
#@return [Array<String>] severity levels
|
51
|
+
def to_a
|
52
|
+
s = Collins::Api::Logging::Severity
|
53
|
+
s.constants.map{|c| s.const_get(c)}
|
54
|
+
end
|
55
|
+
end # module Severity
|
56
|
+
|
57
|
+
# Log a message against an asset using the specified level
|
58
|
+
# @param [String,Collins::Asset] asset_or_tag
|
59
|
+
# @param [String] message
|
60
|
+
# @param [Severity] level severity level to use
|
61
|
+
# @return [Boolean] true if logged successfully
|
62
|
+
# @raise [Collins::ExpectationFailed] the specified level was invalid
|
63
|
+
# @raise [Collins::RequestError,Collins::UnexpectedResponseError] if the asset or message invalid
|
64
|
+
def log! asset_or_tag, message, level = nil
|
65
|
+
asset = get_asset_or_tag asset_or_tag
|
66
|
+
parameters = {
|
67
|
+
:message => message,
|
68
|
+
:type => log_level_from_string(level)
|
69
|
+
}
|
70
|
+
parameters = select_non_empty_parameters parameters
|
71
|
+
logger.debug("Logging to #{asset.tag} with parameters #{parameters.inspect}")
|
72
|
+
http_put("/api/asset/#{asset.tag}/log", parameters, asset.location) do |response|
|
73
|
+
parse_response response, :as => :status, :expects => 201
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Fetch logs for an asset according to the options specified
|
78
|
+
# @example
|
79
|
+
# :filter => "EMERGENCY;ALERT" # Only retrieve emergency and alert messages
|
80
|
+
# :filter => "!DEBUG;!NOTE" # Only retrieve non-debug/non-notes
|
81
|
+
# @param [String,Collins::Asset] asset_or_tag
|
82
|
+
# @param [Hash] options query options
|
83
|
+
# @option options [Fixnum] :page (0) Page of results
|
84
|
+
# @option options [Fixnum] :size (25) Number of results to retrieve
|
85
|
+
# @option options [String] :sort (DESC) Sort ordering for results
|
86
|
+
# @option options [String] :filter Semicolon separated list of severity levels to include or exclude
|
87
|
+
# @option options [String] :all_tag If specified, an asset tag is this value, proxy to the all_logs method
|
88
|
+
# @note To exclude a level via a filter it must be prepended with a `!`
|
89
|
+
# @return [Array<OpenStruct>] Array of log objects
|
90
|
+
# @raise [Collins::UnexpectedResponseError] on a non-200 response
|
91
|
+
def logs asset_or_tag, options = {}
|
92
|
+
asset = get_asset_or_tag asset_or_tag
|
93
|
+
all_tag = options.delete(:all_tag)
|
94
|
+
if all_tag && all_tag.to_s.downcase == asset.tag.to_s.downcase then
|
95
|
+
return all_logs options
|
96
|
+
end
|
97
|
+
parameters = get_page_options(options).merge(
|
98
|
+
:filter => get_option(:filter, options, nil)
|
99
|
+
)
|
100
|
+
parameters = select_non_empty_parameters parameters
|
101
|
+
logger.debug("Fetching logs for #{asset.tag} with parameters #{parameters.inspect}")
|
102
|
+
http_get("/api/asset/#{asset.tag}/logs", parameters, asset.location) do |response|
|
103
|
+
parse_response response, :as => :paginated, :default => [], :raise => strict?, :expects => 200 do |json|
|
104
|
+
json.map{|j| OpenStruct.new(symbolize_hash(j))}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Same as logs but for all assets
|
110
|
+
# @see #logs
|
111
|
+
def all_logs options = {}
|
112
|
+
parameters = get_page_options(options).merge(
|
113
|
+
:filter => get_option(:filter, options, nil)
|
114
|
+
)
|
115
|
+
parameters = select_non_empty_parameters parameters
|
116
|
+
logger.debug("Fetching logs for all assets with parameters #{parameters.inspect}")
|
117
|
+
http_get("/api/assets/logs", parameters) do |response|
|
118
|
+
parse_response response, :as => :paginated, :default => [], :raise => strict?, :expects => 200 do |json|
|
119
|
+
json.map{|j| OpenStruct.new(symbolize_hash(j))}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
def log_level_from_string level
|
126
|
+
return nil if (level.nil? || level.empty?)
|
127
|
+
s = Collins::Api::Logging::Severity
|
128
|
+
if s.valid? level then
|
129
|
+
s.value_of level
|
130
|
+
else
|
131
|
+
raise Collins::ExpectationFailedError.new("#{level} is not a valid log level")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end # module Log
|
136
|
+
|
137
|
+
end; end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'collins/power'
|
2
|
+
require 'collins/profile'
|
3
|
+
|
4
|
+
module Collins; module Api
|
5
|
+
|
6
|
+
module Management
|
7
|
+
|
8
|
+
def provisioning_profiles
|
9
|
+
logger.debug("Getting provisioning profiles from collins")
|
10
|
+
http_get("/api/provision/profiles") do |response|
|
11
|
+
parse_response response, :expects => 200, :as => :data do |json|
|
12
|
+
json["PROFILES"].map { |o| Collins::Profile.new(o) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def provision asset_or_tag, profile, contact, options = {}
|
18
|
+
asset = get_asset_or_tag asset_or_tag
|
19
|
+
parameters = {
|
20
|
+
:profile => profile,
|
21
|
+
:contact => contact,
|
22
|
+
:suffix => options[:suffix],
|
23
|
+
:primary_role => options[:primary_role],
|
24
|
+
:secondary_role => options[:secondary_role],
|
25
|
+
:pool => options[:pool],
|
26
|
+
:activate => options[:activate]
|
27
|
+
}
|
28
|
+
parameters = select_non_empty_parameters parameters
|
29
|
+
if parameters.empty? then
|
30
|
+
raise CollinsError.new("provision requires at least a profile")
|
31
|
+
end
|
32
|
+
http_post("/api/provision/#{asset.tag}", parameters, asset.location) do |response|
|
33
|
+
parse_response response, :expects => 200, :as => :status
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def power_status asset_or_tag
|
38
|
+
asset = get_asset_or_tag asset_or_tag
|
39
|
+
logger.debug("Checking power status of #{asset.tag}")
|
40
|
+
http_get("/api/asset/#{asset.tag}/power", {}, asset.location) do |response|
|
41
|
+
parse_response response, :expects => 200, :as => :message, :raise => strict?, :default => "Unknown"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def power! asset_or_tag, action
|
46
|
+
asset = get_asset_or_tag asset_or_tag
|
47
|
+
if action.to_s.downcase == "status" then
|
48
|
+
return power_status asset_or_tag
|
49
|
+
end
|
50
|
+
action = Collins::Power.normalize_action action
|
51
|
+
parameters = {
|
52
|
+
:action => action
|
53
|
+
}
|
54
|
+
logger.debug("Calling power action on #{asset.tag}, action #{action}")
|
55
|
+
http_post("/api/asset/#{asset.tag}/power", parameters, asset.location) do |response|
|
56
|
+
parse_response response, :expects => 200, :as => :status
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def ipmi_create asset_or_tag, username, password, address, gateway, netmask
|
61
|
+
ipmi_update asset_or_tag, :username => username, :password => password, :address => address,
|
62
|
+
:gateway => gateway, :netmask => netmask
|
63
|
+
end
|
64
|
+
|
65
|
+
def ipmi_update asset_or_tag, options = {}
|
66
|
+
asset = get_asset_or_tag asset_or_tag
|
67
|
+
parameters = {
|
68
|
+
:username => get_option(:username, options, nil),
|
69
|
+
:password => get_option(:password, options, nil),
|
70
|
+
:address => get_option(:address, options, nil),
|
71
|
+
:gateway => get_option(:gateway, options, nil),
|
72
|
+
:netmask => get_option(:netmask, options, nil)
|
73
|
+
}
|
74
|
+
parameters = select_non_empty_parameters parameters
|
75
|
+
return true if parameters.empty?
|
76
|
+
logger.debug("Updating asset #{asset.tag} IPMI info with parameters #{parameters.inspect}")
|
77
|
+
http_post("/api/asset/#{asset.tag}/ipmi", parameters, asset.location) do |response|
|
78
|
+
parse_response response, :expects => [200,201], :as => :status
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end # module Management
|
83
|
+
|
84
|
+
end; end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Collins; module Api
|
4
|
+
|
5
|
+
# @api collins
|
6
|
+
module Tag
|
7
|
+
|
8
|
+
include Collins::Util
|
9
|
+
|
10
|
+
# Get all collins tags
|
11
|
+
#
|
12
|
+
# Sample output
|
13
|
+
# @example
|
14
|
+
# [
|
15
|
+
# {:name => "", :label => "", :description => ""},
|
16
|
+
# ]
|
17
|
+
#
|
18
|
+
# @raise [UnexpectedResponseError] if strict is true and the response is not a 200
|
19
|
+
# @return [Array<OpenStruct>] Array of tags containing name, label and description keys
|
20
|
+
def get_all_tags
|
21
|
+
http_get("/api/tags") do |response|
|
22
|
+
parse_response response, :expects => 200, :default => [], :raise => strict? do |json|
|
23
|
+
json["data"]["tags"].map{|t| OpenStruct.new(symbolize_hash(t))}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get all values associated with the specified tag
|
29
|
+
#
|
30
|
+
# @note You will get a 404 if the tag does not exist. Depending on strict mode, this will result in an empty array or an exception
|
31
|
+
# @param [String] tag The tag you would like values for
|
32
|
+
# @param [Boolean] strict Here for backwards API compatibility
|
33
|
+
# @raise [UnexpectedResponseError] if strict is true and the response is not a 200
|
34
|
+
# @return [Array<String>] values associated with this tag
|
35
|
+
def get_tag_values tag, strict = false
|
36
|
+
http_get("/api/tag/#{tag}") do |response|
|
37
|
+
parse_response response, :expects => 200, :default => [], :raise => strict?(strict) do |json|
|
38
|
+
json["data"]["values"]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end # module Tag
|
44
|
+
|
45
|
+
end; end
|
46
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'collins/api/util/parameters'
|
2
|
+
require 'collins/api/util/requests'
|
3
|
+
require 'collins/api/util/responses'
|
4
|
+
|
5
|
+
module Collins; module Api
|
6
|
+
|
7
|
+
module Util
|
8
|
+
|
9
|
+
include Collins::Api::Util::Parameters
|
10
|
+
include Collins::Api::Util::Requests
|
11
|
+
include Collins::Api::Util::Responses
|
12
|
+
|
13
|
+
|
14
|
+
#returns true if successful ping to collins, false otherwise
|
15
|
+
def ping
|
16
|
+
begin
|
17
|
+
http_get("/api/ping") do |response|
|
18
|
+
parse_response response, :expects => 200
|
19
|
+
end
|
20
|
+
true
|
21
|
+
rescue
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end # module Util
|
27
|
+
|
28
|
+
end; end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Collins; module Api; module Util
|
2
|
+
|
3
|
+
module Errors
|
4
|
+
|
5
|
+
protected
|
6
|
+
def handle_error response
|
7
|
+
if response.code >= 400 && rich_error_response?(response) then
|
8
|
+
raise RichRequestError.new(
|
9
|
+
"Error processing request", response.code, error_response(response), error_details(response)
|
10
|
+
)
|
11
|
+
elsif response.code >= 400 && error_response?(response) then
|
12
|
+
raise RequestError.new("Error processing request: #{error_response(response)}", response.code)
|
13
|
+
elsif response.code == 401 then
|
14
|
+
raise AuthenticationError.new("Invalid username or password")
|
15
|
+
elsif response.code > 401 then
|
16
|
+
raise RequestError.new("Response code was #{response.code}, #{response.to_s}", response.code)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
def rich_error_response? response
|
20
|
+
if error_response?(response) then
|
21
|
+
parsed = response.parsed_response
|
22
|
+
parsed.key?("data") && parsed["data"].key?("details")
|
23
|
+
else
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
def error_response? response
|
28
|
+
begin
|
29
|
+
parsed = response.parsed_response
|
30
|
+
parsed["status"] && parsed["status"].include?("error")
|
31
|
+
rescue Exception => e
|
32
|
+
logger.warn("Could not determine if response #{response} was an error. #{e}")
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
def error_details response
|
37
|
+
response.parsed_response["data"]["details"]
|
38
|
+
end
|
39
|
+
def error_response response
|
40
|
+
response.parsed_response["data"]["message"]
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end; end; end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Collins; module Api; module Util
|
2
|
+
|
3
|
+
module Parameters
|
4
|
+
protected
|
5
|
+
|
6
|
+
# retrieve a key from a hash or use the default
|
7
|
+
def get_option key, hash, default
|
8
|
+
if hash.include?(key) then
|
9
|
+
hash[key]
|
10
|
+
elsif hash.include?(key.to_s) then
|
11
|
+
hash[key.to_s]
|
12
|
+
else
|
13
|
+
default
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_page_options options = {}
|
18
|
+
{
|
19
|
+
:page => get_option(:page, options, 0),
|
20
|
+
:size => get_option(:size, options, 25),
|
21
|
+
:sort => get_option(:sort, options, "DESC")
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
# select parameters from a hash matching some options
|
26
|
+
def select_non_empty_parameters params
|
27
|
+
select_parameters params, :nil => false, :empty_string => false
|
28
|
+
end
|
29
|
+
def select_parameters params, options = {}
|
30
|
+
params.inject({}) do |result, (k,v)|
|
31
|
+
if v.nil? && options[:nil] == false then
|
32
|
+
# don't include
|
33
|
+
elsif v.is_a?(String) && v.empty? && options[:empty_string] == false then
|
34
|
+
# don't include
|
35
|
+
else
|
36
|
+
result[k] = v
|
37
|
+
end
|
38
|
+
result
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end # Parameters module
|
43
|
+
|
44
|
+
end; end; end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Collins; module Api; module Util
|
5
|
+
|
6
|
+
module Requests
|
7
|
+
|
8
|
+
protected
|
9
|
+
def http_get uri, parameters = {}, remote = nil
|
10
|
+
http_call(uri) {
|
11
|
+
if parameters.is_a?(Array) then
|
12
|
+
params = {:query => parameters.join("&")}
|
13
|
+
else
|
14
|
+
params = {:query => parameters}
|
15
|
+
end
|
16
|
+
params = strip_request :query, params
|
17
|
+
result = self.class.get(uri, http_options(params, remote))
|
18
|
+
if block_given? then
|
19
|
+
yield(result)
|
20
|
+
else
|
21
|
+
result
|
22
|
+
end
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def http_put uri, parameters = {}, remote = nil
|
27
|
+
http_call(uri) {
|
28
|
+
params = strip_request :body, :body => parameters
|
29
|
+
result = self.class.put(uri, http_options(params, remote))
|
30
|
+
if block_given? then
|
31
|
+
yield(result)
|
32
|
+
else
|
33
|
+
result
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def http_post uri, parameters = {}, remote = nil
|
39
|
+
http_call(uri) {
|
40
|
+
params = strip_request :body, :body => parameters
|
41
|
+
result = self.class.post(uri, http_options(params, remote))
|
42
|
+
if block_given? then
|
43
|
+
yield(result)
|
44
|
+
else
|
45
|
+
result
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def http_delete uri, parameters = {}, remote = nil
|
51
|
+
http_call(uri) {
|
52
|
+
params = strip_request :body, :body => parameters
|
53
|
+
result = self.class.delete(uri, http_options(params, remote))
|
54
|
+
if block_given? then
|
55
|
+
yield(result)
|
56
|
+
else
|
57
|
+
result
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def http_options opts = {}, remote = nil
|
63
|
+
if remote then
|
64
|
+
host_info = get_location_information remote
|
65
|
+
auth = {:username => host_info.username, :password => host_info.password}
|
66
|
+
base_uri = host_info.host
|
67
|
+
else
|
68
|
+
auth = {:username => username, :password => password}
|
69
|
+
base_uri = host
|
70
|
+
end
|
71
|
+
http_opts = opts.merge!({:basic_auth => auth, :base_uri => base_uri, :timeout => timeout_i})
|
72
|
+
http_opts[:headers] = headers unless headers.empty?
|
73
|
+
http_opts[:debug_output] = $stderr if (logger.level < 0 and Module.const_defined?(:HTTP_DEBUG) and HTTP_DEBUG)
|
74
|
+
http_opts
|
75
|
+
end
|
76
|
+
|
77
|
+
def http_call uri, &block
|
78
|
+
trace("Calling uri #{uri}, waiting for #{timeout_i} seconds")
|
79
|
+
begin
|
80
|
+
timeout(timeout_i) {
|
81
|
+
block.call
|
82
|
+
}
|
83
|
+
rescue Timeout::Error => e
|
84
|
+
raise Timeout::Error.new("Timeout talking to #{uri}: #{e}")
|
85
|
+
rescue Collins::RequestError => e
|
86
|
+
e.uri = uri
|
87
|
+
raise e
|
88
|
+
rescue Exception => e
|
89
|
+
if e.class.to_s == "WebMock::NetConnectNotAllowedError" then
|
90
|
+
raise e
|
91
|
+
else
|
92
|
+
raise e.class.new("Exception talking to #{uri}: #{e}")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def strip_request key, options
|
98
|
+
if options[key] && options[key].empty? then
|
99
|
+
{}
|
100
|
+
else
|
101
|
+
options
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def get_location_information location
|
106
|
+
location_s = location.downcase.to_sym
|
107
|
+
return locations[location_s] if locations[location_s]
|
108
|
+
logger.debug("Fetching credentials for location #{location_s}")
|
109
|
+
http_get("/api/asset/#{location}") do |response|
|
110
|
+
result = parse_response response, :expects => 200, :as => :asset, :raise => strict?, :default => nil
|
111
|
+
if result && result.get_attribute(:location) then
|
112
|
+
if result.get_attribute(:location).nil? then
|
113
|
+
raise AuthenticationError.new("Could not find LOCATION attribute on asset #{location}")
|
114
|
+
end
|
115
|
+
uri = URI(result.get_attribute(:location))
|
116
|
+
if uri.port then
|
117
|
+
port = ":#{uri.port}"
|
118
|
+
else
|
119
|
+
port = ""
|
120
|
+
end
|
121
|
+
locations[location_s] = OpenStruct.new Hash[
|
122
|
+
:username => uri.user,
|
123
|
+
:password => uri.password,
|
124
|
+
:host => "#{uri.scheme}://#{uri.host}#{port}"
|
125
|
+
]
|
126
|
+
else
|
127
|
+
raise AuthenticationError.new("Could not find LOCATION attribute on asset #{location}")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
locations[location_s]
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
end # module Requests
|
135
|
+
|
136
|
+
end; end; end
|