occi-api 4.3.5 → 4.3.6

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