misty 1.3.3 → 1.4.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 +332 -267
- data/lib/misty.rb +1 -1
- data/lib/misty/auth.rb +17 -6
- data/lib/misty/auth/auth_v2.rb +3 -0
- data/lib/misty/auth/auth_v3.rb +13 -5
- data/lib/misty/auth/name.rb +3 -3
- data/lib/misty/client_pack.rb +2 -2
- data/lib/misty/cloud.rb +111 -76
- data/lib/misty/config.rb +138 -0
- data/lib/misty/{auth/errors.rb → errors.rb} +9 -1
- data/lib/misty/http/direct.rb +18 -1
- data/lib/misty/http/method_builder.rb +10 -17
- data/lib/misty/http/net_http.rb +1 -1
- data/lib/misty/http/request.rb +26 -14
- data/lib/misty/microversion.rb +22 -41
- data/lib/misty/misty.rb +14 -24
- data/lib/misty/openstack/cinder/v3.rb +8 -0
- data/lib/misty/openstack/ironic/v1.rb +8 -0
- data/lib/misty/openstack/magnum/v1.rb +5 -1
- data/lib/misty/openstack/manila/v2.rb +8 -0
- data/lib/misty/openstack/nova/v2_1.rb +13 -8
- data/lib/misty/openstack/service.rb +88 -0
- data/lib/misty/openstack/swift/v1.rb +2 -2
- data/lib/misty/service.rb +9 -12
- data/lib/misty/version.rb +1 -1
- data/test/integration/{network_test.rb → networking_test.rb} +8 -8
- data/test/integration/test_helper.rb +1 -0
- data/test/integration/vcr/{network_using_neutron_v2_0.yml → networking_using_neutron_v2_0.yml} +0 -0
- data/test/unit/auth/name_test.rb +31 -27
- data/test/unit/auth_helper.rb +4 -4
- data/test/unit/auth_test.rb +44 -30
- data/test/unit/cloud/config_test.rb +165 -0
- data/test/unit/cloud/requests_test.rb +0 -12
- data/test/unit/cloud/services_test.rb +41 -12
- data/test/unit/cloud_test.rb +35 -44
- data/test/unit/http/request_test.rb +1 -1
- data/test/unit/microversion_test.rb +59 -35
- data/test/unit/misty_test.rb +1 -1
- data/test/unit/openstack/service_test.rb +52 -0
- data/test/unit/service_helper.rb +23 -20
- data/test/unit/services_test.rb +1 -1
- data/test/unit/test_helper.rb +0 -4
- metadata +37 -22
- data/lib/misty/client.rb +0 -104
- data/test/unit/client_test.rb +0 -97
@@ -5,8 +5,16 @@ module Misty
|
|
5
5
|
class TokenError < StandardError; end
|
6
6
|
|
7
7
|
class ExpiryError < RuntimeError; end
|
8
|
-
class CredentialsError < RuntimeError; end
|
9
8
|
class InitError < RuntimeError; end
|
10
9
|
class URLError < RuntimeError; end
|
11
10
|
end
|
11
|
+
|
12
|
+
class Config
|
13
|
+
class CredentialsError < RuntimeError; end
|
14
|
+
class InvalidDataError < StandardError; end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Microversion
|
18
|
+
class VersionError < RuntimeError; end
|
19
|
+
end
|
12
20
|
end
|
data/lib/misty/http/direct.rb
CHANGED
@@ -1,7 +1,24 @@
|
|
1
1
|
module Misty
|
2
2
|
module HTTP
|
3
|
-
#
|
3
|
+
# Allows to submit http request wwith provided path and override base_path if needed
|
4
4
|
module Direct
|
5
|
+
|
6
|
+
# ==== Examples
|
7
|
+
# auth = { ... }
|
8
|
+
# cloud = Misty::Cloud.new(:auth => auth)
|
9
|
+
#
|
10
|
+
# net = cloud.network.get('/v2.0/networks')
|
11
|
+
# pp net.body
|
12
|
+
#
|
13
|
+
# id = cloud.identity.get('/')
|
14
|
+
# pp id.body
|
15
|
+
#
|
16
|
+
# servers = cloud.compute.get('/servers')
|
17
|
+
# pp servers.body
|
18
|
+
#
|
19
|
+
# img = cloud.image.get('/v1')
|
20
|
+
# pp img.body
|
21
|
+
|
5
22
|
def base_set(base_path)
|
6
23
|
base = base_path ? base_path : @base_path
|
7
24
|
end
|
@@ -21,13 +21,6 @@ module Misty
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def method_call(method, *args)
|
24
|
-
if args[-1].class == Misty::HTTP::Header
|
25
|
-
header = Misty::HTTP::Header.new(@headers.get.clone)
|
26
|
-
header.add(args.pop.get)
|
27
|
-
else
|
28
|
-
header = @headers
|
29
|
-
end
|
30
|
-
|
31
24
|
base, path = prefixed_path(method[:path])
|
32
25
|
size_path_parameters = count_path_params(path)
|
33
26
|
path_params = args[0, size_path_parameters]
|
@@ -37,26 +30,26 @@ module Misty
|
|
37
30
|
|
38
31
|
case method[:request]
|
39
32
|
when :COPY
|
40
|
-
http_copy(final_path,
|
33
|
+
http_copy(final_path, @request_headers.get)
|
41
34
|
when :DELETE
|
42
|
-
http_delete(final_path,
|
35
|
+
http_delete(final_path, @request_headers.get)
|
43
36
|
when :GET
|
44
37
|
final_path << query_param(args_left.shift) if args_left && args_left.size == 1
|
45
|
-
http_get(final_path,
|
38
|
+
http_get(final_path, @request_headers.get)
|
46
39
|
when :HEAD
|
47
|
-
http_head(final_path,
|
40
|
+
http_head(final_path, @request_headers.get)
|
48
41
|
when :POST
|
49
42
|
final_path << query_param(args_left.shift) if args_left && args_left.size == 2
|
50
|
-
data = process_data(
|
51
|
-
http_post(final_path,
|
43
|
+
data = process_data(@request_headers, args_left)
|
44
|
+
http_post(final_path, @request_headers.get, data)
|
52
45
|
when :PUT
|
53
46
|
final_path << query_param(args_left.shift) if args_left && args_left.size == 2
|
54
|
-
data = process_data(
|
55
|
-
http_put(final_path,
|
47
|
+
data = process_data(@request_headers, args_left)
|
48
|
+
http_put(final_path, @request_headers.get, data)
|
56
49
|
when :PATCH
|
57
50
|
final_path << query_param(args_left.shift) if args_left && args_left.size == 2
|
58
|
-
data = process_data(
|
59
|
-
http_patch(final_path,
|
51
|
+
data = process_data(@request_headers, args_left)
|
52
|
+
http_patch(final_path, @request_headers.get, data)
|
60
53
|
else
|
61
54
|
raise SyntaxError, "Invalid HTTP request: #{method[:request]}"
|
62
55
|
end
|
data/lib/misty/http/net_http.rb
CHANGED
data/lib/misty/http/request.rb
CHANGED
@@ -1,21 +1,32 @@
|
|
1
1
|
module Misty
|
2
2
|
module HTTP
|
3
3
|
module Request
|
4
|
+
|
5
|
+
DECODE_TO_JSON = ["application/json", "application/octet-stream"].freeze
|
6
|
+
|
4
7
|
def decode?(response)
|
5
8
|
return false if response.body.nil? || response.body.empty?
|
6
|
-
if @
|
7
|
-
&& !response.is_a?(Net::
|
8
|
-
&& response.
|
9
|
+
if @request_content_type != :json && response.code =~ /2??/ \
|
10
|
+
&& !response.is_a?(Net::HTTPNoContent) \
|
11
|
+
&& !response.is_a?(Net::HTTPResetContent) \
|
12
|
+
&& response.header['content-type'] && decode_to_json?(response.header['content-type'])
|
9
13
|
return true
|
10
14
|
end
|
11
15
|
false
|
12
16
|
end
|
13
17
|
|
18
|
+
def decode_to_json?(content_type)
|
19
|
+
DECODE_TO_JSON.each do |type|
|
20
|
+
return true if content_type.include?(type)
|
21
|
+
end
|
22
|
+
false
|
23
|
+
end
|
24
|
+
|
14
25
|
def http(request)
|
15
26
|
request['X-Auth-Token'] = @auth.get_token
|
16
27
|
|
17
28
|
Misty::HTTP::NetHTTP.http_request(
|
18
|
-
@uri, ssl_verify_mode: @
|
29
|
+
@uri, ssl_verify_mode: @ssl_verify_mode, log: @log
|
19
30
|
) do |connection|
|
20
31
|
response = connection.request(request)
|
21
32
|
response.body = JSON.parse(response.body) if decode?(response)
|
@@ -24,59 +35,60 @@ module Misty
|
|
24
35
|
end
|
25
36
|
|
26
37
|
def http_delete(path, headers)
|
27
|
-
@
|
38
|
+
@log.info(http_to_s('DELETE', path, headers))
|
28
39
|
request = Net::HTTP::Delete.new(path, headers)
|
29
40
|
http(request)
|
30
41
|
end
|
31
42
|
|
32
43
|
def http_copy(path, headers)
|
33
|
-
@
|
44
|
+
@log.info(http_to_s('COPY', path, headers))
|
34
45
|
request = Net::HTTP::Copy.new(path, headers)
|
35
46
|
http(request)
|
36
47
|
end
|
37
48
|
|
38
49
|
def http_get(path, headers)
|
39
|
-
@
|
50
|
+
@log.info(http_to_s('GET', path, headers))
|
40
51
|
request = Net::HTTP::Get.new(path, headers)
|
41
52
|
http(request)
|
42
53
|
end
|
43
54
|
|
44
55
|
def http_head(path, headers)
|
45
|
-
@
|
56
|
+
@log.info(http_to_s('HEAD', path, headers))
|
46
57
|
request = Net::HTTP::Head.new(path, headers)
|
47
58
|
http(request)
|
48
59
|
end
|
49
60
|
|
50
61
|
def http_options(path, headers)
|
51
|
-
@
|
62
|
+
@log.info(http_to_s('OPTIONS', path, headers))
|
52
63
|
request = Net::HTTP::Options.new(path, headers)
|
53
64
|
http(request)
|
54
65
|
end
|
55
66
|
|
56
67
|
def http_patch(path, headers, data)
|
57
|
-
@
|
68
|
+
@log.info(http_to_s('PATCH', path, headers, data))
|
58
69
|
request = Net::HTTP::Patch.new(path, headers)
|
59
70
|
request.body = data
|
60
71
|
http(request)
|
61
72
|
end
|
62
73
|
|
63
74
|
def http_post(path, headers, data)
|
64
|
-
@
|
75
|
+
@log.info(http_to_s('POST', path, headers, data))
|
65
76
|
request = Net::HTTP::Post.new(path, headers)
|
66
77
|
request.body = data
|
67
78
|
http(request)
|
68
79
|
end
|
69
80
|
|
70
81
|
def http_put(path, headers, data)
|
71
|
-
@
|
82
|
+
@log.info(http_to_s('PUT', path, headers, data))
|
72
83
|
request = Net::HTTP::Put.new(path, headers)
|
73
84
|
request.body = data
|
74
85
|
http(request)
|
75
86
|
end
|
76
87
|
|
77
|
-
def http_to_s(path, headers, data = nil)
|
78
|
-
log = "base_url='#{@uri.host}:#{@uri.port}', path='#{path}', header=#{headers}"
|
88
|
+
def http_to_s(verb, path, headers, data = nil)
|
89
|
+
log = "HTTP #{verb} base_url='#{@uri.host}:#{@uri.port}', path='#{path}', header=#{headers}"
|
79
90
|
log << ", data='#{data}'" if data
|
91
|
+
log
|
80
92
|
end
|
81
93
|
end
|
82
94
|
end
|
data/lib/misty/microversion.rb
CHANGED
@@ -1,54 +1,28 @@
|
|
1
1
|
module Misty
|
2
|
+
# Handles OpenStack Services supporting Microversion feature
|
2
3
|
module Microversion
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def microversion_header
|
14
|
-
{'X-Openstack-API-Version' => "#{baseclass.downcase} #{@version}" }
|
15
|
-
end
|
16
|
-
|
17
|
-
def version_get(version_option)
|
18
|
-
if VERSION_STATES.include?(version_option)
|
19
|
-
return version_by_state(version_option)
|
4
|
+
def set_version(version)
|
5
|
+
case version
|
6
|
+
when nil || ''
|
7
|
+
# TODO:
|
8
|
+
# version_discovery
|
9
|
+
when 'latest'
|
10
|
+
'latest'
|
11
|
+
when /^([1-9]+\d*)\.([1-9]+\d*)$/
|
12
|
+
version if version_match(version)
|
20
13
|
else
|
21
|
-
|
14
|
+
raise VersionError, ":version must be '<number.number>' or 'latest'"
|
22
15
|
end
|
23
16
|
end
|
24
17
|
|
25
|
-
def
|
26
|
-
|
18
|
+
def microversion_header(version)
|
19
|
+
{'X-Openstack-API-Version' => "#{service_names[0]} #{version}" }
|
27
20
|
end
|
28
21
|
|
29
22
|
private
|
30
23
|
|
31
|
-
def
|
32
|
-
versions
|
33
|
-
return number if version['min_version'] <= number && version['version'] >= number
|
34
|
-
end
|
35
|
-
raise VersionError, "Version #{number} is out of range of available versions #{versions}"
|
36
|
-
end
|
37
|
-
|
38
|
-
def version_by_state(state)
|
39
|
-
version_details = nil
|
40
|
-
versions.each do |version|
|
41
|
-
if version['status'] == state
|
42
|
-
version_details = version
|
43
|
-
break
|
44
|
-
end
|
45
|
-
end
|
46
|
-
raise VersionError, "Version #{state} is not available among #{versions}" if version_details.nil?
|
47
|
-
if version_details['version'].empty?
|
48
|
-
@microversion = false
|
49
|
-
return ''
|
50
|
-
end
|
51
|
-
version_details['version']
|
24
|
+
def versions
|
25
|
+
@versions ||= versions_fetch
|
52
26
|
end
|
53
27
|
|
54
28
|
def versions_fetch
|
@@ -59,5 +33,12 @@ module Misty
|
|
59
33
|
raise VersionError, 'Missing version data' unless list
|
60
34
|
list
|
61
35
|
end
|
36
|
+
|
37
|
+
def version_match(number)
|
38
|
+
versions.each do |version|
|
39
|
+
return number if version['min_version'] <= number && version['version'] >= number
|
40
|
+
end
|
41
|
+
raise VersionError, "Version #{number} is out of range of available versions: #{versions}"
|
42
|
+
end
|
62
43
|
end
|
63
44
|
end
|
data/lib/misty/misty.rb
CHANGED
@@ -1,19 +1,23 @@
|
|
1
1
|
require 'misty/services'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
# Misty is a HTTP client for OpenStack APIs, aiming to be fast, flexible and exhaustive.
|
5
|
+
# Misty acts as a conduit to OpenStack APIs by handling requests as transparently as possible.
|
2
6
|
|
3
7
|
module Misty
|
4
8
|
SERVICES = [
|
5
9
|
{ name: :application_catalog, project: :murano, versions: ['v1']},
|
6
10
|
{ name: :alarming, project: :aodh, versions: ['v2']},
|
7
11
|
{ name: :backup, project: :freezer, versions: ['v1']},
|
8
|
-
{ name: :baremetal, project: :ironic, microversion: 'v1'},
|
9
|
-
{ name: :block_storage, project: :cinder,
|
12
|
+
{ name: :baremetal, project: :ironic, versions: ['v1'], microversion: 'v1'},
|
13
|
+
{ name: :block_storage, project: :cinder, versions: ['v3', 'v2', 'v1'], microversion: 'v3'},
|
10
14
|
{ name: :clustering, project: :senlin, versions: ['v1']},
|
11
|
-
{ name: :compute, project: :nova, microversion: 'v2.1'},
|
12
|
-
{ name: :container_infrastructure_management, project: :magnum, microversion: 'v1'},
|
15
|
+
{ name: :compute, project: :nova, versions: ['v2.1'], microversion: 'v2.1'},
|
16
|
+
{ name: :container_infrastructure_management, project: :magnum, versions: ['v1'], microversion: 'v1'},
|
13
17
|
{ name: :data_processing, project: :sahara, versions: ['v1.1']},
|
14
18
|
{ name: :data_protection_orchestration, project: :karbor, versions: ['v1']},
|
15
19
|
{ name: :database, project: :trove, versions: ['v1.0']},
|
16
|
-
{ name: :
|
20
|
+
{ name: :dns , project: :designate, versions: ['v2']},
|
17
21
|
{ name: :identity, project: :keystone, versions: ['v3', 'v2.0']},
|
18
22
|
{ name: :image, project: :glance, versions: ['v2', 'v1']},
|
19
23
|
{ name: :load_balancer, project: :octavia, versions: ['v2.0']},
|
@@ -24,30 +28,12 @@ module Misty
|
|
24
28
|
{ name: :object_storage, project: :swift, versions: ['v1']},
|
25
29
|
{ name: :orchestration, project: :heat, versions: ['v1']},
|
26
30
|
{ name: :search, project: :searchlight, versions: ['v1']},
|
27
|
-
{ name: :shared_file_systems, project: :manila, microversion: 'v2'}
|
31
|
+
{ name: :shared_file_systems, project: :manila, versions: ['v2'], microversion: 'v2'}
|
28
32
|
]
|
29
33
|
|
30
|
-
# Default REST content type. Use :json or :ruby
|
31
|
-
CONTENT_TYPE = :ruby
|
32
|
-
|
33
34
|
# Default Domain ID
|
34
35
|
DOMAIN_ID = 'default'
|
35
36
|
|
36
|
-
# Default Interface
|
37
|
-
INTERFACE = 'public'
|
38
|
-
|
39
|
-
# Default log file. Use :log_file option to override
|
40
|
-
LOG_FILE = 'misty.log'
|
41
|
-
|
42
|
-
# Default log level. Use :log_level option to override
|
43
|
-
LOG_LEVEL = Logger::INFO
|
44
|
-
|
45
|
-
# Default Region ID
|
46
|
-
REGION_ID = 'regionOne'
|
47
|
-
|
48
|
-
# Default when uri.scheme is https
|
49
|
-
SSL_VERIFY_MODE = true
|
50
|
-
|
51
37
|
def self.json_encode?(data)
|
52
38
|
return true if data.is_a?(Array) || data.is_a?(Hash)
|
53
39
|
if data.is_a?(String)
|
@@ -62,6 +48,10 @@ module Misty
|
|
62
48
|
return false
|
63
49
|
end
|
64
50
|
|
51
|
+
# Provides list of supported services
|
52
|
+
# ==== Example
|
53
|
+
# pp Misty.services
|
54
|
+
|
65
55
|
def self.services
|
66
56
|
services = Misty::Services.new
|
67
57
|
SERVICES.each do |service|
|
@@ -10,6 +10,14 @@ module Misty
|
|
10
10
|
include Misty::ClientPack
|
11
11
|
include Misty::Microversion
|
12
12
|
|
13
|
+
def microversion
|
14
|
+
'3.44'
|
15
|
+
end
|
16
|
+
|
17
|
+
def microversion_header(version)
|
18
|
+
{'X-Openstack-Cinder-API-Version' => "#{version}"}
|
19
|
+
end
|
20
|
+
|
13
21
|
def prefix_path_to_ignore
|
14
22
|
'/v3/{tenant_id}'
|
15
23
|
end
|
@@ -10,6 +10,14 @@ module Misty
|
|
10
10
|
include Misty::ClientPack
|
11
11
|
include Misty::Microversion
|
12
12
|
|
13
|
+
def microversion
|
14
|
+
'1.32'
|
15
|
+
end
|
16
|
+
|
17
|
+
def microversion_header(version)
|
18
|
+
{'X-Openstack-Ironic-API-Version' => "#{version}"}
|
19
|
+
end
|
20
|
+
|
13
21
|
def service_names
|
14
22
|
%w{baremetal}
|
15
23
|
end
|
@@ -10,6 +10,14 @@ module Misty
|
|
10
10
|
include Misty::ClientPack
|
11
11
|
include Misty::Microversion
|
12
12
|
|
13
|
+
def microversion
|
14
|
+
'2.40'
|
15
|
+
end
|
16
|
+
|
17
|
+
def microversion_header(version)
|
18
|
+
{'X-Openstack-Manila-API-Version' => "#{version}"}
|
19
|
+
end
|
20
|
+
|
13
21
|
def service_names
|
14
22
|
%w{shared-file-systems shared}
|
15
23
|
end
|
@@ -20,16 +20,21 @@ module Misty
|
|
20
20
|
http_get("/#{version}", headers)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
23
|
+
def microversion
|
24
|
+
'2.60'
|
25
|
+
end
|
26
|
+
|
27
|
+
def microversion_header(version)
|
28
|
+
# Use default 'OpenStack-API-Version' or older 'X-Openstack-Nova-API-Version'
|
29
|
+
if @version >= '2.27'
|
30
|
+
super
|
31
|
+
else
|
32
|
+
{'X-Openstack-Nova-API-Version' => "#{version}"}
|
33
|
+
end
|
25
34
|
end
|
26
35
|
|
27
|
-
def
|
28
|
-
|
29
|
-
header = super
|
30
|
-
# For prior vesions then remove once depcrecated
|
31
|
-
header.merge!('X-Openstack-Nova-API-Version' => "#{@version}",)
|
32
|
-
header
|
36
|
+
def service_names
|
37
|
+
%w{compute}
|
33
38
|
end
|
34
39
|
end
|
35
40
|
end
|