vagrant-openstack-illuin-provider 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rubocop.yml +40 -0
  4. data/CHANGELOG.md +282 -0
  5. data/Gemfile +18 -0
  6. data/RELEASE.md +15 -0
  7. data/Rakefile +25 -0
  8. data/Vagrantfile +20 -0
  9. data/dummy.box +0 -0
  10. data/example_box/README.md +13 -0
  11. data/example_box/metadata.json +3 -0
  12. data/functional_tests/Vagrantfile +58 -0
  13. data/functional_tests/keys/vagrant-openstack +27 -0
  14. data/functional_tests/keys/vagrant-openstack.pub +1 -0
  15. data/functional_tests/run_tests.sh +142 -0
  16. data/lib/vagrant-openstack-illuin-provider.rb +29 -0
  17. data/lib/vagrant-openstack-illuin-provider/action.rb +344 -0
  18. data/lib/vagrant-openstack-illuin-provider/action/abstract_action.rb +22 -0
  19. data/lib/vagrant-openstack-illuin-provider/action/connect_openstack.rb +60 -0
  20. data/lib/vagrant-openstack-illuin-provider/action/create_server.rb +187 -0
  21. data/lib/vagrant-openstack-illuin-provider/action/create_stack.rb +76 -0
  22. data/lib/vagrant-openstack-illuin-provider/action/delete_server.rb +53 -0
  23. data/lib/vagrant-openstack-illuin-provider/action/delete_stack.rb +73 -0
  24. data/lib/vagrant-openstack-illuin-provider/action/message.rb +19 -0
  25. data/lib/vagrant-openstack-illuin-provider/action/provision.rb +60 -0
  26. data/lib/vagrant-openstack-illuin-provider/action/read_ssh_info.rb +74 -0
  27. data/lib/vagrant-openstack-illuin-provider/action/read_state.rb +43 -0
  28. data/lib/vagrant-openstack-illuin-provider/action/resume.rb +24 -0
  29. data/lib/vagrant-openstack-illuin-provider/action/snapshot_cleanup.rb +32 -0
  30. data/lib/vagrant-openstack-illuin-provider/action/snapshot_delete.rb +32 -0
  31. data/lib/vagrant-openstack-illuin-provider/action/snapshot_list.rb +22 -0
  32. data/lib/vagrant-openstack-illuin-provider/action/snapshot_restore.rb +29 -0
  33. data/lib/vagrant-openstack-illuin-provider/action/snapshot_save.rb +51 -0
  34. data/lib/vagrant-openstack-illuin-provider/action/start_server.rb +24 -0
  35. data/lib/vagrant-openstack-illuin-provider/action/stop_server.rb +25 -0
  36. data/lib/vagrant-openstack-illuin-provider/action/suspend.rb +24 -0
  37. data/lib/vagrant-openstack-illuin-provider/action/sync_folders.rb +138 -0
  38. data/lib/vagrant-openstack-illuin-provider/action/wait_active.rb +33 -0
  39. data/lib/vagrant-openstack-illuin-provider/action/wait_stop.rb +33 -0
  40. data/lib/vagrant-openstack-illuin-provider/cap/snapshot_list.rb +15 -0
  41. data/lib/vagrant-openstack-illuin-provider/catalog/openstack_catalog.rb +90 -0
  42. data/lib/vagrant-openstack-illuin-provider/client/cinder.rb +39 -0
  43. data/lib/vagrant-openstack-illuin-provider/client/domain.rb +163 -0
  44. data/lib/vagrant-openstack-illuin-provider/client/glance.rb +65 -0
  45. data/lib/vagrant-openstack-illuin-provider/client/heat.rb +49 -0
  46. data/lib/vagrant-openstack-illuin-provider/client/http_utils.rb +116 -0
  47. data/lib/vagrant-openstack-illuin-provider/client/keystone.rb +128 -0
  48. data/lib/vagrant-openstack-illuin-provider/client/neutron.rb +48 -0
  49. data/lib/vagrant-openstack-illuin-provider/client/nova.rb +303 -0
  50. data/lib/vagrant-openstack-illuin-provider/client/openstack.rb +59 -0
  51. data/lib/vagrant-openstack-illuin-provider/client/request_logger.rb +23 -0
  52. data/lib/vagrant-openstack-illuin-provider/client/rest_utils.rb +28 -0
  53. data/lib/vagrant-openstack-illuin-provider/command/abstract_command.rb +51 -0
  54. data/lib/vagrant-openstack-illuin-provider/command/flavor_list.rb +24 -0
  55. data/lib/vagrant-openstack-illuin-provider/command/floatingip_list.rb +32 -0
  56. data/lib/vagrant-openstack-illuin-provider/command/image_list.rb +29 -0
  57. data/lib/vagrant-openstack-illuin-provider/command/main.rb +52 -0
  58. data/lib/vagrant-openstack-illuin-provider/command/network_list.rb +25 -0
  59. data/lib/vagrant-openstack-illuin-provider/command/openstack_command.rb +16 -0
  60. data/lib/vagrant-openstack-illuin-provider/command/reset.rb +20 -0
  61. data/lib/vagrant-openstack-illuin-provider/command/subnet_list.rb +22 -0
  62. data/lib/vagrant-openstack-illuin-provider/command/utils.rb +22 -0
  63. data/lib/vagrant-openstack-illuin-provider/command/volume_list.rb +25 -0
  64. data/lib/vagrant-openstack-illuin-provider/config.rb +505 -0
  65. data/lib/vagrant-openstack-illuin-provider/config/http.rb +39 -0
  66. data/lib/vagrant-openstack-illuin-provider/config_resolver.rb +334 -0
  67. data/lib/vagrant-openstack-illuin-provider/errors.rb +187 -0
  68. data/lib/vagrant-openstack-illuin-provider/logging.rb +39 -0
  69. data/lib/vagrant-openstack-illuin-provider/plugin.rb +58 -0
  70. data/lib/vagrant-openstack-illuin-provider/provider.rb +50 -0
  71. data/lib/vagrant-openstack-illuin-provider/utils.rb +81 -0
  72. data/lib/vagrant-openstack-illuin-provider/version.rb +15 -0
  73. data/lib/vagrant-openstack-illuin-provider/version_checker.rb +76 -0
  74. data/locales/en.yml +412 -0
  75. data/spec/vagrant-openstack-illuin-provider/action/connect_openstack_spec.rb +770 -0
  76. data/spec/vagrant-openstack-illuin-provider/action/create_server_spec.rb +260 -0
  77. data/spec/vagrant-openstack-illuin-provider/action/create_stack_spec.rb +99 -0
  78. data/spec/vagrant-openstack-illuin-provider/action/delete_server_spec.rb +89 -0
  79. data/spec/vagrant-openstack-illuin-provider/action/delete_stack_spec.rb +63 -0
  80. data/spec/vagrant-openstack-illuin-provider/action/message_spec.rb +33 -0
  81. data/spec/vagrant-openstack-illuin-provider/action/provision_spec.rb +97 -0
  82. data/spec/vagrant-openstack-illuin-provider/action/read_ssh_info_spec.rb +202 -0
  83. data/spec/vagrant-openstack-illuin-provider/action/read_state_spec.rb +81 -0
  84. data/spec/vagrant-openstack-illuin-provider/action/resume_server_spec.rb +49 -0
  85. data/spec/vagrant-openstack-illuin-provider/action/start_server_spec.rb +49 -0
  86. data/spec/vagrant-openstack-illuin-provider/action/stop_server_spec.rb +49 -0
  87. data/spec/vagrant-openstack-illuin-provider/action/suspend_server_spec.rb +49 -0
  88. data/spec/vagrant-openstack-illuin-provider/action/sync_folders_spec.rb +155 -0
  89. data/spec/vagrant-openstack-illuin-provider/action/wait_active_spec.rb +53 -0
  90. data/spec/vagrant-openstack-illuin-provider/action/wait_stop_spec.rb +53 -0
  91. data/spec/vagrant-openstack-illuin-provider/action_spec.rb +120 -0
  92. data/spec/vagrant-openstack-illuin-provider/client/cinder_spec.rb +129 -0
  93. data/spec/vagrant-openstack-illuin-provider/client/glance_spec.rb +145 -0
  94. data/spec/vagrant-openstack-illuin-provider/client/heat_spec.rb +130 -0
  95. data/spec/vagrant-openstack-illuin-provider/client/keystone_spec.rb +226 -0
  96. data/spec/vagrant-openstack-illuin-provider/client/neutron_spec.rb +173 -0
  97. data/spec/vagrant-openstack-illuin-provider/client/nova_spec.rb +760 -0
  98. data/spec/vagrant-openstack-illuin-provider/client/utils_spec.rb +176 -0
  99. data/spec/vagrant-openstack-illuin-provider/command/flavor_list_spec.rb +43 -0
  100. data/spec/vagrant-openstack-illuin-provider/command/floatingip_list_spec.rb +74 -0
  101. data/spec/vagrant-openstack-illuin-provider/command/image_list_spec.rb +95 -0
  102. data/spec/vagrant-openstack-illuin-provider/command/network_list_spec.rb +65 -0
  103. data/spec/vagrant-openstack-illuin-provider/command/reset_spec.rb +24 -0
  104. data/spec/vagrant-openstack-illuin-provider/command/subnet_list_spec.rb +45 -0
  105. data/spec/vagrant-openstack-illuin-provider/command/volume_list_spec.rb +40 -0
  106. data/spec/vagrant-openstack-illuin-provider/config_resolver_spec.rb +879 -0
  107. data/spec/vagrant-openstack-illuin-provider/config_spec.rb +416 -0
  108. data/spec/vagrant-openstack-illuin-provider/e2e_spec.rb.save +27 -0
  109. data/spec/vagrant-openstack-illuin-provider/provider_spec.rb +13 -0
  110. data/spec/vagrant-openstack-illuin-provider/spec_helper.rb +37 -0
  111. data/spec/vagrant-openstack-illuin-provider/utils_spec.rb +197 -0
  112. data/spec/vagrant-openstack-illuin-provider/version_checker_spec.rb +39 -0
  113. data/stackrc +25 -0
  114. data/vagrant-openstack-illuin-provider.gemspec +35 -0
  115. metadata +379 -0
