misty 0.5.1 → 0.6.0
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 +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:
|