vagrant-openstack-illuin-provider 0.12.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 (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