vagrant-openstack-provider 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +13 -5
  2. data/.rubocop.yml +28 -0
  3. data/Appraisals +3 -3
  4. data/CHANGELOG.md +4 -0
  5. data/Gemfile +3 -0
  6. data/Rakefile +6 -2
  7. data/Vagrantfile +4 -15
  8. data/gemfiles/latest_stable.gemfile +2 -0
  9. data/gemfiles/oldest_current.gemfile +2 -0
  10. data/gemfiles/previous_release.gemfile +2 -0
  11. data/lib/vagrant-openstack-provider.rb +18 -13
  12. data/lib/vagrant-openstack-provider/action.rb +112 -46
  13. data/lib/vagrant-openstack-provider/action/connect_openstack.rb +9 -10
  14. data/lib/vagrant-openstack-provider/action/create_server.rb +86 -57
  15. data/lib/vagrant-openstack-provider/action/delete_server.rb +5 -6
  16. data/lib/vagrant-openstack-provider/action/{is_created.rb → message.rb} +4 -3
  17. data/lib/vagrant-openstack-provider/action/read_ssh_info.rb +7 -27
  18. data/lib/vagrant-openstack-provider/action/read_state.rb +7 -9
  19. data/lib/vagrant-openstack-provider/action/resume.rb +20 -0
  20. data/lib/vagrant-openstack-provider/action/start_server.rb +22 -0
  21. data/lib/vagrant-openstack-provider/action/stop_server.rb +22 -0
  22. data/lib/vagrant-openstack-provider/action/suspend.rb +20 -0
  23. data/lib/vagrant-openstack-provider/action/sync_folders.rb +27 -38
  24. data/lib/vagrant-openstack-provider/action/wait_stop.rb +29 -0
  25. data/lib/vagrant-openstack-provider/client/keystone.rb +76 -0
  26. data/lib/vagrant-openstack-provider/client/neutron.rb +32 -0
  27. data/lib/vagrant-openstack-provider/client/nova.rb +166 -0
  28. data/lib/vagrant-openstack-provider/client/openstack.rb +41 -0
  29. data/lib/vagrant-openstack-provider/client/utils.rb +38 -0
  30. data/lib/vagrant-openstack-provider/config.rb +38 -110
  31. data/lib/vagrant-openstack-provider/errors.rb +7 -3
  32. data/lib/vagrant-openstack-provider/plugin.rb +8 -8
  33. data/lib/vagrant-openstack-provider/provider.rb +6 -6
  34. data/lib/vagrant-openstack-provider/version.rb +1 -1
  35. data/locales/en.yml +83 -5
  36. data/numergyrc +22 -0
  37. data/spec/vagrant-openstack-provider/action/create_server_spec.rb +89 -0
  38. data/spec/vagrant-openstack-provider/client/keystone_spec.rb +140 -0
  39. data/spec/vagrant-openstack-provider/client/neutron_spec.rb +53 -0
  40. data/spec/vagrant-openstack-provider/client/nova_spec.rb +373 -0
  41. data/spec/vagrant-openstack-provider/client/utils_spec.rb +125 -0
  42. data/spec/vagrant-openstack-provider/config_spec.rb +117 -0
  43. data/spec/vagrant-openstack-provider/provider_spec.rb +13 -0
  44. data/spec/vagrant-openstack-provider/spec_helper.rb +23 -0
  45. data/vagrant-openstack-provider.gemspec +13 -14
  46. metadata +40 -30
  47. data/features/provision.feature +0 -35
  48. data/features/steps/sdk_steps.rb +0 -13
  49. data/features/steps/server_steps.rb +0 -25
  50. data/features/support/env.rb +0 -37
  51. data/features/support/fog_mock.rb +0 -19
  52. data/features/vagrant-openstack-provider.feature +0 -70
  53. data/lib/vagrant-openstack-provider/action/message_already_created.rb +0 -16
  54. data/lib/vagrant-openstack-provider/action/message_not_created.rb +0 -16
  55. data/lib/vagrant-openstack-provider/openstack_client.rb +0 -98
  56. data/spec/vagrant-openstack/config_spec.rb +0 -184
  57. data/stackrc +0 -31
