occi-api 4.3.5 → 4.3.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c1058d8ebbfc4c35fe0dc5a59725ce4ff6af5578
4
- data.tar.gz: 752bd8e01cc6afc49434261bad1c3d3a3be92f1f
3
+ metadata.gz: d5e457c71d021773fd57e1632882d438166cf935
4
+ data.tar.gz: 9afa187517fd7ef0facc4295085a10a7b9bf1f97
5
5
  SHA512:
6
- metadata.gz: dcb9d62289f0f17212e65645e7f68ed5df18792ec51f39e82757b9cc47e21ac905ac80e7ea4a06597e5e507d767d1861862dfbdf4e4b6bc9e123275dff9dad94
7
- data.tar.gz: 23d10f55966a9457cd02e6e7edc80d2f6c798db37fecb8b27ee3f3f62052ba9cc4827887d7d3f7adf6474efc64f63205c3b73081e23c94c5ab200a2bd75e1ce1
6
+ metadata.gz: 5d531511b8d1fa3d5d2c3658ad9fbb1d29c3c08430779d36ae3b471179443f8afe8b5fc2fd11df0e52df52707a6d09c08dfe9e4919ac86b94759798c855c5bb8
7
+ data.tar.gz: 2ab2461149750834ea980da58f36892366d5872cd55c35809cf873231d86fb24ce81e9ccb0be9bf778b049d09cc440960709a635ec88d19f5b36a60efcfd97e1
data/.travis.yml CHANGED
@@ -4,36 +4,14 @@ rvm:
4
4
  - 1.9.3
5
5
  - 2.0.0
6
6
  - 2.1
7
+ - 2.2
8
+ - 2.3
7
9
  - ruby-head
8
- - jruby-19mode
9
- - jruby-head
10
-
11
- jdk:
12
- - openjdk7
13
- - oraclejdk7
14
- - openjdk6
15
10
 
16
11
  matrix:
17
12
  allow_failures:
13
+ - rvm: 2.3
18
14
  - rvm: ruby-head
19
- - rvm: jruby-head
20
- exclude:
21
- - rvm: 1.9.3
22
- jdk: openjdk7
23
- - rvm: 1.9.3
24
- jdk: oraclejdk7
25
- - rvm: 2.0.0
26
- jdk: openjdk7
27
- - rvm: 2.0.0
28
- jdk: oraclejdk7
29
- - rvm: 2.1
30
- jdk: openjdk7
31
- - rvm: 2.1
32
- jdk: oraclejdk7
33
- - rvm: ruby-head
34
- jdk: openjdk7
35
- - rvm: ruby-head
36
- jdk: oraclejdk7
37
15
  fast_finish: true
38
16
 
39
17
  branches:
@@ -43,3 +21,10 @@ branches:
43
21
  - 4.1.x
44
22
  - 4.2.x
45
23
  - 4.3.x
24
+
25
+ install: 'gem install bundler -v ">= 1.7.12" && bundle install --retry=10'
26
+
27
+ env:
28
+ - ON_TRAVIS_CI=yes
29
+
30
+ sudo: false
@@ -78,10 +78,10 @@ module Occi::Api::Client
78
78
  )
79
79
 
80
80
  response_msg = response_message(response)
81
- raise "HTTP GET failed! #{response_msg}" unless response.code == 200
81
+ raise "HTTP GET failed! #{response_msg}" unless [200, 204].include?(response.code)
82
82
 
83
83
  # TODO: remove the gsub OCCI-OS hack as soon as they stop using 'uri:'
