kitchen-openstack 1.5.2 → 1.5.3
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/.travis.yml +1 -2
- data/CHANGELOG.md +6 -0
- data/README.md +1 -1
- data/Rakefile +3 -5
- data/kitchen-openstack.gemspec +5 -5
- data/lib/kitchen/driver/openstack.rb +67 -82
- data/lib/kitchen/driver/openstack_version.rb +4 -2
- data/spec/kitchen/driver/openstack_spec.rb +288 -251
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7616b4cab10679974a5948b4136caa7740e88154
|
|
4
|
+
data.tar.gz: 5fde868ddac4a5d8c64cc8b21d2cade8821588c6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b39b884a8057e61c4891a7438a866aa6651372e65baf6a0e899a6ad96dc5e0737916dbc6314e0494ab4463d81d3244325677fc12d9a67f2d067755171d1a49d8
|
|
7
|
+
data.tar.gz: fcc37f270a4c08495604f6d5efcc0882c1056ae7e6626373107261f6de4d4f71f81254598479a33c4b527d1fe7f484e10d285deebd91923eb5f706e5be754c93
|
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
# 1.5.3 / 2014-08-01
|
|
2
|
+
|
|
3
|
+
* PR [#53][] - Rework how server names are generated, disallowing possibly
|
|
4
|
+
error-causing punctuation in resultant names
|
|
5
|
+
|
|
1
6
|
# 1.5.2 / 2014-05-31
|
|
2
7
|
|
|
3
8
|
### Bug Fixes
|
|
@@ -101,6 +106,7 @@ certain specified NICs; via [@monsterzz][]
|
|
|
101
106
|
|
|
102
107
|
* Initial release! Woo!
|
|
103
108
|
|
|
109
|
+
[#53]: https://github.com/test-kitchen/kitchen-openstack/pull/53
|
|
104
110
|
[#50]: https://github.com/test-kitchen/kitchen-openstack/pull/50
|
|
105
111
|
[#49]: https://github.com/test-kitchen/kitchen-openstack/pull/49
|
|
106
112
|
[#48]: https://github.com/test-kitchen/kitchen-openstack/pull/48
|
data/README.md
CHANGED
|
@@ -34,7 +34,7 @@ Provide, at a minimum, the required driver options in your `.kitchen.yml` file:
|
|
|
34
34
|
openstack_username: [YOUR OPENSTACK USERNAME]
|
|
35
35
|
openstack_api_key: [YOUR OPENSTACK API KEY]
|
|
36
36
|
openstack_auth_url: [YOUR OPENSTACK AUTH URL]
|
|
37
|
-
require_chef_omnibus:
|
|
37
|
+
require_chef_omnibus: [e.g. 'true' or a version number if you need Chef]
|
|
38
38
|
image_ref: [SERVER IMAGE ID]
|
|
39
39
|
flavor_ref: [SERVER FLAVOR ID]
|
|
40
40
|
|
data/Rakefile
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
# Encoding: UTF-8
|
|
2
2
|
|
|
3
3
|
require 'bundler/setup'
|
|
4
|
-
require '
|
|
4
|
+
require 'rubocop/rake_task'
|
|
5
5
|
require 'cane/rake_task'
|
|
6
6
|
require 'rspec/core/rake_task'
|
|
7
7
|
|
|
8
8
|
Cane::RakeTask.new
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
task.file_set '**/*.rb'
|
|
12
|
-
end
|
|
10
|
+
RuboCop::RakeTask.new
|
|
13
11
|
|
|
14
12
|
desc 'Display LOC stats'
|
|
15
13
|
task :loc do
|
|
@@ -19,4 +17,4 @@ end
|
|
|
19
17
|
|
|
20
18
|
RSpec::Core::RakeTask.new(:spec)
|
|
21
19
|
|
|
22
|
-
task :
|
|
20
|
+
task default: [:cane, :rubocop, :loc, :spec]
|
data/kitchen-openstack.gemspec
CHANGED
|
@@ -9,14 +9,14 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.version = Kitchen::Driver::OPENSTACK_VERSION
|
|
10
10
|
spec.authors = ['Jonathan Hartman']
|
|
11
11
|
spec.email = ['j@p4nt5.com']
|
|
12
|
-
spec.description =
|
|
12
|
+
spec.description = 'A Test Kitchen OpenStack Nova driver'
|
|
13
13
|
spec.summary = spec.description
|
|
14
14
|
spec.homepage = 'https://github.com/test-kitchen/kitchen-openstack'
|
|
15
15
|
spec.license = 'Apache'
|
|
16
16
|
|
|
17
|
-
spec.files = `git ls-files`.split(
|
|
18
|
-
spec.executables = spec.files.grep(
|
|
19
|
-
spec.test_files = spec.files.grep(
|
|
17
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
|
18
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
|
19
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
|
20
20
|
spec.require_paths = ['lib']
|
|
21
21
|
|
|
22
22
|
spec.add_dependency 'test-kitchen', '~> 1.1'
|
|
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
|
27
27
|
|
|
28
28
|
spec.add_development_dependency 'bundler'
|
|
29
29
|
spec.add_development_dependency 'rake'
|
|
30
|
-
spec.add_development_dependency '
|
|
30
|
+
spec.add_development_dependency 'rubocop'
|
|
31
31
|
spec.add_development_dependency 'cane'
|
|
32
32
|
spec.add_development_dependency 'countloc'
|
|
33
33
|
spec.add_development_dependency 'rspec'
|
|
@@ -34,10 +34,10 @@ module Kitchen
|
|
|
34
34
|
|
|
35
35
|
default_config :server_name, nil
|
|
36
36
|
default_config :key_name, nil
|
|
37
|
-
default_config :private_key_path do
|
|
38
|
-
%w
|
|
37
|
+
default_config :private_key_path do
|
|
38
|
+
%w(id_rsa id_dsa).map do |k|
|
|
39
39
|
f = File.expand_path "~/.ssh/#{k}"
|
|
40
|
-
f if File.
|
|
40
|
+
f if File.exist?(f)
|
|
41
41
|
end.compact.first
|
|
42
42
|
end
|
|
43
43
|
default_config :public_key_path do |driver|
|
|
@@ -57,11 +57,15 @@ module Kitchen
|
|
|
57
57
|
|
|
58
58
|
def create(state)
|
|
59
59
|
config[:server_name] ||= generate_name(instance.name)
|
|
60
|
-
config[:disable_ssl_validation]
|
|
60
|
+
config[:disable_ssl_validation] && disable_ssl_validation
|
|
61
61
|
server = create_server
|
|
62
62
|
state[:server_id] = server.id
|
|
63
63
|
info "OpenStack instance <#{state[:server_id]}> created."
|
|
64
|
-
server.wait_for
|
|
64
|
+
server.wait_for do
|
|
65
|
+
print '.'
|
|
66
|
+
ready?
|
|
67
|
+
end
|
|
68
|
+
info "\n(server ready)"
|
|
65
69
|
if config[:floating_ip_pool]
|
|
66
70
|
attach_ip_from_pool(server, config[:floating_ip_pool])
|
|
67
71
|
elsif config[:floating_ip]
|
|
@@ -69,17 +73,15 @@ module Kitchen
|
|
|
69
73
|
end
|
|
70
74
|
state[:hostname] = get_ip(server)
|
|
71
75
|
state[:ssh_key] = config[:private_key_path]
|
|
72
|
-
wait_for_sshd(state[:hostname], config[:username],
|
|
73
|
-
|
|
76
|
+
wait_for_sshd(state[:hostname], config[:username], port: config[:port])
|
|
77
|
+
info '(ssh ready)'
|
|
74
78
|
if config[:key_name]
|
|
75
79
|
info "Using OpenStack keypair <#{config[:key_name]}>"
|
|
76
80
|
end
|
|
77
81
|
info "Using public SSH key <#{config[:public_key_path]}>"
|
|
78
82
|
info "Using private SSH key <#{config[:private_key_path]}>"
|
|
79
|
-
add_ohai_hint(state
|
|
80
|
-
unless config[:key_name]
|
|
81
|
-
do_ssh_setup(state, config, server)
|
|
82
|
-
end
|
|
83
|
+
add_ohai_hint(state)
|
|
84
|
+
do_ssh_setup(state, config, server) unless config[:key_name]
|
|
83
85
|
rescue Fog::Errors::Error, Excon::Errors::Error => ex
|
|
84
86
|
raise ActionFailed, ex.message
|
|
85
87
|
end
|
|
@@ -87,7 +89,7 @@ module Kitchen
|
|
|
87
89
|
def destroy(state)
|
|
88
90
|
return if state[:server_id].nil?
|
|
89
91
|
|
|
90
|
-
config[:disable_ssl_validation]
|
|
92
|
+
config[:disable_ssl_validation] && disable_ssl_validation
|
|
91
93
|
server = compute.servers.get(state[:server_id])
|
|
92
94
|
server.destroy unless server.nil?
|
|
93
95
|
info "OpenStack instance <#{state[:server_id]}> destroyed."
|
|
@@ -99,20 +101,21 @@ module Kitchen
|
|
|
99
101
|
|
|
100
102
|
def openstack_server
|
|
101
103
|
server_def = {
|
|
102
|
-
:
|
|
103
|
-
:openstack_username => config[:openstack_username],
|
|
104
|
-
:openstack_api_key => config[:openstack_api_key],
|
|
105
|
-
:openstack_auth_url => config[:openstack_auth_url]
|
|
104
|
+
provider: 'OpenStack'
|
|
106
105
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
]
|
|
110
|
-
optional.each do |o|
|
|
111
|
-
config[o] and server_def[o] = config[o]
|
|
112
|
-
end
|
|
106
|
+
required_server_settings.each { |s| server_def[s] = config[s] }
|
|
107
|
+
optional_server_settings.each { |s| server_def[s] = config[s] }
|
|
113
108
|
server_def
|
|
114
109
|
end
|
|
115
110
|
|
|
111
|
+
def required_server_settings
|
|
112
|
+
[:openstack_username, :openstack_api_key, :openstack_auth_url]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def optional_server_settings
|
|
116
|
+
[:openstack_tenant, :openstack_region, :openstack_service_name]
|
|
117
|
+
end
|
|
118
|
+
|
|
116
119
|
def network
|
|
117
120
|
Fog::Network.new(openstack_server)
|
|
118
121
|
end
|
|
@@ -148,22 +151,18 @@ module Kitchen
|
|
|
148
151
|
|
|
149
152
|
def init_config
|
|
150
153
|
{
|
|
151
|
-
:
|
|
152
|
-
:
|
|
153
|
-
:
|
|
154
|
+
name: config[:server_name],
|
|
155
|
+
image_ref: find_image(config[:image_ref]).id,
|
|
156
|
+
flavor_ref: find_flavor(config[:flavor_ref]).id
|
|
154
157
|
}
|
|
155
158
|
end
|
|
156
159
|
|
|
157
160
|
def optional_config(c)
|
|
158
161
|
case c
|
|
159
162
|
when :security_groups
|
|
160
|
-
if config[c].
|
|
161
|
-
config[c]
|
|
162
|
-
end
|
|
163
|
+
config[c] if config[c].is_a?(Array)
|
|
163
164
|
when :user_data
|
|
164
|
-
if File.exist?(config[c])
|
|
165
|
-
File.open(config[c]) { |f| f.read }
|
|
166
|
-
end
|
|
165
|
+
File.open(config[c]) { |f| f.read } if File.exist?(config[c])
|
|
167
166
|
else
|
|
168
167
|
config[c]
|
|
169
168
|
end
|
|
@@ -171,61 +170,53 @@ module Kitchen
|
|
|
171
170
|
|
|
172
171
|
def find_image(image_ref)
|
|
173
172
|
image = find_matching(compute.images, image_ref)
|
|
174
|
-
|
|
173
|
+
fail(ActionFailed, 'Image not found') unless image
|
|
175
174
|
debug "Selected image: #{image.id} #{image.name}"
|
|
176
175
|
image
|
|
177
176
|
end
|
|
178
177
|
|
|
179
178
|
def find_flavor(flavor_ref)
|
|
180
179
|
flavor = find_matching(compute.flavors, flavor_ref)
|
|
181
|
-
|
|
180
|
+
fail(ActionFailed, 'Flavor not found') unless flavor
|
|
182
181
|
debug "Selected flavor: #{flavor.id} #{flavor.name}"
|
|
183
182
|
flavor
|
|
184
183
|
end
|
|
185
184
|
|
|
186
185
|
def find_network(network_ref)
|
|
187
186
|
net = find_matching(network.networks.all, network_ref)
|
|
188
|
-
|
|
187
|
+
fail(ActionFailed, 'Network not found') unless net
|
|
189
188
|
debug "Selected net: #{net.id} #{net.name}"
|
|
190
189
|
net
|
|
191
190
|
end
|
|
192
191
|
|
|
192
|
+
# Generate what should be a unique server name up to 63 total chars
|
|
193
|
+
# Base name: 15
|
|
194
|
+
# Username: 15
|
|
195
|
+
# Hostname: 23
|
|
196
|
+
# Random string: 7
|
|
197
|
+
# Separators: 3
|
|
198
|
+
# ================
|
|
199
|
+
# Total: 63
|
|
193
200
|
def generate_name(base)
|
|
194
|
-
# Generate what should be a unique server name up to 63 total chars
|
|
195
|
-
# Base name: 15
|
|
196
|
-
# Username: 15
|
|
197
|
-
# Hostname: 23
|
|
198
|
-
# Random string: 7
|
|
199
|
-
# Separators: 3
|
|
200
|
-
# ================
|
|
201
|
-
# Total: 63
|
|
202
201
|
sep = '-'
|
|
203
202
|
pieces = [
|
|
204
|
-
base,
|
|
205
|
-
Etc.getlogin,
|
|
206
|
-
Socket.gethostname,
|
|
203
|
+
base.gsub(/\W/, '')[0..14],
|
|
204
|
+
Etc.getlogin.gsub(/\W/, '')[0..14],
|
|
205
|
+
Socket.gethostname.gsub(/\W/, '')[0..22],
|
|
207
206
|
Array.new(7) { rand(36).to_s(36) }.join
|
|
208
207
|
]
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
pieces[2] = pieces[2][0..-2]
|
|
212
|
-
elsif pieces[1].length > 15
|
|
213
|
-
pieces[1] = pieces[1][0..-2]
|
|
214
|
-
elsif pieces[0].length > 15
|
|
215
|
-
pieces[0] = pieces[0][0..-2]
|
|
216
|
-
end
|
|
217
|
-
end
|
|
218
|
-
pieces.join sep
|
|
208
|
+
puts "Name: #{pieces.join(sep)}"
|
|
209
|
+
pieces.join(sep)
|
|
219
210
|
end
|
|
220
211
|
|
|
221
212
|
def attach_ip_from_pool(server, pool)
|
|
222
213
|
@@ip_pool_lock.synchronize do
|
|
223
214
|
info "Attaching floating IP from <#{pool}> pool"
|
|
224
|
-
free_addrs = compute.addresses.
|
|
225
|
-
i.ip if i.fixed_ip.nil?
|
|
215
|
+
free_addrs = compute.addresses.map do |i|
|
|
216
|
+
i.ip if i.fixed_ip.nil? && i.instance_id.nil? && i.pool == pool
|
|
226
217
|
end.compact
|
|
227
218
|
if free_addrs.empty?
|
|
228
|
-
|
|
219
|
+
fail ActionFailed, "No available IPs in pool <#{pool}>"
|
|
229
220
|
end
|
|
230
221
|
config[:floating_ip] = free_addrs[0]
|
|
231
222
|
attach_ip(server, free_addrs[0])
|
|
@@ -252,11 +243,11 @@ module Kitchen
|
|
|
252
243
|
rescue Fog::Compute::OpenStack::NotFound
|
|
253
244
|
# See Fog issue: https://github.com/fog/fog/issues/2160
|
|
254
245
|
addrs = server.addresses
|
|
255
|
-
addrs['public']
|
|
256
|
-
addrs['private']
|
|
246
|
+
addrs['public'] && pub = addrs['public'].map { |i| i['addr'] }
|
|
247
|
+
addrs['private'] && priv = addrs['private'].map { |i| i['addr'] }
|
|
257
248
|
end
|
|
258
249
|
pub, priv = parse_ips(pub, priv)
|
|
259
|
-
pub.first || priv.first ||
|
|
250
|
+
pub.first || priv.first || fail(ActionFailed, 'Could not find an IP')
|
|
260
251
|
end
|
|
261
252
|
|
|
262
253
|
def parse_ips(pub, priv)
|
|
@@ -266,27 +257,28 @@ module Kitchen
|
|
|
266
257
|
else
|
|
267
258
|
[pub, priv].each { |n| n.select! { |i| IPAddr.new(i).ipv4? } }
|
|
268
259
|
end
|
|
269
|
-
|
|
260
|
+
[pub, priv]
|
|
270
261
|
end
|
|
271
262
|
|
|
272
|
-
def add_ohai_hint(state
|
|
263
|
+
def add_ohai_hint(state)
|
|
273
264
|
info 'Adding OpenStack hint for ohai'
|
|
274
265
|
ssh = Fog::SSH.new(*build_ssh_args(state))
|
|
275
266
|
ssh.run([
|
|
276
|
-
%
|
|
277
|
-
%
|
|
267
|
+
%(sudo mkdir -p #{Ohai::Config[:hints_path][0]}),
|
|
268
|
+
%(sudo touch #{Ohai::Config[:hints_path][0]}/openstack.json)
|
|
278
269
|
])
|
|
279
270
|
end
|
|
280
271
|
|
|
281
272
|
def do_ssh_setup(state, config, server)
|
|
282
273
|
info "Setting up SSH access for key <#{config[:public_key_path]}>"
|
|
283
|
-
ssh = Fog::SSH.new(state[:hostname],
|
|
284
|
-
|
|
274
|
+
ssh = Fog::SSH.new(state[:hostname],
|
|
275
|
+
config[:username],
|
|
276
|
+
password: server.password)
|
|
285
277
|
pub_key = open(config[:public_key_path]).read
|
|
286
278
|
ssh.run([
|
|
287
|
-
%
|
|
288
|
-
%
|
|
289
|
-
%
|
|
279
|
+
%(mkdir .ssh),
|
|
280
|
+
%(echo "#{pub_key}" >> ~/.ssh/authorized_keys),
|
|
281
|
+
%(passwd -l #{config[:username]})
|
|
290
282
|
])
|
|
291
283
|
end
|
|
292
284
|
|
|
@@ -297,25 +289,18 @@ module Kitchen
|
|
|
297
289
|
|
|
298
290
|
def find_matching(collection, name)
|
|
299
291
|
name = name.to_s
|
|
300
|
-
if name.start_with?('/')
|
|
301
|
-
regex =
|
|
292
|
+
if name.start_with?('/') && name.end_with?('/')
|
|
293
|
+
regex = Regexp.new(name[1...-1])
|
|
302
294
|
# check for regex name match
|
|
303
|
-
collection.each
|
|
304
|
-
return single if regex =~ single.name
|
|
305
|
-
end
|
|
295
|
+
collection.each { |single| return single if regex =~ single.name }
|
|
306
296
|
else
|
|
307
297
|
# check for exact id match
|
|
308
|
-
collection.each
|
|
309
|
-
return single if single.id == name
|
|
310
|
-
end
|
|
298
|
+
collection.each { |single| return single if single.id == name }
|
|
311
299
|
# check for exact name match
|
|
312
|
-
collection.each
|
|
313
|
-
return single if single.name == name
|
|
314
|
-
end
|
|
300
|
+
collection.each { |single| return single if single.name == name }
|
|
315
301
|
end
|
|
316
302
|
nil
|
|
317
303
|
end
|
|
318
|
-
|
|
319
304
|
end
|
|
320
305
|
end
|
|
321
306
|
end
|
|
@@ -17,8 +17,10 @@
|
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
|
|
19
19
|
module Kitchen
|
|
20
|
+
# Version string for OpenStack Kitchen driver
|
|
21
|
+
#
|
|
22
|
+
# @author Jonathan Hartman <j@p4nt5.com>
|
|
20
23
|
module Driver
|
|
21
|
-
|
|
22
|
-
OPENSTACK_VERSION = '1.5.2'
|
|
24
|
+
OPENSTACK_VERSION = '1.5.3'
|
|
23
25
|
end
|
|
24
26
|
end
|
|
@@ -34,7 +34,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
34
34
|
|
|
35
35
|
let(:instance) do
|
|
36
36
|
double(
|
|
37
|
-
:
|
|
37
|
+
name: 'potatoes', logger: logger, to_str: 'instance'
|
|
38
38
|
)
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -45,9 +45,9 @@ describe Kitchen::Driver::Openstack do
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
before(:each) do
|
|
48
|
-
File.
|
|
49
|
-
File.
|
|
50
|
-
File.
|
|
48
|
+
allow(File).to receive(:exist?).and_call_original
|
|
49
|
+
allow(File).to receive(:exist?).with(dsa).and_return(true)
|
|
50
|
+
allow(File).to receive(:exist?).with(rsa).and_return(true)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
describe '#initialize'do
|
|
@@ -64,9 +64,8 @@ describe Kitchen::Driver::Openstack do
|
|
|
64
64
|
|
|
65
65
|
context 'only a DSA SSH key available for the user' do
|
|
66
66
|
before(:each) do
|
|
67
|
-
File.
|
|
68
|
-
File.
|
|
69
|
-
File.stub(:exists?).with(dsa).and_return(true)
|
|
67
|
+
allow(File).to receive(:exist?).and_return(false)
|
|
68
|
+
allow(File).to receive(:exist?).with(dsa).and_return(true)
|
|
70
69
|
end
|
|
71
70
|
|
|
72
71
|
it 'uses the local user\'s DSA private key' do
|
|
@@ -80,9 +79,8 @@ describe Kitchen::Driver::Openstack do
|
|
|
80
79
|
|
|
81
80
|
context 'only a RSA SSH key available for the user' do
|
|
82
81
|
before(:each) do
|
|
83
|
-
File.
|
|
84
|
-
File.
|
|
85
|
-
File.stub(:exists?).with(rsa).and_return(true)
|
|
82
|
+
allow(File).to receive(:exist?).and_return(false)
|
|
83
|
+
allow(File).to receive(:exist?).with(rsa).and_return(true)
|
|
86
84
|
end
|
|
87
85
|
|
|
88
86
|
it 'uses the local user\'s RSA private key' do
|
|
@@ -118,19 +116,19 @@ describe Kitchen::Driver::Openstack do
|
|
|
118
116
|
context 'overridden options' do
|
|
119
117
|
let(:config) do
|
|
120
118
|
{
|
|
121
|
-
:
|
|
122
|
-
:
|
|
123
|
-
:
|
|
124
|
-
:
|
|
125
|
-
:
|
|
126
|
-
:
|
|
127
|
-
:
|
|
128
|
-
:
|
|
129
|
-
:
|
|
130
|
-
:
|
|
131
|
-
:
|
|
132
|
-
:
|
|
133
|
-
:
|
|
119
|
+
image_ref: '22',
|
|
120
|
+
flavor_ref: '33',
|
|
121
|
+
public_key_path: '/tmp',
|
|
122
|
+
username: 'admin',
|
|
123
|
+
port: '2222',
|
|
124
|
+
server_name: 'puppy',
|
|
125
|
+
openstack_tenant: 'that_one',
|
|
126
|
+
openstack_region: 'atlantis',
|
|
127
|
+
openstack_service_name: 'the_service',
|
|
128
|
+
private_key_path: '/path/to/id_rsa',
|
|
129
|
+
floating_ip_pool: 'swimmers',
|
|
130
|
+
floating_ip: '11111',
|
|
131
|
+
network_ref: '0xCAFFE'
|
|
134
132
|
}
|
|
135
133
|
end
|
|
136
134
|
|
|
@@ -145,31 +143,29 @@ describe Kitchen::Driver::Openstack do
|
|
|
145
143
|
|
|
146
144
|
describe '#create' do
|
|
147
145
|
let(:server) do
|
|
148
|
-
double(:
|
|
149
|
-
:public_ip_addresses => %w{1.2.3.4})
|
|
146
|
+
double(id: 'test123', wait_for: true, public_ip_addresses: %w(1.2.3.4))
|
|
150
147
|
end
|
|
151
148
|
let(:driver) do
|
|
152
149
|
d = Kitchen::Driver::Openstack.new(config)
|
|
153
150
|
d.instance = instance
|
|
154
|
-
d.
|
|
155
|
-
|
|
156
|
-
d.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
d.
|
|
161
|
-
d.
|
|
162
|
-
d.stub(:do_ssh_setup).and_return(true)
|
|
151
|
+
allow(d).to receive(:generate_name).with('potatoes')
|
|
152
|
+
.and_return('a_monkey!')
|
|
153
|
+
allow(d).to receive(:create_server).and_return(server)
|
|
154
|
+
allow(d).to receive(:wait_for_sshd).with('1.2.3.4', 'root', port: '22')
|
|
155
|
+
.and_return(true)
|
|
156
|
+
allow(d).to receive(:get_ip).and_return('1.2.3.4')
|
|
157
|
+
allow(d).to receive(:add_ohai_hint).and_return(true)
|
|
158
|
+
allow(d).to receive(:do_ssh_setup).and_return(true)
|
|
163
159
|
d
|
|
164
160
|
end
|
|
165
161
|
|
|
166
162
|
context 'required options provided' do
|
|
167
163
|
let(:config) do
|
|
168
164
|
{
|
|
169
|
-
:
|
|
170
|
-
:
|
|
171
|
-
:
|
|
172
|
-
:
|
|
165
|
+
openstack_username: 'hello',
|
|
166
|
+
openstack_api_key: 'world',
|
|
167
|
+
openstack_auth_url: 'http:',
|
|
168
|
+
openstack_tenant: 'www'
|
|
173
169
|
}
|
|
174
170
|
end
|
|
175
171
|
|
|
@@ -189,16 +185,16 @@ describe Kitchen::Driver::Openstack do
|
|
|
189
185
|
end
|
|
190
186
|
|
|
191
187
|
it 'does not disable SSL validation' do
|
|
192
|
-
driver.
|
|
188
|
+
expect(driver).to_not receive(:disable_ssl_validation)
|
|
193
189
|
driver.create(state)
|
|
194
190
|
end
|
|
195
191
|
end
|
|
196
192
|
|
|
197
193
|
context 'SSL validation disabled' do
|
|
198
|
-
let(:config) { { :
|
|
194
|
+
let(:config) { { disable_ssl_validation: true } }
|
|
199
195
|
|
|
200
196
|
it 'disables SSL cert validation' do
|
|
201
|
-
driver.
|
|
197
|
+
expect(driver).to receive(:disable_ssl_validation)
|
|
202
198
|
driver.create(state)
|
|
203
199
|
end
|
|
204
200
|
end
|
|
@@ -207,27 +203,27 @@ describe Kitchen::Driver::Openstack do
|
|
|
207
203
|
describe '#destroy' do
|
|
208
204
|
let(:server_id) { '12345' }
|
|
209
205
|
let(:hostname) { 'example.com' }
|
|
210
|
-
let(:state) { { :
|
|
211
|
-
let(:server) { double(
|
|
212
|
-
let(:servers) { double(:
|
|
213
|
-
let(:compute) { double(:
|
|
206
|
+
let(:state) { { server_id: server_id, hostname: hostname } }
|
|
207
|
+
let(:server) { double(nil?: false, destroy: true) }
|
|
208
|
+
let(:servers) { double(get: server) }
|
|
209
|
+
let(:compute) { double(servers: servers) }
|
|
214
210
|
|
|
215
211
|
let(:driver) do
|
|
216
212
|
d = Kitchen::Driver::Openstack.new(config)
|
|
217
213
|
d.instance = instance
|
|
218
|
-
d.
|
|
214
|
+
allow(d).to receive(:compute).and_return(compute)
|
|
219
215
|
d
|
|
220
216
|
end
|
|
221
217
|
|
|
222
218
|
context 'a live server that needs to be destroyed' do
|
|
223
219
|
it 'destroys the server' do
|
|
224
|
-
state.
|
|
225
|
-
state.
|
|
220
|
+
expect(state).to receive(:delete).with(:server_id)
|
|
221
|
+
expect(state).to receive(:delete).with(:hostname)
|
|
226
222
|
driver.destroy(state)
|
|
227
223
|
end
|
|
228
224
|
|
|
229
225
|
it 'does not disable SSL cert validation' do
|
|
230
|
-
driver.
|
|
226
|
+
expect(driver).to_not receive(:disable_ssl_validation)
|
|
231
227
|
driver.destroy(state)
|
|
232
228
|
end
|
|
233
229
|
end
|
|
@@ -236,9 +232,9 @@ describe Kitchen::Driver::Openstack do
|
|
|
236
232
|
let(:state) { Hash.new }
|
|
237
233
|
|
|
238
234
|
it 'does nothing' do
|
|
239
|
-
driver.
|
|
240
|
-
driver.
|
|
241
|
-
state.
|
|
235
|
+
allow(driver).to receive(:compute)
|
|
236
|
+
expect(driver).to_not receive(:compute)
|
|
237
|
+
expect(state).to_not receive(:delete)
|
|
242
238
|
driver.destroy(state)
|
|
243
239
|
end
|
|
244
240
|
end
|
|
@@ -246,14 +242,14 @@ describe Kitchen::Driver::Openstack do
|
|
|
246
242
|
context 'a server that was already destroyed' do
|
|
247
243
|
let(:servers) do
|
|
248
244
|
s = double('servers')
|
|
249
|
-
s.
|
|
245
|
+
allow(s).to receive(:get).with('12345').and_return(nil)
|
|
250
246
|
s
|
|
251
247
|
end
|
|
252
|
-
let(:compute) { double(:
|
|
248
|
+
let(:compute) { double(servers: servers) }
|
|
253
249
|
let(:driver) do
|
|
254
250
|
d = Kitchen::Driver::Openstack.new(config)
|
|
255
251
|
d.instance = instance
|
|
256
|
-
d.
|
|
252
|
+
allow(d).to receive(:compute).and_return(compute)
|
|
257
253
|
d
|
|
258
254
|
end
|
|
259
255
|
|
|
@@ -264,43 +260,79 @@ describe Kitchen::Driver::Openstack do
|
|
|
264
260
|
end
|
|
265
261
|
|
|
266
262
|
context 'SSL validation disabled' do
|
|
267
|
-
let(:config) { { :
|
|
263
|
+
let(:config) { { disable_ssl_validation: true } }
|
|
268
264
|
|
|
269
265
|
it 'disables SSL cert validation' do
|
|
270
|
-
driver.
|
|
266
|
+
expect(driver).to receive(:disable_ssl_validation)
|
|
271
267
|
driver.destroy(state)
|
|
272
268
|
end
|
|
273
269
|
end
|
|
274
270
|
end
|
|
275
271
|
|
|
272
|
+
describe '#openstack_server' do
|
|
273
|
+
let(:config) do
|
|
274
|
+
{
|
|
275
|
+
openstack_username: 'a',
|
|
276
|
+
openstack_api_key: 'b',
|
|
277
|
+
openstack_auth_url: 'http://',
|
|
278
|
+
openstack_tenant: 'me',
|
|
279
|
+
openstack_region: 'ORD',
|
|
280
|
+
openstack_service_name: 'stack'
|
|
281
|
+
}
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
it 'returns a hash of server settings' do
|
|
285
|
+
expected = config.merge(provider: 'OpenStack')
|
|
286
|
+
expect(driver.send(:openstack_server)).to eq(expected)
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
describe '#required_server_settings' do
|
|
291
|
+
it 'returns the required settings for an OpenStack server' do
|
|
292
|
+
expected = [
|
|
293
|
+
:openstack_username, :openstack_api_key, :openstack_auth_url
|
|
294
|
+
]
|
|
295
|
+
expect(driver.send(:required_server_settings)).to eq(expected)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
describe '#optional_server_settings' do
|
|
300
|
+
it 'returns the optional settings for an OpenStack server' do
|
|
301
|
+
expected = [
|
|
302
|
+
:openstack_tenant, :openstack_region, :openstack_service_name
|
|
303
|
+
]
|
|
304
|
+
expect(driver.send(:optional_server_settings)).to eq(expected)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
276
308
|
describe '#compute' do
|
|
277
309
|
let(:config) do
|
|
278
310
|
{
|
|
279
|
-
:
|
|
280
|
-
:
|
|
281
|
-
:
|
|
282
|
-
:
|
|
283
|
-
:
|
|
284
|
-
:
|
|
311
|
+
openstack_username: 'monkey',
|
|
312
|
+
openstack_api_key: 'potato',
|
|
313
|
+
openstack_auth_url: 'http:',
|
|
314
|
+
openstack_tenant: 'link',
|
|
315
|
+
openstack_region: 'ord',
|
|
316
|
+
openstack_service_name: 'the_service'
|
|
285
317
|
}
|
|
286
318
|
end
|
|
287
319
|
|
|
288
320
|
context 'all requirements provided' do
|
|
289
321
|
it 'creates a new compute connection' do
|
|
290
|
-
Fog::Compute.
|
|
291
|
-
res = config.merge(
|
|
322
|
+
allow(Fog::Compute).to receive(:new) { |arg| arg }
|
|
323
|
+
res = config.merge(provider: 'OpenStack')
|
|
292
324
|
expect(driver.send(:compute)).to eq(res)
|
|
293
325
|
end
|
|
294
326
|
|
|
295
327
|
it 'creates a new network connection' do
|
|
296
|
-
Fog::Network.
|
|
297
|
-
res = config.merge(
|
|
328
|
+
allow(Fog::Network).to receive(:new) { |arg| arg }
|
|
329
|
+
res = config.merge(provider: 'OpenStack')
|
|
298
330
|
expect(driver.send(:network)).to eq(res)
|
|
299
331
|
end
|
|
300
332
|
end
|
|
301
333
|
|
|
302
334
|
context 'only an API key provided' do
|
|
303
|
-
let(:config) { { :
|
|
335
|
+
let(:config) { { openstack_api_key: '1234' } }
|
|
304
336
|
|
|
305
337
|
it 'raises an error' do
|
|
306
338
|
expect { driver.send(:compute) }.to raise_error(ArgumentError)
|
|
@@ -308,7 +340,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
308
340
|
end
|
|
309
341
|
|
|
310
342
|
context 'only a username provided' do
|
|
311
|
-
let(:config) { { :
|
|
343
|
+
let(:config) { { openstack_username: 'monkey' } }
|
|
312
344
|
|
|
313
345
|
it 'raises an error' do
|
|
314
346
|
expect { driver.send(:compute) }.to raise_error(ArgumentError)
|
|
@@ -319,51 +351,45 @@ describe Kitchen::Driver::Openstack do
|
|
|
319
351
|
describe '#create_server' do
|
|
320
352
|
let(:config) do
|
|
321
353
|
{
|
|
322
|
-
:
|
|
323
|
-
:
|
|
324
|
-
:
|
|
325
|
-
:
|
|
354
|
+
server_name: 'hello',
|
|
355
|
+
image_ref: '111',
|
|
356
|
+
flavor_ref: '1',
|
|
357
|
+
public_key_path: 'tarpals'
|
|
326
358
|
}
|
|
327
359
|
end
|
|
328
360
|
let(:servers) do
|
|
329
361
|
s = double('servers')
|
|
330
|
-
s.
|
|
362
|
+
allow(s).to receive(:create) { |arg| arg }
|
|
331
363
|
s
|
|
332
364
|
end
|
|
333
|
-
let(:vlan1_net) { double(:
|
|
334
|
-
let(:vlan2_net) { double(:
|
|
335
|
-
let(:ubuntu_image) { double(:
|
|
336
|
-
let(:fedora_image) { double(:
|
|
337
|
-
let(:tiny_flavor) { double(:
|
|
338
|
-
let(:small_flavor) { double(:
|
|
365
|
+
let(:vlan1_net) { double(id: '1', name: 'vlan1') }
|
|
366
|
+
let(:vlan2_net) { double(id: '2', name: 'vlan2') }
|
|
367
|
+
let(:ubuntu_image) { double(id: '111', name: 'ubuntu') }
|
|
368
|
+
let(:fedora_image) { double(id: '222', name: 'fedora') }
|
|
369
|
+
let(:tiny_flavor) { double(id: '1', name: 'tiny') }
|
|
370
|
+
let(:small_flavor) { double(id: '2', name: 'small') }
|
|
339
371
|
let(:compute) do
|
|
340
372
|
double(
|
|
341
|
-
:
|
|
342
|
-
:
|
|
343
|
-
:
|
|
373
|
+
servers: servers,
|
|
374
|
+
images: [ubuntu_image, fedora_image],
|
|
375
|
+
flavors: [tiny_flavor, small_flavor]
|
|
344
376
|
)
|
|
345
377
|
end
|
|
346
378
|
let(:network) do
|
|
347
|
-
double(
|
|
348
|
-
:networks => double(
|
|
349
|
-
:all => [vlan1_net, vlan2_net]
|
|
350
|
-
)
|
|
351
|
-
)
|
|
379
|
+
double(networks: double(all: [vlan1_net, vlan2_net]))
|
|
352
380
|
end
|
|
353
381
|
let(:driver) do
|
|
354
382
|
d = Kitchen::Driver::Openstack.new(config)
|
|
355
383
|
d.instance = instance
|
|
356
|
-
d.
|
|
357
|
-
d.
|
|
384
|
+
allow(d).to receive(:compute).and_return(compute)
|
|
385
|
+
allow(d).to receive(:network).and_return(network)
|
|
358
386
|
d
|
|
359
387
|
end
|
|
360
388
|
|
|
361
389
|
context 'a default config' do
|
|
362
390
|
before(:each) do
|
|
363
|
-
@expected = config.merge(:
|
|
364
|
-
@expected.delete_if
|
|
365
|
-
k == :server_name
|
|
366
|
-
end
|
|
391
|
+
@expected = config.merge(name: config[:server_name])
|
|
392
|
+
@expected.delete_if { |k, _| k == :server_name }
|
|
367
393
|
end
|
|
368
394
|
|
|
369
395
|
it 'creates the server using a compute connection' do
|
|
@@ -374,17 +400,15 @@ describe Kitchen::Driver::Openstack do
|
|
|
374
400
|
context 'a provided public key path' do
|
|
375
401
|
let(:config) do
|
|
376
402
|
{
|
|
377
|
-
:
|
|
378
|
-
:
|
|
379
|
-
:
|
|
380
|
-
:
|
|
403
|
+
server_name: 'hello',
|
|
404
|
+
image_ref: '111',
|
|
405
|
+
flavor_ref: '1',
|
|
406
|
+
public_key_path: 'tarpals'
|
|
381
407
|
}
|
|
382
408
|
end
|
|
383
409
|
before(:each) do
|
|
384
|
-
@expected = config.merge(:
|
|
385
|
-
@expected.delete_if
|
|
386
|
-
k == :server_name
|
|
387
|
-
end
|
|
410
|
+
@expected = config.merge(name: config[:server_name])
|
|
411
|
+
@expected.delete_if { |k, _| k == :server_name }
|
|
388
412
|
end
|
|
389
413
|
|
|
390
414
|
it 'passes that public key path to Fog' do
|
|
@@ -395,19 +419,17 @@ describe Kitchen::Driver::Openstack do
|
|
|
395
419
|
context 'a provided key name' do
|
|
396
420
|
let(:config) do
|
|
397
421
|
{
|
|
398
|
-
:
|
|
399
|
-
:
|
|
400
|
-
:
|
|
401
|
-
:
|
|
402
|
-
:
|
|
422
|
+
server_name: 'hello',
|
|
423
|
+
image_ref: '111',
|
|
424
|
+
flavor_ref: '1',
|
|
425
|
+
public_key_path: 'montgomery',
|
|
426
|
+
key_name: 'tarpals'
|
|
403
427
|
}
|
|
404
428
|
end
|
|
405
429
|
|
|
406
430
|
before(:each) do
|
|
407
|
-
@expected = config.merge(:
|
|
408
|
-
@expected.delete_if
|
|
409
|
-
k == :server_name
|
|
410
|
-
end
|
|
431
|
+
@expected = config.merge(name: config[:server_name])
|
|
432
|
+
@expected.delete_if { |k, _| k == :server_name }
|
|
411
433
|
end
|
|
412
434
|
|
|
413
435
|
it 'passes that key name to Fog' do
|
|
@@ -418,20 +440,18 @@ describe Kitchen::Driver::Openstack do
|
|
|
418
440
|
context 'a provided security group' do
|
|
419
441
|
let(:config) do
|
|
420
442
|
{
|
|
421
|
-
:
|
|
422
|
-
:
|
|
423
|
-
:
|
|
424
|
-
:
|
|
425
|
-
:
|
|
426
|
-
:
|
|
443
|
+
server_name: 'hello',
|
|
444
|
+
image_ref: '111',
|
|
445
|
+
flavor_ref: '1',
|
|
446
|
+
public_key_path: 'montgomery',
|
|
447
|
+
key_name: 'tarpals',
|
|
448
|
+
security_groups: ['ping-and-ssh']
|
|
427
449
|
}
|
|
428
450
|
end
|
|
429
451
|
|
|
430
452
|
before(:each) do
|
|
431
|
-
@expected = config.merge(:
|
|
432
|
-
@expected.delete_if
|
|
433
|
-
k == :server_name
|
|
434
|
-
end
|
|
453
|
+
@expected = config.merge(name: config[:server_name])
|
|
454
|
+
@expected.delete_if { |k, _| k == :server_name }
|
|
435
455
|
end
|
|
436
456
|
|
|
437
457
|
it 'passes that security group to Fog' do
|
|
@@ -442,17 +462,18 @@ describe Kitchen::Driver::Openstack do
|
|
|
442
462
|
context 'image/flavor specifies id' do
|
|
443
463
|
let(:config) do
|
|
444
464
|
{
|
|
445
|
-
:
|
|
446
|
-
:
|
|
447
|
-
:
|
|
448
|
-
:
|
|
465
|
+
server_name: 'hello',
|
|
466
|
+
image_ref: '111',
|
|
467
|
+
flavor_ref: '1',
|
|
468
|
+
public_key_path: 'tarpals'
|
|
449
469
|
}
|
|
450
470
|
end
|
|
451
471
|
|
|
452
472
|
it 'exact id match' do
|
|
453
|
-
servers.
|
|
454
|
-
|
|
455
|
-
|
|
473
|
+
expect(servers).to receive(:create).with(name: 'hello',
|
|
474
|
+
image_ref: '111',
|
|
475
|
+
flavor_ref: '1',
|
|
476
|
+
public_key_path: 'tarpals')
|
|
456
477
|
driver.send(:create_server)
|
|
457
478
|
end
|
|
458
479
|
end
|
|
@@ -460,17 +481,18 @@ describe Kitchen::Driver::Openstack do
|
|
|
460
481
|
context 'image/flavor specifies name' do
|
|
461
482
|
let(:config) do
|
|
462
483
|
{
|
|
463
|
-
:
|
|
464
|
-
:
|
|
465
|
-
:
|
|
466
|
-
:
|
|
484
|
+
server_name: 'hello',
|
|
485
|
+
image_ref: 'fedora',
|
|
486
|
+
flavor_ref: 'small',
|
|
487
|
+
public_key_path: 'tarpals'
|
|
467
488
|
}
|
|
468
489
|
end
|
|
469
490
|
|
|
470
491
|
it 'exact name match' do
|
|
471
|
-
servers.
|
|
472
|
-
|
|
473
|
-
|
|
492
|
+
expect(servers).to receive(:create).with(name: 'hello',
|
|
493
|
+
image_ref: '222',
|
|
494
|
+
flavor_ref: '2',
|
|
495
|
+
public_key_path: 'tarpals')
|
|
474
496
|
driver.send(:create_server)
|
|
475
497
|
end
|
|
476
498
|
end
|
|
@@ -478,18 +500,19 @@ describe Kitchen::Driver::Openstack do
|
|
|
478
500
|
context 'image/flavor specifies regex' do
|
|
479
501
|
let(:config) do
|
|
480
502
|
{
|
|
481
|
-
:
|
|
503
|
+
server_name: 'hello',
|
|
482
504
|
# pass regex as string as yml returns string values
|
|
483
|
-
:
|
|
484
|
-
:
|
|
485
|
-
:
|
|
505
|
+
image_ref: '/edo/',
|
|
506
|
+
flavor_ref: '/in/',
|
|
507
|
+
public_key_path: 'tarpals'
|
|
486
508
|
}
|
|
487
509
|
end
|
|
488
510
|
|
|
489
511
|
it 'regex name match' do
|
|
490
|
-
servers.
|
|
491
|
-
|
|
492
|
-
|
|
512
|
+
expect(servers).to receive(:create).with(name: 'hello',
|
|
513
|
+
image_ref: '222',
|
|
514
|
+
flavor_ref: '1',
|
|
515
|
+
public_key_path: 'tarpals')
|
|
493
516
|
driver.send(:create_server)
|
|
494
517
|
end
|
|
495
518
|
end
|
|
@@ -497,11 +520,11 @@ describe Kitchen::Driver::Openstack do
|
|
|
497
520
|
context 'network specifies id' do
|
|
498
521
|
let(:config) do
|
|
499
522
|
{
|
|
500
|
-
:
|
|
501
|
-
:
|
|
502
|
-
:
|
|
503
|
-
:
|
|
504
|
-
:
|
|
523
|
+
server_name: 'hello',
|
|
524
|
+
image_ref: '111',
|
|
525
|
+
flavor_ref: '1',
|
|
526
|
+
public_key_path: 'tarpals',
|
|
527
|
+
network_ref: '1'
|
|
505
528
|
}
|
|
506
529
|
end
|
|
507
530
|
|
|
@@ -509,12 +532,12 @@ describe Kitchen::Driver::Openstack do
|
|
|
509
532
|
networks = [
|
|
510
533
|
{ 'net_id' => '1' }
|
|
511
534
|
]
|
|
512
|
-
servers.
|
|
513
|
-
:
|
|
514
|
-
:
|
|
515
|
-
:
|
|
516
|
-
:
|
|
517
|
-
:
|
|
535
|
+
expect(servers).to receive(:create).with(
|
|
536
|
+
name: 'hello',
|
|
537
|
+
image_ref: '111',
|
|
538
|
+
flavor_ref: '1',
|
|
539
|
+
public_key_path: 'tarpals',
|
|
540
|
+
nics: networks
|
|
518
541
|
)
|
|
519
542
|
driver.send(:create_server)
|
|
520
543
|
end
|
|
@@ -523,11 +546,11 @@ describe Kitchen::Driver::Openstack do
|
|
|
523
546
|
context 'network specifies name' do
|
|
524
547
|
let(:config) do
|
|
525
548
|
{
|
|
526
|
-
:
|
|
527
|
-
:
|
|
528
|
-
:
|
|
529
|
-
:
|
|
530
|
-
:
|
|
549
|
+
server_name: 'hello',
|
|
550
|
+
image_ref: '111',
|
|
551
|
+
flavor_ref: '1',
|
|
552
|
+
public_key_path: 'tarpals',
|
|
553
|
+
network_ref: 'vlan1'
|
|
531
554
|
}
|
|
532
555
|
end
|
|
533
556
|
|
|
@@ -535,12 +558,12 @@ describe Kitchen::Driver::Openstack do
|
|
|
535
558
|
networks = [
|
|
536
559
|
{ 'net_id' => '1' }
|
|
537
560
|
]
|
|
538
|
-
servers.
|
|
539
|
-
:
|
|
540
|
-
:
|
|
541
|
-
:
|
|
542
|
-
:
|
|
543
|
-
:
|
|
561
|
+
expect(servers).to receive(:create).with(
|
|
562
|
+
name: 'hello',
|
|
563
|
+
image_ref: '111',
|
|
564
|
+
flavor_ref: '1',
|
|
565
|
+
public_key_path: 'tarpals',
|
|
566
|
+
nics: networks
|
|
544
567
|
)
|
|
545
568
|
driver.send(:create_server)
|
|
546
569
|
end
|
|
@@ -549,25 +572,25 @@ describe Kitchen::Driver::Openstack do
|
|
|
549
572
|
context 'multiple networks specifies id' do
|
|
550
573
|
let(:config) do
|
|
551
574
|
{
|
|
552
|
-
:
|
|
553
|
-
:
|
|
554
|
-
:
|
|
555
|
-
:
|
|
556
|
-
:
|
|
575
|
+
server_name: 'hello',
|
|
576
|
+
image_ref: '111',
|
|
577
|
+
flavor_ref: '1',
|
|
578
|
+
public_key_path: 'tarpals',
|
|
579
|
+
network_ref: %w(1 2)
|
|
557
580
|
}
|
|
558
581
|
end
|
|
559
582
|
|
|
560
583
|
it 'exact id match' do
|
|
561
584
|
networks = [
|
|
562
585
|
{ 'net_id' => '1' },
|
|
563
|
-
{ 'net_id' => '2' }
|
|
586
|
+
{ 'net_id' => '2' }
|
|
564
587
|
]
|
|
565
|
-
servers.
|
|
566
|
-
:
|
|
567
|
-
:
|
|
568
|
-
:
|
|
569
|
-
:
|
|
570
|
-
:
|
|
588
|
+
expect(servers).to receive(:create).with(
|
|
589
|
+
name: 'hello',
|
|
590
|
+
image_ref: '111',
|
|
591
|
+
flavor_ref: '1',
|
|
592
|
+
public_key_path: 'tarpals',
|
|
593
|
+
nics: networks
|
|
571
594
|
)
|
|
572
595
|
driver.send(:create_server)
|
|
573
596
|
end
|
|
@@ -576,27 +599,27 @@ describe Kitchen::Driver::Openstack do
|
|
|
576
599
|
context 'user_data specified' do
|
|
577
600
|
let(:config) do
|
|
578
601
|
{
|
|
579
|
-
:
|
|
580
|
-
:
|
|
581
|
-
:
|
|
582
|
-
:
|
|
583
|
-
:
|
|
602
|
+
server_name: 'hello',
|
|
603
|
+
image_ref: '111',
|
|
604
|
+
flavor_ref: '1',
|
|
605
|
+
public_key_path: 'tarpals',
|
|
606
|
+
user_data: 'cloud-init.txt'
|
|
584
607
|
}
|
|
585
608
|
end
|
|
586
609
|
let(:data) { "#cloud-config\n" }
|
|
587
610
|
|
|
588
611
|
before(:each) do
|
|
589
|
-
File.
|
|
590
|
-
File.
|
|
612
|
+
allow(File).to receive(:exist?).and_return(true)
|
|
613
|
+
allow(File).to receive(:open).and_return(data)
|
|
591
614
|
end
|
|
592
615
|
|
|
593
|
-
it '
|
|
594
|
-
servers.
|
|
595
|
-
:
|
|
596
|
-
:
|
|
597
|
-
:
|
|
598
|
-
:
|
|
599
|
-
:
|
|
616
|
+
it 'passes file contents' do
|
|
617
|
+
expect(servers).to receive(:create).with(
|
|
618
|
+
name: 'hello',
|
|
619
|
+
image_ref: '111',
|
|
620
|
+
flavor_ref: '1',
|
|
621
|
+
public_key_path: 'tarpals',
|
|
622
|
+
user_data: data)
|
|
600
623
|
driver.send(:create_server)
|
|
601
624
|
end
|
|
602
625
|
end
|
|
@@ -604,8 +627,8 @@ describe Kitchen::Driver::Openstack do
|
|
|
604
627
|
|
|
605
628
|
describe '#generate_name' do
|
|
606
629
|
before(:each) do
|
|
607
|
-
Etc.
|
|
608
|
-
Socket.
|
|
630
|
+
allow(Etc).to receive(:getlogin).and_return('user')
|
|
631
|
+
allow(Socket).to receive(:gethostname).and_return('host')
|
|
609
632
|
end
|
|
610
633
|
|
|
611
634
|
it 'generates a name' do
|
|
@@ -615,41 +638,55 @@ describe Kitchen::Driver::Openstack do
|
|
|
615
638
|
|
|
616
639
|
context 'local node with a long hostname' do
|
|
617
640
|
before(:each) do
|
|
618
|
-
Socket.
|
|
619
|
-
Socket.stub(:gethostname).and_return('ab.c' * 20)
|
|
641
|
+
allow(Socket).to receive(:gethostname).and_return('ab.c' * 20)
|
|
620
642
|
end
|
|
621
643
|
|
|
622
644
|
it 'limits the generated name to 63 characters' do
|
|
623
|
-
expect(driver.send(:generate_name, 'long').length).to
|
|
645
|
+
expect(driver.send(:generate_name, 'long').length).to be <= (63)
|
|
624
646
|
end
|
|
625
647
|
end
|
|
626
648
|
|
|
627
649
|
context 'node with a long hostname, username, and base name' do
|
|
628
650
|
before(:each) do
|
|
629
|
-
Socket.
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
Etc.unstub(:getlogin)
|
|
633
|
-
Etc.stub(:getlogin).and_return('user' * 20)
|
|
651
|
+
allow(Socket).to receive(:gethostname).and_return('abc' * 20)
|
|
652
|
+
allow(Etc).to receive(:getlogin).and_return('user' * 20)
|
|
634
653
|
end
|
|
635
654
|
|
|
636
655
|
it 'limits the generated name to 63 characters' do
|
|
637
656
|
expect(driver.send(:generate_name, 'long' * 20).length).to eq(63)
|
|
638
657
|
end
|
|
639
658
|
end
|
|
659
|
+
|
|
660
|
+
context 'a login and hostname with punctuation in them' do
|
|
661
|
+
let(:base) { 'a.base-name' }
|
|
662
|
+
|
|
663
|
+
before(:each) do
|
|
664
|
+
allow(Etc).to receive(:getlogin).and_return('some.u-se-r' * 20)
|
|
665
|
+
allow(Socket).to receive(:gethostname).and_return('a.host-name' * 20)
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
it 'strips out the dots to prevent bad server names' do
|
|
669
|
+
expect(driver.send(:generate_name, base)).to_not include('.')
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
it 'strips out all but the three hyphen separators' do
|
|
673
|
+
expect(driver.send(:generate_name, base).count('-')).to eq(3)
|
|
674
|
+
end
|
|
675
|
+
end
|
|
640
676
|
end
|
|
641
677
|
|
|
642
678
|
describe '#attach_ip_from_pool' do
|
|
643
679
|
let(:server) { nil }
|
|
644
680
|
let(:pool) { 'swimmers' }
|
|
645
681
|
let(:ip) { '1.1.1.1' }
|
|
646
|
-
let(:address)
|
|
647
|
-
:
|
|
648
|
-
|
|
682
|
+
let(:address) do
|
|
683
|
+
double(ip: ip, fixed_ip: nil, instance_id: nil, pool: pool)
|
|
684
|
+
end
|
|
685
|
+
let(:compute) { double(addresses: [address]) }
|
|
649
686
|
|
|
650
687
|
before(:each) do
|
|
651
|
-
driver.
|
|
652
|
-
driver.
|
|
688
|
+
allow(driver).to receive(:attach_ip).with(server, ip).and_return('bing!')
|
|
689
|
+
allow(driver).to receive(:compute).and_return(compute)
|
|
653
690
|
end
|
|
654
691
|
|
|
655
692
|
it 'determines an IP to attempt to attach' do
|
|
@@ -657,8 +694,10 @@ describe Kitchen::Driver::Openstack do
|
|
|
657
694
|
end
|
|
658
695
|
|
|
659
696
|
context 'no free addresses in the specified pool' do
|
|
660
|
-
let(:address)
|
|
661
|
-
:
|
|
697
|
+
let(:address) do
|
|
698
|
+
double(ip: ip, fixed_ip: nil, instance_id: nil,
|
|
699
|
+
pool: 'some_other_pool')
|
|
700
|
+
end
|
|
662
701
|
|
|
663
702
|
it 'raises an exception' do
|
|
664
703
|
expect { driver.send(:attach_ip_from_pool, server, pool) }.to \
|
|
@@ -672,8 +711,8 @@ describe Kitchen::Driver::Openstack do
|
|
|
672
711
|
let(:addresses) { {} }
|
|
673
712
|
let(:server) do
|
|
674
713
|
s = double('server')
|
|
675
|
-
s.
|
|
676
|
-
s.
|
|
714
|
+
expect(s).to receive(:associate_address).with(ip).and_return(true)
|
|
715
|
+
allow(s).to receive(:addresses).and_return(addresses)
|
|
677
716
|
s
|
|
678
717
|
end
|
|
679
718
|
|
|
@@ -691,19 +730,19 @@ describe Kitchen::Driver::Openstack do
|
|
|
691
730
|
let(:driver) do
|
|
692
731
|
d = Kitchen::Driver::Openstack.new(config)
|
|
693
732
|
d.instance = instance
|
|
694
|
-
d.
|
|
733
|
+
allow(d).to receive(:parse_ips).and_return(parsed_ips)
|
|
695
734
|
d
|
|
696
735
|
end
|
|
697
736
|
let(:server) do
|
|
698
|
-
double(:
|
|
699
|
-
|
|
700
|
-
|
|
737
|
+
double(addresses: addresses,
|
|
738
|
+
public_ip_addresses: public_ip_addresses,
|
|
739
|
+
private_ip_addresses: private_ip_addresses)
|
|
701
740
|
end
|
|
702
741
|
|
|
703
742
|
context 'both public and private IPs' do
|
|
704
|
-
let(:public_ip_addresses) { %w
|
|
705
|
-
let(:private_ip_addresses) { %w
|
|
706
|
-
let(:parsed_ips) { [%w
|
|
743
|
+
let(:public_ip_addresses) { %w(1::1 1.2.3.4) }
|
|
744
|
+
let(:private_ip_addresses) { %w(5.5.5.5) }
|
|
745
|
+
let(:parsed_ips) { [%w(1.2.3.4), %w(5.5.5.5)] }
|
|
707
746
|
|
|
708
747
|
it 'returns a public IPv4 address' do
|
|
709
748
|
expect(driver.send(:get_ip, server)).to eq('1.2.3.4')
|
|
@@ -711,8 +750,8 @@ describe Kitchen::Driver::Openstack do
|
|
|
711
750
|
end
|
|
712
751
|
|
|
713
752
|
context 'only public IPs' do
|
|
714
|
-
let(:public_ip_addresses) { %w
|
|
715
|
-
let(:parsed_ips) { [%w
|
|
753
|
+
let(:public_ip_addresses) { %w(4.3.2.1 2::1) }
|
|
754
|
+
let(:parsed_ips) { [%w(4.3.2.1), []] }
|
|
716
755
|
|
|
717
756
|
it 'returns a public IPv4 address' do
|
|
718
757
|
expect(driver.send(:get_ip, server)).to eq('4.3.2.1')
|
|
@@ -720,8 +759,8 @@ describe Kitchen::Driver::Openstack do
|
|
|
720
759
|
end
|
|
721
760
|
|
|
722
761
|
context 'only private IPs' do
|
|
723
|
-
let(:private_ip_addresses) { %w
|
|
724
|
-
let(:parsed_ips) { [[], %w
|
|
762
|
+
let(:private_ip_addresses) { %w(3::1 5.5.5.5) }
|
|
763
|
+
let(:parsed_ips) { [[], %w(5.5.5.5)] }
|
|
725
764
|
|
|
726
765
|
it 'returns a private IPv4 address' do
|
|
727
766
|
expect(driver.send(:get_ip, server)).to eq('5.5.5.5')
|
|
@@ -729,7 +768,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
729
768
|
end
|
|
730
769
|
|
|
731
770
|
context 'IPs in user-defined network group' do
|
|
732
|
-
let(:config) { { :
|
|
771
|
+
let(:config) { { openstack_network_name: 'mynetwork' } }
|
|
733
772
|
let(:addresses) do
|
|
734
773
|
{
|
|
735
774
|
'mynetwork' => [
|
|
@@ -747,10 +786,10 @@ describe Kitchen::Driver::Openstack do
|
|
|
747
786
|
context 'an OpenStack deployment without the floating IP extension' do
|
|
748
787
|
let(:server) do
|
|
749
788
|
s = double('server')
|
|
750
|
-
s.
|
|
751
|
-
s.
|
|
789
|
+
allow(s).to receive(:addresses).and_return(addresses)
|
|
790
|
+
allow(s).to receive(:public_ip_addresses).and_raise(
|
|
752
791
|
Fog::Compute::OpenStack::NotFound)
|
|
753
|
-
s.
|
|
792
|
+
allow(s).to receive(:private_ip_addresses).and_raise(
|
|
754
793
|
Fog::Compute::OpenStack::NotFound)
|
|
755
794
|
s
|
|
756
795
|
end
|
|
@@ -762,7 +801,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
762
801
|
'private' => [{ 'addr' => '8.8.8.8' }, { 'addr' => '9.9.9.9' }]
|
|
763
802
|
}
|
|
764
803
|
end
|
|
765
|
-
let(:parsed_ips) { [%w
|
|
804
|
+
let(:parsed_ips) { [%w(6.6.6.6 7.7.7.7), %w(8.8.8.8 9.9.9.9)] }
|
|
766
805
|
|
|
767
806
|
it 'selects the first public IP' do
|
|
768
807
|
expect(driver.send(:get_ip, server)).to eq('6.6.6.6')
|
|
@@ -773,7 +812,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
773
812
|
let(:addresses) do
|
|
774
813
|
{ 'public' => [{ 'addr' => '6.6.6.6' }, { 'addr' => '7.7.7.7' }] }
|
|
775
814
|
end
|
|
776
|
-
let(:parsed_ips) { [%w
|
|
815
|
+
let(:parsed_ips) { [%w(6.6.6.6 7.7.7.7), []] }
|
|
777
816
|
|
|
778
817
|
it 'selects the first public IP' do
|
|
779
818
|
expect(driver.send(:get_ip, server)).to eq('6.6.6.6')
|
|
@@ -784,7 +823,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
784
823
|
let(:addresses) do
|
|
785
824
|
{ 'private' => [{ 'addr' => '8.8.8.8' }, { 'addr' => '9.9.9.9' }] }
|
|
786
825
|
end
|
|
787
|
-
let(:parsed_ips) { [[], %w
|
|
826
|
+
let(:parsed_ips) { [[], %w(8.8.8.8 9.9.9.9)] }
|
|
788
827
|
|
|
789
828
|
it 'selects the first private IP' do
|
|
790
829
|
expect(driver.send(:get_ip, server)).to eq('8.8.8.8')
|
|
@@ -800,10 +839,10 @@ describe Kitchen::Driver::Openstack do
|
|
|
800
839
|
end
|
|
801
840
|
|
|
802
841
|
describe '#parse_ips' do
|
|
803
|
-
let(:pub_v4) { %w
|
|
804
|
-
let(:pub_v6) { %w
|
|
805
|
-
let(:priv_v4) { %w
|
|
806
|
-
let(:priv_v6) { %w
|
|
842
|
+
let(:pub_v4) { %w(1.1.1.1 2.2.2.2) }
|
|
843
|
+
let(:pub_v6) { %w(1::1 2::2) }
|
|
844
|
+
let(:priv_v4) { %w(3.3.3.3 4.4.4.4) }
|
|
845
|
+
let(:priv_v6) { %w(3::3 4::4) }
|
|
807
846
|
let(:pub) { pub_v4 + pub_v6 }
|
|
808
847
|
let(:priv) { priv_v4 + priv_v6 }
|
|
809
848
|
|
|
@@ -815,7 +854,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
815
854
|
end
|
|
816
855
|
|
|
817
856
|
context 'IPv6' do
|
|
818
|
-
let(:config) { { :
|
|
857
|
+
let(:config) { { use_ipv6: true } }
|
|
819
858
|
|
|
820
859
|
it 'returns only the v6 IPs' do
|
|
821
860
|
expect(driver.send(:parse_ips, pub, priv)).to eq([pub_v6, priv_v6])
|
|
@@ -833,7 +872,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
833
872
|
end
|
|
834
873
|
|
|
835
874
|
context 'IPv6' do
|
|
836
|
-
let(:config) { { :
|
|
875
|
+
let(:config) { { use_ipv6: true } }
|
|
837
876
|
|
|
838
877
|
it 'returns only the v6 IPs' do
|
|
839
878
|
expect(driver.send(:parse_ips, pub, priv)).to eq([pub_v6, []])
|
|
@@ -851,7 +890,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
851
890
|
end
|
|
852
891
|
|
|
853
892
|
context 'IPv6' do
|
|
854
|
-
let(:config) { { :
|
|
893
|
+
let(:config) { { use_ipv6: true } }
|
|
855
894
|
|
|
856
895
|
it 'returns only the v6 IPs' do
|
|
857
896
|
expect(driver.send(:parse_ips, pub, priv)).to eq([[], priv_v6])
|
|
@@ -870,7 +909,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
870
909
|
end
|
|
871
910
|
|
|
872
911
|
context 'IPv6' do
|
|
873
|
-
let(:config) { { :
|
|
912
|
+
let(:config) { { use_ipv6: true } }
|
|
874
913
|
|
|
875
914
|
it 'returns empty lists' do
|
|
876
915
|
expect(driver.send(:parse_ips, nil, nil)).to eq([[], []])
|
|
@@ -880,21 +919,21 @@ describe Kitchen::Driver::Openstack do
|
|
|
880
919
|
end
|
|
881
920
|
|
|
882
921
|
describe '#do_ssh_setup' do
|
|
883
|
-
let(:config) { { :
|
|
884
|
-
let(:server) { double(:
|
|
885
|
-
let(:state) { { :
|
|
886
|
-
let(:read) { double(:
|
|
922
|
+
let(:config) { { public_key_path: '/pub_key' } }
|
|
923
|
+
let(:server) { double(password: 'aloha') }
|
|
924
|
+
let(:state) { { hostname: 'host' } }
|
|
925
|
+
let(:read) { double(read: 'a_key') }
|
|
887
926
|
let(:ssh) do
|
|
888
927
|
s = double('ssh')
|
|
889
|
-
s.
|
|
928
|
+
allow(s).to receive(:run) { |args| args }
|
|
890
929
|
s
|
|
891
930
|
end
|
|
892
931
|
|
|
893
932
|
it 'opens an SSH session to the server' do
|
|
894
|
-
Fog::SSH.
|
|
895
|
-
|
|
896
|
-
driver.
|
|
897
|
-
read.
|
|
933
|
+
allow(Fog::SSH).to receive(:new).with('host', 'root', password: 'aloha')
|
|
934
|
+
.and_return(ssh)
|
|
935
|
+
allow(driver).to receive(:open).with('/pub_key').and_return(read)
|
|
936
|
+
allow(read).to receive(:read).and_return('a_key')
|
|
898
937
|
res = driver.send(:do_ssh_setup, state, config, server)
|
|
899
938
|
expected = [
|
|
900
939
|
'mkdir .ssh',
|
|
@@ -906,18 +945,16 @@ describe Kitchen::Driver::Openstack do
|
|
|
906
945
|
end
|
|
907
946
|
|
|
908
947
|
describe '#add_ohai_hint' do
|
|
909
|
-
let(:
|
|
910
|
-
let(:server) { double(:password => 'aloha') }
|
|
911
|
-
let(:state) { { :hostname => 'host' } }
|
|
948
|
+
let(:state) { { hostname: 'host' } }
|
|
912
949
|
let(:ssh) do
|
|
913
950
|
s = double('ssh')
|
|
914
|
-
s.
|
|
951
|
+
allow(s).to receive(:run) { |args| args }
|
|
915
952
|
s
|
|
916
953
|
end
|
|
917
954
|
it 'opens an SSH session to the server' do
|
|
918
|
-
Fog::SSH.
|
|
919
|
-
|
|
920
|
-
res = driver.send(:add_ohai_hint, state
|
|
955
|
+
allow(Fog::SSH).to receive(:new).with('host', 'root', anything)
|
|
956
|
+
.and_return(ssh)
|
|
957
|
+
res = driver.send(:add_ohai_hint, state)
|
|
921
958
|
expected = [
|
|
922
959
|
"sudo mkdir -p #{Ohai::Config[:hints_path][0]}",
|
|
923
960
|
"sudo touch #{Ohai::Config[:hints_path][0]}/openstack.json"
|