misty 1.3.3 → 1.4.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 +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
|