@@ -0,0 +1,22 @@
1
+ #!/bin/bash
2
+
3
+ export OS_AUTH_URL=https://cloud.numergy.com/identity/v2.0/tokens
4
+ export OS_COMPUTE_URL=https://cloud.numergy.com/compute/v2
5
+
6
+ if [ -z "$OS_USERNAME" ]; then
7
+ echo "Please enter your OpenStack tenant name: "
8
+ read -sr OS_TENANT_NAME_INPUT
9
+ export OS_TENANT_NAME=$OS_TENANT_NAME_INPUT
10
+ fi
11
+
12
+ if [ -z "$OS_USERNAME" ]; then
13
+ echo "Please enter your OpenStack username: "
14
+ read -sr OS_USERNAME_INPUT
15
+ export OS_USERNAME=$OS_USERNAME_INPUT
16
+ fi
17
+
18
+ if [ -z "$OS_PASSWORD" ]; then
19
+ echo "Please enter your OpenStack Password: "
20
+ read -sr OS_PASSWORD_INPUT
21
+ export OS_PASSWORD=$OS_PASSWORD_INPUT
22
+ fi
@@ -0,0 +1,89 @@
1
+ require 'vagrant-openstack-provider/spec_helper'
2
+
3
+ include VagrantPlugins::Openstack::Action
4
+
5
+ describe VagrantPlugins::Openstack::Action::CreateServer do
6
+
7
+ let(:config) do
8
+ double('config').tap do |config|
9
+ config.stub(:openstack_auth_url) { 'http://keystoneAuthV2' }
10
+ config.stub(:openstack_compute_url) { nil }
11
+ config.stub(:openstack_network_url) { nil }
12
+ config.stub(:tenant_name) { 'testTenant' }
13
+ config.stub(:username) { 'username' }
14
+ config.stub(:password) { 'password' }
15
+ end
16
+ end
17
+
18
+ let(:neutron) do
19
+ double('neutron').tap do |neutron|
20
+ neutron.stub(:get_private_networks).with(anything) do
21
+ [{ id: 'net-id-1', name: 'net-1' }, { id: 'net-id-2', name: 'net-2' }]
22
+ end
23
+ end
24
+ end
25
+
26
+ let(:env) do
27
+ Hash.new.tap do |env|
28
+ env[:ui] = double('ui')
29
+ env[:ui].stub(:info).with(anything)
30
+ env[:machine] = double('machine')
31
+ env[:machine].stub(:provider_config) { config }
32
+ env[:openstack_client] = double('openstack_client')
33
+ env[:openstack_client].stub(:neutron) { neutron }
34
+ end
35
+ end
36
+
37
+ before :each do
38
+ CreateServer.send(:public, *CreateServer.private_instance_methods)
39
+ @action = CreateServer.new(nil, nil)
40
+ end
41
+
42
+ describe 'resolve_networks' do
43
+
44
+ context 'with only ids of existing networks' do
45
+ it 'return the ids array' do
46
+ config.stub(:networks) { %w(net-id-1 net-id-2) }
47
+ @action.resolve_networks(env).should eq(%w(net-id-1 net-id-2))
48
+ end
49
+ end
50
+
51
+ context 'with only names of existing networks' do
52
+ it 'return the ids array' do
53
+ config.stub(:networks) { %w(net-1 net-2) }
54
+ @action.resolve_networks(env).should eq(%w(net-id-1 net-id-2))
55
+ end
56
+ end
57
+
58
+ context 'with only names and ids of existing networks' do
59
+ it 'return the ids array' do
60
+ config.stub(:networks) { %w(net-1 net-id-2) }
61
+ @action.resolve_networks(env).should eq(%w(net-id-1 net-id-2))
62
+ end
63
+ end
64
+
65
+ context 'with not existing networks' do
66
+ it 'return the ids array' do
67
+ config.stub(:networks) { %w(net-1 net-id-3) }
68
+ expect { @action.resolve_networks(env) }.to raise_error
69
+ end
70
+ end
71
+
72
+ context 'with no network returned by neutron and no network specified in vagrant provider' do
73
+ it 'return the ids array' do
74
+ neutron.stub(:get_private_networks).with(anything) { [] }
75
+ config.stub(:networks) { [] }
76
+ @action.resolve_networks(env).should eq([])
77
+ end
78
+ end
79
+
80
+ context 'with no network returned by neutron and one network specified in vagrant provider' do
81
+ it 'return the ids array' do
82
+ neutron.stub(:get_private_networks).with(anything) { [] }
83
+ config.stub(:networks) { ['net-id-1'] }
84
+ expect { @action.resolve_networks(env) }.to raise_error
85
+ end
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,140 @@
1
+ require 'vagrant-openstack-provider/spec_helper'
2
+
3
+ describe VagrantPlugins::Openstack::KeystoneClient do
4
+
5
+ let(:config) do
6
+ double('config').tap do |config|
7
+ config.stub(:openstack_auth_url) { 'http://keystoneAuthV2' }
8
+ config.stub(:openstack_compute_url) { nil }
9
+ config.stub(:openstack_network_url) { nil }
10
+ config.stub(:tenant_name) { 'testTenant' }
11
+ config.stub(:username) { 'username' }
12
+ config.stub(:password) { 'password' }
13
+ end
14
+ end
15
+
16
+ let(:env) do
17
+ Hash.new.tap do |env|
18
+ env[:ui] = double('ui')
19
+ env[:ui].stub(:info).with(anything)
20
+ env[:machine] = double('machine')
21
+ env[:machine].stub(:provider_config) { config }
22
+ end
23
+ end
24
+
25
+ let(:session) do
26
+ VagrantPlugins::Openstack.session
27
+ end
28
+
29
+ describe 'authenticate' do
30
+
31
+ let(:keystone_request_headers) do
32
+ {
33
+ 'Accept' => 'application/json',
34
+ 'Content-Type' => 'application/json'
35
+ }
36
+ end
37
+
38
+ let(:keystone_request_body) do
39
+ '{"auth":{"tenantName":"testTenant","passwordCredentials":{"username":"username","password":"password"}}}'
40
+ end
41
+
42
+ let(:keystone_response_body) do
43
+ '{"access":{"token":{"id":"0123456789","tenant":{"id":"testTenantId"}},"serviceCatalog":[
44
+ {"endpoints":[{"id":"eid1","publicURL":"http://nova"}],"type":"compute"},
45
+ {"endpoints":[{"id":"eid2","publicURL":"http://neutron"}],"type":"network"}
46
+ ]}}'
47
+ end
48
+
49
+ before :each do
50
+ @keystone_client = VagrantPlugins::Openstack::KeystoneClient.instance
51
+ end
52
+
53
+ context 'with good credentials' do
54
+
55
+ it 'store token and tenant id' do
56
+ stub_request(:post, 'http://keystoneAuthV2')
57
+ .with(
58
+ body: keystone_request_body,
59
+ headers: keystone_request_headers)
60
+ .to_return(
61
+ status: 200,
62
+ body: keystone_response_body,
63
+ headers: keystone_request_headers)
64
+
65
+ @keystone_client.authenticate(env)
66
+
67
+ session.token.should eq('0123456789')
68
+ session.project_id.should eq('testTenantId')
69
+ session.endpoints[:compute].should eq('http://nova')
70
+ session.endpoints[:network].should eq('http://neutron')
71
+ end
72
+
73
+ context 'with compute endpoint override' do
74
+ it 'store token and tenant id' do
75
+ config.stub(:openstack_compute_url) { 'http://novaOverride' }
76
+
77
+ stub_request(:post, 'http://keystoneAuthV2')
78
+ .with(
79
+ body: keystone_request_body,
80
+ headers: keystone_request_headers)
81
+ .to_return(
82
+ status: 200,
83
+ body: keystone_response_body,
84
+ headers: keystone_request_headers)
85
+
86
+ @keystone_client.authenticate(env)
87
+
88
+ session.token.should eq('0123456789')
89
+ session.project_id.should eq('testTenantId')
90
+ session.endpoints[:compute].should eq('http://novaOverride')
91
+ session.endpoints[:network].should eq('http://neutron')
92
+ end
93
+ end
94
+
95
+ context 'with network endpoint override' do
96
+ it 'store token and tenant id' do
97
+ config.stub(:openstack_network_url) { 'http://neutronOverride' }
98
+
99
+ stub_request(:post, 'http://keystoneAuthV2')
100
+ .with(
101
+ body: keystone_request_body,
102
+ headers: keystone_request_headers)
103
+ .to_return(
104
+ status: 200,
105
+ body: keystone_response_body,
106
+ headers: keystone_request_headers)
107
+
108
+ @keystone_client.authenticate(env)
109
+
110
+ session.token.should eq('0123456789')
111
+ session.project_id.should eq('testTenantId')
112
+ session.endpoints[:compute].should eq('http://nova')
113
+ session.endpoints[:network].should eq('http://neutronOverride')
114
+ end
115
+ end
116
+ end
117
+
118
+ context 'with wrong credentials' do
119
+ it 'raise an unauthorized error' do
120
+ stub_request(:post, 'http://keystoneAuthV2')
121
+ .with(
122
+ body: keystone_request_body,
123
+ headers: keystone_request_headers)
124
+ .to_return(
125
+ status: 401,
126
+ body: '{
127
+ "error": {
128
+ "message": "The request you have made requires authentication.",
129
+ "code": 401,
130
+ "title": "Unauthorized"
131
+ }
132
+ }',
133
+ headers: keystone_request_headers)
134
+
135
+ expect { @keystone_client.authenticate(env) }.to raise_error(RestClient::Unauthorized)
136
+ end
137
+ end
138
+
139
+ end
140
+ end
@@ -0,0 +1,53 @@
1
+ require 'vagrant-openstack-provider/spec_helper'
2
+
3
+ describe VagrantPlugins::Openstack::NeutronClient do
4
+
5
+ let(:env) do
6
+ Hash.new
7
+ end
8
+
9
+ let(:session) do
10
+ VagrantPlugins::Openstack.session
11
+ end
12
+
13
+ before :each do
14
+ session.token = '123456'
15
+ session.project_id = 'a1b2c3'
16
+ session.endpoints = { network: 'http://neutron' }
17
+ @neutron_client = VagrantPlugins::Openstack::NeutronClient.instance
18
+ end
19
+
20
+ describe 'get_private_networks' do
21
+ context 'with token' do
22
+ it 'returns only private networks for project in session' do
23
+
24
+ stub_request(:get, 'http://neutron/networks')
25
+ .with(
26
+ headers:
27
+ {
28
+ 'Accept' => 'application/json',
29
+ 'X-Auth-Token' => '123456'
30
+ })
31
+ .to_return(
32
+ status: 200,
33
+ body: '
34
+ {
35
+ "networks": [
36
+ { "name": "PublicNetwork", "tenant_id": "admin-tenant-id", "id": "net-pub" },
37
+ { "name": "net1", "tenant_id": "a1b2c3", "id": "net-1" },
38
+ { "name": "net2", "tenant_id": "a1b2c3", "id": "net-2" }
39
+ ]
40
+ }
41
+ ')
42
+
43
+ networks = @neutron_client.get_private_networks(env)
44
+
45
+ expect(networks.length).to eq(2)
46
+ expect(networks[0][:id]).to eq('net-1')
47
+ expect(networks[0][:name]).to eq('net1')
48
+ expect(networks[1][:id]).to eq('net-2')
49
+ expect(networks[1][:name]).to eq('net2')
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,373 @@
1
+ require 'vagrant-openstack-provider/spec_helper'
2
+
3
+ describe VagrantPlugins::Openstack::NovaClient do
4
+
5
+ let(:config) do
6
+ double('config').tap do |config|
7
+ config.stub(:openstack_auth_url) { 'http://novaAuthV2' }
8
+ config.stub(:openstack_compute_url) { nil }
9
+ config.stub(:tenant_name) { 'testTenant' }
10
+ config.stub(:username) { 'username' }
11
+ config.stub(:password) { 'password' }
12
+ end
13
+ end
14
+
15
+ let(:env) do
16
+ Hash.new.tap do |env|
17
+ env[:ui] = double('ui')
18
+ env[:ui].stub(:info).with(anything)
19
+ env[:machine] = double('machine')
20
+ env[:machine].stub(:provider_config) { config }
21
+ end
22
+ end
23
+
24
+ let(:session) do
25
+ VagrantPlugins::Openstack.session
26
+ end
27
+
28
+ before :each do
29
+ session.token = '123456'
30
+ session.project_id = 'a1b2c3'
31
+ session.endpoints = { compute: 'http://nova/a1b2c3' }
32
+ @nova_client = VagrantPlugins::Openstack::NovaClient.instance
33
+ end
34
+
35
+ describe 'get_all_flavors' do
36
+ context 'with token and project_id acquainted' do
37
+ it 'returns all flavors' do
38
+ stub_request(:get, 'http://nova/a1b2c3/flavors')
39
+ .with(
40
+ headers:
41
+ {
42
+ 'Accept' => 'application/json',
43
+ 'X-Auth-Token' => '123456'
44
+ })
45
+ .to_return(
46
+ status: 200,
47
+ body: '{ "flavors": [ { "id": "f1", "name": "flavor1"}, { "id": "f2", "name": "flavor2"} ] }')
48
+
49
+ flavors = @nova_client.get_all_flavors(env)
50
+
51
+ expect(flavors.length).to eq(2)
52
+ expect(flavors[0].id).to eq('f1')
53
+ expect(flavors[0].name).to eq('flavor1')
54
+ expect(flavors[1].id).to eq('f2')
55
+ expect(flavors[1].name).to eq('flavor2')
56
+ end
57
+ end
58
+ end
59
+
60
+ describe 'get_all_images' do
61
+ context 'with token and project_id acquainted' do
62
+ it 'returns all images' do
63
+ stub_request(:get, 'http://nova/a1b2c3/images')
64
+ .with(
65
+ headers:
66
+ {
67
+ 'Accept' => 'application/json',
68
+ 'X-Auth-Token' => '123456'
69
+ })
70
+ .to_return(
71
+ status: 200,
72
+ body: '{ "images": [ { "id": "i1", "name": "image1"}, { "id": "i2", "name": "image2"} ] }')
73
+
74
+ images = @nova_client.get_all_images(env)
75
+
76
+ expect(images.length).to eq(2)
77
+ expect(images[0].id).to eq('i1')
78
+ expect(images[0].name).to eq('image1')
79
+ expect(images[1].id).to eq('i2')
80
+ expect(images[1].name).to eq('image2')
81
+ end
82
+ end
83
+ end
84
+
85
+ describe 'create_server' do
86
+ context 'with token and project_id acquainted' do
87
+ it 'returns new instance id' do
88
+
89
+ stub_request(:post, 'http://nova/a1b2c3/servers')
90
+ .with(
91
+ body: '{"server":{"name":"inst","imageRef":"img","flavorRef":"flav","key_name":"key"}}',
92
+ headers:
93
+ {
94
+ 'Accept' => 'application/json',
95
+ 'Content-Type' => 'application/json',
96
+ 'X-Auth-Token' => '123456'
97
+ })
98
+ .to_return(status: 202, body: '{ "server": { "id": "o1o2o3" } }')
99
+
100
+ instance_id = @nova_client.create_server(env, 'inst', 'img', 'flav', nil, 'key')
101
+
102
+ expect(instance_id).to eq('o1o2o3')
103
+ end
104
+
105
+ context 'with one two networks' do
106
+ it 'returns new instance id' do
107
+
108
+ stub_request(:post, 'http://nova/a1b2c3/servers')
109
+ .with(
110
+ body: '{"server":{"name":"inst","imageRef":"img","flavorRef":"flav","key_name":"key","networks":[{"uuid":"net1"},{"uuid":"net2"}]}}',
111
+ headers:
112
+ {
113
+ 'Accept' => 'application/json',
114
+ 'Content-Type' => 'application/json',
115
+ 'X-Auth-Token' => '123456'
116
+ })
117
+ .to_return(status: 202, body: '{ "server": { "id": "o1o2o3" } }')
118
+
119
+ instance_id = @nova_client.create_server(env, 'inst', 'img', 'flav', %w(net1 net2), 'key')
120
+
121
+ expect(instance_id).to eq('o1o2o3')
122
+ end
123
+ end
124
+
125
+ end
126
+ end
127
+
128
+ describe 'delete_server' do
129
+ context 'with token and project_id acquainted' do
130
+ it 'returns new instance id' do
131
+
132
+ stub_request(:delete, 'http://nova/a1b2c3/servers/o1o2o3')
133
+ .with(
134
+ headers: {
135
+ 'Accept' => 'application/json',
136
+ 'X-Auth-Token' => '123456'
137
+ })
138
+ .to_return(status: 204)
139
+
140
+ @nova_client.delete_server(env, 'o1o2o3')
141
+
142
+ end
143
+ end
144
+ end
145
+
146
+ describe 'suspend_server' do
147
+ context 'with token and project_id acquainted' do
148
+ it 'returns new instance id' do
149
+
150
+ stub_request(:post, 'http://nova/a1b2c3/servers/o1o2o3/action')
151
+ .with(
152
+ body: '{ "suspend": null }',
153
+ headers:
154
+ {
155
+ 'Accept' => 'application/json',
156
+ 'Content-Type' => 'application/json',
157
+ 'X-Auth-Token' => '123456'
158
+ })
159
+ .to_return(status: 202)
160
+
161
+ @nova_client.suspend_server(env, 'o1o2o3')
162
+ end
163
+ end
164
+ end
165
+
166
+ describe 'resume_server' do
167
+ context 'with token and project_id acquainted' do
168
+ it 'returns new instance id' do
169
+
170
+ stub_request(:post, 'http://nova/a1b2c3/servers/o1o2o3/action')
171
+ .with(
172
+ body: '{ "resume": null }',
173
+ headers:
174
+ {
175
+ 'Accept' => 'application/json',
176
+ 'Content-Type' => 'application/json',
177
+ 'X-Auth-Token' => '123456'
178
+ })
179
+ .to_return(status: 202)
180
+
181
+ @nova_client.resume_server(env, 'o1o2o3')
182
+ end
183
+ end
184
+ end
185
+
186
+ describe 'stop_server' do
187
+ context 'with token and project_id acquainted' do
188
+ it 'returns new instance id' do
189
+
190
+ stub_request(:post, 'http://nova/a1b2c3/servers/o1o2o3/action')
191
+ .with(
192
+ body: '{ "os-stop": null }',
193
+ headers:
194
+ {
195
+ 'Accept' => 'application/json',
196
+ 'Content-Type' => 'application/json',
197
+ 'X-Auth-Token' => '123456'
198
+ })
199
+ .to_return(status: 202)
200
+
201
+ @nova_client.stop_server(env, 'o1o2o3')
202
+
203
+ end
204
+ end
205
+ end
206
+
207
+ describe 'start_server' do
208
+ context 'with token and project_id acquainted' do
209
+ it 'returns new instance id' do
210
+
211
+ stub_request(:post, 'http://nova/a1b2c3/servers/o1o2o3/action')
212
+ .with(
213
+ body: '{ "os-start": null }',
214
+ headers:
215
+ {
216
+ 'Accept' => 'application/json',
217
+ 'Content-Type' => 'application/json',
218
+ 'X-Auth-Token' => '123456'
219
+ })
220
+ .to_return(status: 202)
221
+
222
+ @nova_client.start_server(env, 'o1o2o3')
223
+
224
+ end
225
+ end
226
+ end
227
+
228
+ describe 'get_server_details' do
229
+ context 'with token and project_id acquainted' do
230
+ it 'returns server details' do
231
+
232
+ stub_request(:get, 'http://nova/a1b2c3/servers/o1o2o3')
233
+ .with(headers:
234
+ {
235
+ 'Accept' => 'application/json',
236
+ 'X-Auth-Token' => '123456'
237
+ })
238
+ .to_return(status: 200, body: '
239
+ {
240
+ "server": {
241
+ "addresses": { "private": [ { "addr": "192.168.0.3", "version": 4 } ] },
242
+ "created": "2012-08-20T21:11:09Z",
243
+ "flavor": { "id": "1" },
244
+ "id": "o1o2o3",
245
+ "image": { "id": "i1" },
246
+ "name": "new-server-test",
247
+ "progress": 0,
248
+ "status": "ACTIVE",
249
+ "tenant_id": "openstack",
250
+ "updated": "2012-08-20T21:11:09Z",
251
+ "user_id": "fake"
252
+ }
253
+ }
254
+ ')
255
+
256
+ server = @nova_client.get_server_details(env, 'o1o2o3')
257
+
258
+ expect(server['id']).to eq('o1o2o3')
259
+ expect(server['status']).to eq('ACTIVE')
260
+ expect(server['tenant_id']).to eq('openstack')
261
+ expect(server['image']['id']).to eq('i1')
262
+ expect(server['flavor']['id']).to eq('1')
263
+
264
+ end
265
+ end
266
+ end
267
+
268
+ describe 'add_floating_ip' do
269
+
270
+ context 'with token and project_id acquainted and IP available' do
271
+ it 'returns server details' do
272
+
273
+ stub_request(:get, 'http://nova/a1b2c3/os-floating-ips')
274
+ .with(headers:
275
+ {
276
+ 'Accept' => 'application/json',
277
+ 'X-Auth-Token' => '123456'
278
+ })
279
+ .to_return(status: 200, body: '
280
+ {
281
+ "floating_ips": [
282
+ {
283
+ "fixed_ip": null,
284
+ "id": 1,
285
+ "instance_id": null,
286
+ "ip": "1.2.3.4",
287
+ "pool": "nova"
288
+ },
289
+ {
290
+ "fixed_ip": null,
291
+ "id": 2,
292
+ "instance_id": null,
293
+ "ip": "5.6.7.8",
294
+ "pool": "nova"
295
+ }
296
+ ]
297
+ }')
298
+
299
+ stub_request(:post, 'http://nova/a1b2c3/servers/o1o2o3/action')
300
+ .with(body: '{"addFloatingIp":{"address":"1.2.3.4"}}',
301
+ headers:
302
+ {
303
+ 'Accept' => 'application/json',
304
+ 'Content-Type' => 'application/json',
305
+ 'X-Auth-Token' => '123456'
306
+ })
307
+ .to_return(status: 202)
308
+
309
+ @nova_client.add_floating_ip(env, 'o1o2o3', '1.2.3.4')
310
+ end
311
+ end
312
+
313
+ context 'with token and project_id acquainted and IP already in use' do
314
+ it 'raise an error' do
315
+
316
+ stub_request(:get, 'http://nova/a1b2c3/os-floating-ips')
317
+ .with(headers:
318
+ {
319
+ 'Accept' => 'application/json',
320
+ 'X-Auth-Token' => '123456'
321
+ })
322
+ .to_return(status: 200, body: '
323
+ {
324
+ "floating_ips": [
325
+ {
326
+ "fixed_ip": null,
327
+ "id": 1,
328
+ "instance_id": "inst",
329
+ "ip": "1.2.3.4",
330
+ "pool": "nova"
331
+ },
332
+ {
333
+ "fixed_ip": null,
334
+ "id": 2,
335
+ "instance_id": null,
336
+ "ip": "5.6.7.8",
337
+ "pool": "nova"
338
+ }
339
+ ]
340
+ }')
341
+
342
+ expect { @nova_client.add_floating_ip(env, 'o1o2o3', '1.2.3.4') }.to raise_error(RuntimeError)
343
+ end
344
+ end
345
+
346
+ context 'with token and project_id acquainted and IP not allocated' do
347
+ it 'raise an error' do
348
+
349
+ stub_request(:get, 'http://nova/a1b2c3/os-floating-ips')
350
+ .with(headers:
351
+ {
352
+ 'Accept' => 'application/json',
353
+ 'X-Auth-Token' => '123456'
354
+ })
355
+ .to_return(status: 200, body: '
356
+ {
357
+ "floating_ips": [
358
+ {
359
+ "fixed_ip": null,
360
+ "id": 2,
361
+ "instance_id": null,
362
+ "ip": "5.6.7.8",
363
+ "pool": "nova"
364
+ }
365
+ ]
366
+ }')
367
+
368
+ expect { @nova_client.add_floating_ip(env, 'o1o2o3', '1.2.3.4') }.to raise_error(RuntimeError)
369
+ end
370
+ end
371
+
372
+ end
373
+ end