misty 0.1.0 → 0.3.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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +222 -1
  3. data/lib/misty.rb +8 -0
  4. data/lib/misty/auth.rb +60 -0
  5. data/lib/misty/auth/auth_v2.rb +46 -0
  6. data/lib/misty/auth/auth_v3.rb +58 -0
  7. data/lib/misty/autoload.rb +82 -0
  8. data/lib/misty/cloud.rb +133 -0
  9. data/lib/misty/http/client.rb +115 -0
  10. data/lib/misty/http/direct.rb +26 -0
  11. data/lib/misty/http/method_builder.rb +96 -0
  12. data/lib/misty/http/request.rb +75 -0
  13. data/lib/misty/misty.rb +51 -0
  14. data/lib/misty/openstack/aodh/aodh_v2.rb +12 -0
  15. data/lib/misty/openstack/aodh/v2.rb +20 -0
  16. data/lib/misty/openstack/ceilometer/ceilometer_v2.rb +13 -0
  17. data/lib/misty/openstack/ceilometer/v2.rb +20 -0
  18. data/lib/misty/openstack/cinder/cinder_v1.rb +35 -0
  19. data/lib/misty/openstack/cinder/cinder_v3.rb +148 -0
  20. data/lib/misty/openstack/cinder/v1.rb +24 -0
  21. data/lib/misty/openstack/cinder/v3.rb +24 -0
  22. data/lib/misty/openstack/designate/designate_v2.rb +69 -0
  23. data/lib/misty/openstack/designate/v2.rb +20 -0
  24. data/lib/misty/openstack/glance/glance_v1.rb +16 -0
  25. data/lib/misty/openstack/glance/glance_v2.rb +29 -0
  26. data/lib/misty/openstack/glance/v1.rb +20 -0
  27. data/lib/misty/openstack/glance/v2.rb +20 -0
  28. data/lib/misty/openstack/heat/heat_v1.rb +85 -0
  29. data/lib/misty/openstack/heat/v1.rb +24 -0
  30. data/lib/misty/openstack/ironic/ironic_v1.rb +71 -0
  31. data/lib/misty/openstack/ironic/v1.rb +26 -0
  32. data/lib/misty/openstack/karbor/karbor_v1.rb +32 -0
  33. data/lib/misty/openstack/karbor/v1.rb +20 -0
  34. data/lib/misty/openstack/keystone/keystone_v2_0.rb +11 -0
  35. data/lib/misty/openstack/keystone/keystone_v2_0_ext.rb +32 -0
  36. data/lib/misty/openstack/keystone/keystone_v3.rb +147 -0
  37. data/lib/misty/openstack/keystone/keystone_v3_ext.rb +124 -0
  38. data/lib/misty/openstack/keystone/v2_0.rb +23 -0
  39. data/lib/misty/openstack/keystone/v3.rb +23 -0
  40. data/lib/misty/openstack/magnum/magnum_v1.rb +41 -0
  41. data/lib/misty/openstack/magnum/v1.rb +26 -0
  42. data/lib/misty/openstack/manila/manila_v2.rb +143 -0
  43. data/lib/misty/openstack/manila/v2.rb +26 -0
  44. data/lib/misty/openstack/microversion.rb +62 -0
  45. data/lib/misty/openstack/neutron/neutron_v2_0.rb +205 -0
  46. data/lib/misty/openstack/neutron/v2_0.rb +20 -0
  47. data/lib/misty/openstack/nova/nova_v2_1.rb +269 -0
  48. data/lib/misty/openstack/nova/v2_1.rb +40 -0
  49. data/lib/misty/openstack/sahara/sahara_v1_1.rb +77 -0
  50. data/lib/misty/openstack/sahara/v1_1.rb +20 -0
  51. data/lib/misty/openstack/searchlight/searchlight_v1.rb +15 -0
  52. data/lib/misty/openstack/searchlight/v1.rb +20 -0
  53. data/lib/misty/openstack/senlin/senlin_v1.rb +66 -0
  54. data/lib/misty/openstack/senlin/v1.rb +20 -0
  55. data/lib/misty/openstack/swift/swift_v1.rb +23 -0
  56. data/lib/misty/openstack/swift/v1.rb +20 -0
  57. data/lib/misty/openstack/trove/trove_v1_0.rb +51 -0
  58. data/lib/misty/openstack/trove/v1_0.rb +20 -0
  59. data/lib/misty/openstack/zaqar/v2.rb +20 -0
  60. data/lib/misty/openstack/zaqar/zaqar_v2.rb +46 -0
  61. data/lib/misty/version.rb +2 -2
  62. data/test/integration/compute_test.rb +35 -0
  63. data/test/integration/network_test.rb +34 -0
  64. data/test/integration/orchestration_test.rb +92 -0
  65. data/test/integration/test_helper.rb +19 -0
  66. data/test/integration/vcr/compute_using_nova_v2_1.yml +1107 -0
  67. data/test/integration/vcr/network_using_neutron_v2_0.yml +1029 -0
  68. data/test/integration/vcr/orchestration_using_heat_v1.yml +1457 -0
  69. data/test/unit/auth_helper.rb +52 -0
  70. data/test/unit/auth_test.rb +99 -0
  71. data/test/unit/cloud/requests_test.rb +113 -0
  72. data/test/unit/cloud/services_test.rb +171 -0
  73. data/test/unit/cloud_test.rb +145 -0
  74. data/test/unit/http/client_test.rb +74 -0
  75. data/test/unit/http/direct_test.rb +103 -0
  76. data/test/unit/http/method_builder_test.rb +133 -0
  77. data/test/unit/http/request_test.rb +123 -0
  78. data/test/unit/misty_test.rb +36 -0
  79. data/test/unit/openstack/APIs_test.rb +40 -0
  80. data/test/unit/openstack/microversion_test.rb +70 -0
  81. data/test/unit/service_helper.rb +25 -0
  82. data/test/unit/test_helper.rb +8 -0
  83. metadata +170 -5