84
- response.body.gsub(/\# uri:\/(compute|storage|network)\/[\n]?/, '').split("\n").compact
84
+ (response.body || '').gsub(/\# uri:\/(compute|storage|network)\/[\n]?/, '').split("\n").compact
85
85
  end
86
86
 
87
87
  # @see Occi::Api::Client::ClientBase
@@ -5,20 +5,14 @@ module Occi::Api::Client
5
5
  class Keystone < Base
6
6
 
7
7
  KEYSTONE_URI_REGEXP = /^(Keystone|snf-auth) uri='(.+)'$/
8
+ KEYSTONE_VERSION_REGEXP = /^v([0-9]).*$/
8
9
 
9
10
  def setup(options = {})
10
11
  # get Keystone URL if possible
11
12
  set_keystone_base_url
12
13
 
13
- if !ENV['ROCCI_CLIENT_KEYSTONE_TENANT'].blank?
14
- # get a scoped token for the specified tenant directly
15
- set_auth_token ENV['ROCCI_CLIENT_KEYSTONE_TENANT']
16
- else
17
- # get an unscoped token, use the unscoped token
18
- # for tenant discovery and get a scoped token
19
- set_auth_token
20
- get_first_working_tenant
21
- end
14
+ # discover Keystone API version
15
+ set_auth_token ENV['ROCCI_CLIENT_KEYSTONE_TENANT']
22
16
 
23
17
  raise ::Occi::Api::Client::Errors::AuthnError,
24
18
  "Unable to get a tenant from Keystone, fallback failed!" if @env_ref.class.headers['X-Auth-Token'].blank?
@@ -56,12 +50,73 @@ module Occi::Api::Client
56
50
  raise ::Occi::Api::Client::Errors::AuthnError,
57
51
  "Unable to get Keystone's URL from the response, fallback failed!" unless match && match[2]
58
52
 
59
- @keystone_url = match[2].chomp('/').chomp('/v2.0')
53
+ @keystone_url = match[2]
54
+ end
55
+
56
+ def set_auth_token(tenant = nil)
57
+ response = @env_ref.class.get @keystone_url
58
+ Occi::Api::Log.debug response.inspect
59
+
60
+ raise ::Occi::Api::Client::Errors::AuthnError,
61
+ "Unable to get Keystone API version from the response, fallback failed!" if (400..599).include?(response.code)
62
+
63
+ # multiple choices, sort them by version id
64
+ if response.code == 300
65
+ versions = response['versions']['values'].sort_by { |v| v['id']}
66
+ else
67
+ # assume a single version
68
+ versions = [response['version']]
69
+ end
70
+
71
+ versions.each do |v|
72
+ match = KEYSTONE_VERSION_REGEXP.match(v['id'])
73
+ raise ::Occi::Api::Client::Errors::AuthnError,
74
+ "Unable to get Keystone API version from the response, fallback failed!" unless match && match[1]
75
+ if match[1] == '2'
76
+ handler_class = KeystoneV2
77
+ elsif match[1] == '3'
78
+ handler_class = KeystoneV3
79
+ end
80
+ v['links'].each do |link|
81
+ begin
82
+ if link['rel'] == 'self'
83
+ keystone_url = link['href'].chomp('/')
84
+ keystone_handler = handler_class.new(keystone_url, @env_ref, @options)
85
+ token = keystone_handler.set_auth_token(tenant)
86
+ # found a working keystone, stop looking
87
+ return
88
+ end
89
+ rescue ::Occi::Api::Client::Errors::AuthnError
90
+ # ignore and try with next link
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ end
97
+
98
+ class KeystoneV2
99
+ def initialize(base_url, env_ref, options = {})
100
+ @base_url = base_url
101
+ @env_ref = env_ref
102
+ @options = options
60
103
  end
61
104
 
62
105
  def set_auth_token(tenant = nil)
106
+ if !tenant.blank?
107
+ # get a scoped token for the specified tenant directly
108
+ authenticate ENV['ROCCI_CLIENT_KEYSTONE_TENANT']
109
+ else
110
+ # get an unscoped token, use the unscoped token
111
+ # for tenant discovery and get a scoped token
112
+ authenticate
113
+ get_first_working_tenant
114
+ end
115
+ end
116
+
117
+ def authenticate(tenant = nil)
63
118
  response = @env_ref.class.post(
64
- "#{@keystone_url}/v2.0/tokens",
119
+ "#{@base_url}/tokens",
65
120
  :body => get_keystone_req(tenant),
66
121
  :headers => get_req_headers
67
122
  )
@@ -99,7 +154,7 @@ module Occi::Api::Client
99
154
 
100
155
  def get_first_working_tenant
101
156
  response = @env_ref.class.get(
102
- "#{@keystone_url}/v2.0/tenants",
157
+ "#{@base_url}/tenants",
103
158
  :headers => get_req_headers
104
159
  )
105
160
  Occi::Api::Log.debug response.inspect
@@ -110,7 +165,7 @@ module Occi::Api::Client
110
165
  response['tenants'].each do |tenant|
111
166
  begin
112
167
  Occi::Api::Log.debug "Authenticating for tenant #{tenant['name'].inspect}"
113
- set_auth_token(tenant['name'])
168
+ authenticate(tenant['name'])
114
169
 
115
170
  # found a working tenant, stop looking
116
171
  break
@@ -120,6 +175,115 @@ module Occi::Api::Client
120
175
  end
121
176
  end
122
177
 
178
+ def get_req_headers
179
+ headers = @env_ref.class.headers.clone
180
+ headers['Content-Type'] = "application/json"
181
+ headers['Accept'] = headers['Content-Type']
182
+
183
+ headers
184
+ end
185
+ end
186
+
187
+ class KeystoneV3
188
+ def initialize(base_url, env_ref, options = {})
189
+ @base_url = base_url
190
+ @env_ref = env_ref
191
+ @options = options
192
+ end
193
+
194
+ def set_auth_token(tenant = nil)
195
+ if @options[:original_type] == "x509"
196
+ voms_authenticate(tenant)
197
+ elsif @options[:username] && @options[:password]
198
+ passwd_authenticate(tenant)
199
+ else
200
+ raise ::Occi::Api::Client::Errors::AuthnError,
201
+ "Unable to request a token from Keystone! Chosen " \
202
+ "AuthN is not supported, fallback failed!"
203
+ end
204
+ end
205
+
206
+ def passwd_authenticate(tenant = nil)
207
+ raise ::Occi::Api::Client::Errors::AuthnError,
208
+ "Needs to be implemented, check http://developer.openstack.org/api-ref-identity-v3.html#authenticatePasswordUnscoped"
209
+ end
210
+
211
+ def voms_authenticate(tenant = nil)
212
+ set_voms_unscoped_token
213
+
214
+ if !tenant.blank?
215
+ set_scoped_token(tenant)
216
+ else
217
+ get_first_working_project
218
+ end
219
+ end
220
+
221
+ def set_voms_unscoped_token
222
+ response = @env_ref.class.post(
223
+ # egi.eu and voms below should be configurable
224
+ "#{@base_url}/OS-FEDERATION/identity_providers/egi.eu/protocols/mapped/voms",
225
+ )
226
+ Occi::Api::Log.debug response.inspect
227
+
228
+ if response.success?
229
+ @env_ref.class.headers['X-Auth-Token'] = response.headers['x-subject-token']
230
+ else
231
+ raise ::Occi::Api::Client::Errors::AuthnError,
232
+ "Unable to get a token from Keystone, fallback failed!"
233
+ end
234
+ end
235
+
236
+ def get_first_working_project
237
+ response = @env_ref.class.get(
238
+ "#{@base_url}/projects",
239
+ :headers => get_req_headers
240
+ )
241
+ Occi::Api::Log.debug response.inspect
242
+
243
+ raise ::Occi::Api::Client::Errors::AuthnError,
244
+ "Keystone didn't return any projects, fallback failed!" if response['projects'].blank?
245
+
246
+ response['projects'].each do |project|
247
+ begin
248
+ Occi::Api::Log.debug "Authenticating for project #{project['name'].inspect}"
249
+ set_scoped_token(project['id'])
250
+
251
+ # found a working project, stop looking
252
+ break
253
+ rescue ::Occi::Api::Client::Errors::AuthnError
254
+ # ignoring and trying the next tenant
255
+ end
256
+ end
257
+ end
258
+
259
+ def set_scoped_token(project)
260
+ body = {
261
+ "auth" => {
262
+ "identity" => {
263
+ "methods" => ["token"],
264
+ "token" => {"id" => @env_ref.class.headers['X-Auth-Token'] }
265
+ },
266
+ "scope" => {
267
+ "project" => {"id" => project}
268
+ }
269
+ }
270
+ }
271
+ response = @env_ref.class.post(
272
+ "#{@base_url}/auth/tokens",
273
+ :body => body,
274
+ :headers => get_req_headers
275
+ )
276
+
277
+ Occi::Api::Log.debug response.inspect
278
+
279
+ if response.success?
280
+ @env_ref.class.headers['X-Auth-Token'] = response.headers['x-subject-token']
281
+ else
282
+ raise ::Occi::Api::Client::Errors::AuthnError,
283
+ "Unable to get a token from Keystone, fallback failed!"
284
+ end
285
+ end
286
+
123
287
  def get_req_headers
124
288
  headers = @env_ref.class.headers.clone
125
289
  headers['Content-Type'] = "application/json"
@@ -1,5 +1,5 @@
1
1
  module Occi
2
2
  module Api
3
- VERSION = "4.3.5" unless defined?(::Occi::Api::VERSION)
3
+ VERSION = "4.3.6" unless defined?(::Occi::Api::VERSION)
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: occi-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.5
4
+ version: 4.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Feldhaus
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-01-10 00:00:00.000000000 Z
13
+ date: 2016-06-24 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: occi-core