misty 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -4
- data/lib/misty/auth.rb +13 -17
- data/lib/misty/auth/auth_v2.rb +33 -32
- data/lib/misty/auth/auth_v3.rb +48 -35
- data/lib/misty/cloud.rb +24 -47
- data/lib/misty/http/client.rb +13 -10
- data/lib/misty/http/method_builder.rb +10 -3
- data/lib/misty/http/net_http.rb +2 -2
- data/lib/misty/http/request.rb +9 -9
- data/lib/misty/misty.rb +23 -29
- data/lib/misty/openstack/microversion.rb +1 -1
- data/lib/misty/services.rb +49 -0
- data/lib/misty/version.rb +1 -1
- data/test/unit/auth_test.rb +49 -15
- data/test/unit/cloud_test.rb +21 -23
- data/test/unit/http/client_test.rb +1 -2
- data/test/unit/http/method_builder_test.rb +15 -4
- data/test/unit/misty_test.rb +110 -9
- data/test/unit/openstack/microversion_test.rb +2 -4
- data/test/unit/service_helper.rb +2 -4
- data/test/unit/services_test.rb +16 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f77fca7e84ccf06eb7cf92b3c2ee1a9233d0427
|
4
|
+
data.tar.gz: d8d73c45718a708d0da3f5bf076aa0cc802c0f4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a98bcc69158a796d55ee9ce9ba7ccb5cc6d6f99bc0fc9217137e00905a243cc1608aea11dd9dc996423dcfdc9c2ad25a1435bc17cbbe66cfc03c1c9e491ed78
|
7
|
+
data.tar.gz: 72475d27ad43c025522654ce010b520a837cfd70c403ae8ac70b632300ab7c900e03eda7f860d2fe53b095ce6324e3438304143e9957ff4866ee8c7849b68b84
|
data/README.md
CHANGED
@@ -152,6 +152,10 @@ The following parameters can be used:
|
|
152
152
|
User domain id
|
153
153
|
* `:user_domain`
|
154
154
|
User domain name
|
155
|
+
* `:password`
|
156
|
+
Password for user. Cannot be used together with `:token`.
|
157
|
+
* `:token`
|
158
|
+
Previous Keystone v3 token for user. Can only be used with Keystone v3. Overrides all user and password parameters.
|
155
159
|
|
156
160
|
#### Keystone v3
|
157
161
|
Keystone v3 is default recommended version:
|
@@ -212,10 +216,6 @@ The following options are applied to each service unless specifically provided f
|
|
212
216
|
Type: String
|
213
217
|
Allowed values: "public", "internal", "admin"
|
214
218
|
Default: "public"
|
215
|
-
* :http_proxy
|
216
|
-
For example: `"http://userid:password@somewhere.com:8080/"` or `ENV["http_proxy"]`
|
217
|
-
Type: String
|
218
|
-
Default: `""`
|
219
219
|
* :ssl_verify_mode
|
220
220
|
When using SSL mode (defined by URI scheme => "https://")
|
221
221
|
Type: Boolean
|
@@ -276,8 +276,12 @@ openstack.network.post("/v2.0/qos/policies/48985e6b8da145699d411f12a3459fca/dscp
|
|
276
276
|
# Requirements
|
277
277
|
|
278
278
|
## Ruby versions tested
|
279
|
+
* Ruby 2.4.1
|
279
280
|
* Ruby 2.4.0
|
281
|
+
* Ruby 2.3.4
|
280
282
|
* Ruby 2.3.3
|
283
|
+
* Ruby 2.3.2
|
284
|
+
* Ruby 2.3.1
|
281
285
|
* Ruby 2.3.0
|
282
286
|
|
283
287
|
# Contributing
|
data/lib/misty/auth.rb
CHANGED
@@ -14,31 +14,27 @@ module Misty
|
|
14
14
|
|
15
15
|
include Misty::HTTP::NetHTTP
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
attr_reader :catalog
|
18
|
+
|
19
|
+
def self.factory(auth, config)
|
20
|
+
if auth[:tenant_id] || auth[:tenant]
|
21
|
+
return Misty::AuthV2.new(auth, config)
|
20
22
|
else
|
21
|
-
return Misty::AuthV3.new(
|
23
|
+
return Misty::AuthV3.new(auth, config)
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
@
|
29
|
-
@credentials = scoped_authentication
|
30
|
-
|
31
|
-
raise URLError, "No URL provided" unless options[:url] && !options[:url].empty?
|
32
|
-
@uri = URI.parse(options[:url])
|
33
|
-
@proxy = proxy
|
27
|
+
def initialize(auth, config)
|
28
|
+
raise URLError, "No URL provided" unless auth[:url] && !auth[:url].empty?
|
29
|
+
@credentials = set_credentials(auth)
|
30
|
+
@http = net_http(URI.parse(auth[:url]), config.ssl_verify_mode, config.log)
|
34
31
|
@token = nil
|
35
|
-
|
32
|
+
@token, @catalog, @expires = set(authenticate)
|
36
33
|
raise CatalogError, "No catalog provided during authentication" if @catalog.empty?
|
37
34
|
end
|
38
35
|
|
39
36
|
def authenticate
|
40
|
-
|
41
|
-
response = http.post(self.class.path, @credentials.to_json, Misty::HEADER_JSON)
|
37
|
+
response = @http.post(self.class.path, @credentials.to_json, Misty::HEADER_JSON)
|
42
38
|
raise AuthenticationError, "Response code=#{response.code}, Msg=#{response.msg}" unless response.code =~ /200|201/
|
43
39
|
response
|
44
40
|
end
|
@@ -58,7 +54,7 @@ module Misty
|
|
58
54
|
end
|
59
55
|
|
60
56
|
def get_token
|
61
|
-
authenticate if expired?
|
57
|
+
@token, @catalog, @expires = set(authenticate) if expired?
|
62
58
|
@token
|
63
59
|
end
|
64
60
|
end
|
data/lib/misty/auth/auth_v2.rb
CHANGED
@@ -6,13 +6,6 @@ module Misty
|
|
6
6
|
"/v2.0/tokens"
|
7
7
|
end
|
8
8
|
|
9
|
-
def initialize(options, *args)
|
10
|
-
@user = Misty::Auth::User.new(options[:user_id], options[:user])
|
11
|
-
@user.password = options[:password]
|
12
|
-
@tenant = Misty::Auth::Name.new(options[:tenant_id], options[:tenant])
|
13
|
-
super(options, *args)
|
14
|
-
end
|
15
|
-
|
16
9
|
def catalog_endpoints(endpoints, region, interface)
|
17
10
|
endpoints.each do |endpoint|
|
18
11
|
if endpoint["region"] == region && endpoint["#{interface}URL"]
|
@@ -21,50 +14,58 @@ module Misty
|
|
21
14
|
end
|
22
15
|
end
|
23
16
|
|
24
|
-
def
|
25
|
-
endpoint = endpoints.select { |ep| !ep[interface].empty? }
|
26
|
-
raise CatalogError, "No endpoint available for region '#{region}' and interface '#{interface}'" unless endpoint
|
27
|
-
endpoint[0][interface]
|
28
|
-
end
|
29
|
-
|
30
|
-
def setup(response)
|
31
|
-
payload = JSON.load(response.body)
|
32
|
-
@token = payload["access"]["token"]["id"]
|
33
|
-
@catalog = payload["access"]["serviceCatalog"]
|
34
|
-
@expires = payload["access"]["token"]["expires"]
|
35
|
-
end
|
36
|
-
|
37
|
-
def scoped_authentication
|
17
|
+
def credentials
|
38
18
|
raise Misty::Auth::CredentialsError, "#{self.class}: User name is required" if @user.name.nil?
|
39
19
|
raise Misty::Auth::CredentialsError, "#{self.class}: User password is required" if @user.password.nil?
|
40
|
-
return
|
41
|
-
return
|
20
|
+
return creds_by_id if @tenant.id
|
21
|
+
return creds_by_name if @tenant.name
|
42
22
|
raise Misty::Auth::CredentialsError, "#{self.class}: No tenant available"
|
43
23
|
end
|
44
24
|
|
45
|
-
def
|
25
|
+
def credentials_data
|
26
|
+
{
|
27
|
+
"username": @user.name,
|
28
|
+
"password": @user.password
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def creds_by_name
|
46
33
|
{
|
47
34
|
"auth": {
|
48
|
-
"passwordCredentials":
|
35
|
+
"passwordCredentials": credentials_data,
|
49
36
|
"tenantName": @tenant.name
|
50
37
|
}
|
51
38
|
}
|
52
39
|
end
|
53
40
|
|
54
|
-
def
|
41
|
+
def creds_by_id
|
55
42
|
{
|
56
43
|
"auth": {
|
57
|
-
"passwordCredentials":
|
44
|
+
"passwordCredentials": credentials_data,
|
58
45
|
"tenantId": @tenant.id
|
59
46
|
}
|
60
47
|
}
|
61
48
|
end
|
62
49
|
|
63
|
-
def
|
64
|
-
{
|
65
|
-
|
66
|
-
|
67
|
-
|
50
|
+
def get_endpoint_url(endpoints, region, interface)
|
51
|
+
endpoint = endpoints.select { |ep| !ep[interface].empty? }
|
52
|
+
raise CatalogError, "No endpoint available for region '#{region}' and interface '#{interface}'" unless endpoint
|
53
|
+
endpoint[0][interface]
|
54
|
+
end
|
55
|
+
|
56
|
+
def set(response)
|
57
|
+
payload = JSON.load(response.body)
|
58
|
+
token = payload["access"]["token"]["id"]
|
59
|
+
catalog = payload["access"]["serviceCatalog"]
|
60
|
+
expires = payload["access"]["token"]["expires"]
|
61
|
+
[token, catalog, expires]
|
62
|
+
end
|
63
|
+
|
64
|
+
def set_credentials(auth)
|
65
|
+
@user = Misty::Auth::User.new(auth[:user_id], auth[:user])
|
66
|
+
@user.password = auth[:password]
|
67
|
+
@tenant = Misty::Auth::Name.new(auth[:tenant_id], auth[:tenant])
|
68
|
+
credentials
|
68
69
|
end
|
69
70
|
end
|
70
71
|
end
|
data/lib/misty/auth/auth_v3.rb
CHANGED
@@ -2,26 +2,6 @@ require 'misty/auth'
|
|
2
2
|
|
3
3
|
module Misty
|
4
4
|
class AuthV3 < Misty::Auth
|
5
|
-
def initialize(options, *args)
|
6
|
-
if options[:project_id] || options[:project]
|
7
|
-
# scope: project
|
8
|
-
project_domain_id = options[:project_domain_id] ? options[:project_domain_id] : Misty::DOMAIN_ID
|
9
|
-
@project = Misty::Auth::ProjectScope.new(options[:project_id], options[:project])
|
10
|
-
@project.domain = Misty::Auth::Name.new(project_domain_id, options[:user_domain])
|
11
|
-
else
|
12
|
-
# scope: domain
|
13
|
-
domain_id = options[:domain_id] ? options[:domain_id] : Misty::DOMAIN_ID
|
14
|
-
@domain = Misty::Auth::DomainScope.new(domain_id, options[:domain]) if domain_id || options[:domain]
|
15
|
-
end
|
16
|
-
|
17
|
-
user_domain_id = options[:user_domain_id] ? options[:user_domain_id] : Misty::DOMAIN_ID
|
18
|
-
@user = Misty::Auth::User.new(options[:user_id], options[:user])
|
19
|
-
@user.password = options[:password]
|
20
|
-
@user.domain = Misty::Auth::Name.new(user_domain_id, options[:user_domain])
|
21
|
-
|
22
|
-
super(options, *args)
|
23
|
-
end
|
24
|
-
|
25
5
|
def self.path
|
26
6
|
"/v3/auth/tokens"
|
27
7
|
end
|
@@ -34,35 +14,68 @@ module Misty
|
|
34
14
|
end
|
35
15
|
end
|
36
16
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
17
|
+
def credentials
|
18
|
+
if @token
|
19
|
+
identity = {
|
20
|
+
"methods": ["token"],
|
21
|
+
"token": { "id": @token }
|
22
|
+
}
|
23
|
+
else
|
24
|
+
identity = {
|
25
|
+
"methods": ["password"],
|
26
|
+
"password": @user.identity
|
27
|
+
}
|
28
|
+
end
|
44
29
|
{
|
45
30
|
"auth": {
|
46
|
-
"identity":
|
47
|
-
"methods": ["password"],
|
48
|
-
"password": @user.identity
|
49
|
-
},
|
31
|
+
"identity": identity,
|
50
32
|
"scope": scope
|
51
33
|
}
|
52
34
|
}
|
53
35
|
end
|
54
36
|
|
37
|
+
def get_endpoint_url(endpoints, region, interface)
|
38
|
+
endpoint = endpoints.select { |ep| ep["region_id"] == region && ep["interface"] == interface }
|
39
|
+
raise CatalogError, "No endpoint available for region '#{region}' and interface '#{interface}'" unless endpoint
|
40
|
+
endpoint[0]["url"]
|
41
|
+
end
|
42
|
+
|
55
43
|
def scope
|
56
44
|
return @project.identity if @project
|
57
45
|
return @domain.identity if @domain
|
58
46
|
raise Misty::Auth::CredentialsError, "#{self.class}: No scope available"
|
59
47
|
end
|
60
48
|
|
61
|
-
def
|
49
|
+
def set(response)
|
62
50
|
payload = JSON.load(response.body)
|
63
|
-
|
64
|
-
|
65
|
-
|
51
|
+
token = response["x-subject-token"]
|
52
|
+
catalog = payload["token"]["catalog"]
|
53
|
+
expires = payload["token"]["expires_at"]
|
54
|
+
[token, catalog, expires]
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_credentials(auth)
|
58
|
+
if auth[:project_id] || auth[:project]
|
59
|
+
# scope: project
|
60
|
+
project_domain_id = auth[:project_domain_id] ? auth[:project_domain_id] : Misty::DOMAIN_ID
|
61
|
+
@project = Misty::Auth::ProjectScope.new(auth[:project_id], auth[:project])
|
62
|
+
@project.domain = Misty::Auth::Name.new(project_domain_id, auth[:user_domain])
|
63
|
+
else
|
64
|
+
# scope: domain
|
65
|
+
domain_id = auth[:domain_id] ? auth[:domain_id] : Misty::DOMAIN_ID
|
66
|
+
@domain = Misty::Auth::DomainScope.new(domain_id, auth[:domain]) if domain_id || auth[:domain]
|
67
|
+
end
|
68
|
+
|
69
|
+
if auth[:token]
|
70
|
+
@token = auth[:token]
|
71
|
+
else
|
72
|
+
user_domain_id = auth[:user_domain_id] ? auth[:user_domain_id] : Misty::DOMAIN_ID
|
73
|
+
@user = Misty::Auth::User.new(auth[:user_id], auth[:user])
|
74
|
+
@user.password = auth[:password]
|
75
|
+
@user.domain = Misty::Auth::Name.new(user_domain_id, auth[:user_domain])
|
76
|
+
end
|
77
|
+
|
78
|
+
credentials
|
66
79
|
end
|
67
80
|
end
|
68
81
|
end
|
data/lib/misty/cloud.rb
CHANGED
@@ -3,62 +3,39 @@ require 'misty/auth/auth_v3'
|
|
3
3
|
|
4
4
|
module Misty
|
5
5
|
class Cloud
|
6
|
-
class
|
7
|
-
attr_accessor :auth, :content_type, :
|
6
|
+
class Config
|
7
|
+
attr_accessor :auth, :content_type, :interface, :log, :region_id, :ssl_verify_mode
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
:orchestration, :search, :shared_file_systems)
|
13
|
-
|
14
|
-
attr_reader :services
|
15
|
-
|
16
|
-
def initialize(params = {:auth => {}})
|
17
|
-
@setup = self.class.setup(params)
|
18
|
-
@options = Options.new
|
19
|
-
@services = setup_services(params)
|
10
|
+
def self.dot_to_underscore(val)
|
11
|
+
val.gsub(/\./,'_')
|
20
12
|
end
|
21
13
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
setup.log.level = params[:log_level] ? params[:log_level] : Misty::LOG_LEVEL
|
28
|
-
setup.region_id = params[:region_id] ? params[:region_id] : Misty::REGION_ID
|
29
|
-
setup.ssl_verify_mode = params.key?(:ssl_verify_mode) ? params[:ssl_verify_mode] : Misty::SSL_VERIFY_MODE
|
30
|
-
http_proxy = params[:http_proxy] ? params[:http_proxy] : ""
|
31
|
-
setup.proxy = URI.parse(http_proxy)
|
32
|
-
setup.auth = Misty::Auth.factory(params[:auth], setup.proxy, setup.ssl_verify_mode, setup.log)
|
33
|
-
setup
|
14
|
+
def initialize(params)# = {:auth => {}})
|
15
|
+
@params = params
|
16
|
+
@config = self.class.set_configuration(params)
|
17
|
+
@services = Misty.services
|
18
|
+
@auth = Misty::Auth.factory(params[:auth], @config)
|
34
19
|
end
|
35
20
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
# Highest version is used by default!
|
46
|
-
services.merge!(service.name => {service.project => service.versions.sort[-1]})
|
47
|
-
end
|
48
|
-
end
|
49
|
-
services
|
21
|
+
def self.set_configuration(params)
|
22
|
+
config = Config.new
|
23
|
+
config.content_type = params[:content_type] ? params[:content_type] : Misty::CONTENT_TYPE
|
24
|
+
config.interface = params[:interface] ? params[:interface] : Misty::INTERFACE
|
25
|
+
config.log = Logger.new(params[:log_file] ? params[:log_file] : Misty::LOG_FILE)
|
26
|
+
config.log.level = params[:log_level] ? params[:log_level] : Misty::LOG_LEVEL
|
27
|
+
config.region_id = params[:region_id] ? params[:region_id] : Misty::REGION_ID
|
28
|
+
config.ssl_verify_mode = params.key?(:ssl_verify_mode) ? params[:ssl_verify_mode] : Misty::SSL_VERIFY_MODE
|
29
|
+
config
|
50
30
|
end
|
51
31
|
|
52
32
|
def build_service(service_name)
|
53
|
-
|
54
|
-
|
55
|
-
version =
|
56
|
-
|
57
|
-
klass.
|
58
|
-
|
59
|
-
|
60
|
-
def self.dot_to_underscore(val)
|
61
|
-
val.gsub(/\./,'_')
|
33
|
+
service = @services.find {|service| service.name == service_name}
|
34
|
+
service.options = @params[service.name] if @params[service.name]
|
35
|
+
service.version = service.options[:api_version]
|
36
|
+
version = self.class.dot_to_underscore(service.version)
|
37
|
+
klass = Object.const_get("Misty::Openstack::#{service.project.capitalize}::#{version.capitalize}")
|
38
|
+
klass.new(@auth, @config, service.options)
|
62
39
|
end
|
63
40
|
|
64
41
|
def alarming
|
data/lib/misty/http/client.rb
CHANGED
@@ -6,6 +6,10 @@ require 'misty/http/direct'
|
|
6
6
|
module Misty
|
7
7
|
module HTTP
|
8
8
|
class Client
|
9
|
+
class Options
|
10
|
+
attr_accessor :base_path, :base_url, :interface, :region_id, :service_names, :ssl_verify_mode, :version
|
11
|
+
end
|
12
|
+
|
9
13
|
class InvalidDataError < StandardError; end
|
10
14
|
|
11
15
|
include Misty::HTTP::NetHTTP
|
@@ -17,8 +21,6 @@ module Misty
|
|
17
21
|
|
18
22
|
attr_reader :microversion
|
19
23
|
|
20
|
-
Options = Struct.new(:base_path, :base_url, :interface, :region_id, :service_names, :ssl_verify_mode, :version)
|
21
|
-
|
22
24
|
def requests
|
23
25
|
list = []
|
24
26
|
self.class.api.each do |_path, verbs|
|
@@ -45,13 +47,14 @@ module Misty
|
|
45
47
|
# :ssl_verify_mode => true
|
46
48
|
# (micro)version: Can be numbered (3.1) or by state (CURRENT, LATEST or SUPPORTED)
|
47
49
|
# :version => "CURRENT"
|
48
|
-
def initialize(
|
49
|
-
@
|
50
|
+
def initialize(auth, config, options)
|
51
|
+
@auth = auth
|
52
|
+
@config = config
|
50
53
|
@options = setup(options)
|
51
|
-
@uri = URI.parse(@
|
54
|
+
@uri = URI.parse(@auth.get_endpoint(@options.service_names, @options.region_id, @options.interface))
|
52
55
|
@base_path = @options.base_path ? @options.base_path : @uri.path
|
53
56
|
@base_path = @base_path.chomp("/")
|
54
|
-
@http = net_http(@uri, @
|
57
|
+
@http = net_http(@uri, @options.ssl_verify_mode, @config.log)
|
55
58
|
@version = nil
|
56
59
|
@microversion = false
|
57
60
|
end
|
@@ -72,7 +75,7 @@ module Misty
|
|
72
75
|
end
|
73
76
|
|
74
77
|
def headers
|
75
|
-
h = headers_default.merge("X-Auth-Token" => "#{@
|
78
|
+
h = headers_default.merge("X-Auth-Token" => "#{@auth.get_token}")
|
76
79
|
h.merge!(microversion_header) if microversion
|
77
80
|
h
|
78
81
|
end
|
@@ -87,10 +90,10 @@ module Misty
|
|
87
90
|
options = Options.new()
|
88
91
|
options.base_path = params[:base_path] ? params[:base_path] : nil
|
89
92
|
options.base_url = params[:base_url] ? params[:base_url] : nil
|
90
|
-
options.interface = params[:interface] ? params[:interface] : @
|
91
|
-
options.region_id = params[:region_id] ? params[:region_id] : @
|
93
|
+
options.interface = params[:interface] ? params[:interface] : @config.interface
|
94
|
+
options.region_id = params[:region_id] ? params[:region_id] : @config.region_id
|
92
95
|
options.service_names = params[:service_name] ? self.class.service_names << params[:service_name] : self.class.service_names
|
93
|
-
options.ssl_verify_mode = params[:ssl_verify_mode] ? params[:ssl_verify_mode] : @
|
96
|
+
options.ssl_verify_mode = params[:ssl_verify_mode] ? params[:ssl_verify_mode] : @config.ssl_verify_mode
|
94
97
|
options.version = params[:version] ? params[:version] : "CURRENT"
|
95
98
|
|
96
99
|
unless INTERFACES.include?(options.interface)
|
@@ -85,11 +85,18 @@ module Misty
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def query_param(data)
|
88
|
+
result = nil
|
88
89
|
if data.is_a? String
|
89
|
-
|
90
|
-
|
91
|
-
|
90
|
+
result = ''
|
91
|
+
if data != ''
|
92
|
+
result = '?'
|
93
|
+
result.force_encoding('ASCII-8BIT')
|
94
|
+
result << data
|
95
|
+
end
|
96
|
+
elsif data.is_a? Hash
|
97
|
+
result = data.empty? ? '' : '?' + URI.encode_www_form(data)
|
92
98
|
end
|
99
|
+
return result
|
93
100
|
end
|
94
101
|
end
|
95
102
|
end
|
data/lib/misty/http/net_http.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Misty
|
2
2
|
module HTTP
|
3
3
|
module NetHTTP
|
4
|
-
def net_http(endpoint,
|
5
|
-
http = Net::HTTP.new(endpoint.host, endpoint.port
|
4
|
+
def net_http(endpoint, ssl_verify_mode, log)
|
5
|
+
http = Net::HTTP.new(endpoint.host, endpoint.port)
|
6
6
|
http.set_debug_output(log) if log.level == Logger::DEBUG
|
7
7
|
if endpoint.scheme == "https"
|
8
8
|
http.use_ssl = true
|
data/lib/misty/http/request.rb
CHANGED
@@ -2,7 +2,7 @@ module Misty
|
|
2
2
|
module HTTP
|
3
3
|
module Request
|
4
4
|
def decode?(response)
|
5
|
-
if @
|
5
|
+
if @config.content_type != :json && response.code =~ /2??/ && !response.is_a?(Net::HTTPNoContent) \
|
6
6
|
&& !response.is_a?(Net::HTTPResetContent) && response.header["content-type"] \
|
7
7
|
&& response.header["content-type"].include?("application/json")
|
8
8
|
true
|
@@ -16,51 +16,51 @@ module Misty
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def http_delete(path, headers)
|
19
|
-
@
|
19
|
+
@config.log.info(http_to_s(path, headers))
|
20
20
|
request = Net::HTTP::Delete.new(path, headers)
|
21
21
|
http(request)
|
22
22
|
end
|
23
23
|
|
24
24
|
def http_copy(path, headers)
|
25
|
-
@
|
25
|
+
@config.log.info(http_to_s(path, headers))
|
26
26
|
request = Net::HTTP::Copy.new(path, headers)
|
27
27
|
http(request)
|
28
28
|
end
|
29
29
|
|
30
30
|
def http_get(path, headers)
|
31
|
-
@
|
31
|
+
@config.log.info(http_to_s(path, headers))
|
32
32
|
request = Net::HTTP::Get.new(path, headers)
|
33
33
|
http(request)
|
34
34
|
end
|
35
35
|
|
36
36
|
def http_head(path, headers)
|
37
|
-
@
|
37
|
+
@config.log.info(http_to_s(path, headers))
|
38
38
|
request = Net::HTTP::Head.new(path, headers)
|
39
39
|
http(request)
|
40
40
|
end
|
41
41
|
|
42
42
|
def http_options(path, headers)
|
43
|
-
@
|
43
|
+
@config.log.info(http_to_s(path, headers))
|
44
44
|
request = Net::HTTP::Options.new(path, headers)
|
45
45
|
http(request)
|
46
46
|
end
|
47
47
|
|
48
48
|
def http_patch(path, headers, data)
|
49
|
-
@
|
49
|
+
@config.log.info(http_to_s(path, headers, data))
|
50
50
|
request = Net::HTTP::Patch.new(path, headers)
|
51
51
|
request.body = Misty.to_json(data)
|
52
52
|
http(request)
|
53
53
|
end
|
54
54
|
|
55
55
|
def http_post(path, headers, data)
|
56
|
-
@
|
56
|
+
@config.log.info(http_to_s(path, headers, data))
|
57
57
|
request = Net::HTTP::Post.new(path, headers)
|
58
58
|
request.body = Misty.to_json(data)
|
59
59
|
http(request)
|
60
60
|
end
|
61
61
|
|
62
62
|
def http_put(path, headers, data)
|
63
|
-
@
|
63
|
+
@config.log.info(http_to_s(path, headers, data))
|
64
64
|
request = Net::HTTP::Put.new(path, headers)
|
65
65
|
request.body = Misty.to_json(data)
|
66
66
|
http(request)
|
data/lib/misty/misty.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'misty/services'
|
2
|
+
|
1
3
|
module Misty
|
2
4
|
HEADER_JSON = {
|
3
5
|
"Content-Type" => "application/json",
|
@@ -26,36 +28,28 @@ module Misty
|
|
26
28
|
# Default mode when SSL is used (uri.scheme == "https")
|
27
29
|
SSL_VERIFY_MODE = true
|
28
30
|
|
29
|
-
Service = Struct.new(:name, :project, :versions) do
|
30
|
-
def to_s
|
31
|
-
"#{name}: #{project} => #{versions}"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
SERVICES = []
|
36
|
-
SERVICES << Service.new(:alarming, :aodh, ["v2"])
|
37
|
-
SERVICES << Service.new(:baremetal, :ironic, ["v1"])
|
38
|
-
SERVICES << Service.new(:block_storage, :cinder, ["v3", "v1"])
|
39
|
-
SERVICES << Service.new(:clustering, :senlin, ["v1"])
|
40
|
-
SERVICES << Service.new(:compute, :nova, ["v2.1"])
|
41
|
-
SERVICES << Service.new(:container, :magnum, ["v1"])
|
42
|
-
SERVICES << Service.new(:data_processing, :sahara, ["v1.1"])
|
43
|
-
SERVICES << Service.new(:data_protection, :karbor, ["v1"])
|
44
|
-
SERVICES << Service.new(:database, :trove, ["v1.0"])
|
45
|
-
SERVICES << Service.new(:dns, :designate, ["v2"])
|
46
|
-
SERVICES << Service.new(:identity, :keystone, ["v3", "v2.0"])
|
47
|
-
SERVICES << Service.new(:image, :glance, ["v2", "v1"])
|
48
|
-
SERVICES << Service.new(:messaging, :zaqar, ["v2"])
|
49
|
-
SERVICES << Service.new(:metering, :ceilometer, ["v2"])
|
50
|
-
SERVICES << Service.new(:network, :neutron, ["v2.0"])
|
51
|
-
SERVICES << Service.new(:object_storage, :swift, ["v1"])
|
52
|
-
SERVICES << Service.new(:orchestration, :heat, ["v1"])
|
53
|
-
SERVICES << Service.new(:search, :searchlight, ["v1"])
|
54
|
-
SERVICES << Service.new(:shared_file_systems, :manila, ["v2"])
|
55
|
-
SERVICES.freeze
|
56
|
-
|
57
31
|
def self.services
|
58
|
-
|
32
|
+
services = Misty::Services.new
|
33
|
+
services.add(:alarming, :aodh, ["v2"])
|
34
|
+
services.add(:baremetal, :ironic, ["v1"])
|
35
|
+
services.add(:block_storage, :cinder, ["v3", "v1"])
|
36
|
+
services.add(:clustering, :senlin, ["v1"])
|
37
|
+
services.add(:compute, :nova, ["v2.1"])
|
38
|
+
services.add(:container, :magnum, ["v1"])
|
39
|
+
services.add(:data_processing, :sahara, ["v1.1"])
|
40
|
+
services.add(:data_protection, :karbor, ["v1"])
|
41
|
+
services.add(:database, :trove, ["v1.0"])
|
42
|
+
services.add(:dns, :designate, ["v2"])
|
43
|
+
services.add(:identity, :keystone, ["v3", "v2.0"])
|
44
|
+
services.add(:image, :glance, ["v2", "v1"])
|
45
|
+
services.add(:messaging, :zaqar, ["v2"])
|
46
|
+
services.add(:metering, :ceilometer, ["v2"])
|
47
|
+
services.add(:network, :neutron, ["v2.0"])
|
48
|
+
services.add(:object_storage, :swift, ["v1"])
|
49
|
+
services.add(:orchestration, :heat, ["v1"])
|
50
|
+
services.add(:search, :searchlight, ["v1"])
|
51
|
+
services.add(:shared_file_systems, :manila, ["v2"])
|
52
|
+
services
|
59
53
|
end
|
60
54
|
|
61
55
|
def self.to_json(data)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Misty
|
2
|
+
class Services
|
3
|
+
class Service
|
4
|
+
attr_reader :name, :options, :project, :versions, :version
|
5
|
+
|
6
|
+
def initialize(name, project, versions)
|
7
|
+
@name = name
|
8
|
+
@project = project
|
9
|
+
@versions = versions
|
10
|
+
@options = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def options=(val)
|
14
|
+
@options = val
|
15
|
+
end
|
16
|
+
|
17
|
+
def version=(val)
|
18
|
+
if @versions.include?(val)
|
19
|
+
@version = val
|
20
|
+
else
|
21
|
+
# Use highest version
|
22
|
+
@version = versions.sort[-1]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
"#{name}: #{project} => #{versions}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
include Enumerable
|
32
|
+
|
33
|
+
attr_reader :services
|
34
|
+
|
35
|
+
def initialize
|
36
|
+
@services = []
|
37
|
+
end
|
38
|
+
|
39
|
+
def add(*args)
|
40
|
+
@services << Service.new(*args)
|
41
|
+
end
|
42
|
+
|
43
|
+
def each
|
44
|
+
@services.each do |service|
|
45
|
+
yield service
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/misty/version.rb
CHANGED
data/test/unit/auth_test.rb
CHANGED
@@ -2,11 +2,16 @@ require 'test_helper'
|
|
2
2
|
require 'auth_helper'
|
3
3
|
|
4
4
|
describe Misty::Auth do
|
5
|
-
let(:
|
5
|
+
let(:config) do
|
6
|
+
config = Misty::Cloud::Config.new
|
7
|
+
config.log = Logger.new('/dev/null')
|
8
|
+
config.ssl_verify_mode = false
|
9
|
+
config
|
10
|
+
end
|
6
11
|
|
7
12
|
describe Misty::AuthV3 do
|
8
13
|
describe "#new" do
|
9
|
-
it "authenticates using project scoped authorization" do
|
14
|
+
it "authenticates with password using project scoped authorization" do
|
10
15
|
auth = {
|
11
16
|
:url => "http://localhost:5000",
|
12
17
|
:user_id => "user_id",
|
@@ -19,10 +24,10 @@ describe Misty::Auth do
|
|
19
24
|
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/json'}).
|
20
25
|
to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
|
21
26
|
|
22
|
-
Misty::AuthV3.new(auth,
|
27
|
+
Misty::AuthV3.new(auth, config)
|
23
28
|
end
|
24
29
|
|
25
|
-
it "authenticates using domain scoped authorization" do
|
30
|
+
it "authenticates with password using domain scoped authorization" do
|
26
31
|
auth = {
|
27
32
|
:url => "http://localhost:5000",
|
28
33
|
:user_id => "user_id",
|
@@ -34,7 +39,36 @@ describe Misty::Auth do
|
|
34
39
|
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/json'}).
|
35
40
|
to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
|
36
41
|
|
37
|
-
Misty::AuthV3.new(auth,
|
42
|
+
Misty::AuthV3.new(auth, config)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "authenticates with token using project scoped authorization" do
|
46
|
+
auth = {
|
47
|
+
:url => "http://localhost:5000",
|
48
|
+
:token => "exampletoken",
|
49
|
+
:project_id => "project_id"
|
50
|
+
}
|
51
|
+
|
52
|
+
stub_request(:post, "http://localhost:5000/v3/auth/tokens").
|
53
|
+
with(:body => "{\"auth\":{\"identity\":{\"methods\":[\"token\"],\"token\":{\"id\":\"exampletoken\"}},\"scope\":{\"project\":{\"id\":\"project_id\"}}}}",
|
54
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/json'}).
|
55
|
+
to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
|
56
|
+
|
57
|
+
Misty::AuthV3.new(auth, config)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "authenticates with token using domain scoped authorization" do
|
61
|
+
auth = {
|
62
|
+
:url => "http://localhost:5000",
|
63
|
+
:token => "exampletoken",
|
64
|
+
}
|
65
|
+
|
66
|
+
stub_request(:post, "http://localhost:5000/v3/auth/tokens").
|
67
|
+
with(:body => "{\"auth\":{\"identity\":{\"methods\":[\"token\"],\"token\":{\"id\":\"exampletoken\"}},\"scope\":{\"domain\":{\"id\":\"default\"}}}}",
|
68
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/json'}).
|
69
|
+
to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
|
70
|
+
|
71
|
+
Misty::AuthV3.new(auth, config)
|
38
72
|
end
|
39
73
|
end
|
40
74
|
|
@@ -53,15 +87,15 @@ describe Misty::Auth do
|
|
53
87
|
to_return(:status => 200, :body => "{\"token\":{\"catalog\":[]}}", :headers => {"x-subject-token"=>"token_data"})
|
54
88
|
|
55
89
|
proc do
|
56
|
-
Misty::AuthV3.new({},
|
57
|
-
end.must_raise Misty::Auth::
|
90
|
+
Misty::AuthV3.new({}, config)
|
91
|
+
end.must_raise Misty::Auth::URLError
|
58
92
|
end
|
59
93
|
|
60
94
|
it "#get_token" do
|
61
95
|
stub_request(:post, "http://localhost:5000/v3/auth/tokens").
|
62
96
|
to_return(:status => 200, :body => "{\"token\":{\"catalog\":[\"catalog_data\"]}}", :headers => {"x-subject-token"=>"token_data"})
|
63
97
|
|
64
|
-
auth = Misty::AuthV3.new(authv3_creds,
|
98
|
+
auth = Misty::AuthV3.new(authv3_creds, config)
|
65
99
|
auth.stub :expired?, false do
|
66
100
|
auth.get_token.must_equal "token_data"
|
67
101
|
end
|
@@ -71,7 +105,7 @@ describe Misty::Auth do
|
|
71
105
|
stub_request(:post, "http://localhost:5000/v3/auth/tokens").
|
72
106
|
to_return(:status => 200, :body => "{\"token\":{\"catalog\":[\"catalog_data\"]}}", :headers => {"x-subject-token"=>"token_data"})
|
73
107
|
|
74
|
-
auth = Misty::AuthV3.new(authv3_creds,
|
108
|
+
auth = Misty::AuthV3.new(authv3_creds, config)
|
75
109
|
auth.catalog.must_equal ["catalog_data"]
|
76
110
|
end
|
77
111
|
|
@@ -79,7 +113,7 @@ describe Misty::Auth do
|
|
79
113
|
stub_request(:post, "http://localhost:5000/v3/auth/tokens").
|
80
114
|
to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
|
81
115
|
|
82
|
-
auth = Misty::AuthV3.new(authv3_creds,
|
116
|
+
auth = Misty::AuthV3.new(authv3_creds, config)
|
83
117
|
auth.get_endpoint(%w{identity}, "regionOne", "public").must_equal "http://localhost"
|
84
118
|
end
|
85
119
|
end
|
@@ -92,8 +126,8 @@ describe Misty::Auth do
|
|
92
126
|
to_return(:status => 200, :body => "{\"access\":{\"token\":{\"id\":\"token_data\"}}}", :headers => {})
|
93
127
|
|
94
128
|
proc do
|
95
|
-
Misty::AuthV2.new({},
|
96
|
-
end.must_raise Misty::Auth::
|
129
|
+
Misty::AuthV2.new({}, config)
|
130
|
+
end.must_raise Misty::Auth::URLError
|
97
131
|
end
|
98
132
|
end
|
99
133
|
|
@@ -111,7 +145,7 @@ describe Misty::Auth do
|
|
111
145
|
stub_request(:post, "http://localhost:5000/v2.0/tokens").
|
112
146
|
to_return(:status => 200, :body => "{\"access\":{\"token\":{\"id\":\"token_data\"},\"serviceCatalog\":[\"catalog_data\"]}}", :headers => {})
|
113
147
|
|
114
|
-
auth = Misty::AuthV2.new(authv2_creds,
|
148
|
+
auth = Misty::AuthV2.new(authv2_creds, config)
|
115
149
|
auth.stub :expired?, false do
|
116
150
|
auth.get_token.must_equal "token_data"
|
117
151
|
end
|
@@ -121,7 +155,7 @@ describe Misty::Auth do
|
|
121
155
|
stub_request(:post, "http://localhost:5000/v2.0/tokens").
|
122
156
|
to_return(:status => 200, :body => "{\"access\":{\"token\":{\"id\":\"token_data\"},\"serviceCatalog\":[\"catalog_data\"]}}", :headers => {})
|
123
157
|
|
124
|
-
auth = Misty::AuthV2.new(authv2_creds,
|
158
|
+
auth = Misty::AuthV2.new(authv2_creds, config)
|
125
159
|
auth.catalog.must_equal ["catalog_data"]
|
126
160
|
end
|
127
161
|
|
@@ -129,7 +163,7 @@ describe Misty::Auth do
|
|
129
163
|
stub_request(:post, "http://localhost:5000/v2.0/tokens").
|
130
164
|
to_return(:status => 200, :body => JSON.dump(auth_response_v2("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
|
131
165
|
|
132
|
-
auth = Misty::AuthV2.new(authv2_creds,
|
166
|
+
auth = Misty::AuthV2.new(authv2_creds, config)
|
133
167
|
auth.get_endpoint(%w{identity}, "regionOne", "public").must_equal "http://localhost"
|
134
168
|
end
|
135
169
|
end
|
data/test/unit/cloud_test.rb
CHANGED
@@ -27,57 +27,55 @@ describe Misty::Cloud do
|
|
27
27
|
|
28
28
|
it "uses default version" do
|
29
29
|
cloud = Misty::Cloud.new(:auth => auth)
|
30
|
-
cloud.
|
31
|
-
end
|
32
|
-
|
33
|
-
it "uses provided version" do
|
34
|
-
cloud = Misty::Cloud.new(:auth => auth, :identity => {:api_version => "v2.0"})
|
35
|
-
cloud.services[:identity].must_equal ({:keystone => "v2.0"})
|
30
|
+
cloud.identity.must_be_kind_of Misty::Openstack::Keystone::V3
|
36
31
|
end
|
37
32
|
|
38
33
|
it "uses default version when provided version is out of range" do
|
39
34
|
cloud = Misty::Cloud.new(:auth => auth, :identity => {:api_version => "v1"})
|
40
|
-
cloud.
|
35
|
+
cloud.identity.must_be_kind_of Misty::Openstack::Keystone::V3
|
36
|
+
end
|
37
|
+
|
38
|
+
it "uses provided version" do
|
39
|
+
cloud = Misty::Cloud.new(:auth => auth, :identity => {:api_version => "v2.0"})
|
40
|
+
cloud.identity.must_be_kind_of Misty::Openstack::Keystone::V2_0
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
describe "
|
45
|
-
it "
|
46
|
-
Misty::
|
44
|
+
describe "Each service" do
|
45
|
+
it "has a method defined" do
|
46
|
+
Misty::services.each do |service|
|
47
47
|
method = Misty::Cloud.method_defined?(service.name)
|
48
48
|
method.must_equal true
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
describe "#
|
53
|
+
describe "#config" do
|
54
54
|
it "sets up default values" do
|
55
55
|
Misty::Auth.stub :factory, nil do
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
setup.region_id.must_equal Misty::REGION_ID
|
64
|
-
setup.ssl_verify_mode.must_equal Misty::SSL_VERIFY_MODE
|
56
|
+
config = Misty::Cloud.set_configuration({})
|
57
|
+
config.must_be_kind_of Misty::Cloud::Config
|
58
|
+
config.content_type.must_equal Misty::CONTENT_TYPE
|
59
|
+
config.log.must_be_kind_of Logger
|
60
|
+
config.interface.must_equal Misty::INTERFACE
|
61
|
+
config.region_id.must_equal Misty::REGION_ID
|
62
|
+
config.ssl_verify_mode.must_equal Misty::SSL_VERIFY_MODE
|
65
63
|
end
|
66
64
|
end
|
67
65
|
end
|
68
66
|
|
69
67
|
describe "#new" do
|
70
68
|
describe "fails" do
|
71
|
-
it "when no
|
69
|
+
it "when no parameters" do
|
72
70
|
proc do
|
73
71
|
Misty::Cloud.new
|
74
|
-
end.must_raise
|
72
|
+
end.must_raise ArgumentError
|
75
73
|
end
|
76
74
|
|
77
75
|
it "with empty credentials" do
|
78
76
|
proc do
|
79
77
|
Misty::Cloud.new(:auth => {})
|
80
|
-
end.must_raise Misty::Auth::
|
78
|
+
end.must_raise Misty::Auth::URLError
|
81
79
|
end
|
82
80
|
|
83
81
|
it "with incomplete credentials" do
|
@@ -42,8 +42,7 @@ describe Misty::HTTP::Client do
|
|
42
42
|
describe "#net_http" do
|
43
43
|
it "returns a Net/http instance" do
|
44
44
|
endpoint = URI.parse("http://localhost")
|
45
|
-
|
46
|
-
service.send(:net_http, endpoint, proxy, false, Logger.new("/dev/null")).must_be_instance_of Net::HTTP
|
45
|
+
service.send(:net_http, endpoint, false, Logger.new("/dev/null")).must_be_instance_of Net::HTTP
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
@@ -122,12 +122,23 @@ describe Misty::HTTP::MethodBuilder do
|
|
122
122
|
service.send(:query_param, "name=foobar").must_equal "?name=foobar"
|
123
123
|
end
|
124
124
|
|
125
|
-
it "returns
|
126
|
-
service.send(:query_param, "").
|
125
|
+
it "returns empty string when passing an empty String" do
|
126
|
+
service.send(:query_param, "").must_equal ""
|
127
127
|
end
|
128
128
|
|
129
|
-
it "returns
|
130
|
-
service.send(:query_param,
|
129
|
+
it "returns a query string when passing in a Hash" do
|
130
|
+
service.send(:query_param, {}).must_equal ''
|
131
|
+
|
132
|
+
service.send(:query_param, {:foo => 'bar'}).must_equal '?foo=bar'
|
133
|
+
service.send(:query_param, {'foo' => 'bar'}).must_equal '?foo=bar'
|
134
|
+
|
135
|
+
service.send(:query_param, {:foo => ['bar', 'baz'], :value => 42, :flag => nil }).must_equal '?foo=bar&foo=baz&value=42&flag'
|
136
|
+
|
137
|
+
service.send(:query_param, {'===' => 'Ëncøding is hárd!'}).must_equal '?%3D%3D%3D=%C3%8Bnc%C3%B8ding+is+h%C3%A1rd%21'
|
138
|
+
end
|
139
|
+
|
140
|
+
it "returns nil unless passing a String or Hash" do
|
141
|
+
service.send(:query_param, 42).must_be_nil
|
131
142
|
end
|
132
143
|
end
|
133
144
|
end
|
data/test/unit/misty_test.rb
CHANGED
@@ -1,15 +1,116 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
+
def validate(service)
|
4
|
+
service.must_be_kind_of Misty::Services::Service
|
5
|
+
service.name.must_be_kind_of Symbol
|
6
|
+
service.project.must_be_kind_of Symbol
|
7
|
+
service.versions.must_be_kind_of Array
|
8
|
+
service.versions.each do |version|
|
9
|
+
version.must_be_kind_of String
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
3
13
|
describe Misty do
|
4
|
-
describe "
|
5
|
-
it "has
|
6
|
-
Misty::
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
14
|
+
describe "#set_services" do
|
15
|
+
it "has alarming service" do
|
16
|
+
service = Misty::services.find { |s| s.name == :alarming}
|
17
|
+
validate(service)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "has baremetal service" do
|
21
|
+
service = Misty::services.find { |s| s.name == :baremetal}
|
22
|
+
validate(service)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "has block_storage service" do
|
26
|
+
service = Misty::services.find { |s| s.name == :block_storage}
|
27
|
+
validate(service)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "has clustering service" do
|
31
|
+
service = Misty::services.find { |s| s.name == :clustering}
|
32
|
+
validate(service)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "has compute service" do
|
36
|
+
service = Misty::services.find { |s| s.name == :compute}
|
37
|
+
validate(service)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "has container service" do
|
41
|
+
service = Misty::services.find { |s| s.name == :container}
|
42
|
+
validate(service)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "has data_processing service" do
|
46
|
+
service = Misty::services.find { |s| s.name == :data_processing}
|
47
|
+
validate(service)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "has data_protection service" do
|
51
|
+
service = Misty::services.find { |s| s.name == :data_protection}
|
52
|
+
validate(service)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "has database service" do
|
56
|
+
service = Misty::services.find { |s| s.name == :database}
|
57
|
+
validate(service)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "has dns service" do
|
61
|
+
service = Misty::services.find { |s| s.name == :dns}
|
62
|
+
validate(service)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "has identity service" do
|
66
|
+
service = Misty::services.find { |s| s.name == :identity}
|
67
|
+
validate(service)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "has image service" do
|
71
|
+
service = Misty::services.find { |s| s.name == :image}
|
72
|
+
validate(service)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "has messaging service" do
|
76
|
+
service = Misty::services.find { |s| s.name == :messaging}
|
77
|
+
validate(service)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "has metering service" do
|
81
|
+
service = Misty::services.find { |s| s.name == :metering}
|
82
|
+
validate(service)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "has network service" do
|
86
|
+
service = Misty::services.find { |s| s.name == :network}
|
87
|
+
validate(service)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "has object_storage service" do
|
91
|
+
service = Misty::services.find { |s| s.name == :object_storage}
|
92
|
+
validate(service)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "has orchestration service" do
|
96
|
+
service = Misty::services.find { |s| s.name == :orchestration}
|
97
|
+
validate(service)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "has search service" do
|
101
|
+
service = Misty::services.find { |s| s.name == :search}
|
102
|
+
validate(service)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "has shared_file_systems service" do
|
106
|
+
service = Misty::services.find { |s| s.name == :shared_file_systems}
|
107
|
+
validate(service)
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#services" do
|
111
|
+
it "returns Services" do
|
112
|
+
services = Misty::services
|
113
|
+
services.must_be_kind_of Misty::Services
|
13
114
|
end
|
14
115
|
end
|
15
116
|
end
|
@@ -31,12 +31,10 @@ describe Misty::HTTP::Microversion do
|
|
31
31
|
"token_id"
|
32
32
|
end
|
33
33
|
|
34
|
-
setup = Misty::Cloud::
|
35
|
-
setup.auth = auth
|
34
|
+
setup = Misty::Cloud::Config.new
|
36
35
|
setup.content_type = :ruby
|
37
36
|
setup.log = Logger.new('/dev/null')
|
38
37
|
setup.interface = Misty::INTERFACE
|
39
|
-
setup.proxy = URI.parse('')
|
40
38
|
setup.region_id = Misty::REGION_ID
|
41
39
|
setup.ssl_verify_mode = Misty::SSL_VERIFY_MODE
|
42
40
|
|
@@ -44,7 +42,7 @@ describe Misty::HTTP::Microversion do
|
|
44
42
|
with(:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/json'}).
|
45
43
|
to_return(:status => 200, :body => JSON.dump(versions_data), :headers => {})
|
46
44
|
|
47
|
-
Misty::Openstack::Nova::V2_1.new(setup, {})
|
45
|
+
Misty::Openstack::Nova::V2_1.new(auth, setup, {})
|
48
46
|
end
|
49
47
|
|
50
48
|
describe "#version_get" do
|
data/test/unit/service_helper.rb
CHANGED
@@ -15,12 +15,10 @@ def service(content_type = :ruby)
|
|
15
15
|
"token_id"
|
16
16
|
end
|
17
17
|
|
18
|
-
setup = Misty::Cloud::
|
19
|
-
setup.auth = auth
|
18
|
+
setup = Misty::Cloud::Config.new
|
20
19
|
setup.content_type = content_type
|
21
20
|
setup.log = Logger.new('/dev/null')
|
22
21
|
setup.interface = Misty::INTERFACE
|
23
|
-
setup.proxy = URI.parse("")
|
24
22
|
setup.region_id = Misty::REGION_ID
|
25
23
|
setup.ssl_verify_mode = Misty::SSL_VERIFY_MODE
|
26
24
|
|
@@ -28,5 +26,5 @@ def service(content_type = :ruby)
|
|
28
26
|
with(:headers => request_header).
|
29
27
|
to_return(:status => 200, :body => "", :headers => {})
|
30
28
|
|
31
|
-
Misty::Openstack::Neutron::V2_0.new(setup, {})
|
29
|
+
Misty::Openstack::Neutron::V2_0.new(auth, setup, {})
|
32
30
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe "Services" do
|
4
|
+
describe "#add" do
|
5
|
+
it "Adds a service" do
|
6
|
+
services = Misty::Services.new
|
7
|
+
services.add(:name, :project, ["v1", "v2.0"])
|
8
|
+
services.services.size.must_equal 1
|
9
|
+
service = services.services[0]
|
10
|
+
service.must_be_kind_of Misty::Services::Service
|
11
|
+
service.name.must_equal :name
|
12
|
+
service.project.must_equal :project
|
13
|
+
service.versions.must_include "v1"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: misty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gilles Dubreuil
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -186,6 +186,7 @@ files:
|
|
186
186
|
- lib/misty/openstack/trove/v1_0.rb
|
187
187
|
- lib/misty/openstack/zaqar/v2.rb
|
188
188
|
- lib/misty/openstack/zaqar/zaqar_v2.rb
|
189
|
+
- lib/misty/services.rb
|
189
190
|
- lib/misty/version.rb
|
190
191
|
- test/integration/compute_test.rb
|
191
192
|
- test/integration/network_test.rb
|
@@ -208,6 +209,7 @@ files:
|
|
208
209
|
- test/unit/openstack/APIs_test.rb
|
209
210
|
- test/unit/openstack/microversion_test.rb
|
210
211
|
- test/unit/service_helper.rb
|
212
|
+
- test/unit/services_test.rb
|
211
213
|
- test/unit/test_helper.rb
|
212
214
|
homepage: https://github.com/flystack/misty
|
213
215
|
licenses:
|