@@ -0,0 +1,24 @@
1
+ require 'vagrant-openstack-illuin-provider/spec_helper'
2
+
3
+ describe VagrantPlugins::Openstack::Command::Reset do
4
+ describe 'cmd' do
5
+ let(:env) do
6
+ {}.tap do |env|
7
+ env[:ui] = double('ui')
8
+ env[:ui].stub(:info).with(anything)
9
+ env[:machine] = double('machine')
10
+ env[:machine].stub(:data_dir) { '/my/data/dir' }
11
+ end
12
+ end
13
+
14
+ before :each do
15
+ @reset_cmd = VagrantPlugins::Openstack::Command::Reset.new(nil, env)
16
+ end
17
+
18
+ it 'resets vagrant openstack machines' do
19
+ expect(env[:ui]).to receive(:info).with('Vagrant OpenStack Provider has been reset')
20
+ expect(FileUtils).to receive(:remove_dir).with('/my/data/dir')
21
+ @reset_cmd.cmd('reset', [], env)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ require 'vagrant-openstack-illuin-provider/spec_helper'
2
+
3
+ describe VagrantPlugins::Openstack::Command::SubnetList do
4
+ describe 'cmd' do
5
+ let(:neutron) do
6
+ double('neutron').tap do |neutron|
7
+ neutron.stub(:get_subnets) do
8
+ [
9
+ Subnet.new('subnet-01', 'Subnet 1', '192.168.1.0/24', true, 'net-01'),
10
+ Subnet.new('subnet-02', 'Subnet 2', '192.168.2.0/24', false, 'net-01'),
11
+ Subnet.new('subnet-03', 'Subnet 3', '192.168.100.0/24', true, 'net-02')
12
+ ]
13
+ end
14
+ end
15
+ end
16
+
17
+ let(:env) do
18
+ {}.tap do |env|
19
+ env[:ui] = double('ui')
20
+ env[:ui].stub(:info).with(anything)
21
+ env[:openstack_client] = double
22
+ env[:openstack_client].stub(:neutron) { neutron }
23
+ end
24
+ end
25
+
26
+ before :each do
27
+ @subnet_list_cmd = VagrantPlugins::Openstack::Command::SubnetList.new(nil, env)
28
+ end
29
+
30
+ it 'prints subnet list from server' do
31
+ neutron.should_receive(:get_subnets).with(env)
32
+
33
+ expect(env[:ui]).to receive(:info).with('
34
+ +-----------+----------+------------------+-------+------------+
35
+ | ID | Name | CIDR | DHCP | Network ID |
36
+ +-----------+----------+------------------+-------+------------+
37
+ | subnet-01 | Subnet 1 | 192.168.1.0/24 | true | net-01 |
38
+ | subnet-02 | Subnet 2 | 192.168.2.0/24 | false | net-01 |
39
+ | subnet-03 | Subnet 3 | 192.168.100.0/24 | true | net-02 |
40
+ +-----------+----------+------------------+-------+------------+')
41
+
42
+ @subnet_list_cmd.cmd('subnet-list', [], env)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,40 @@
1
+ require 'vagrant-openstack-illuin-provider/spec_helper'
2
+
3
+ describe VagrantPlugins::Openstack::Command::VolumeList do
4
+ describe 'cmd' do
5
+ let(:cinder) do
6
+ double('cinder').tap do |cinder|
7
+ cinder.stub(:get_all_volumes) do
8
+ [Volume.new('987', 'vol-01', '2', 'available', 'true', nil, nil),
9
+ Volume.new('654', 'vol-02', '4', 'in-use', 'false', 'inst-01', '/dev/vdc')]
10
+ end
11
+ end
12
+ end
13
+
14
+ let(:env) do
15
+ {}.tap do |env|
16
+ env[:ui] = double('ui')
17
+ env[:ui].stub(:info).with(anything)
18
+ env[:openstack_client] = double
19
+ env[:openstack_client].stub(:cinder) { cinder }
20
+ end
21
+ end
22
+
23
+ before :each do
24
+ @volume_list_cmd = VagrantPlugins::Openstack::Command::VolumeList.new(nil, env)
25
+ end
26
+
27
+ it 'prints volumes list from server' do
28
+ cinder.should_receive(:get_all_volumes).with(env)
29
+ expect(env[:ui]).to receive(:info).with('
30
+ +-----+--------+-----------+-----------+-------------------------------------+
31
+ | ID | Name | Size (Go) | Status | Attachment (instance ID and device) |
32
+ +-----+--------+-----------+-----------+-------------------------------------+
33
+ | 987 | vol-01 | 2 | available | |
34
+ | 654 | vol-02 | 4 | in-use | inst-01 (/dev/vdc) |
35
+ +-----+--------+-----------+-----------+-------------------------------------+')
36
+
37
+ @volume_list_cmd.cmd('volume-list', [], env)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,879 @@
1
+ require 'vagrant-openstack-illuin-provider/spec_helper'
2
+
3
+ describe VagrantPlugins::Openstack::ConfigResolver do
4
+ let(:config) do
5
+ double('config').tap do |config|
6
+ config.stub(:tenant_name) { 'testTenant' }
7
+ config.stub(:server_name) { 'testName' }
8
+ config.stub(:floating_ip) { nil }
9
+ config.stub(:floating_ip_pool) { nil }
10
+ config.stub(:floating_ip_pool_always_allocate) { false }
11
+ config.stub(:keypair_name) { nil }
12
+ config.stub(:public_key_path) { nil }
13
+ config.stub(:networks) { nil }
14
+ config.stub(:volumes) { nil }
15
+ end
16
+ end
17
+
18
+ let(:ssh_key) do
19
+ double('ssh_key').tap do |key|
20
+ key.stub(:ssh_public_key) { 'ssh public key' }
21
+ key.stub(:private_key) { 'private key' }
22
+ end
23
+ end
24
+
25
+ let(:neutron) do
26
+ double('neutron').tap do |neutron|
27
+ neutron.stub(:get_all_networks).with(anything) do
28
+ [Item.new('001', 'net-01'),
29
+ Item.new('002', 'net-02'),
30
+ Item.new('003', 'net-03'),
31
+ Item.new('004', 'net-04'),
32
+ Item.new('005', 'net-05'),
33
+ Item.new('006', 'net-06'),
34
+ Item.new('007', 'net-07-08'),
35
+ Item.new('008', 'net-07-08')]
36
+ end
37
+ end
38
+ end
39
+
40
+ let(:nova) do
41
+ double('nova').tap do |nova|
42
+ nova.stub(:get_all_floating_ips).with(anything) do
43
+ [FloatingIP.new('80.81.82.83', 'pool-1', nil), FloatingIP.new('30.31.32.33', 'pool-2', '1234')]
44
+ end
45
+ end
46
+ end
47
+
48
+ let(:cinder) do
49
+ double('cinder').tap do |cinder|
50
+ cinder.stub(:get_all_volumes).with(anything) do
51
+ [Volume.new('001', 'vol-01', '1', 'available', 'true', nil, nil),
52
+ Volume.new('002', 'vol-02', '2', 'available', 'true', nil, nil),
53
+ Volume.new('003', 'vol-03', '3', 'available', 'true', nil, nil),
54
+ Volume.new('004', 'vol-04', '4', 'available', 'false', nil, nil),
55
+ Volume.new('005', 'vol-05', '5', 'available', 'false', nil, nil),
56
+ Volume.new('006', 'vol-06', '6', 'available', 'false', nil, nil),
57
+ Volume.new('007', 'vol-07-08', '6', 'available', 'false', nil, nil),
58
+ Volume.new('008', 'vol-07-08', '6', 'available', 'false', nil, nil)]
59
+ end
60
+ end
61
+ end
62
+
63
+ let(:session) do
64
+ double('session').tap do |s|
65
+ s.stub(:endpoints) do
66
+ {
67
+ identity: 'http://keystone',
68
+ compute: 'http://nova',
69
+ volume: 'http://cinder',
70
+ network: 'http://neutron'
71
+ }
72
+ end
73
+ end
74
+ end
75
+
76
+ let(:env) do
77
+ {}.tap do |env|
78
+ env[:ui] = double('ui')
79
+ env[:ui].stub(:info).with(anything)
80
+ env[:machine] = double('machine')
81
+ env[:machine].stub(:provider_config) { config }
82
+ env[:machine].stub(:data_dir) { '/data/dir' }
83
+ env[:machine].stub(:config) { machine_config }
84
+ env[:openstack_client] = double('openstack_client')
85
+ env[:openstack_client].stub(:neutron) { neutron }
86
+ env[:openstack_client].stub(:nova) { nova }
87
+ env[:openstack_client].stub(:cinder) { cinder }
88
+ env[:openstack_client].stub(:session) { session }
89
+ end
90
+ end
91
+
92
+ let(:ssh_config) do
93
+ double('ssh_config').tap do |config|
94
+ config.stub(:username) { nil }
95
+ config.stub(:port) { nil }
96
+ config.stub(:insert_key) { true }
97
+ end
98
+ end
99
+
100
+ let(:machine_config) do
101
+ double('machine_config').tap do |config|
102
+ config.stub(:ssh) { ssh_config }
103
+ end
104
+ end
105
+
106
+ before :each do
107
+ ConfigResolver.send(:public, *ConfigResolver.private_instance_methods)
108
+ @action = ConfigResolver.new
109
+ end
110
+
111
+ describe 'resolve_ssh_username' do
112
+ context 'with machine.ssh.username' do
113
+ it 'returns machine.ssh.username' do
114
+ ssh_config.stub(:username) { 'machine ssh username' }
115
+ config.stub(:ssh_username) { nil }
116
+ expect(@action.resolve_ssh_username(env)).to eq('machine ssh username')
117
+ end
118
+ end
119
+ context 'with machine.ssh.username and config.ssh_username' do
120
+ it 'returns machine.ssh.username' do
121
+ ssh_config.stub(:username) { 'machine ssh username' }
122
+ config.stub(:ssh_username) { 'provider ssh username' }
123
+ expect(@action.resolve_ssh_username(env)).to eq('machine ssh username')
124
+ end
125
+ end
126
+ context 'with config.ssh_username' do
127
+ it 'returns config.ssh_username' do
128
+ ssh_config.stub(:username) { nil }
129
+ config.stub(:ssh_username) { 'provider ssh username' }
130
+ expect(@action.resolve_ssh_username(env)).to eq('provider ssh username')
131
+ end
132
+ end
133
+ context 'with no ssh username config' do
134
+ it 'fails' do
135
+ ssh_config.stub(:username) { nil }
136
+ config.stub(:ssh_username) { nil }
137
+ expect { @action.resolve_ssh_username(env) }.to raise_error(Errors::NoMatchingSshUsername)
138
+ end
139
+ end
140
+ end
141
+
142
+ describe 'resolve_flavor' do
143
+ context 'with id' do
144
+ it 'returns the specified flavor' do
145
+ config.stub(:flavor) { 'fl-001' }
146
+ nova.stub(:get_all_flavors).with(anything) do
147
+ [Flavor.new('fl-001', 'flavor-01', 2, 1024, 10),
148
+ Flavor.new('fl-002', 'flavor-02', 4, 2048, 50)]
149
+ end
150
+ @action.resolve_flavor(env).should eq(Flavor.new('fl-001', 'flavor-01', 2, 1024, 10))
151
+ end
152
+ end
153
+ context 'with name' do
154
+ it 'returns the specified flavor' do
155
+ config.stub(:flavor) { 'flavor-02' }
156
+ nova.stub(:get_all_flavors).with(anything) do
157
+ [Flavor.new('fl-001', 'flavor-01', 2, 1024, 10),
158
+ Flavor.new('fl-002', 'flavor-02', 4, 2048, 50)]
159
+ end
160
+ @action.resolve_flavor(env).should eq(Flavor.new('fl-002', 'flavor-02', 4, 2048, 50))
161
+ end
162
+ end
163
+ context 'with list' do
164
+ it 'returns the first matching flavor' do
165
+ config.stub(:flavor) { %w(not-existing flavor-02 flavor-01) }
166
+ nova.stub(:get_all_flavors).with(anything) do
167
+ [Flavor.new('fl-001', 'flavor-01', 2, 1024, 10),
168
+ Flavor.new('fl-002', 'flavor-02', 4, 2048, 50)]
169
+ end
170
+ @action.resolve_flavor(env).should eq(Flavor.new('fl-002', 'flavor-02', 4, 2048, 50))
171
+ end
172
+ end
173
+ context 'with invalid identifier' do
174
+ it 'raise an error' do
175
+ config.stub(:flavor) { 'not-existing' }
176
+ nova.stub(:get_all_flavors).with(anything) do
177
+ [Flavor.new('fl-001', 'flavor-01', 2, 1024, 10),
178
+ Flavor.new('fl-002', 'flavor-02', 4, 2048, 50)]
179
+ end
180
+ expect { @action.resolve_flavor(env) }.to raise_error(Errors::NoMatchingFlavor)
181
+ end
182
+ end
183
+ end
184
+
185
+ describe 'resolve_image' do
186
+ context 'with id' do
187
+ it 'returns the specified flavor' do
188
+ config.stub(:image) { 'img-001' }
189
+ config.stub(:volume_boot) { nil }
190
+ nova.stub(:get_all_images).with(anything) do
191
+ [Item.new('img-001', 'image-01'),
192
+ Item.new('img-002', 'image-02')]
193
+ end
194
+ @action.resolve_image(env).should eq(Item.new('img-001', 'image-01'))
195
+ end
196
+ end
197
+ context 'with name' do
198
+ it 'returns the specified flavor' do
199
+ config.stub(:image) { 'image-02' }
200
+ config.stub(:volume_boot) { nil }
201
+ nova.stub(:get_all_images).with(anything) do
202
+ [Item.new('img-001', 'image-01'),
203
+ Item.new('img-002', 'image-02')]
204
+ end
205
+ @action.resolve_image(env).should eq(Item.new('img-002', 'image-02'))
206
+ end
207
+ end
208
+ context 'with invalid identifier' do
209
+ it 'raise an error' do
210
+ config.stub(:image) { 'not-existing' }
211
+ config.stub(:volume_boot) { nil }
212
+ nova.stub(:get_all_images).with(anything) do
213
+ [Item.new('img-001', 'image-01'),
214
+ Item.new('img-002', 'image-02')]
215
+ end
216
+ expect { @action.resolve_image(env) }.to raise_error(Errors::NoMatchingImage)
217
+ end
218
+ end
219
+ context 'with no images in config' do
220
+ it 'return nil' do
221
+ config.stub(:image) { nil }
222
+ config.stub(:volume_boot) { nil }
223
+ nova.stub(:get_all_images).with(anything) do
224
+ [Item.new('img-001', 'image-01'),
225
+ Item.new('img-002', 'image-02')]
226
+ end
227
+ @action.resolve_image(env).should eq(nil)
228
+ end
229
+ end
230
+ end
231
+
232
+ describe 'resolve_floating_ip' do
233
+ context 'with config.floating_ip specified' do
234
+ it 'return the specified floating ip' do
235
+ config.stub(:floating_ip) { '80.80.80.80' }
236
+ @action.resolve_floating_ip(env).should eq('80.80.80.80')
237
+ end
238
+ end
239
+
240
+ context 'with only one config.floating_ip_pool specified' do
241
+ context 'if an ip in the same pool is available' do
242
+ context 'with config.floating_ip_pool_always_allocate true' do
243
+ it 'allocate a new floating_ip from the pool' do
244
+ config.stub(:floating_ip_pool_always_allocate) { true }
245
+ nova.stub(:get_all_floating_ips).with(anything) do
246
+ [FloatingIP.new('80.81.82.84', 'pool-1', '1234'),
247
+ FloatingIP.new('80.81.82.83', 'pool-1', nil)]
248
+ end
249
+ nova.stub(:allocate_floating_ip).with(env, 'pool-1') do
250
+ FloatingIP.new('80.81.82.85', 'pool-1', nil)
251
+ end
252
+ config.stub(:floating_ip_pool) { ['pool-1'] }
253
+ config.stub(:floating_ip=) { nil }
254
+ @action.resolve_floating_ip(env).should eq('80.81.82.85')
255
+ end
256
+ end
257
+
258
+ context 'with config.floating_ip_pool_always_allocate false' do
259
+ it 'return one of the available ips' do
260
+ config.stub(:floating_ip_pool_always_allocate) { false }
261
+ nova.stub(:get_all_floating_ips).with(anything) do
262
+ [FloatingIP.new('80.81.82.84', 'pool-1', '1234'),
263
+ FloatingIP.new('80.81.82.83', 'pool-1', nil)]
264
+ end
265
+ config.stub(:floating_ip_pool) { ['pool-1'] }
266
+ config.stub(:floating_ip=) { nil }
267
+ @action.resolve_floating_ip(env).should eq('80.81.82.83')
268
+ end
269
+ end
270
+ end
271
+
272
+ context 'if no ip in the same pool is available' do
273
+ it 'allocate a new floating_ip from the pool' do
274
+ nova.stub(:get_all_floating_ips).with(anything) do
275
+ [FloatingIP.new('80.81.82.83', 'pool-1', '1234')]
276
+ end
277
+ nova.stub(:allocate_floating_ip).with(env, 'pool-1') do
278
+ FloatingIP.new('80.81.82.84', 'pool-1', nil)
279
+ end
280
+ config.stub(:floating_ip_pool) { ['pool-1'] }
281
+ config.stub(:floating_ip=) { nil }
282
+ @action.resolve_floating_ip(env).should eq('80.81.82.84')
283
+ end
284
+ end
285
+ end
286
+
287
+ context 'with several floating_ip_pool defined' do
288
+ context 'if an ip in a pool is available' do
289
+ context 'with config.floating_ip_pool_always_allocate true' do
290
+ it 'allocate a new floating_ip from the first pool defined' do
291
+ config.stub(:floating_ip_pool_always_allocate) { true }
292
+ nova.stub(:get_all_floating_ips).with(anything) do
293
+ [FloatingIP.new('80.81.82.84', 'pool-1', '1234'),
294
+ FloatingIP.new('80.81.82.83', 'pool-1', nil),
295
+ FloatingIP.new('80.81.82.82', 'pool-2', '5678')]
296
+ end
297
+ nova.stub(:allocate_floating_ip).with(env, 'pool-1') do
298
+ FloatingIP.new('80.81.82.85', 'pool-1', nil)
299
+ end
300
+ config.stub(:floating_ip_pool) { %w(pool-1 pool-2) }
301
+ config.stub(:floating_ip=) { nil }
302
+ @action.resolve_floating_ip(env).should eq('80.81.82.85')
303
+ end
304
+ end
305
+
306
+ context 'with config.floating_ip_pool_always_allocate false' do
307
+ it 'return one of the available ips' do
308
+ config.stub(:floating_ip_pool_always_allocate) { false }
309
+ nova.stub(:get_all_floating_ips).with(anything) do
310
+ [FloatingIP.new('80.81.82.84', 'pool-1', '1234'),
311
+ FloatingIP.new('80.81.82.83', 'pool-2', nil)]
312
+ end
313
+ config.stub(:floating_ip_pool) { %w(pool-1 pool-2) }
314
+ config.stub(:floating_ip=) { nil }
315
+ @action.resolve_floating_ip(env).should eq('80.81.82.83')
316
+ end
317
+ end
318
+ end
319
+
320
+ context 'if no ip in the pools is available' do
321
+ context 'if allocate an ip in first pool is possible' do
322
+ it 'allocate a new floating_ip from first pool' do
323
+ nova.stub(:get_all_floating_ips).with(anything) do
324
+ [FloatingIP.new('80.81.82.83', 'pool-1', '1234'),
325
+ FloatingIP.new('80.81.82.82', 'pool-2', '5678')]
326
+ end
327
+ nova.stub(:allocate_floating_ip).with(env, 'pool-1') do
328
+ FloatingIP.new('80.81.82.84', 'pool-1', nil)
329
+ end
330
+ config.stub(:floating_ip_pool) { %w(pool-1 pool-2) }
331
+ config.stub(:floating_ip=) { nil }
332
+ @action.resolve_floating_ip(env).should eq('80.81.82.84')
333
+ end
334
+ end
335
+
336
+ context 'if allocate an ip in first pool is not possible' do
337
+ it 'allocate a new floating_ip from second pool' do
338
+ nova.stub(:get_all_floating_ips).with(anything) do
339
+ [FloatingIP.new('80.81.82.83', 'pool-1', '1234'),
340
+ FloatingIP.new('80.81.82.82', 'pool-2', '5678')]
341
+ end
342
+ nova.stub(:allocate_floating_ip).with(env, 'pool-1').and_raise Errors::VagrantOpenstackError, message: 'error', code: 404
343
+ nova.stub(:allocate_floating_ip).with(env, 'pool-2') do
344
+ FloatingIP.new('80.81.82.84', 'pool-2', nil)
345
+ end
346
+ config.stub(:floating_ip_pool) { %w(pool-1 pool-2) }
347
+ config.stub(:floating_ip=) { nil }
348
+ @action.resolve_floating_ip(env).should eq('80.81.82.84')
349
+ end
350
+ end
351
+
352
+ context 'if allocate an ip in either first and second pool is not possible' do
353
+ it 'shoud raise an error', :simon do
354
+ nova.stub(:get_all_floating_ips).with(anything) do
355
+ [FloatingIP.new('80.81.82.83', 'pool-1', '1234'),
356
+ FloatingIP.new('80.81.82.82', 'pool-2', '5678')]
357
+ end
358
+ nova.stub(:allocate_floating_ip).with(env, 'pool-1').and_raise Errors::VagrantOpenstackError, message: 'error', code: 404
359
+ nova.stub(:allocate_floating_ip).with(env, 'pool-2').and_raise Errors::VagrantOpenstackError, message: 'error', code: 404
360
+ config.stub(:floating_ip_pool) { %w(pool-1 pool-2) }
361
+ config.stub(:floating_ip=) { nil }
362
+ expect { @action.resolve_floating_ip(env) }.to raise_error(Errors::VagrantOpenstackError)
363
+ end
364
+ end
365
+ end
366
+ end
367
+
368
+ context 'with neither floating_ip nor floating_ip_pool' do
369
+ it 'fails with an UnableToResolveFloatingIP error' do
370
+ config.stub(:floating_ip) { nil }
371
+ config.stub(:floating_ip_pool) { nil }
372
+ expect { @action.resolve_floating_ip(env) }.to raise_error(Errors::UnableToResolveFloatingIP)
373
+ end
374
+ end
375
+ end
376
+
377
+ describe 'resolve_keypair' do
378
+ context 'with keypair_name provided' do
379
+ it 'return the provided keypair_name' do
380
+ config.stub(:keypair_name) { 'my-keypair' }
381
+ @action.resolve_keypair(env).should eq('my-keypair')
382
+ end
383
+ end
384
+
385
+ context 'with keypair_name and public_key_path provided' do
386
+ it 'return the provided keypair_name' do
387
+ config.stub(:keypair_name) { 'my-keypair' }
388
+ config.stub(:public_key_path) { '/path/to/key' }
389
+ @action.resolve_keypair(env).should eq('my-keypair')
390
+ end
391
+ end
392
+
393
+ context 'with public_key_path provided' do
394
+ it 'return the keypair_name created into nova' do
395
+ config.stub(:public_key_path) { '/path/to/key' }
396
+ nova.stub(:import_keypair_from_file).with(env, '/path/to/key') { 'my-keypair-imported' }
397
+ @action.resolve_keypair(env).should eq('my-keypair-imported')
398
+ end
399
+ end
400
+
401
+ context 'with no keypair_name and no public_key_path provided' do
402
+ it 'generates a new keypair and return the keypair name imported into nova' do
403
+ config.stub(:keypair_name) { nil }
404
+ config.stub(:public_key_path) { nil }
405
+ @action.stub(:generate_keypair) { 'my-keypair-imported' }
406
+ @action.resolve_keypair(env).should eq('my-keypair-imported')
407
+ end
408
+ end
409
+
410
+ context 'with insert_key false' do
411
+ it 'does nothing and return nil' do
412
+ config.stub(:keypair_name) { 'my-keypair' }
413
+ ssh_config.stub(:insert_key) { false }
414
+ nova.should_not_receive(:import_keypair_from_file)
415
+ @action.should_not_receive(:generate_keypair)
416
+ @action.resolve_keypair(env).should be_nil
417
+ end
418
+ end
419
+ end
420
+
421
+ describe 'generate_keypair' do
422
+ it 'returns a generated keypair name imported into nova' do
423
+ nova.stub(:import_keypair) { 'my-keypair-imported' }
424
+ SSHKey.stub(:generate) { ssh_key }
425
+ File.should_receive(:write).with('/data/dir/my-keypair-imported', 'private key')
426
+ File.should_receive(:chmod).with(0600, '/data/dir/my-keypair-imported')
427
+ @action.generate_keypair(env).should eq('my-keypair-imported')
428
+ end
429
+ end
430
+
431
+ describe 'resolve_networks' do
432
+ context 'neutron service is available' do
433
+ context 'with network configured in all possible ways' do
434
+ it 'returns normalized network list' do
435
+ config.stub(:networks) do
436
+ ['001',
437
+ 'net-02',
438
+ { id: '003', address: '1.2.3.4' },
439
+ { name: 'net-04', address: '5.6.7.8' },
440
+ { name: 'net-05' },
441
+ { id: '006' }]
442
+ end
443
+
444
+ expect(@action.resolve_networks(env)).to eq [{ uuid: '001' },
445
+ { uuid: '002' },
446
+ { uuid: '003', fixed_ip: '1.2.3.4' },
447
+ { uuid: '004', fixed_ip: '5.6.7.8' },
448
+ { uuid: '005' },
449
+ { uuid: '006' }]
450
+ end
451
+ end
452
+
453
+ context 'with invalid network object' do
454
+ it 'raises an error' do
455
+ config.stub(:networks) { [1] }
456
+ expect { @action.resolve_networks(env) }.to raise_error(Errors::InvalidNetworkObject)
457
+ end
458
+ end
459
+
460
+ context 'with string that is neither an id nor name matching a network' do
461
+ it 'raises an error' do
462
+ config.stub(:networks) { ['not-exist'] }
463
+ expect { @action.resolve_networks(env) }.to raise_error(Errors::UnresolvedNetwork)
464
+ end
465
+ end
466
+
467
+ context 'with hash containing a bad id' do
468
+ it 'raises an error' do
469
+ config.stub(:networks) { [{ id: 'not-exist' }] }
470
+ expect { @action.resolve_networks(env) }.to raise_error(Errors::UnresolvedNetworkId)
471
+ end
472
+ end
473
+
474
+ context 'with hash containing a bad name' do
475
+ it 'raises an error' do
476
+ config.stub(:networks) { [{ name: 'not-exist' }] }
477
+ expect { @action.resolve_networks(env) }.to raise_error(Errors::UnresolvedNetworkName)
478
+ end
479
+ end
480
+
481
+ context 'with empty hash' do
482
+ it 'raises an error' do
483
+ config.stub(:networks) { [{}] }
484
+ expect { @action.resolve_networks(env) }.to raise_error(Errors::ConflictNetworkNameId)
485
+ end
486
+ end
487
+
488
+ context 'with hash containing both id and name' do
489
+ it 'raises an error' do
490
+ config.stub(:networks) { [{ id: '001', name: 'net-01' }] }
491
+ expect { @action.resolve_networks(env) }.to raise_error(Errors::ConflictNetworkNameId)
492
+ end
493
+ end
494
+
495
+ context 'with hash containing a name matching more than one network' do
496
+ it 'raises an error' do
497
+ config.stub(:networks) { [{ name: 'net-07-08' }] }
498
+ expect { @action.resolve_networks(env) }.to raise_error(Errors::MultipleNetworkName)
499
+ end
500
+ end
501
+ end
502
+
503
+ context 'neutron service is not available' do
504
+ context 'with network configured in all possible ways' do
505
+ it 'returns normalized network list' do
506
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
507
+ config.stub(:networks) do
508
+ ['001',
509
+ { id: '003', address: '1.2.3.4' },
510
+ { id: '006' }]
511
+ end
512
+
513
+ expect(@action.resolve_networks(env)).to eq [{ uuid: '001' },
514
+ { uuid: '003', fixed_ip: '1.2.3.4' },
515
+ { uuid: '006' }]
516
+ end
517
+ end
518
+
519
+ context 'with hash containing both id and name' do
520
+ it 'raises an error' do
521
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
522
+ config.stub(:networks) { [{ id: '001', name: 'net-01' }] }
523
+ expect { @action.resolve_networks(env) }.to raise_error(Errors::ConflictNetworkNameId)
524
+ end
525
+ end
526
+
527
+ context 'with hash containing name' do
528
+ it 'raises an error' do
529
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
530
+ config.stub(:networks) { [{ name: 'net-01' }] }
531
+ expect { @action.resolve_networks(env) }.to raise_error(Errors::NetworkServiceUnavailable)
532
+ end
533
+ end
534
+ end
535
+ end
536
+
537
+ describe 'resolve_volume_boot' do
538
+ context 'cinder service is available' do
539
+ context 'with string volume id' do
540
+ it 'returns normalized volume' do
541
+ config.stub(:volume_boot) { '001' }
542
+ expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vda'
543
+ end
544
+ end
545
+
546
+ context 'with string volume name' do
547
+ it 'returns normalized volume' do
548
+ config.stub(:volume_boot) { 'vol-01' }
549
+ nova.stub(:get_all_images).with(anything) do
550
+ [Item.new('img-001', 'image-01'),
551
+ Item.new('img-002', 'image-02')]
552
+ end
553
+ expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vda'
554
+ end
555
+ end
556
+
557
+ context 'with hash volume id' do
558
+ it 'returns normalized volume' do
559
+ config.stub(:volume_boot) { { id: '001' } }
560
+ expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vda'
561
+ end
562
+ end
563
+
564
+ context 'with hash volume name' do
565
+ it 'returns normalized volume' do
566
+ config.stub(:volume_boot) { { name: 'vol-01' } }
567
+ nova.stub(:get_all_images).with(anything) do
568
+ [Item.new('img-001', 'image-01'),
569
+ Item.new('img-002', 'image-02')]
570
+ end
571
+ expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vda'
572
+ end
573
+ end
574
+
575
+ context 'with hash volume id and device' do
576
+ it 'returns normalized volume' do
577
+ config.stub(:volume_boot) { { id: '001', device: 'vdb' } }
578
+ expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vdb'
579
+ end
580
+ end
581
+
582
+ context 'with hash volume name and device' do
583
+ it 'returns normalized volume' do
584
+ config.stub(:volume_boot) { { name: 'vol-01', device: 'vdb' } }
585
+ nova.stub(:get_all_images).with(anything) do
586
+ [Item.new('img-001', 'image-01'),
587
+ Item.new('img-002', 'image-02')]
588
+ end
589
+ expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vdb'
590
+ end
591
+ end
592
+
593
+ context 'with empty hash' do
594
+ it 'raises an error' do
595
+ config.stub(:volume_boot) { {} }
596
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictBootVolume)
597
+ end
598
+ end
599
+
600
+ context 'with invalid volume object' do
601
+ it 'raises an error' do
602
+ config.stub(:volume_boot) { 1 }
603
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::InvalidVolumeObject)
604
+ end
605
+ end
606
+
607
+ context 'with hash containing a bad id' do
608
+ it 'raises an error' do
609
+ config.stub(:volume_boot) { { id: 'not-exist' } }
610
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::UnresolvedVolumeId)
611
+ end
612
+ end
613
+
614
+ context 'with hash containing a bad name' do
615
+ it 'raises an error' do
616
+ config.stub(:volume_boot) { { name: 'not-exist' } }
617
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::UnresolvedVolumeName)
618
+ end
619
+ end
620
+
621
+ context 'with hash containing both id and name' do
622
+ it 'raises an error' do
623
+ config.stub(:volume_boot) { { id: '001', name: 'vol-01' } }
624
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictVolumeNameId)
625
+ end
626
+ end
627
+
628
+ context 'with hash containing a name matching more than one volume' do
629
+ it 'raises an error' do
630
+ config.stub(:volume_boot) { { name: 'vol-07-08' } }
631
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::MultipleVolumeName)
632
+ end
633
+ end
634
+
635
+ context 'with hash containing a name and an image_name' do
636
+ it 'raises an error' do
637
+ config.stub(:volume_boot) { { name: 'vol-01', image: 'img_001' } }
638
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictBootVolume)
639
+ end
640
+ end
641
+
642
+ context 'with hash containing a name and a size' do
643
+ it 'raises an error' do
644
+ config.stub(:volume_boot) { { name: 'vol-01', size: '10' } }
645
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictBootVolume)
646
+ end
647
+ end
648
+
649
+ context 'with hash containing a name and a delete_on_destroy indication' do
650
+ it 'raises an error' do
651
+ config.stub(:volume_boot) { { name: 'vol-01', delete_on_destroy: 'true' } }
652
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictBootVolume)
653
+ end
654
+ end
655
+
656
+ context 'with hash containing a volume_id and an image_name' do
657
+ it 'raises an error' do
658
+ config.stub(:volume_boot) { { id: 'id', image: 'img_001' } }
659
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictBootVolume)
660
+ end
661
+ end
662
+
663
+ context 'with hash containing a volume_id and a size' do
664
+ it 'raises an error' do
665
+ config.stub(:volume_boot) { { id: 'id', size: '10' } }
666
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictBootVolume)
667
+ end
668
+ end
669
+
670
+ context 'with hash containing a volume_id and a delete_on_destroy indication' do
671
+ it 'raises an error' do
672
+ config.stub(:volume_boot) { { id: 'id', delete_on_destroy: 'true' } }
673
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictBootVolume)
674
+ end
675
+ end
676
+
677
+ context 'with hash containing an image_name without size' do
678
+ it 'raises an error' do
679
+ config.stub(:volume_boot) { { image: 'img-001' } }
680
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::UnresolvedVolume)
681
+ end
682
+ end
683
+
684
+ context 'with hash containing an image_name with a size' do
685
+ it 'return normalized volume' do
686
+ config.stub(:volume_boot) { { image: 'image-01', size: '10' } }
687
+ nova.stub(:get_all_images).with(anything) do
688
+ [Item.new('img-001', 'image-01'),
689
+ Item.new('img-002', 'image-02')]
690
+ end
691
+ expect(@action.resolve_volume_boot(env)).to eq image: 'img-001', device: 'vda', size: '10', delete_on_destroy: 'true'
692
+ end
693
+ end
694
+
695
+ context 'with hash containing an image_name, size, device and delete_on_destroy' do
696
+ it 'return normalized volume' do
697
+ config.stub(:volume_boot) { { image: 'image-01', size: '10', device: 'vdb', delete_on_destroy: 'false' } }
698
+ nova.stub(:get_all_images).with(anything) do
699
+ [Item.new('img-001', 'image-01'),
700
+ Item.new('img-002', 'image-02')]
701
+ end
702
+ expect(@action.resolve_volume_boot(env)).to eq image: 'img-001', device: 'vdb', size: '10', delete_on_destroy: 'false'
703
+ end
704
+ end
705
+ end
706
+
707
+ context 'cinder service is not available' do
708
+ context 'with string volume id' do
709
+ it 'returns normalized volume' do
710
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
711
+ config.stub(:volume_boot) { '001' }
712
+ expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vda'
713
+ end
714
+ end
715
+
716
+ context 'with hash volume id' do
717
+ it 'returns normalized volume' do
718
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
719
+ config.stub(:volume_boot) { { id: '001' } }
720
+ expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vda'
721
+ end
722
+ end
723
+
724
+ context 'with hash volume name' do
725
+ it 'raise an error' do
726
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
727
+ config.stub(:volume_boot) { { name: 'vol-01' } }
728
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::VolumeServiceUnavailable)
729
+ end
730
+ end
731
+
732
+ context 'with hash volume id and device' do
733
+ it 'returns normalized volume' do
734
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
735
+ config.stub(:volume_boot) { { id: '001', device: 'vdb' } }
736
+ expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vdb'
737
+ end
738
+ end
739
+
740
+ context 'with hash volume name and device' do
741
+ it 'raise an error' do
742
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
743
+ config.stub(:volume_boot) { { name: 'vol-01', device: 'vdb' } }
744
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::VolumeServiceUnavailable)
745
+ end
746
+ end
747
+
748
+ context 'with invalid volume object' do
749
+ it 'raises an error' do
750
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
751
+ config.stub(:volume_boot) { 1 }
752
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::InvalidVolumeObject)
753
+ end
754
+ end
755
+
756
+ context 'with hash containing both id and name' do
757
+ it 'raises an error' do
758
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
759
+ config.stub(:volume_boot) { { id: '001', name: 'vol-01' } }
760
+ expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictVolumeNameId)
761
+ end
762
+ end
763
+ end
764
+ end
765
+
766
+ describe 'resolve_volumes' do
767
+ context 'cinder service is available' do
768
+ context 'with volume attached in all possible ways' do
769
+ it 'returns normalized volume list' do
770
+ config.stub(:volumes) do
771
+ ['001',
772
+ 'vol-02',
773
+ { id: '003', device: '/dev/vdz' },
774
+ { name: 'vol-04', device: '/dev/vdy' },
775
+ { name: 'vol-05' },
776
+ { id: '006' }]
777
+ end
778
+
779
+ expect(@action.resolve_volumes(env)).to eq [{ id: '001', device: nil },
780
+ { id: '002', device: nil },
781
+ { id: '003', device: '/dev/vdz' },
782
+ { id: '004', device: '/dev/vdy' },
783
+ { id: '005', device: nil },
784
+ { id: '006', device: nil }]
785
+ end
786
+ end
787
+
788
+ context 'with invalid volume object' do
789
+ it 'raises an error' do
790
+ config.stub(:volumes) { [1] }
791
+ expect { @action.resolve_volumes(env) }.to raise_error(Errors::InvalidVolumeObject)
792
+ end
793
+ end
794
+
795
+ context 'with string that is neither an id nor name matching a volume' do
796
+ it 'raises an error' do
797
+ config.stub(:volumes) { ['not-exist'] }
798
+ expect { @action.resolve_volumes(env) }.to raise_error(Errors::UnresolvedVolume)
799
+ end
800
+ end
801
+
802
+ context 'with hash containing a bad id' do
803
+ it 'raises an error' do
804
+ config.stub(:volumes) { [{ id: 'not-exist' }] }
805
+ expect { @action.resolve_volumes(env) }.to raise_error(Errors::UnresolvedVolumeId)
806
+ end
807
+ end
808
+
809
+ context 'with hash containing a bad name' do
810
+ it 'raises an error' do
811
+ config.stub(:volumes) { [{ name: 'not-exist' }] }
812
+ expect { @action.resolve_volumes(env) }.to raise_error(Errors::UnresolvedVolumeName)
813
+ end
814
+ end
815
+
816
+ context 'with empty hash' do
817
+ it 'raises an error' do
818
+ config.stub(:volumes) { [{}] }
819
+ expect { @action.resolve_volumes(env) }.to raise_error(Errors::ConflictBootVolume)
820
+ end
821
+ end
822
+
823
+ context 'with hash containing both id and name' do
824
+ it 'raises an error' do
825
+ config.stub(:volumes) { [{ id: '001', name: 'vol-01' }] }
826
+ expect { @action.resolve_volumes(env) }.to raise_error(Errors::ConflictVolumeNameId)
827
+ end
828
+ end
829
+
830
+ context 'with hash containing a name matching more than one volume' do
831
+ it 'raises an error' do
832
+ config.stub(:volumes) { [{ name: 'vol-07-08' }] }
833
+ expect { @action.resolve_volumes(env) }.to raise_error(Errors::MultipleVolumeName)
834
+ end
835
+ end
836
+ end
837
+
838
+ context 'cinder service is not available' do
839
+ context 'with volume attached in all possible ways' do
840
+ it 'returns normalized volume list' do
841
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
842
+ config.stub(:volumes) do
843
+ ['001',
844
+ { id: '003', device: '/dev/vdz' },
845
+ { id: '006' }]
846
+ end
847
+
848
+ expect(@action.resolve_volumes(env)).to eq [{ id: '001', device: nil },
849
+ { id: '003', device: '/dev/vdz' },
850
+ { id: '006', device: nil }]
851
+ end
852
+
853
+ context 'with hash containing both id and name' do
854
+ it 'raises an error' do
855
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
856
+ config.stub(:volumes) { [{ id: '001', name: 'vol-01' }] }
857
+ expect { @action.resolve_volumes(env) }.to raise_error(Errors::ConflictVolumeNameId)
858
+ end
859
+ end
860
+ context 'with hash containing name' do
861
+ it 'raises an error' do
862
+ session.stub(:endpoints) { { identity: 'http://keystone', compute: 'http://nova' } }
863
+ config.stub(:volumes) { [{ name: 'vol-01' }] }
864
+ expect { @action.resolve_volumes(env) }.to raise_error(Errors::VolumeServiceUnavailable)
865
+ end
866
+ end
867
+ end
868
+ end
869
+ end
870
+
871
+ describe 'resolve_security_groups' do
872
+ context 'with Hash and String objects' do
873
+ it 'returns normalized Hash list' do
874
+ config.stub(:security_groups) { ['group1', { name: 'group2' }] }
875
+ expect(@action.resolve_security_groups(env)).to eq([{ name: 'group1' }, { name: 'group2' }])
876
+ end
877
+ end
878
+ end
879
+ end