aviator 0.0.1 → 0.0.2
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/.coveralls.yml +1 -0
- data/.gitignore +6 -1
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +13 -0
- data/Guardfile +6 -0
- data/LICENSE.txt +1 -1
- data/README.md +151 -2
- data/Rakefile +8 -0
- data/aviator.gemspec +14 -1
- data/bin/aviator +110 -0
- data/lib/aviator/core.rb +9 -0
- data/lib/aviator/core/request.rb +229 -0
- data/lib/aviator/core/response.rb +33 -0
- data/lib/aviator/core/service.rb +203 -0
- data/lib/aviator/core/session.rb +187 -0
- data/lib/aviator/openstack/compute/v2/public/list_images.rb +49 -0
- data/lib/aviator/openstack/identity/v2/admin/create_tenant.rb +42 -0
- data/lib/aviator/openstack/identity/v2/admin/list_tenants.rb +43 -0
- data/lib/aviator/openstack/identity/v2/public/create_token.rb +61 -0
- data/lib/aviator/openstack/identity/v2/public/list_tenants.rb +44 -0
- data/lib/aviator/version.rb +1 -1
- data/test/aviator/core/request_test.rb +342 -0
- data/test/aviator/core/service_test.rb +158 -0
- data/test/aviator/core/session_test.rb +201 -0
- data/test/aviator/openstack/compute/v2/public/list_images_test.rb +179 -0
- data/test/aviator/openstack/identity/v2/admin/create_tenant_test.rb +151 -0
- data/test/aviator/openstack/identity/v2/public/create_token_test.rb +159 -0
- data/test/cassettes/core/service/i_default_session_data_/sets_the_service_s_default_session_data.yml +63 -0
- data/test/cassettes/core/service/i_request/accepts_an_endpoint_type_option_for_selecting_a_specific_request.yml +140 -0
- data/test/cassettes/core/service/i_request/can_find_the_correct_request_based_on_bootstrapped_session_data.yml +63 -0
- data/test/cassettes/core/service/i_request/can_find_the_correct_request_based_on_non-bootstrapped_session_data.yml +97 -0
- data/test/cassettes/core/service/i_request/can_find_the_correct_request_if_api_version_is_not_defined_but_can_be_inferred_from_host_uri.yml +63 -0
- data/test/cassettes/core/service/i_request/uses_the_default_session_data_if_session_data_is_not_provided.yml +97 -0
- data/test/cassettes/core/session/c_load/creates_a_new_instance_from_the_given_session_dump.yml +63 -0
- data/test/cassettes/core/session/c_load/uses_the_loaded_auth_info_for_its_services.yml +63 -0
- data/test/cassettes/core/session/c_new/directs_log_entries_to_the_given_log_file.yml +63 -0
- data/test/cassettes/core/session/i_authenticate/authenticates_against_the_auth_service_indicated_in_the_config_file.yml +63 -0
- data/test/cassettes/core/session/i_authenticate/authenticates_against_the_auth_service_using_the_credentials_in_the_given_block.yml +38 -0
- data/test/cassettes/core/session/i_authenticate/raises_an_AuthenticationError_when_authentication_fails.yml +35 -0
- data/test/cassettes/core/session/i_authenticate/updates_the_session_data_of_its_service_objects.yml +123 -0
- data/test/cassettes/core/session/i_dump/serializes_the_session_data_for_caching.yml +63 -0
- data/test/cassettes/core/session/i_validate/returns_false_if_session_is_no_longer_valid.yml +97 -0
- data/test/cassettes/core/session/i_validate/returns_true_if_session_is_still_valid.yml +98 -0
- data/test/cassettes/core/session/i_xxx_service/returns_an_instance_of_the_indicated_service.yml +63 -0
- data/test/cassettes/openstack/compute/v2/public/list_images/leads_to_a_valid_response_when_no_parameters_are_provided.yml +108 -0
- data/test/cassettes/openstack/compute/v2/public/list_images/leads_to_a_valid_response_when_parameters_are_invalid.yml +96 -0
- data/test/cassettes/openstack/compute/v2/public/list_images/leads_to_a_valid_response_when_parameters_are_valid.yml +103 -0
- data/test/cassettes/openstack/compute/v2/public/list_images/returns_the_correct_value_for_body.yml +63 -0
- data/test/cassettes/openstack/compute/v2/public/list_images/returns_the_correct_value_for_body_.yml +63 -0
- data/test/cassettes/openstack/compute/v2/public/list_images/returns_the_correct_value_for_headers.yml +63 -0
- data/test/cassettes/openstack/compute/v2/public/list_images/returns_the_correct_value_for_headers_.yml +63 -0
- data/test/cassettes/openstack/compute/v2/public/list_images/returns_the_correct_value_for_url.yml +63 -0
- data/test/cassettes/openstack/compute/v2/public/list_images/returns_the_correct_value_for_url_.yml +63 -0
- data/test/cassettes/openstack/identity/v2/admin/create_tenant/leads_to_a_valid_response_when_params_are_invalid.yml +97 -0
- data/test/cassettes/openstack/identity/v2/admin/create_tenant/leads_to_a_valid_response_when_params_are_valid.yml +97 -0
- data/test/cassettes/openstack/identity/v2/admin/create_tenant/leads_to_a_valid_response_when_provided_with_invalid_params.yml +97 -0
- data/test/cassettes/openstack/identity/v2/public/create_token/leads_to_a_valid_response_when_parameters_are_invalid.yml +35 -0
- data/test/cassettes/openstack/identity/v2/public/create_token/leads_to_a_valid_response_when_parameters_are_valid.yml +38 -0
- data/test/cassettes/openstack/identity/v2/public/create_token/leads_to_a_valid_response_when_provided_with_a_token.yml +98 -0
- data/test/environment.yml.example +22 -0
- data/test/environment.yml.travis-ci +24 -0
- data/test/support/openstack_request_test_helper.rb +57 -0
- data/test/support/test_base_class.rb +39 -0
- data/test/support/test_environment.rb +37 -0
- data/test/support/test_reporter.rb +45 -0
- data/test/support/vcr_setup.rb +41 -0
- data/test/test_helper.rb +35 -0
- data/tmp/.gitignore +0 -0
- metadata +310 -8
- data/lib/aviator.rb +0 -5
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Aviator
|
|
2
|
+
|
|
3
|
+
class Response
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def method_missing(name, *args)
|
|
7
|
+
case name
|
|
8
|
+
when :body
|
|
9
|
+
@body ||= JSON.parse(response.body).with_indifferent_access
|
|
10
|
+
@body.dup
|
|
11
|
+
when :headers, :status
|
|
12
|
+
response.send(name)
|
|
13
|
+
when :request
|
|
14
|
+
request
|
|
15
|
+
else
|
|
16
|
+
super(name, *args)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
attr_reader :response,
|
|
24
|
+
:request
|
|
25
|
+
|
|
26
|
+
def initialize(response, request)
|
|
27
|
+
@response = response
|
|
28
|
+
@request = request
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
module Aviator
|
|
2
|
+
|
|
3
|
+
class Service
|
|
4
|
+
|
|
5
|
+
class AccessDetailsNotDefinedError < StandardError
|
|
6
|
+
def initialize
|
|
7
|
+
super ":access_details is not defined."
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class ProviderNotDefinedError < StandardError
|
|
12
|
+
def initialize
|
|
13
|
+
super ":provider is not defined."
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class ServiceNameNotDefinedError < StandardError
|
|
18
|
+
def initialize
|
|
19
|
+
super ":service is not defined."
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class SessionDataNotProvidedError < StandardError
|
|
24
|
+
def initialize
|
|
25
|
+
super "default_session_data is not initialized and no session data was "\
|
|
26
|
+
"provided in the method call."
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class UnknownRequestError < StandardError
|
|
32
|
+
def initialize(request_name)
|
|
33
|
+
super "Unknown request #{ request_name }."
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Logger < Faraday::Response::Logger
|
|
39
|
+
def initialize(app, logger=nil)
|
|
40
|
+
super(app)
|
|
41
|
+
@logger = logger || begin
|
|
42
|
+
require 'logger'
|
|
43
|
+
::Logger.new(self.class::LOG_FILE_PATH)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Because we define requests in a flattened scope, we want to make sure that when each
|
|
49
|
+
# request is initialized it doesn't get polluted by instance variables and methods
|
|
50
|
+
# of the containing class. This builder class makes that happen by being a
|
|
51
|
+
# scope gate for the file. See Metaprogramming Ruby, specifically on blocks and scope
|
|
52
|
+
class RequestBuilder
|
|
53
|
+
|
|
54
|
+
# This method gets called by the request file eval'd in self.build below
|
|
55
|
+
def define_request(request_name, &block)
|
|
56
|
+
klass = Class.new(Aviator::Request, &block)
|
|
57
|
+
return klass, request_name
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def self.build(path_to_request_file)
|
|
62
|
+
clean_room = new
|
|
63
|
+
clean_room.instance_eval(File.read(path_to_request_file))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
private_class_method :new
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
attr_accessor :default_session_data
|
|
73
|
+
|
|
74
|
+
attr_reader :service,
|
|
75
|
+
:provider
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def initialize(opts={})
|
|
79
|
+
@provider = opts[:provider] || (raise ProviderNotDefinedError.new)
|
|
80
|
+
@service = opts[:service] || (raise ServiceNameNotDefinedError.new)
|
|
81
|
+
@log_file = opts[:log_file]
|
|
82
|
+
|
|
83
|
+
@default_session_data = opts[:default_session_data]
|
|
84
|
+
|
|
85
|
+
load_requests
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def request(request_name, options={}, ¶ms)
|
|
90
|
+
session_data = options[:session_data] || default_session_data
|
|
91
|
+
|
|
92
|
+
raise SessionDataNotProvidedError.new unless session_data
|
|
93
|
+
|
|
94
|
+
request_class = find_request(request_name, session_data, options[:endpoint_type])
|
|
95
|
+
|
|
96
|
+
raise UnknownRequestError.new(request_name) unless request_class
|
|
97
|
+
|
|
98
|
+
request = request_class.new(session_data, ¶ms)
|
|
99
|
+
|
|
100
|
+
response = http_connection.send(request.http_method) do |r|
|
|
101
|
+
r.url request.url
|
|
102
|
+
r.headers.merge!(request.headers) if request.headers?
|
|
103
|
+
r.query = request.querystring if request.querystring?
|
|
104
|
+
r.body = JSON.generate(request.body) if request.body?
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
Aviator::Response.send(:new, response, request)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def requests
|
|
112
|
+
@requests
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
private
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def http_connection
|
|
120
|
+
@http_connection ||= Faraday.new do |conn|
|
|
121
|
+
if log_file
|
|
122
|
+
# Ugly hack to make logger configurable
|
|
123
|
+
const_name = 'LOG_FILE_PATH'
|
|
124
|
+
Logger.send(:remove_const, const_name) if Logger.const_defined?(const_name)
|
|
125
|
+
Logger.const_set(const_name, log_file)
|
|
126
|
+
conn.use Logger.dup
|
|
127
|
+
end
|
|
128
|
+
conn.adapter Faraday.default_adapter
|
|
129
|
+
conn.headers['Content-Type'] = 'application/json'
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# Candidate for extraction to aviator/openstack
|
|
135
|
+
def find_request(name, session_data, endpoint_type=nil)
|
|
136
|
+
endpoint_types = if endpoint_type
|
|
137
|
+
[endpoint_type.to_sym]
|
|
138
|
+
else
|
|
139
|
+
[:public, :admin]
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
version = infer_version(session_data)
|
|
143
|
+
|
|
144
|
+
return nil unless version && requests[version]
|
|
145
|
+
|
|
146
|
+
endpoint_types.each do |endpoint_type|
|
|
147
|
+
next unless requests[version][endpoint_type]
|
|
148
|
+
pair = requests[version][endpoint_type].find{ |k, v| k == name }
|
|
149
|
+
return pair[1] unless pair.nil?
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
nil
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# Candidate for extraction to aviator/openstack
|
|
157
|
+
def infer_version(session_data)
|
|
158
|
+
if session_data.has_key?(:auth_service) && session_data[:auth_service][:api_version]
|
|
159
|
+
session_data[:auth_service][:api_version].to_sym
|
|
160
|
+
|
|
161
|
+
elsif session_data.has_key?(:auth_service) && session_data[:auth_service][:host_uri]
|
|
162
|
+
m = session_data[:auth_service][:host_uri].match(/(v\d+)\.?\d*/)
|
|
163
|
+
return m[1].to_sym unless m.nil?
|
|
164
|
+
|
|
165
|
+
elsif session_data.has_key? :access
|
|
166
|
+
service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == service }
|
|
167
|
+
service_spec[:endpoints][0][:publicURL].match(/(v\d+)\.?\d*/)[1].to_sym
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def load_requests
|
|
173
|
+
# TODO: This should be determined by a provider-specific module.
|
|
174
|
+
# e.g. Aviator::OpenStack::requests_base_dir
|
|
175
|
+
request_file_paths = Dir.glob(Pathname.new(__FILE__).join(
|
|
176
|
+
'..',
|
|
177
|
+
'..',
|
|
178
|
+
provider.to_s,
|
|
179
|
+
service.to_s,
|
|
180
|
+
'**',
|
|
181
|
+
'*.rb'
|
|
182
|
+
).expand_path
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
@requests ||= {}
|
|
186
|
+
|
|
187
|
+
request_file_paths.each do |path_to_file|
|
|
188
|
+
klass, request_name = RequestBuilder.build(path_to_file)
|
|
189
|
+
|
|
190
|
+
api_version = @requests[klass.api_version] ||= {}
|
|
191
|
+
endpoint_type = api_version[klass.endpoint_type] ||= {}
|
|
192
|
+
endpoint_type[request_name] = klass
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def log_file
|
|
198
|
+
@log_file
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
end
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
module Aviator
|
|
2
|
+
|
|
3
|
+
class Session
|
|
4
|
+
|
|
5
|
+
class AuthenticationError < StandardError
|
|
6
|
+
def initialize(last_auth_body)
|
|
7
|
+
super("Authentication failed. The server returned #{ last_auth_body }")
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class EnvironmentNotDefinedError < ArgumentError
|
|
13
|
+
def initialize(path, env)
|
|
14
|
+
super("The environment '#{ env }' is not defined in #{ path }.")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class InvalidConfigFilePathError < ArgumentError
|
|
20
|
+
def initialize(path)
|
|
21
|
+
super("The config file at #{ path } does not exist!")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class NotAuthenticatedError < StandardError
|
|
27
|
+
def initialize
|
|
28
|
+
super("Session is not authenticated. Please authenticate before proceeding.")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ValidatorNotDefinedError < StandardError
|
|
34
|
+
def initialize
|
|
35
|
+
super("The validator request name is not defined for this session object.")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def initialize(opts={})
|
|
41
|
+
config_path = opts[:config_file]
|
|
42
|
+
environment = opts[:environment]
|
|
43
|
+
session_dump = opts[:session_dump]
|
|
44
|
+
|
|
45
|
+
if session_dump
|
|
46
|
+
initialize_with_dump(session_dump)
|
|
47
|
+
else
|
|
48
|
+
initialize_with_config(config_path, environment)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
@log_file = opts[:log_file]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def authenticate(&block)
|
|
56
|
+
block ||= lambda do |params|
|
|
57
|
+
environment[:auth_credentials].each do |key, value|
|
|
58
|
+
params[key] = value
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
response = auth_service.request environment[:auth_service][:request].to_sym, &block
|
|
63
|
+
|
|
64
|
+
if response.status == 200
|
|
65
|
+
@auth_info = response.body
|
|
66
|
+
update_services_session_data
|
|
67
|
+
else
|
|
68
|
+
raise AuthenticationError.new(response.body)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def authenticated?
|
|
74
|
+
!auth_info.nil?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def dump
|
|
79
|
+
JSON.generate({
|
|
80
|
+
environment: environment,
|
|
81
|
+
auth_info: auth_info
|
|
82
|
+
})
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def method_missing(name, *args, &block)
|
|
87
|
+
service_name_parts = name.to_s.match(/^(\w+)_service$/)
|
|
88
|
+
|
|
89
|
+
if service_name_parts
|
|
90
|
+
get_service_obj(service_name_parts[1])
|
|
91
|
+
else
|
|
92
|
+
super name, *args, &block
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def self.load(session_dump, opts={})
|
|
98
|
+
opts[:session_dump] = session_dump
|
|
99
|
+
|
|
100
|
+
new(opts)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def validate
|
|
105
|
+
raise NotAuthenticatedError.new unless authenticated?
|
|
106
|
+
raise ValidatorNotDefinedError.new unless environment[:auth_service][:validator]
|
|
107
|
+
|
|
108
|
+
response = auth_service.request environment[:auth_service][:validator].to_sym, session_data: auth_info
|
|
109
|
+
|
|
110
|
+
response.status == 200 || response.status == 203
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def auth_info
|
|
118
|
+
@auth_info
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def auth_service
|
|
123
|
+
@auth_service ||= Service.new(
|
|
124
|
+
provider: environment[:provider],
|
|
125
|
+
service: environment[:auth_service][:name],
|
|
126
|
+
default_session_data: { auth_service: environment[:auth_service] },
|
|
127
|
+
log_file: log_file
|
|
128
|
+
)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def environment
|
|
133
|
+
@environment
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def get_service_obj(service_name)
|
|
138
|
+
raise NotAuthenticatedError.new unless self.authenticated?
|
|
139
|
+
|
|
140
|
+
@services ||= {}
|
|
141
|
+
|
|
142
|
+
@services[service_name] ||= Service.new(
|
|
143
|
+
provider: environment[:provider],
|
|
144
|
+
service: service_name,
|
|
145
|
+
default_session_data: auth_info,
|
|
146
|
+
log_file: log_file
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
@services[service_name]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def initialize_with_config(config_path, environment)
|
|
154
|
+
raise InvalidConfigFilePathError.new(config_path) unless Pathname.new(config_path).file?
|
|
155
|
+
|
|
156
|
+
config = YAML.load_file(config_path).with_indifferent_access
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
raise EnvironmentNotDefinedError.new(config_path, environment) unless config[environment]
|
|
160
|
+
|
|
161
|
+
@environment = config[environment]
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def initialize_with_dump(session_dump)
|
|
166
|
+
session_info = JSON.parse(session_dump).with_indifferent_access
|
|
167
|
+
@environment = session_info[:environment]
|
|
168
|
+
@auth_info = session_info[:auth_info]
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def log_file
|
|
173
|
+
@log_file
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def update_services_session_data
|
|
178
|
+
return unless @services
|
|
179
|
+
|
|
180
|
+
@services.each do |name, obj|
|
|
181
|
+
obj.default_session_data = auth_info
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
define_request :list_images do
|
|
2
|
+
|
|
3
|
+
endpoint_type :public
|
|
4
|
+
api_version :v2
|
|
5
|
+
http_method :get
|
|
6
|
+
|
|
7
|
+
link_to 'documentation',
|
|
8
|
+
'http://docs.openstack.org/api/openstack-compute/2/content/List_Images-d1e4435.html'
|
|
9
|
+
|
|
10
|
+
optional_param :details
|
|
11
|
+
optional_param :server
|
|
12
|
+
optional_param :name
|
|
13
|
+
optional_param :status
|
|
14
|
+
optional_param 'changes-since'
|
|
15
|
+
optional_param :marker
|
|
16
|
+
optional_param :limit
|
|
17
|
+
optional_param :type
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def url
|
|
22
|
+
service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'compute' }
|
|
23
|
+
|
|
24
|
+
str = "#{ service_spec[:endpoints][0][:publicURL] }/images"
|
|
25
|
+
str += "/detail" if params[:details]
|
|
26
|
+
|
|
27
|
+
filters = []
|
|
28
|
+
|
|
29
|
+
(optional_params + required_params - [:details]).each do |param_name|
|
|
30
|
+
filters << "#{ param_name }=#{ params[param_name] }" if params[param_name]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
str += "?#{ filters.join('&') }" unless filters.empty?
|
|
34
|
+
|
|
35
|
+
str
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def headers
|
|
40
|
+
h = {}
|
|
41
|
+
|
|
42
|
+
unless self.anonymous?
|
|
43
|
+
h['X-Auth-Token'] = session_data[:access][:token][:id]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
h
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|