vagrant-openstack-provider 0.1.2 → 0.2.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 (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