misty 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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