@@ -0,0 +1,52 @@
1
+ def auth_response_v3(type, name)
2
+ { 'token' =>
3
+ { 'methods' => ['password'],
4
+ 'roles' => [{ 'id' => 'id_roles', 'name' => 'admin' }],
5
+ 'expires_at' => '2016-11-29T07:45:29.908554Z',
6
+ 'project' => { 'domain' => { 'id' => 'default', 'name' => 'Default' }, 'id' => 'id_project', 'name' => 'admin' },
7
+ 'catalog' =>
8
+ [{ 'endpoints' =>
9
+ [{ 'region_id' => 'regionOne',
10
+ 'url' => 'http://localhost',
11
+ 'region' => 'regionOne',
12
+ 'interface' => 'internal',
13
+ 'id' => 'id_endpoint_internal' },
14
+ { 'region_id' => 'regionOne',
15
+ 'url' => 'http://localhost',
16
+ 'region' => 'regionOne',
17
+ 'interface' => 'public',
18
+ 'id' => 'id_endpoint_public' },
19
+ { 'region_id' => 'regionOne',
20
+ 'url' => 'http://localhost',
21
+ 'region' => 'regionOne',
22
+ 'interface' => 'admin',
23
+ 'id' => 'id_endpoint_admin' }],
24
+ 'type' => type,
25
+ 'id' => 'id_endpoints',
26
+ 'name' => name }],
27
+ 'user' => { 'domain' => { 'id' => 'default', 'name' => 'Default' }, 'id' => 'id_user', 'name' => 'admin' },
28
+ 'audit_ids' => ['id_audits'],
29
+ 'issued_at' => '2016-11-29T06:45:29.908578Z' } }
30
+ end
31
+
32
+ def auth_response_v2(type, name)
33
+ { 'access' =>
34
+ { 'token' =>
35
+ { 'issued_at' => '2016-12-05T10:44:31.454741Z',
36
+ 'expires' => '2016-12-05T11:44:31Z',
37
+ 'id' => '4ae647d3a5294690a3c29bc658e17e26',
38
+ 'tenant' => { 'description' => 'admin tenant', 'enabled' => true, 'id' => 'tenant_id', 'name' => 'admin' },
39
+ 'audit_ids' => ['Ye0Rq1HzTk2ggUAg8nDGbQ'] },
40
+ 'serviceCatalog' =>
41
+ [{ 'endpoints' =>
42
+ [{ 'adminURL' => 'http://localhost',
43
+ 'region' => 'regionOne',
44
+ 'internalURL' => 'http://localhost',
45
+ 'id' => 'id_endpoints',
46
+ 'publicURL' => 'http://localhost' }],
47
+ 'endpoints_links' => [],
48
+ 'type' => type,
49
+ 'name' => name }],
50
+ 'user' => { 'username' => 'admin', 'roles_links' => [], 'id' => 'user_id', 'roles' => [{ 'name' => 'admin' }], 'name' => 'admin' },
51
+ 'metadata' => { 'is_admin' => 0, 'roles' => ['role_id'] } } }
52
+ end
@@ -0,0 +1,99 @@
1
+ require 'test_helper'
2
+ require 'auth_helper'
3
+
4
+ describe Misty::Auth do
5
+ describe ".new" do
6
+ let(:authv3_creds) do
7
+ {
8
+ :url => "http://localhost:5000",
9
+ :user => "admin",
10
+ :password => "secret",
11
+ :project => "admin",
12
+ :domain => "default"
13
+ }
14
+ end
15
+
16
+ let(:authv2_creds) do
17
+ {
18
+ :url => "http://localhost:5000",
19
+ :user => "admin",
20
+ :password => "secret",
21
+ :tenant => "admin"
22
+ }
23
+ end
24
+
25
+ describe Misty::AuthV3 do
26
+ it "#new fails when missing credentials" do
27
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
28
+ to_return(:status => 200, :body => "{\"token\":{\"catalog\":[]}}", :headers => {"x-subject-token"=>"token_data"})
29
+
30
+ proc do
31
+ Misty::AuthV3.new({})
32
+ end.must_raise Misty::Auth::CredentialsError
33
+ end
34
+
35
+ it "#get_token" do
36
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
37
+ to_return(:status => 200, :body => "{\"token\":{\"catalog\":[\"catalog_data\"]}}", :headers => {"x-subject-token"=>"token_data"})
38
+
39
+ auth = Misty::AuthV3.new(authv3_creds)
40
+ auth.stub :expired?, false do
41
+ auth.get_token.must_equal "token_data"
42
+ end
43
+ end
44
+
45
+ it "#catalog" do
46
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
47
+ to_return(:status => 200, :body => "{\"token\":{\"catalog\":[\"catalog_data\"]}}", :headers => {"x-subject-token"=>"token_data"})
48
+
49
+ auth = Misty::AuthV3.new(authv3_creds)
50
+ auth.catalog.must_equal ["catalog_data"]
51
+ end
52
+
53
+ it "#get_endpoint" do
54
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
55
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
56
+
57
+ auth = Misty::AuthV3.new(authv3_creds)
58
+ auth.get_endpoint(%w{identity}, "regionOne", "public").must_equal "http://localhost"
59
+ end
60
+ end
61
+
62
+ describe Misty::AuthV2 do
63
+ it "#new fails when missing credentials" do
64
+ stub_request(:post, "http://localhost:5000/v2.0/tokens").
65
+ to_return(:status => 200, :body => "{\"access\":{\"token\":{\"id\":\"token_data\"}}}", :headers => {})
66
+
67
+ proc do
68
+ Misty::AuthV2.new({})
69
+ end.must_raise Misty::Auth::CredentialsError
70
+ end
71
+
72
+ it "#get_token" do
73
+ stub_request(:post, "http://localhost:5000/v2.0/tokens").
74
+ to_return(:status => 200, :body => "{\"access\":{\"token\":{\"id\":\"token_data\"},\"serviceCatalog\":[\"catalog_data\"]}}", :headers => {})
75
+
76
+ auth = Misty::AuthV2.new(authv2_creds)
77
+ auth.stub :expired?, false do
78
+ auth.get_token.must_equal "token_data"
79
+ end
80
+ end
81
+
82
+ it "#catalog" do
83
+ stub_request(:post, "http://localhost:5000/v2.0/tokens").
84
+ to_return(:status => 200, :body => "{\"access\":{\"token\":{\"id\":\"token_data\"},\"serviceCatalog\":[\"catalog_data\"]}}", :headers => {})
85
+
86
+ auth = Misty::AuthV2.new(authv2_creds)
87
+ auth.catalog.must_equal ["catalog_data"]
88
+ end
89
+
90
+ it "#get_endpoint" do
91
+ stub_request(:post, "http://localhost:5000/v2.0/tokens").
92
+ to_return(:status => 200, :body => JSON.dump(auth_response_v2("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
93
+
94
+ auth = Misty::AuthV2.new(authv2_creds)
95
+ auth.get_endpoint(%w{identity}, "regionOne", "public").must_equal "http://localhost"
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,113 @@
1
+ require 'test_helper'
2
+ require 'auth_helper'
3
+
4
+ describe Misty::Cloud do
5
+ let(:cloud) do
6
+ auth = {
7
+ :url => "http://localhost:5000",
8
+ :user => "admin",
9
+ :password => "secret",
10
+ :project => "admin",
11
+ :domain => "default"
12
+ }
13
+
14
+ Misty::Cloud.new(:auth => auth)
15
+ end
16
+
17
+ describe "GET request" do
18
+ it "success without elements in path" do
19
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
20
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("network", "neutron")), :headers => {"x-subject-token"=>"token_data"})
21
+
22
+ stub_request(:get, "http://localhost/v2.0/networks").
23
+ to_return(:status => 200, :body => "list of networks", :headers => {})
24
+
25
+ cloud.network.list_networks.response.must_be_kind_of Net::HTTPOK
26
+ end
27
+
28
+ it "success adds the query option in path" do
29
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
30
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("network", "neutron")), :headers => {"x-subject-token"=>"token_data"})
31
+
32
+ stub_request(:get, "http://localhost/v2.0/networks?name=value").
33
+ to_return(:status => 200, :body => "list of networks", :headers => {})
34
+
35
+ cloud.network.list_networks("name=value").response.must_be_kind_of Net::HTTPOK
36
+ end
37
+
38
+ it "successful whith elements in path" do
39
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
40
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("image", "glance")), :headers => {"x-subject-token"=>"token_data"})
41
+
42
+ stub_request(:get, "http://localhost/v2/images/id1/members/id2").
43
+ to_return(:status => 200, :body => "list of images", :headers => {})
44
+
45
+ cloud.image.show_image_member_details("id1", "id2").response.must_be_kind_of Net::HTTPOK
46
+ end
47
+
48
+ it "fails when not enough arguments" do
49
+ proc do
50
+ # "/v2/images/{image_id}/members/{member_id}"
51
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
52
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("image", "glance")), :headers => {"x-subject-token"=>"token_data"})
53
+
54
+ cloud.image.show_image_member_details("id1")
55
+ end.must_raise ArgumentError
56
+ end
57
+ end
58
+
59
+ describe "POST request" do
60
+ it "successful without elements in path" do
61
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
62
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
63
+
64
+ stub_request(:post, "http://localhost/v3/projects").
65
+ to_return(:status => 201, :body => "list of projects", :headers => {})
66
+
67
+ cloud.identity.create_project("{\"project\":{\"name\":\"value\"}}").response.must_be_kind_of Net::HTTPCreated
68
+ end
69
+
70
+ it "sucessful whith elements in pathwhith elements in path" do
71
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
72
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("orchestration", "heat")), :headers => {"x-subject-token"=>"token_data"})
73
+
74
+ stub_request(:post, "http://localhost/stacks/id1/id2/snapshots").
75
+ to_return(:status => 201, :body => "snapshots", :headers => {})
76
+
77
+ cloud.orchestration.snapshot_a_stack("id1", "id2", "{\"key\": \"value\"}").response.must_be_kind_of Net::HTTPCreated
78
+ end
79
+
80
+ it "fails when not enough arguments" do
81
+ proc do
82
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
83
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("orchestration", "heat")), :headers => {"x-subject-token"=>"token_data"})
84
+
85
+ cloud.orchestration.snapshot_a_stack("id1")
86
+ end.must_raise ArgumentError
87
+ end
88
+ end
89
+
90
+ describe "DELETE request" do
91
+ it "success" do
92
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
93
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
94
+
95
+ stub_request(:delete, "http://localhost/v3/projects/project_id").
96
+ to_return(:status => 204, :body => "list of projects", :headers => {})
97
+
98
+ cloud.identity.delete_project("project_id").response.must_be_kind_of Net::HTTPNoContent
99
+ end
100
+ end
101
+
102
+ describe "PUT request" do
103
+ it "success" do
104
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
105
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
106
+
107
+ stub_request(:put, "http://localhost/v3/domains/domain_id/groups/group_id/roles/roles_id").
108
+ to_return(:status => 200, :body => "list of group/role for a domain", :headers => {})
109
+
110
+ cloud.identity.assign_role_to_group_on_domain("domain_id", "group_id", "roles_id").response.must_be_kind_of Net::HTTPOK
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,171 @@
1
+ require 'test_helper'
2
+ require 'auth_helper'
3
+
4
+ describe "Misty::Cloud" do
5
+ let(:cloud) do
6
+ auth = {
7
+ :url => "http://localhost:5000",
8
+ :user => "admin",
9
+ :password => "secret",
10
+ :project => "admin",
11
+ :domain => "default"
12
+ }
13
+
14
+ Misty::Cloud.new(:auth => auth)
15
+ end
16
+
17
+ let(:auth_body) do
18
+ { 'auth' => {
19
+ 'identity' => {
20
+ 'methods' => ['password'],
21
+ 'password' => {
22
+ 'user' => {
23
+ 'name' => 'admin',
24
+ 'domain' => { 'id' => 'default' },
25
+ 'password' => 'secret'
26
+ }
27
+ }
28
+ },
29
+ 'scope' => { 'project' => { 'name' => 'admin', 'domain' => { 'id' => 'default' } } }
30
+ } }
31
+ end
32
+
33
+ let(:auth_headers) do
34
+ { 'Accept' => 'application/json',
35
+ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
36
+ 'Content-Type' => 'application/json',
37
+ 'User-Agent' => 'Ruby' }
38
+ end
39
+
40
+ let(:versions) do
41
+ { 'versions' =>
42
+ [{ 'status' => 'SUPPORTED',
43
+ 'updated' => '2011-01-21T11:33:21Z',
44
+ 'links' => [{ 'href' => 'http://localhost/v2/', 'rel' => 'self' }],
45
+ 'min_version' => '',
46
+ 'version' => '',
47
+ 'id' => 'v2.0' },
48
+ { 'status' => 'CURRENT',
49
+ 'updated' => '2013-07-23T11:33:21Z',
50
+ 'links' => [{ 'href' => 'http://localhost/v2.1/', 'rel' => 'self' }],
51
+ 'min_version' => '2.1',
52
+ 'version' => '2.25',
53
+ 'id' => 'v2.1' }] }
54
+ end
55
+
56
+ let(:token_header) { {"x-subject-token"=>"token_data"} }
57
+
58
+ it "fails when method is missing" do
59
+ proc do
60
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
61
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
62
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("compute", "nova")), :headers => token_header)
63
+
64
+ stub_request(:get, "http://localhost/").
65
+ with(:headers => auth_headers).
66
+ to_return(:status => 200, :body => JSON.dump(versions), :headers => {})
67
+
68
+ cloud.compute.undefined_method
69
+ end.must_raise NoMethodError
70
+ end
71
+
72
+ it "#baremetal" do
73
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
74
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
75
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("baremetal", "ironic")), :headers => token_header)
76
+
77
+ stub_request(:get, "http://localhost/").
78
+ with(:headers => auth_headers).
79
+ to_return(:status => 200, :body => JSON.dump(versions), :headers => {})
80
+
81
+ cloud.baremetal.must_be_kind_of Misty::Openstack::Ironic::V1
82
+ end
83
+
84
+ it "#blockStorage" do
85
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
86
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
87
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("volume", "cinder")), :headers => token_header)
88
+
89
+ cloud.block_storage.must_be_kind_of Misty::Openstack::Cinder::V3
90
+ end
91
+
92
+ it "#compute" do
93
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
94
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
95
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("compute", "nova")), :headers => token_header)
96
+
97
+ stub_request(:get, "http://localhost/").
98
+ with(:headers => auth_headers).
99
+ to_return(:status => 200, :body => JSON.dump(versions), :headers => {})
100
+
101
+ cloud.compute.must_be_kind_of Misty::Openstack::Nova::V2_1
102
+ end
103
+
104
+ it "#dataProcessing" do
105
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
106
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
107
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("data-processing", "sahara")), :headers => token_header)
108
+
109
+ cloud.data_processing.must_be_kind_of Misty::Openstack::Sahara::V1_1
110
+ end
111
+
112
+ it "#identity" do
113
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
114
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
115
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => token_header)
116
+
117
+ cloud.identity.must_be_kind_of Misty::Openstack::Keystone::V3
118
+ end
119
+
120
+ it "#image" do
121
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
122
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
123
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("image", "glance")), :headers => token_header)
124
+
125
+ cloud.image.must_be_kind_of Misty::Openstack::Glance::V2
126
+ end
127
+
128
+ it "#network" do
129
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
130
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
131
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("network", "neutron")), :headers => token_header)
132
+
133
+ cloud.network.must_be_kind_of Misty::Openstack::Neutron::V2_0
134
+ end
135
+
136
+ it "#objectStorage" do
137
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
138
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
139
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("object-store", "swift")), :headers => token_header)
140
+
141
+ cloud.object_storage.must_be_kind_of Misty::Openstack::Swift::V1
142
+ end
143
+
144
+ it "#orchestration" do
145
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
146
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
147
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("orchestration", "heat")), :headers => token_header)
148
+
149
+ cloud.orchestration.must_be_kind_of Misty::Openstack::Heat::V1
150
+ end
151
+
152
+ it "#search" do
153
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
154
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
155
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("search", "searchlight")), :headers => token_header)
156
+
157
+ cloud.search.must_be_kind_of Misty::Openstack::Searchlight::V1
158
+ end
159
+
160
+ it "#sharedFileSystems" do
161
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
162
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
163
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("shared-file-systems", "manila")), :headers => token_header)
164
+
165
+ stub_request(:get, "http://localhost/").
166
+ with(:headers => auth_headers).
167
+ to_return(:status => 200, :body => JSON.dump(versions), :headers => {})
168
+
169
+ cloud.shared_file_systems.must_be_kind_of Misty::Openstack::Manila::V2
170
+ end
171
+ end
@@ -0,0 +1,145 @@
1
+ require 'test_helper'
2
+ require 'service_helper'
3
+ require 'auth_helper'
4
+
5
+ describe "#dot_to_underscore" do
6
+ it "returns a valid name" do
7
+ name = Misty::Cloud.dot_to_underscore("v20.90.01")
8
+ name.must_equal "v20_90_01"
9
+ end
10
+ end
11
+
12
+ describe Misty::Cloud do
13
+ describe "A service" do
14
+ let(:auth) do
15
+ stub_request(:post, "http://localhost:5000/v3/auth/tokens").
16
+ with(:body => "{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"name\":\"admin\",\"domain\":{\"id\":\"default\"},\"password\":\"secret\"}}},\"scope\":{\"project\":{\"name\":\"admin\",\"domain\":{\"id\":\"default\"}}}}}",
17
+ :headers => {'Accept'=>'application/json', 'Content-Type'=>'application/json', 'User-Agent'=>'Ruby'}).
18
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3("identity", "keystone")), :headers => {"x-subject-token"=>"token_data"})
19
+
20
+ auth = {
21
+ :url => "http://localhost:5000",
22
+ :user => "admin",
23
+ :password => "secret",
24
+ :project => "admin",
25
+ :domain => "default"
26
+ }
27
+ end
28
+
29
+ it "uses default version" do
30
+ cloud = Misty::Cloud.new(:auth => auth)
31
+ cloud.services[:identity].must_equal ({:keystone => "v3"})
32
+ end
33
+
34
+ it "uses provided version" do
35
+ cloud = Misty::Cloud.new(:auth => auth, :identity => {:api_version => "v2.0"})
36
+ cloud.services[:identity].must_equal ({:keystone => "v2.0"})
37
+ end
38
+
39
+ it "uses default version when provided version is out of range" do
40
+ cloud = Misty::Cloud.new(:auth => auth, :identity => {:api_version => "v1"})
41
+ cloud.services[:identity].must_equal ({:keystone => "v3"})
42
+ end
43
+ end
44
+
45
+ describe "All SERVICES" do
46
+ it "have a method defined" do
47
+ Misty::SERVICES.each do |service|
48
+ method = Misty::Cloud.method_defined?(service.name)
49
+ method.must_equal true
50
+ end
51
+ end
52
+ end
53
+
54
+ describe "#new" do
55
+ describe "fails" do
56
+ it "when no credentials" do
57
+ proc do
58
+ Misty::Cloud.new
59
+ end.must_raise Misty::Auth::CredentialsError
60
+ end
61
+
62
+ it "with empty credentials" do
63
+ proc do
64
+ Misty::Cloud.new(:auth => {})
65
+ end.must_raise Misty::Auth::CredentialsError
66
+ end
67
+
68
+ it "with incomplete credentials" do
69
+ proc do
70
+ Misty::Cloud.new(:auth => {:user => "user", :url => "http://localhost" })
71
+ end.must_raise Misty::Auth::CredentialsError
72
+ end
73
+
74
+ it "without url" do
75
+ authv3_data = {
76
+ :user => "admin",
77
+ :password => "secret",
78
+ :project => "admin",
79
+ :domain => "default"
80
+ }
81
+
82
+ proc do
83
+ Misty::Cloud.new(:auth => authv3_data)
84
+ end.must_raise Misty::Auth::URLError
85
+ end
86
+
87
+ it "with empty url" do
88
+ authv3_data = {
89
+ :url => "",
90
+ :user => "admin",
91
+ :password => "secret",
92
+ :project => "admin",
93
+ :domain => "default"
94
+ }
95
+
96
+ proc do
97
+ Misty::Cloud.new(:auth => authv3_data)
98
+ end.must_raise Misty::Auth::URLError
99
+ end
100
+ end
101
+
102
+ describe "Authenticates" do
103
+ describe "with v2 credentials" do
104
+ let(:authv2_data) do
105
+ {
106
+ :url => "http://localhost:5000",
107
+ :user => "admin",
108
+ :password => "secret",
109
+ :tenant => "admin"
110
+ }
111
+ end
112
+
113
+ it "uses AuthV2" do
114
+ authv2 = Minitest::Mock.new
115
+
116
+ Misty::AuthV2.stub :new, authv2 do
117
+ cloud = Misty::Cloud.new(:auth => authv2_data)
118
+ authv2.verify
119
+ end
120
+ end
121
+ end
122
+
123
+ describe "with v3 credentials" do
124
+ let(:authv3_data) do
125
+ {
126
+ :url => "http://localhost:5000",
127
+ :user => "admin",
128
+ :password => "secret",
129
+ :project => "admin",
130
+ :domain => "default"
131
+ }
132
+ end
133
+
134
+ it "uses AuthV3" do
135
+ authv3 = Minitest::Mock.new
136
+
137
+ Misty::AuthV3.stub :new, authv3 do
138
+ cloud = Misty::Cloud.new(:auth => authv3_data)
139
+ authv3.verify
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end