kitchen-openstack 3.5.0 → 3.5.1
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/.travis.yml +4 -3
- data/CHANGELOG.md +14 -1
- data/Gemfile +1 -1
- data/Rakefile +8 -7
- data/kitchen-openstack.gemspec +24 -24
- data/lib/kitchen/driver/openstack.rb +58 -60
- data/lib/kitchen/driver/openstack/volume.rb +9 -9
- data/lib/kitchen/driver/openstack_version.rb +1 -1
- data/spec/kitchen/driver/openstack/volume_spec.rb +37 -37
- data/spec/kitchen/driver/openstack_spec.rb +508 -508
- data/spec/spec_helper.rb +6 -6
- metadata +10 -10
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
# See the License for the specific language governing permissions and
|
|
18
18
|
# limitations under the License.
|
|
19
19
|
|
|
20
|
-
require
|
|
21
|
-
require
|
|
20
|
+
require "fog/openstack"
|
|
21
|
+
require "kitchen"
|
|
22
22
|
|
|
23
23
|
module Kitchen
|
|
24
24
|
module Driver
|
|
@@ -41,17 +41,17 @@ module Kitchen
|
|
|
41
41
|
def create_volume(config, os)
|
|
42
42
|
opt = {}
|
|
43
43
|
bdm = config[:block_device_mapping]
|
|
44
|
-
vanilla_options = %i
|
|
45
|
-
source_volid availability_zone
|
|
44
|
+
vanilla_options = %i{snapshot_id imageRef volume_type
|
|
45
|
+
source_volid availability_zone}
|
|
46
46
|
vanilla_options.select { |o| bdm[o] }.each do |key|
|
|
47
47
|
opt[key] = bdm[key]
|
|
48
48
|
end
|
|
49
|
-
@logger.info
|
|
49
|
+
@logger.info "Creating Volume..."
|
|
50
50
|
resp = volume(os).create_volume("#{config[:server_name]}-volume",
|
|
51
51
|
"#{config[:server_name]} volume",
|
|
52
52
|
bdm[:volume_size],
|
|
53
53
|
opt)
|
|
54
|
-
vol_id = resp[:body][
|
|
54
|
+
vol_id = resp[:body]["volume"]["id"]
|
|
55
55
|
|
|
56
56
|
# Get Volume Model to make waiting for ready easy
|
|
57
57
|
vol_model = volume(os).volumes.first { |x| x.id == vol_id }
|
|
@@ -62,14 +62,14 @@ module Kitchen
|
|
|
62
62
|
creation_timeout = bdm[:creation_timeout]
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
-
@logger.debug "Waiting for volume to be ready for #{creation_timeout} seconds"
|
|
65
|
+
@logger.debug "Waiting for volume to be ready for #{creation_timeout} seconds"
|
|
66
66
|
vol_model.wait_for(creation_timeout) do
|
|
67
67
|
sleep(1)
|
|
68
|
-
|
|
68
|
+
raise("Failed to make volume") if status.casecmp("error".downcase) == 0
|
|
69
69
|
ready?
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
-
@logger.debug
|
|
72
|
+
@logger.debug "Volume Ready"
|
|
73
73
|
|
|
74
74
|
vol_id
|
|
75
75
|
end
|
|
@@ -1,59 +1,59 @@
|
|
|
1
1
|
# Encoding: UTF-8
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
3
|
+
require_relative "../../../spec_helper"
|
|
4
|
+
require_relative "../../../../lib/kitchen/driver/openstack/volume"
|
|
5
5
|
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
require
|
|
6
|
+
require "logger"
|
|
7
|
+
require "stringio"
|
|
8
|
+
require "rspec"
|
|
9
|
+
require "kitchen"
|
|
10
|
+
require "ohai"
|
|
11
11
|
|
|
12
12
|
describe Kitchen::Driver::Openstack::Volume do
|
|
13
13
|
let(:os) do
|
|
14
14
|
{
|
|
15
|
-
openstack_username:
|
|
16
|
-
openstack_api_key:
|
|
17
|
-
openstack_auth_url:
|
|
18
|
-
openstack_tenant:
|
|
19
|
-
openstack_region:
|
|
20
|
-
openstack_service_name:
|
|
15
|
+
openstack_username: "twilight",
|
|
16
|
+
openstack_api_key: "sparkle",
|
|
17
|
+
openstack_auth_url: "http:",
|
|
18
|
+
openstack_tenant: "trixie",
|
|
19
|
+
openstack_region: "syd",
|
|
20
|
+
openstack_service_name: "the_service",
|
|
21
21
|
}
|
|
22
22
|
end
|
|
23
23
|
let(:logger_io) { StringIO.new }
|
|
24
24
|
let(:logger) { Kitchen::Logger.new(logdev: logger_io) }
|
|
25
|
-
describe
|
|
25
|
+
describe "#volume" do
|
|
26
26
|
let(:vol_driver) do
|
|
27
27
|
described_class.new(logger)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
it
|
|
30
|
+
it "creates a new block device connection" do
|
|
31
31
|
allow(Fog::Volume).to receive(:new) { |arg| arg }
|
|
32
32
|
expect(vol_driver.send(:volume, os)).to eq(os)
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
|
-
describe
|
|
35
|
+
describe "#create_volume" do
|
|
36
36
|
let(:config) do
|
|
37
37
|
{
|
|
38
|
-
server_name:
|
|
38
|
+
server_name: "applejack",
|
|
39
39
|
block_device_mapping: {
|
|
40
|
-
snapshot_id:
|
|
41
|
-
volume_size:
|
|
42
|
-
creation_timeout:
|
|
43
|
-
}
|
|
40
|
+
snapshot_id: "444",
|
|
41
|
+
volume_size: "5",
|
|
42
|
+
creation_timeout: "30",
|
|
43
|
+
},
|
|
44
44
|
}
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
let(:create_volume) do
|
|
48
48
|
{
|
|
49
|
-
body: {
|
|
49
|
+
body: { "volume" => { "id" => "555" } },
|
|
50
50
|
}
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
let(:volume_model) do
|
|
54
54
|
{
|
|
55
|
-
id:
|
|
56
|
-
status:
|
|
55
|
+
id: "555",
|
|
56
|
+
status: "ACTIVE"
|
|
57
57
|
# wait_for: true
|
|
58
58
|
# ready?: true
|
|
59
59
|
}
|
|
@@ -69,7 +69,7 @@ describe Kitchen::Driver::Openstack::Volume do
|
|
|
69
69
|
let(:wait_for) do
|
|
70
70
|
{
|
|
71
71
|
ready?: true,
|
|
72
|
-
status:
|
|
72
|
+
status: "ACTIVE",
|
|
73
73
|
}
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -80,42 +80,42 @@ describe Kitchen::Driver::Openstack::Volume do
|
|
|
80
80
|
d
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
it
|
|
83
|
+
it "creates a volume" do
|
|
84
84
|
# This seems like a hack
|
|
85
85
|
# how would we do this on the volume_model instead?
|
|
86
86
|
# This makes rspec work
|
|
87
87
|
# but the vol_driver doesnt have these methods properties?
|
|
88
|
-
allow(vol_driver).to receive(:status).and_return(
|
|
88
|
+
allow(vol_driver).to receive(:status).and_return("ACTIVE")
|
|
89
89
|
allow(vol_driver).to receive(:ready?).and_return(true)
|
|
90
90
|
allow(volume_model).to receive(:wait_for)
|
|
91
91
|
.with(an_instance_of(String)).and_yield
|
|
92
92
|
|
|
93
93
|
# allow(vol_driver).a
|
|
94
|
-
expect(vol_driver.send(:create_volume, config, os)).to eq(
|
|
94
|
+
expect(vol_driver.send(:create_volume, config, os)).to eq("555")
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
-
describe
|
|
98
|
+
describe "#get_bdm" do
|
|
99
99
|
let(:config) do
|
|
100
100
|
{
|
|
101
101
|
block_device_mapping: {
|
|
102
102
|
make_volue: true,
|
|
103
|
-
snapshot_id:
|
|
104
|
-
volume_id:
|
|
105
|
-
volume_size:
|
|
106
|
-
volume_device_name:
|
|
107
|
-
delete_on_termination: true
|
|
108
|
-
}
|
|
103
|
+
snapshot_id: "333",
|
|
104
|
+
volume_id: "555",
|
|
105
|
+
volume_size: "5",
|
|
106
|
+
volume_device_name: "vda",
|
|
107
|
+
delete_on_termination: true,
|
|
108
|
+
},
|
|
109
109
|
}
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
let(:vol_driver) do
|
|
113
113
|
d = described_class.new(logger)
|
|
114
|
-
allow(d).to receive(:create_volume).and_return(
|
|
114
|
+
allow(d).to receive(:create_volume).and_return("555")
|
|
115
115
|
d
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
-
it
|
|
118
|
+
it "returns the block device mapping config" do
|
|
119
119
|
expects = config[:block_device_mapping]
|
|
120
120
|
expects.delete_if { |k, _| k == :make_volume }
|
|
121
121
|
expects.delete_if { |k, _| k == :snapshot_id }
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
# Encoding: UTF-8
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
5
|
-
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
require
|
|
11
|
-
require
|
|
12
|
-
require
|
|
13
|
-
require
|
|
14
|
-
require
|
|
15
|
-
require
|
|
16
|
-
require
|
|
3
|
+
require_relative "../../spec_helper"
|
|
4
|
+
require_relative "../../../lib/kitchen/driver/openstack"
|
|
5
|
+
|
|
6
|
+
require "logger"
|
|
7
|
+
require "stringio"
|
|
8
|
+
require "rspec"
|
|
9
|
+
require "kitchen"
|
|
10
|
+
require "kitchen/driver/openstack"
|
|
11
|
+
require "kitchen/provisioner/dummy"
|
|
12
|
+
require "kitchen/transport/dummy"
|
|
13
|
+
require "kitchen/verifier/dummy"
|
|
14
|
+
require "ohai"
|
|
15
|
+
require "excon"
|
|
16
|
+
require "fog/openstack"
|
|
17
17
|
|
|
18
18
|
describe Kitchen::Driver::Openstack do
|
|
19
19
|
let(:logged_output) { StringIO.new }
|
|
20
20
|
let(:logger) { Logger.new(logged_output) }
|
|
21
21
|
let(:config) { {} }
|
|
22
22
|
let(:state) { {} }
|
|
23
|
-
let(:instance_name) {
|
|
23
|
+
let(:instance_name) { "potatoes" }
|
|
24
24
|
let(:transport) { Kitchen::Transport::Dummy.new }
|
|
25
|
-
let(:platform) { Kitchen::Platform.new(name:
|
|
25
|
+
let(:platform) { Kitchen::Platform.new(name: "fake_platform") }
|
|
26
26
|
let(:driver) { Kitchen::Driver::Openstack.new(config) }
|
|
27
27
|
|
|
28
28
|
let(:instance) do
|
|
@@ -31,7 +31,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
31
31
|
transport: transport,
|
|
32
32
|
logger: logger,
|
|
33
33
|
platform: platform,
|
|
34
|
-
to_str:
|
|
34
|
+
to_str: "instance"
|
|
35
35
|
)
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -43,33 +43,33 @@ describe Kitchen::Driver::Openstack do
|
|
|
43
43
|
allow(File).to receive(:exist?).and_call_original
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
describe
|
|
46
|
+
describe "#finalize_config" do
|
|
47
47
|
before(:each) { allow(File).to receive(:exist?).and_return(false) }
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
describe
|
|
51
|
-
context
|
|
52
|
-
it
|
|
50
|
+
describe "#initialize" do
|
|
51
|
+
context "default options" do
|
|
52
|
+
it "uses the normal SSH status check" do
|
|
53
53
|
expect(driver[:no_ssh_tcp_check]).to eq(false)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
it
|
|
56
|
+
it "sets a default TCP check wait time" do
|
|
57
57
|
expect(driver[:no_ssh_tcp_check_sleep]).to eq(120)
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
it
|
|
60
|
+
it "sets a default Openstack API read timeout" do
|
|
61
61
|
expect(driver[:read_timeout]).to eq(60)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
it
|
|
64
|
+
it "sets a default Openstack API write timeout" do
|
|
65
65
|
expect(driver[:write_timeout]).to eq(60)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
it
|
|
68
|
+
it "sets a default ssh connection timeout" do
|
|
69
69
|
expect(driver[:connect_timeout]).to eq(60)
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
-
nils = %i
|
|
72
|
+
nils = %i{
|
|
73
73
|
server_name
|
|
74
74
|
openstack_tenant
|
|
75
75
|
openstack_region
|
|
@@ -80,7 +80,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
80
80
|
security_groups
|
|
81
81
|
network_ref
|
|
82
82
|
metadata
|
|
83
|
-
|
|
83
|
+
}
|
|
84
84
|
nils.each do |i|
|
|
85
85
|
it "defaults to no #{i}" do
|
|
86
86
|
expect(driver[i]).to eq(nil)
|
|
@@ -88,130 +88,130 @@ describe Kitchen::Driver::Openstack do
|
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
-
context
|
|
91
|
+
context "overridden options" do
|
|
92
92
|
let(:config) do
|
|
93
93
|
{
|
|
94
|
-
image_ref:
|
|
95
|
-
image_id:
|
|
96
|
-
flavor_ref:
|
|
97
|
-
flavor_id:
|
|
98
|
-
public_key_path:
|
|
99
|
-
username:
|
|
100
|
-
port:
|
|
101
|
-
server_name:
|
|
102
|
-
server_name_prefix:
|
|
103
|
-
openstack_tenant:
|
|
104
|
-
openstack_region:
|
|
105
|
-
openstack_service_name:
|
|
106
|
-
floating_ip_pool:
|
|
107
|
-
floating_ip:
|
|
108
|
-
network_ref:
|
|
109
|
-
network_id:
|
|
94
|
+
image_ref: "22",
|
|
95
|
+
image_id: "4391b03e-f7fb-46fd-a356-fa5e42f6d728",
|
|
96
|
+
flavor_ref: "33",
|
|
97
|
+
flavor_id: "19a2281e-591e-4b47-be06-631c3c7704e8",
|
|
98
|
+
public_key_path: "/tmp",
|
|
99
|
+
username: "admin",
|
|
100
|
+
port: "2222",
|
|
101
|
+
server_name: "puppy",
|
|
102
|
+
server_name_prefix: "parsnip",
|
|
103
|
+
openstack_tenant: "that_one",
|
|
104
|
+
openstack_region: "atlantis",
|
|
105
|
+
openstack_service_name: "the_service",
|
|
106
|
+
floating_ip_pool: "swimmers",
|
|
107
|
+
floating_ip: "11111",
|
|
108
|
+
network_ref: "0xCAFFE",
|
|
109
|
+
network_id: "57d6e41a-f369-4c92-9ebe-1fbf198bc783",
|
|
110
110
|
use_ssh_agent: true,
|
|
111
111
|
connect_timeout: 123,
|
|
112
112
|
read_timeout: 234,
|
|
113
113
|
write_timeout: 345,
|
|
114
114
|
block_device_mapping: {
|
|
115
115
|
make_volume: true,
|
|
116
|
-
snapshot_id:
|
|
117
|
-
volume_id:
|
|
118
|
-
volume_size:
|
|
119
|
-
device_name:
|
|
120
|
-
delete_on_termination: true
|
|
116
|
+
snapshot_id: "44",
|
|
117
|
+
volume_id: "55",
|
|
118
|
+
volume_size: "5",
|
|
119
|
+
device_name: "vda",
|
|
120
|
+
delete_on_termination: true,
|
|
121
121
|
},
|
|
122
122
|
metadata: {
|
|
123
|
-
name:
|
|
124
|
-
ohai:
|
|
125
|
-
}
|
|
123
|
+
name: "test",
|
|
124
|
+
ohai: "chef",
|
|
125
|
+
},
|
|
126
126
|
}
|
|
127
127
|
end
|
|
128
128
|
|
|
129
|
-
it
|
|
129
|
+
it "uses all the overridden options" do
|
|
130
130
|
drv = driver
|
|
131
131
|
config.each do |k, v|
|
|
132
132
|
expect(drv[k]).to eq(v)
|
|
133
133
|
end
|
|
134
134
|
end
|
|
135
135
|
|
|
136
|
-
it
|
|
136
|
+
it "overrides server name prefix with explicit server name, if given" do
|
|
137
137
|
expect(driver[:server_name]).to eq(config[:server_name])
|
|
138
138
|
end
|
|
139
139
|
end
|
|
140
140
|
end
|
|
141
141
|
|
|
142
|
-
describe
|
|
142
|
+
describe "#create" do
|
|
143
143
|
let(:server) do
|
|
144
|
-
double(id:
|
|
144
|
+
double(id: "test123", wait_for: true, public_ip_addresses: %w{1.2.3.4})
|
|
145
145
|
end
|
|
146
146
|
let(:driver) do
|
|
147
147
|
d = super()
|
|
148
|
-
allow(d).to receive(:default_name).and_return(
|
|
148
|
+
allow(d).to receive(:default_name).and_return("a_monkey!")
|
|
149
149
|
allow(d).to receive(:create_server).and_return(server)
|
|
150
|
-
allow(d).to receive(:wait_for_sshd).with(
|
|
150
|
+
allow(d).to receive(:wait_for_sshd).with("1.2.3.4", "root", port: "22")
|
|
151
151
|
.and_return(true)
|
|
152
|
-
allow(d).to receive(:get_ip).and_return(
|
|
152
|
+
allow(d).to receive(:get_ip).and_return("1.2.3.4")
|
|
153
153
|
allow(d).to receive(:add_ohai_hint).and_return(true)
|
|
154
154
|
allow(d).to receive(:do_ssh_setup).and_return(true)
|
|
155
155
|
allow(d).to receive(:sleep)
|
|
156
|
-
allow(d).to receive(:wait_for_ssh_key_access).and_return(
|
|
156
|
+
allow(d).to receive(:wait_for_ssh_key_access).and_return("SSH key authetication successful") # rubocop:disable Metrics/LineLength
|
|
157
157
|
allow(d).to receive(:disable_ssl_validation).and_return(false)
|
|
158
158
|
d
|
|
159
159
|
end
|
|
160
160
|
|
|
161
|
-
context
|
|
162
|
-
it
|
|
163
|
-
state[:server_id] =
|
|
161
|
+
context "when a server is already created" do
|
|
162
|
+
it "does not create a new instance" do
|
|
163
|
+
state[:server_id] = "1"
|
|
164
164
|
expect(driver).not_to receive(:create_server)
|
|
165
165
|
driver.create(state)
|
|
166
166
|
end
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
-
context
|
|
169
|
+
context "required options provided" do
|
|
170
170
|
let(:config) do
|
|
171
171
|
{
|
|
172
|
-
openstack_username:
|
|
173
|
-
openstack_api_key:
|
|
174
|
-
openstack_auth_url:
|
|
175
|
-
openstack_tenant:
|
|
172
|
+
openstack_username: "hello",
|
|
173
|
+
openstack_api_key: "world",
|
|
174
|
+
openstack_auth_url: "http:",
|
|
175
|
+
openstack_tenant: "www",
|
|
176
176
|
glance_cache_wait_timeout: 600,
|
|
177
|
-
disable_ssl_validation: false
|
|
177
|
+
disable_ssl_validation: false,
|
|
178
178
|
}
|
|
179
179
|
end
|
|
180
180
|
let(:server) do
|
|
181
|
-
double(id:
|
|
181
|
+
double(id: "test123", wait_for: true, public_ip_addresses: %w{1.2.3.4})
|
|
182
182
|
end
|
|
183
183
|
|
|
184
184
|
let(:driver) do
|
|
185
185
|
d = described_class.new(config)
|
|
186
|
-
allow(d).to receive(:config_server_name).and_return(
|
|
186
|
+
allow(d).to receive(:config_server_name).and_return("a_monkey!")
|
|
187
187
|
allow(d).to receive(:create_server).and_return(server)
|
|
188
|
-
allow(server).to receive(:id).and_return(
|
|
188
|
+
allow(server).to receive(:id).and_return("test123")
|
|
189
189
|
|
|
190
190
|
# Inside the yield block we are calling ready? So we fake it here
|
|
191
191
|
allow(d).to receive(:ready?).and_return(true)
|
|
192
192
|
allow(server).to receive(:wait_for)
|
|
193
193
|
.with(an_instance_of(Integer)).and_yield
|
|
194
194
|
|
|
195
|
-
allow(d).to receive(:get_ip).and_return(
|
|
195
|
+
allow(d).to receive(:get_ip).and_return("1.2.3.4")
|
|
196
196
|
allow(d).to receive(:bourne_shell?).and_return(false)
|
|
197
197
|
d
|
|
198
198
|
end
|
|
199
199
|
|
|
200
|
-
it
|
|
200
|
+
it "returns nil, but modifies the state" do
|
|
201
201
|
expect(driver.send(:create, state)).to eq(nil)
|
|
202
|
-
expect(state[:server_id]).to eq(
|
|
202
|
+
expect(state[:server_id]).to eq("test123")
|
|
203
203
|
end
|
|
204
204
|
|
|
205
|
-
it
|
|
205
|
+
it "throws an Action error when trying to create_server" do
|
|
206
206
|
allow(driver).to receive(:create_server).and_raise(Fog::Errors::Error)
|
|
207
207
|
expect { driver.send(:create, state) }.to raise_error(Kitchen::ActionFailed) # rubocop:disable Metrics/LineLength
|
|
208
208
|
end
|
|
209
209
|
end
|
|
210
210
|
end
|
|
211
211
|
|
|
212
|
-
describe
|
|
213
|
-
let(:server_id) {
|
|
214
|
-
let(:hostname) {
|
|
212
|
+
describe "#destroy" do
|
|
213
|
+
let(:server_id) { "12345" }
|
|
214
|
+
let(:hostname) { "example.com" }
|
|
215
215
|
let(:state) { { server_id: server_id, hostname: hostname } }
|
|
216
216
|
let(:server) { double(nil?: false, destroy: true) }
|
|
217
217
|
let(:servers) { double(get: server) }
|
|
@@ -223,23 +223,23 @@ describe Kitchen::Driver::Openstack do
|
|
|
223
223
|
d
|
|
224
224
|
end
|
|
225
225
|
|
|
226
|
-
context
|
|
227
|
-
it
|
|
226
|
+
context "a live server that needs to be destroyed" do
|
|
227
|
+
it "destroys the server" do
|
|
228
228
|
expect(state).to receive(:delete).with(:server_id)
|
|
229
229
|
expect(state).to receive(:delete).with(:hostname)
|
|
230
230
|
driver.destroy(state)
|
|
231
231
|
end
|
|
232
232
|
|
|
233
|
-
it
|
|
233
|
+
it "does not disable SSL cert validation" do
|
|
234
234
|
expect(driver).to_not receive(:disable_ssl_validation)
|
|
235
235
|
driver.destroy(state)
|
|
236
236
|
end
|
|
237
237
|
end
|
|
238
238
|
|
|
239
|
-
context
|
|
239
|
+
context "no server ID present" do
|
|
240
240
|
let(:state) { {} }
|
|
241
241
|
|
|
242
|
-
it
|
|
242
|
+
it "does nothing" do
|
|
243
243
|
allow(driver).to receive(:compute)
|
|
244
244
|
expect(driver).to_not receive(:compute)
|
|
245
245
|
expect(state).to_not receive(:delete)
|
|
@@ -247,10 +247,10 @@ describe Kitchen::Driver::Openstack do
|
|
|
247
247
|
end
|
|
248
248
|
end
|
|
249
249
|
|
|
250
|
-
context
|
|
250
|
+
context "a server that was already destroyed" do
|
|
251
251
|
let(:servers) do
|
|
252
|
-
s = double(
|
|
253
|
-
allow(s).to receive(:get).with(
|
|
252
|
+
s = double("servers")
|
|
253
|
+
allow(s).to receive(:get).with("12345").and_return(nil)
|
|
254
254
|
s
|
|
255
255
|
end
|
|
256
256
|
let(:compute) { double(servers: servers) }
|
|
@@ -260,37 +260,37 @@ describe Kitchen::Driver::Openstack do
|
|
|
260
260
|
d
|
|
261
261
|
end
|
|
262
262
|
|
|
263
|
-
it
|
|
263
|
+
it "does not try to destroy the server again" do
|
|
264
264
|
allow_message_expectations_on_nil
|
|
265
265
|
driver.destroy(state)
|
|
266
266
|
end
|
|
267
267
|
end
|
|
268
268
|
|
|
269
|
-
context
|
|
269
|
+
context "SSL validation disabled" do
|
|
270
270
|
let(:config) { { disable_ssl_validation: true } }
|
|
271
271
|
|
|
272
|
-
it
|
|
272
|
+
it "disables SSL cert validation" do
|
|
273
273
|
expect(driver).to receive(:disable_ssl_validation)
|
|
274
274
|
driver.destroy(state)
|
|
275
275
|
end
|
|
276
276
|
end
|
|
277
277
|
|
|
278
|
-
context
|
|
278
|
+
context "Deallocate floating IP" do
|
|
279
279
|
let(:config) do
|
|
280
280
|
{
|
|
281
|
-
floating_ip_pool:
|
|
282
|
-
allocate_floating_ip: true
|
|
281
|
+
floating_ip_pool: "swimmers",
|
|
282
|
+
allocate_floating_ip: true,
|
|
283
283
|
}
|
|
284
284
|
end
|
|
285
|
-
let(:ip) {
|
|
286
|
-
let(:ip_id) {
|
|
285
|
+
let(:ip) { "1.1.1.1" }
|
|
286
|
+
let(:ip_id) { "123" }
|
|
287
287
|
|
|
288
288
|
let(:network_response) do
|
|
289
|
-
double(body: {
|
|
289
|
+
double(body: { "floatingips" => [{ "id" => ip_id }] })
|
|
290
290
|
end
|
|
291
291
|
|
|
292
292
|
let(:network) do
|
|
293
|
-
s = double(
|
|
293
|
+
s = double("network")
|
|
294
294
|
expect(s).to receive(:list_floating_ips).with(floating_ip_address: ip).and_return(network_response) # rubocop:disable Metrics/LineLength
|
|
295
295
|
expect(s).to receive(:delete_floating_ip).with(ip_id)
|
|
296
296
|
s
|
|
@@ -303,129 +303,129 @@ describe Kitchen::Driver::Openstack do
|
|
|
303
303
|
allow(d).to receive(:network).and_return(network)
|
|
304
304
|
d
|
|
305
305
|
end
|
|
306
|
-
it
|
|
306
|
+
it "deallocates the ip" do
|
|
307
307
|
driver.destroy(state)
|
|
308
308
|
end
|
|
309
309
|
end
|
|
310
310
|
end
|
|
311
311
|
|
|
312
|
-
describe
|
|
312
|
+
describe "#openstack_server" do
|
|
313
313
|
let(:config) do
|
|
314
314
|
{
|
|
315
|
-
openstack_username:
|
|
316
|
-
openstack_api_key:
|
|
317
|
-
openstack_auth_url:
|
|
318
|
-
openstack_tenant:
|
|
319
|
-
openstack_region:
|
|
320
|
-
openstack_service_name:
|
|
315
|
+
openstack_username: "a",
|
|
316
|
+
openstack_api_key: "b",
|
|
317
|
+
openstack_auth_url: "http://",
|
|
318
|
+
openstack_tenant: "me",
|
|
319
|
+
openstack_region: "ORD",
|
|
320
|
+
openstack_service_name: "stack",
|
|
321
321
|
connection_options:
|
|
322
322
|
{
|
|
323
323
|
read_timeout: 60,
|
|
324
324
|
write_timeout: 60,
|
|
325
|
-
connect_timeout: 60
|
|
326
|
-
}
|
|
325
|
+
connect_timeout: 60,
|
|
326
|
+
},
|
|
327
327
|
}
|
|
328
328
|
end
|
|
329
329
|
|
|
330
|
-
it
|
|
331
|
-
expected = config.merge(provider:
|
|
330
|
+
it "returns a hash of server settings" do
|
|
331
|
+
expected = config.merge(provider: "OpenStack")
|
|
332
332
|
expect(driver.send(:openstack_server)).to eq(expected)
|
|
333
333
|
end
|
|
334
334
|
end
|
|
335
335
|
|
|
336
|
-
describe
|
|
337
|
-
it
|
|
338
|
-
expected = %i
|
|
336
|
+
describe "#required_server_settings" do
|
|
337
|
+
it "returns the required settings for an OpenStack server" do
|
|
338
|
+
expected = %i{
|
|
339
339
|
openstack_username openstack_api_key openstack_auth_url
|
|
340
|
-
|
|
340
|
+
}
|
|
341
341
|
expect(driver.send(:required_server_settings)).to eq(expected)
|
|
342
342
|
end
|
|
343
343
|
end
|
|
344
344
|
|
|
345
|
-
describe
|
|
346
|
-
it
|
|
347
|
-
excluded = %i
|
|
345
|
+
describe "#optional_server_settings" do
|
|
346
|
+
it "returns the optional settings for an OpenStack server" do
|
|
347
|
+
excluded = %i{
|
|
348
348
|
openstack_username openstack_api_key openstack_auth_url
|
|
349
|
-
|
|
349
|
+
}
|
|
350
350
|
expect(driver.send(:optional_server_settings)).not_to include(*excluded)
|
|
351
351
|
end
|
|
352
352
|
end
|
|
353
353
|
|
|
354
|
-
describe
|
|
354
|
+
describe "#compute" do
|
|
355
355
|
let(:config) do
|
|
356
356
|
{
|
|
357
|
-
openstack_username:
|
|
358
|
-
openstack_api_key:
|
|
359
|
-
openstack_auth_url:
|
|
360
|
-
openstack_tenant:
|
|
361
|
-
openstack_region:
|
|
362
|
-
openstack_service_name:
|
|
357
|
+
openstack_username: "monkey",
|
|
358
|
+
openstack_api_key: "potato",
|
|
359
|
+
openstack_auth_url: "http:",
|
|
360
|
+
openstack_tenant: "link",
|
|
361
|
+
openstack_region: "ord",
|
|
362
|
+
openstack_service_name: "the_service",
|
|
363
363
|
connection_options:
|
|
364
364
|
{
|
|
365
365
|
read_timeout: 60,
|
|
366
366
|
write_timeout: 60,
|
|
367
|
-
connect_timeout: 60
|
|
368
|
-
}
|
|
367
|
+
connect_timeout: 60,
|
|
368
|
+
},
|
|
369
369
|
}
|
|
370
370
|
end
|
|
371
371
|
|
|
372
|
-
context
|
|
373
|
-
it
|
|
372
|
+
context "all requirements provided" do
|
|
373
|
+
it "creates a new compute connection" do
|
|
374
374
|
allow(Fog::Compute).to receive(:new) { |arg| arg }
|
|
375
|
-
res = config.merge(provider:
|
|
375
|
+
res = config.merge(provider: "OpenStack")
|
|
376
376
|
expect(driver.send(:compute)).to eq(res)
|
|
377
377
|
end
|
|
378
378
|
|
|
379
|
-
it
|
|
379
|
+
it "creates a new network connection" do
|
|
380
380
|
allow(Fog::Network).to receive(:new) { |arg| arg }
|
|
381
|
-
res = config.merge(provider:
|
|
381
|
+
res = config.merge(provider: "OpenStack")
|
|
382
382
|
expect(driver.send(:network)).to eq(res)
|
|
383
383
|
end
|
|
384
384
|
end
|
|
385
385
|
|
|
386
|
-
context
|
|
387
|
-
let(:config) { { openstack_api_key:
|
|
386
|
+
context "only an API key provided" do
|
|
387
|
+
let(:config) { { openstack_api_key: "1234" } }
|
|
388
388
|
|
|
389
|
-
it
|
|
389
|
+
it "raises an error" do
|
|
390
390
|
expect { driver.send(:compute) }.to raise_error(ArgumentError)
|
|
391
391
|
end
|
|
392
392
|
end
|
|
393
393
|
|
|
394
|
-
context
|
|
395
|
-
let(:config) { { openstack_username:
|
|
394
|
+
context "only a username provided" do
|
|
395
|
+
let(:config) { { openstack_username: "monkey" } }
|
|
396
396
|
|
|
397
|
-
it
|
|
397
|
+
it "raises an error" do
|
|
398
398
|
expect { driver.send(:compute) }.to raise_error(ArgumentError)
|
|
399
399
|
end
|
|
400
400
|
end
|
|
401
401
|
end
|
|
402
402
|
|
|
403
|
-
describe
|
|
403
|
+
describe "#create_server" do
|
|
404
404
|
let(:config) do
|
|
405
405
|
{
|
|
406
|
-
server_name:
|
|
407
|
-
image_ref:
|
|
408
|
-
flavor_ref:
|
|
406
|
+
server_name: "hello",
|
|
407
|
+
image_ref: "111",
|
|
408
|
+
flavor_ref: "1",
|
|
409
409
|
availability_zone: nil,
|
|
410
410
|
block_device_mapping: {
|
|
411
|
-
volume_size:
|
|
412
|
-
volume_id:
|
|
413
|
-
volume_device_name:
|
|
414
|
-
delete_on_termination:
|
|
415
|
-
}
|
|
411
|
+
volume_size: "5",
|
|
412
|
+
volume_id: "333",
|
|
413
|
+
volume_device_name: "vda",
|
|
414
|
+
delete_on_termination: "true",
|
|
415
|
+
},
|
|
416
416
|
}
|
|
417
417
|
end
|
|
418
418
|
let(:servers) do
|
|
419
|
-
s = double(
|
|
419
|
+
s = double("servers")
|
|
420
420
|
allow(s).to receive(:create) { |arg| arg }
|
|
421
421
|
s
|
|
422
422
|
end
|
|
423
|
-
let(:vlan1_net) { double(id:
|
|
424
|
-
let(:vlan2_net) { double(id:
|
|
425
|
-
let(:ubuntu_image) { double(id:
|
|
426
|
-
let(:fedora_image) { double(id:
|
|
427
|
-
let(:tiny_flavor) { double(id:
|
|
428
|
-
let(:small_flavor) { double(id:
|
|
423
|
+
let(:vlan1_net) { double(id: "1", name: "vlan1") }
|
|
424
|
+
let(:vlan2_net) { double(id: "2", name: "vlan2") }
|
|
425
|
+
let(:ubuntu_image) { double(id: "111", name: "ubuntu") }
|
|
426
|
+
let(:fedora_image) { double(id: "222", name: "fedora") }
|
|
427
|
+
let(:tiny_flavor) { double(id: "1", name: "tiny") }
|
|
428
|
+
let(:small_flavor) { double(id: "2", name: "small") }
|
|
429
429
|
let(:compute) do
|
|
430
430
|
double(
|
|
431
431
|
servers: servers,
|
|
@@ -438,10 +438,10 @@ describe Kitchen::Driver::Openstack do
|
|
|
438
438
|
end
|
|
439
439
|
let(:block_device_mapping) do
|
|
440
440
|
{
|
|
441
|
-
volume_id:
|
|
442
|
-
volume_size:
|
|
443
|
-
volume_device_name:
|
|
444
|
-
delete_on_termination:
|
|
441
|
+
volume_id: "333",
|
|
442
|
+
volume_size: "5",
|
|
443
|
+
volume_device_name: "vda",
|
|
444
|
+
delete_on_termination: "true",
|
|
445
445
|
}
|
|
446
446
|
end
|
|
447
447
|
let(:driver) do
|
|
@@ -452,25 +452,25 @@ describe Kitchen::Driver::Openstack do
|
|
|
452
452
|
d
|
|
453
453
|
end
|
|
454
454
|
|
|
455
|
-
context
|
|
455
|
+
context "a default config" do
|
|
456
456
|
before(:each) do
|
|
457
457
|
@expected = config.merge(name: config[:server_name])
|
|
458
458
|
@expected.delete_if { |k, _| k == :server_name }
|
|
459
459
|
end
|
|
460
460
|
|
|
461
|
-
it
|
|
461
|
+
it "creates the server using a compute connection" do
|
|
462
462
|
expect(driver.send(:create_server)).to eq(@expected)
|
|
463
463
|
end
|
|
464
464
|
end
|
|
465
465
|
|
|
466
|
-
context
|
|
466
|
+
context "a provided key name" do
|
|
467
467
|
let(:config) do
|
|
468
468
|
{
|
|
469
|
-
server_name:
|
|
470
|
-
image_ref:
|
|
471
|
-
flavor_ref:
|
|
469
|
+
server_name: "hello",
|
|
470
|
+
image_ref: "111",
|
|
471
|
+
flavor_ref: "1",
|
|
472
472
|
availability_zone: nil,
|
|
473
|
-
key_name:
|
|
473
|
+
key_name: "tarpals",
|
|
474
474
|
}
|
|
475
475
|
end
|
|
476
476
|
|
|
@@ -479,20 +479,20 @@ describe Kitchen::Driver::Openstack do
|
|
|
479
479
|
@expected.delete_if { |k, _| k == :server_name }
|
|
480
480
|
end
|
|
481
481
|
|
|
482
|
-
it
|
|
482
|
+
it "passes that key name to Fog" do
|
|
483
483
|
expect(driver.send(:create_server)).to eq(@expected)
|
|
484
484
|
end
|
|
485
485
|
end
|
|
486
486
|
|
|
487
|
-
context
|
|
487
|
+
context "a provided security group" do
|
|
488
488
|
let(:config) do
|
|
489
489
|
{
|
|
490
|
-
server_name:
|
|
491
|
-
image_ref:
|
|
492
|
-
flavor_ref:
|
|
490
|
+
server_name: "hello",
|
|
491
|
+
image_ref: "111",
|
|
492
|
+
flavor_ref: "1",
|
|
493
493
|
availability_zone: nil,
|
|
494
|
-
key_name:
|
|
495
|
-
security_groups: [
|
|
494
|
+
key_name: "tarpals",
|
|
495
|
+
security_groups: ["ping-and-ssh"],
|
|
496
496
|
}
|
|
497
497
|
end
|
|
498
498
|
|
|
@@ -501,19 +501,19 @@ describe Kitchen::Driver::Openstack do
|
|
|
501
501
|
@expected.delete_if { |k, _| k == :server_name }
|
|
502
502
|
end
|
|
503
503
|
|
|
504
|
-
it
|
|
504
|
+
it "passes that security group to Fog" do
|
|
505
505
|
expect(driver.send(:create_server)).to eq(@expected)
|
|
506
506
|
end
|
|
507
507
|
end
|
|
508
508
|
|
|
509
|
-
context
|
|
509
|
+
context "a provided availability zone" do
|
|
510
510
|
let(:config) do
|
|
511
511
|
{
|
|
512
|
-
server_name:
|
|
513
|
-
image_ref:
|
|
514
|
-
flavor_ref:
|
|
515
|
-
availability_zone:
|
|
516
|
-
key_name:
|
|
512
|
+
server_name: "hello",
|
|
513
|
+
image_ref: "111",
|
|
514
|
+
flavor_ref: "1",
|
|
515
|
+
availability_zone: "elsewhere",
|
|
516
|
+
key_name: "tarpals",
|
|
517
517
|
}
|
|
518
518
|
end
|
|
519
519
|
|
|
@@ -522,196 +522,196 @@ describe Kitchen::Driver::Openstack do
|
|
|
522
522
|
@expected.delete_if { |k, _| k == :server_name }
|
|
523
523
|
end
|
|
524
524
|
|
|
525
|
-
it
|
|
525
|
+
it "passes that availability zone to Fog" do
|
|
526
526
|
expect(driver.send(:create_server)).to eq(@expected)
|
|
527
527
|
end
|
|
528
528
|
end
|
|
529
529
|
|
|
530
|
-
context
|
|
530
|
+
context "image_id specified" do
|
|
531
531
|
let(:config) do
|
|
532
532
|
{
|
|
533
|
-
server_name:
|
|
534
|
-
image_id:
|
|
535
|
-
flavor_ref:
|
|
533
|
+
server_name: "hello",
|
|
534
|
+
image_id: "1e1f4346-e3ea-48ba-9d1b-0002bfcb8981",
|
|
535
|
+
flavor_ref: "1",
|
|
536
536
|
}
|
|
537
537
|
end
|
|
538
538
|
|
|
539
|
-
it
|
|
539
|
+
it "exact id match" do
|
|
540
540
|
expect(servers).to receive(:create).with(
|
|
541
|
-
name:
|
|
542
|
-
image_ref:
|
|
543
|
-
flavor_ref:
|
|
541
|
+
name: "hello",
|
|
542
|
+
image_ref: "1e1f4346-e3ea-48ba-9d1b-0002bfcb8981",
|
|
543
|
+
flavor_ref: "1",
|
|
544
544
|
availability_zone: nil
|
|
545
545
|
)
|
|
546
546
|
driver.send(:create_server)
|
|
547
547
|
end
|
|
548
548
|
end
|
|
549
549
|
|
|
550
|
-
context
|
|
550
|
+
context "image_id and image_ref specified" do
|
|
551
551
|
let(:config) do
|
|
552
552
|
{
|
|
553
|
-
server_name:
|
|
554
|
-
image_id:
|
|
555
|
-
image_ref:
|
|
556
|
-
flavor_ref:
|
|
553
|
+
server_name: "hello",
|
|
554
|
+
image_id: "1e1f4346-e3ea-48ba-9d1b-0002bfcb8981",
|
|
555
|
+
image_ref: "111",
|
|
556
|
+
flavor_ref: "1",
|
|
557
557
|
}
|
|
558
558
|
end
|
|
559
559
|
|
|
560
|
-
it
|
|
560
|
+
it "raises an exception" do
|
|
561
561
|
expect { driver.send(:create_server) }.to \
|
|
562
562
|
raise_error(Kitchen::ActionFailed)
|
|
563
563
|
end
|
|
564
564
|
end
|
|
565
565
|
|
|
566
|
-
context
|
|
566
|
+
context "flavor_id specified" do
|
|
567
567
|
let(:config) do
|
|
568
568
|
{
|
|
569
|
-
server_name:
|
|
570
|
-
flavor_id:
|
|
571
|
-
image_ref:
|
|
569
|
+
server_name: "hello",
|
|
570
|
+
flavor_id: "1e1f4346-e3ea-48ba-9d1b-0002bfcb8981",
|
|
571
|
+
image_ref: "111",
|
|
572
572
|
}
|
|
573
573
|
end
|
|
574
574
|
|
|
575
|
-
it
|
|
575
|
+
it "exact id match" do
|
|
576
576
|
expect(servers).to receive(:create).with(
|
|
577
|
-
name:
|
|
578
|
-
flavor_ref:
|
|
579
|
-
image_ref:
|
|
577
|
+
name: "hello",
|
|
578
|
+
flavor_ref: "1e1f4346-e3ea-48ba-9d1b-0002bfcb8981",
|
|
579
|
+
image_ref: "111",
|
|
580
580
|
availability_zone: nil
|
|
581
581
|
)
|
|
582
582
|
driver.send(:create_server)
|
|
583
583
|
end
|
|
584
584
|
end
|
|
585
585
|
|
|
586
|
-
context
|
|
586
|
+
context "flavor_id and flavor_ref specified" do
|
|
587
587
|
let(:config) do
|
|
588
588
|
{
|
|
589
|
-
server_name:
|
|
590
|
-
image_id:
|
|
591
|
-
flavor_id:
|
|
592
|
-
flavor_ref:
|
|
589
|
+
server_name: "hello",
|
|
590
|
+
image_id: "1e1f4346-e3ea-48ba-9d1b-0002bfcb8981",
|
|
591
|
+
flavor_id: "1e1f4346-e3ea-48ba-9d1b-0002bfcb8981",
|
|
592
|
+
flavor_ref: "1",
|
|
593
593
|
}
|
|
594
594
|
end
|
|
595
595
|
|
|
596
|
-
it
|
|
596
|
+
it "raises an exception" do
|
|
597
597
|
expect { driver.send(:create_server) }.to \
|
|
598
598
|
raise_error(Kitchen::ActionFailed)
|
|
599
599
|
end
|
|
600
600
|
end
|
|
601
601
|
|
|
602
|
-
context
|
|
602
|
+
context "image/flavor specifies id" do
|
|
603
603
|
let(:config) do
|
|
604
604
|
{
|
|
605
|
-
server_name:
|
|
606
|
-
image_ref:
|
|
607
|
-
flavor_ref:
|
|
605
|
+
server_name: "hello",
|
|
606
|
+
image_ref: "111",
|
|
607
|
+
flavor_ref: "1",
|
|
608
608
|
}
|
|
609
609
|
end
|
|
610
610
|
|
|
611
|
-
it
|
|
612
|
-
expect(servers).to receive(:create).with(name:
|
|
613
|
-
image_ref:
|
|
614
|
-
flavor_ref:
|
|
611
|
+
it "exact id match" do
|
|
612
|
+
expect(servers).to receive(:create).with(name: "hello",
|
|
613
|
+
image_ref: "111",
|
|
614
|
+
flavor_ref: "1",
|
|
615
615
|
availability_zone: nil)
|
|
616
616
|
driver.send(:create_server)
|
|
617
617
|
end
|
|
618
618
|
end
|
|
619
619
|
|
|
620
|
-
context
|
|
620
|
+
context "image/flavor specifies name" do
|
|
621
621
|
let(:config) do
|
|
622
622
|
{
|
|
623
|
-
server_name:
|
|
624
|
-
image_ref:
|
|
625
|
-
flavor_ref:
|
|
623
|
+
server_name: "hello",
|
|
624
|
+
image_ref: "fedora",
|
|
625
|
+
flavor_ref: "small",
|
|
626
626
|
}
|
|
627
627
|
end
|
|
628
628
|
|
|
629
|
-
it
|
|
630
|
-
expect(servers).to receive(:create).with(name:
|
|
631
|
-
image_ref:
|
|
632
|
-
flavor_ref:
|
|
629
|
+
it "exact name match" do
|
|
630
|
+
expect(servers).to receive(:create).with(name: "hello",
|
|
631
|
+
image_ref: "222",
|
|
632
|
+
flavor_ref: "2",
|
|
633
633
|
availability_zone: nil)
|
|
634
634
|
driver.send(:create_server)
|
|
635
635
|
end
|
|
636
636
|
end
|
|
637
637
|
|
|
638
|
-
context
|
|
638
|
+
context "image/flavor specifies regex" do
|
|
639
639
|
let(:config) do
|
|
640
640
|
{
|
|
641
|
-
server_name:
|
|
641
|
+
server_name: "hello",
|
|
642
642
|
# pass regex as string as yml returns string values
|
|
643
|
-
image_ref:
|
|
644
|
-
flavor_ref:
|
|
643
|
+
image_ref: "/edo/",
|
|
644
|
+
flavor_ref: "/in/",
|
|
645
645
|
}
|
|
646
646
|
end
|
|
647
647
|
|
|
648
|
-
it
|
|
649
|
-
expect(servers).to receive(:create).with(name:
|
|
650
|
-
image_ref:
|
|
651
|
-
flavor_ref:
|
|
648
|
+
it "regex name match" do
|
|
649
|
+
expect(servers).to receive(:create).with(name: "hello",
|
|
650
|
+
image_ref: "222",
|
|
651
|
+
flavor_ref: "1",
|
|
652
652
|
availability_zone: nil)
|
|
653
653
|
driver.send(:create_server)
|
|
654
654
|
end
|
|
655
655
|
end
|
|
656
656
|
|
|
657
|
-
context
|
|
657
|
+
context "network specifies network_id" do
|
|
658
658
|
let(:config) do
|
|
659
659
|
{
|
|
660
|
-
server_name:
|
|
661
|
-
image_ref:
|
|
662
|
-
flavor_ref:
|
|
663
|
-
network_id:
|
|
660
|
+
server_name: "hello",
|
|
661
|
+
image_ref: "111",
|
|
662
|
+
flavor_ref: "1",
|
|
663
|
+
network_id: "0922b7aa-0a2f-4e68-8ff7-2886c4fc472d",
|
|
664
664
|
}
|
|
665
665
|
end
|
|
666
666
|
|
|
667
|
-
it
|
|
667
|
+
it "exact id match" do
|
|
668
668
|
networks = [
|
|
669
|
-
{
|
|
669
|
+
{ "net_id" => "0922b7aa-0a2f-4e68-8ff7-2886c4fc472d" },
|
|
670
670
|
]
|
|
671
|
-
expect(servers).to receive(:create).with(name:
|
|
672
|
-
image_ref:
|
|
673
|
-
flavor_ref:
|
|
671
|
+
expect(servers).to receive(:create).with(name: "hello",
|
|
672
|
+
image_ref: "111",
|
|
673
|
+
flavor_ref: "1",
|
|
674
674
|
availability_zone: nil,
|
|
675
675
|
nics: networks)
|
|
676
676
|
driver.send(:create_server)
|
|
677
677
|
end
|
|
678
678
|
end
|
|
679
679
|
|
|
680
|
-
context
|
|
680
|
+
context "network_id and network_ref specified" do
|
|
681
681
|
let(:config) do
|
|
682
682
|
{
|
|
683
|
-
server_name:
|
|
684
|
-
image_id:
|
|
685
|
-
flavor_id:
|
|
686
|
-
network_id:
|
|
687
|
-
network_ref:
|
|
683
|
+
server_name: "hello",
|
|
684
|
+
image_id: "1e1f4346-e3ea-48ba-9d1b-0002bfcb8981",
|
|
685
|
+
flavor_id: "1e1f4346-e3ea-48ba-9d1b-0002bfcb8981",
|
|
686
|
+
network_id: "0922b7aa-0a2f-4e68-8ff7-2886c4fc472d",
|
|
687
|
+
network_ref: "1",
|
|
688
688
|
}
|
|
689
689
|
end
|
|
690
690
|
|
|
691
|
-
it
|
|
691
|
+
it "raises an exception" do
|
|
692
692
|
expect { driver.send(:create_server) }.to \
|
|
693
693
|
raise_error(Kitchen::ActionFailed)
|
|
694
694
|
end
|
|
695
695
|
end
|
|
696
696
|
|
|
697
|
-
context
|
|
697
|
+
context "network specifies id" do
|
|
698
698
|
let(:config) do
|
|
699
699
|
{
|
|
700
|
-
server_name:
|
|
701
|
-
image_ref:
|
|
702
|
-
flavor_ref:
|
|
703
|
-
network_ref:
|
|
700
|
+
server_name: "hello",
|
|
701
|
+
image_ref: "111",
|
|
702
|
+
flavor_ref: "1",
|
|
703
|
+
network_ref: "1",
|
|
704
704
|
}
|
|
705
705
|
end
|
|
706
706
|
|
|
707
|
-
it
|
|
707
|
+
it "exact id match" do
|
|
708
708
|
networks = [
|
|
709
|
-
{
|
|
709
|
+
{ "net_id" => "1" },
|
|
710
710
|
]
|
|
711
711
|
expect(servers).to receive(:create).with(
|
|
712
|
-
name:
|
|
713
|
-
image_ref:
|
|
714
|
-
flavor_ref:
|
|
712
|
+
name: "hello",
|
|
713
|
+
image_ref: "111",
|
|
714
|
+
flavor_ref: "1",
|
|
715
715
|
availability_zone: nil,
|
|
716
716
|
nics: networks
|
|
717
717
|
)
|
|
@@ -719,24 +719,24 @@ describe Kitchen::Driver::Openstack do
|
|
|
719
719
|
end
|
|
720
720
|
end
|
|
721
721
|
|
|
722
|
-
context
|
|
722
|
+
context "network specifies name" do
|
|
723
723
|
let(:config) do
|
|
724
724
|
{
|
|
725
|
-
server_name:
|
|
726
|
-
image_ref:
|
|
727
|
-
flavor_ref:
|
|
728
|
-
network_ref:
|
|
725
|
+
server_name: "hello",
|
|
726
|
+
image_ref: "111",
|
|
727
|
+
flavor_ref: "1",
|
|
728
|
+
network_ref: "vlan1",
|
|
729
729
|
}
|
|
730
730
|
end
|
|
731
731
|
|
|
732
|
-
it
|
|
732
|
+
it "exact id match" do
|
|
733
733
|
networks = [
|
|
734
|
-
{
|
|
734
|
+
{ "net_id" => "1" },
|
|
735
735
|
]
|
|
736
736
|
expect(servers).to receive(:create).with(
|
|
737
|
-
name:
|
|
738
|
-
image_ref:
|
|
739
|
-
flavor_ref:
|
|
737
|
+
name: "hello",
|
|
738
|
+
image_ref: "111",
|
|
739
|
+
flavor_ref: "1",
|
|
740
740
|
availability_zone: nil,
|
|
741
741
|
nics: networks
|
|
742
742
|
)
|
|
@@ -744,25 +744,25 @@ describe Kitchen::Driver::Openstack do
|
|
|
744
744
|
end
|
|
745
745
|
end
|
|
746
746
|
|
|
747
|
-
context
|
|
747
|
+
context "multiple networks specifies id" do
|
|
748
748
|
let(:config) do
|
|
749
749
|
{
|
|
750
|
-
server_name:
|
|
751
|
-
image_ref:
|
|
752
|
-
flavor_ref:
|
|
753
|
-
network_ref: %w
|
|
750
|
+
server_name: "hello",
|
|
751
|
+
image_ref: "111",
|
|
752
|
+
flavor_ref: "1",
|
|
753
|
+
network_ref: %w{1 2},
|
|
754
754
|
}
|
|
755
755
|
end
|
|
756
756
|
|
|
757
|
-
it
|
|
757
|
+
it "exact id match" do
|
|
758
758
|
networks = [
|
|
759
|
-
{
|
|
760
|
-
{
|
|
759
|
+
{ "net_id" => "1" },
|
|
760
|
+
{ "net_id" => "2" },
|
|
761
761
|
]
|
|
762
762
|
expect(servers).to receive(:create).with(
|
|
763
|
-
name:
|
|
764
|
-
image_ref:
|
|
765
|
-
flavor_ref:
|
|
763
|
+
name: "hello",
|
|
764
|
+
image_ref: "111",
|
|
765
|
+
flavor_ref: "1",
|
|
766
766
|
availability_zone: nil,
|
|
767
767
|
nics: networks
|
|
768
768
|
)
|
|
@@ -770,13 +770,13 @@ describe Kitchen::Driver::Openstack do
|
|
|
770
770
|
end
|
|
771
771
|
end
|
|
772
772
|
|
|
773
|
-
context
|
|
773
|
+
context "user_data specified" do
|
|
774
774
|
let(:config) do
|
|
775
775
|
{
|
|
776
|
-
server_name:
|
|
777
|
-
image_ref:
|
|
778
|
-
flavor_ref:
|
|
779
|
-
user_data:
|
|
776
|
+
server_name: "hello",
|
|
777
|
+
image_ref: "111",
|
|
778
|
+
flavor_ref: "1",
|
|
779
|
+
user_data: "cloud-init.txt",
|
|
780
780
|
}
|
|
781
781
|
end
|
|
782
782
|
let(:data) { "#cloud-config\n" }
|
|
@@ -786,11 +786,11 @@ describe Kitchen::Driver::Openstack do
|
|
|
786
786
|
allow(File).to receive(:open).and_return(data)
|
|
787
787
|
end
|
|
788
788
|
|
|
789
|
-
it
|
|
789
|
+
it "passes file contents" do
|
|
790
790
|
expect(servers).to receive(:create).with(
|
|
791
|
-
name:
|
|
792
|
-
image_ref:
|
|
793
|
-
flavor_ref:
|
|
791
|
+
name: "hello",
|
|
792
|
+
image_ref: "111",
|
|
793
|
+
flavor_ref: "1",
|
|
794
794
|
availability_zone: nil,
|
|
795
795
|
user_data: data
|
|
796
796
|
)
|
|
@@ -798,21 +798,21 @@ describe Kitchen::Driver::Openstack do
|
|
|
798
798
|
end
|
|
799
799
|
end
|
|
800
800
|
|
|
801
|
-
context
|
|
801
|
+
context "config drive enabled" do
|
|
802
802
|
let(:config) do
|
|
803
803
|
{
|
|
804
|
-
server_name:
|
|
805
|
-
image_ref:
|
|
806
|
-
flavor_ref:
|
|
807
|
-
config_drive: true
|
|
804
|
+
server_name: "hello",
|
|
805
|
+
image_ref: "111",
|
|
806
|
+
flavor_ref: "1",
|
|
807
|
+
config_drive: true,
|
|
808
808
|
}
|
|
809
809
|
end
|
|
810
810
|
|
|
811
|
-
it
|
|
811
|
+
it "enables config drive" do
|
|
812
812
|
expect(servers).to receive(:create).with(
|
|
813
|
-
name:
|
|
814
|
-
image_ref:
|
|
815
|
-
flavor_ref:
|
|
813
|
+
name: "hello",
|
|
814
|
+
image_ref: "111",
|
|
815
|
+
flavor_ref: "1",
|
|
816
816
|
availability_zone: nil,
|
|
817
817
|
config_drive: true
|
|
818
818
|
)
|
|
@@ -820,30 +820,30 @@ describe Kitchen::Driver::Openstack do
|
|
|
820
820
|
end
|
|
821
821
|
end
|
|
822
822
|
|
|
823
|
-
context
|
|
823
|
+
context "metadata specified" do
|
|
824
824
|
let(:config) do
|
|
825
825
|
{
|
|
826
|
-
server_name:
|
|
827
|
-
image_ref:
|
|
828
|
-
flavor_ref:
|
|
826
|
+
server_name: "hello",
|
|
827
|
+
image_ref: "111",
|
|
828
|
+
flavor_ref: "1",
|
|
829
829
|
metadata: {
|
|
830
|
-
name:
|
|
831
|
-
ohai:
|
|
832
|
-
}
|
|
830
|
+
name: "hello",
|
|
831
|
+
ohai: "chef",
|
|
832
|
+
},
|
|
833
833
|
}
|
|
834
834
|
end
|
|
835
835
|
let(:data) do
|
|
836
836
|
{
|
|
837
|
-
name:
|
|
838
|
-
ohai:
|
|
837
|
+
name: "hello",
|
|
838
|
+
ohai: "chef",
|
|
839
839
|
}
|
|
840
840
|
end
|
|
841
841
|
|
|
842
|
-
it
|
|
842
|
+
it "passes metadata contents" do
|
|
843
843
|
expect(servers).to receive(:create).with(
|
|
844
|
-
name:
|
|
845
|
-
image_ref:
|
|
846
|
-
flavor_ref:
|
|
844
|
+
name: "hello",
|
|
845
|
+
image_ref: "111",
|
|
846
|
+
flavor_ref: "1",
|
|
847
847
|
availability_zone: nil,
|
|
848
848
|
metadata: data
|
|
849
849
|
)
|
|
@@ -852,64 +852,64 @@ describe Kitchen::Driver::Openstack do
|
|
|
852
852
|
end
|
|
853
853
|
end
|
|
854
854
|
|
|
855
|
-
describe
|
|
856
|
-
let(:login) {
|
|
857
|
-
let(:hostname) {
|
|
855
|
+
describe "#default_name" do
|
|
856
|
+
let(:login) { "user" }
|
|
857
|
+
let(:hostname) { "host" }
|
|
858
858
|
|
|
859
859
|
before(:each) do
|
|
860
860
|
allow(Etc).to receive(:getlogin).and_return(login)
|
|
861
861
|
allow(Socket).to receive(:gethostname).and_return(hostname)
|
|
862
862
|
end
|
|
863
863
|
|
|
864
|
-
it
|
|
864
|
+
it "generates a name" do
|
|
865
865
|
expect(driver.send(:default_name)).to match(/^potatoes-user-host-(\S*)/)
|
|
866
866
|
end
|
|
867
867
|
|
|
868
|
-
context
|
|
869
|
-
let(:hostname) {
|
|
868
|
+
context "local node with a long hostname" do
|
|
869
|
+
let(:hostname) { "ab.c" * 20 }
|
|
870
870
|
|
|
871
|
-
it
|
|
871
|
+
it "limits the generated name to 63 characters" do
|
|
872
872
|
expect(driver.send(:default_name).length).to be <= 63
|
|
873
873
|
end
|
|
874
874
|
end
|
|
875
875
|
|
|
876
|
-
context
|
|
877
|
-
let(:login) {
|
|
878
|
-
let(:hostname) {
|
|
879
|
-
let(:instance_name) {
|
|
876
|
+
context "node with a long hostname, username, and base name" do
|
|
877
|
+
let(:login) { "abcd" * 20 }
|
|
878
|
+
let(:hostname) { "efgh" * 20 }
|
|
879
|
+
let(:instance_name) { "ijkl" * 20 }
|
|
880
880
|
|
|
881
|
-
it
|
|
881
|
+
it "limits the generated name to 63 characters" do
|
|
882
882
|
expect(driver.send(:default_name).length).to eq(63)
|
|
883
883
|
end
|
|
884
884
|
end
|
|
885
885
|
|
|
886
|
-
context
|
|
887
|
-
let(:login) {
|
|
888
|
-
let(:hostname) {
|
|
889
|
-
let(:instance_name) {
|
|
886
|
+
context "a login and hostname with punctuation in them" do
|
|
887
|
+
let(:login) { "some.u-se-r" }
|
|
888
|
+
let(:hostname) { "a.host-name" }
|
|
889
|
+
let(:instance_name) { "a.instance-name" }
|
|
890
890
|
|
|
891
|
-
it
|
|
892
|
-
expect(driver.send(:default_name)).to_not include(
|
|
891
|
+
it "strips out the dots to prevent bad server names" do
|
|
892
|
+
expect(driver.send(:default_name)).to_not include(".")
|
|
893
893
|
end
|
|
894
894
|
|
|
895
|
-
it
|
|
896
|
-
expect(driver.send(:default_name).count(
|
|
895
|
+
it "strips out all but the three hyphen separators" do
|
|
896
|
+
expect(driver.send(:default_name).count("-")).to eq(3)
|
|
897
897
|
end
|
|
898
898
|
end
|
|
899
899
|
|
|
900
|
-
context
|
|
900
|
+
context "a non-login shell" do
|
|
901
901
|
let(:login) { nil }
|
|
902
902
|
|
|
903
|
-
it
|
|
903
|
+
it "subs in a placeholder login string" do
|
|
904
904
|
expect(driver.send(:default_name)).to match(/^potatoes-nologin-/)
|
|
905
905
|
end
|
|
906
906
|
end
|
|
907
907
|
end
|
|
908
908
|
|
|
909
|
-
describe
|
|
910
|
-
let(:login) {
|
|
911
|
-
let(:hostname) {
|
|
912
|
-
let(:prefix) {
|
|
909
|
+
describe "#server_name_prefix" do
|
|
910
|
+
let(:login) { "user" }
|
|
911
|
+
let(:hostname) { "host" }
|
|
912
|
+
let(:prefix) { "parsnip" }
|
|
913
913
|
|
|
914
914
|
# These are still used in the "blank prefix" test
|
|
915
915
|
before(:each) do
|
|
@@ -917,116 +917,116 @@ describe Kitchen::Driver::Openstack do
|
|
|
917
917
|
allow(Socket).to receive(:gethostname).and_return(hostname)
|
|
918
918
|
end
|
|
919
919
|
|
|
920
|
-
it
|
|
920
|
+
it "generates a name with the selected prefix" do
|
|
921
921
|
expect(driver.send(:server_name_prefix, prefix))
|
|
922
922
|
.to match(/^parsnip-(\S*)/)
|
|
923
923
|
end
|
|
924
924
|
|
|
925
|
-
context
|
|
926
|
-
let(:long_prefix) {
|
|
925
|
+
context "very long prefix provided" do
|
|
926
|
+
let(:long_prefix) { "a" * 70 }
|
|
927
927
|
|
|
928
|
-
it
|
|
928
|
+
it "limits the generated name to 63 characters" do
|
|
929
929
|
expect(driver.send(:server_name_prefix, long_prefix).length)
|
|
930
930
|
.to be <= 63
|
|
931
931
|
end
|
|
932
932
|
end
|
|
933
933
|
|
|
934
|
-
context
|
|
935
|
-
let(:bad_char_prefix) {
|
|
934
|
+
context "a prefix with punctuation" do
|
|
935
|
+
let(:bad_char_prefix) { "pa-rsn.ip" }
|
|
936
936
|
|
|
937
|
-
it
|
|
937
|
+
it "strips out the dots to prevent bad server names" do
|
|
938
938
|
expect(driver.send(:server_name_prefix, bad_char_prefix))
|
|
939
|
-
.to_not include(
|
|
939
|
+
.to_not include(".")
|
|
940
940
|
end
|
|
941
941
|
|
|
942
|
-
it
|
|
942
|
+
it "strips out all but the one hyphen separator" do
|
|
943
943
|
expect(driver.send(:server_name_prefix, bad_char_prefix)
|
|
944
|
-
.count(
|
|
944
|
+
.count("-")).to eq(1)
|
|
945
945
|
end
|
|
946
946
|
end
|
|
947
947
|
|
|
948
|
-
context
|
|
949
|
-
it
|
|
950
|
-
expect(driver.send(:server_name_prefix,
|
|
948
|
+
context "blank prefix" do
|
|
949
|
+
it "generates fully random server name" do
|
|
950
|
+
expect(driver.send(:server_name_prefix, ""))
|
|
951
951
|
.to match(/potatoes-user-host-(\S*)/)
|
|
952
952
|
end
|
|
953
953
|
end
|
|
954
954
|
end
|
|
955
955
|
|
|
956
|
-
describe
|
|
956
|
+
describe "#attach_ip_from_pool" do
|
|
957
957
|
let(:server) { nil }
|
|
958
|
-
let(:pool) {
|
|
959
|
-
let(:ip) {
|
|
958
|
+
let(:pool) { "swimmers" }
|
|
959
|
+
let(:ip) { "1.1.1.1" }
|
|
960
960
|
let(:address) do
|
|
961
961
|
double(ip: ip, fixed_ip: nil, instance_id: nil, pool: pool)
|
|
962
962
|
end
|
|
963
963
|
let(:compute) { double(addresses: [address]) }
|
|
964
964
|
|
|
965
965
|
before(:each) do
|
|
966
|
-
allow(driver).to receive(:attach_ip).with(server, ip).and_return(
|
|
966
|
+
allow(driver).to receive(:attach_ip).with(server, ip).and_return("bing!")
|
|
967
967
|
allow(driver).to receive(:compute).and_return(compute)
|
|
968
968
|
end
|
|
969
969
|
|
|
970
|
-
it
|
|
971
|
-
expect(driver.send(:attach_ip_from_pool, server, pool)).to eq(
|
|
970
|
+
it "determines an IP to attempt to attach" do
|
|
971
|
+
expect(driver.send(:attach_ip_from_pool, server, pool)).to eq("bing!")
|
|
972
972
|
end
|
|
973
973
|
|
|
974
|
-
context
|
|
974
|
+
context "no free addresses in the specified pool" do
|
|
975
975
|
let(:address) do
|
|
976
976
|
double(ip: ip, fixed_ip: nil, instance_id: nil,
|
|
977
|
-
pool:
|
|
977
|
+
pool: "some_other_pool")
|
|
978
978
|
end
|
|
979
979
|
|
|
980
|
-
it
|
|
980
|
+
it "raises an exception" do
|
|
981
981
|
expect { driver.send(:attach_ip_from_pool, server, pool) }.to \
|
|
982
982
|
raise_error(Kitchen::ActionFailed)
|
|
983
983
|
end
|
|
984
984
|
end
|
|
985
985
|
end
|
|
986
986
|
|
|
987
|
-
describe
|
|
987
|
+
describe "#allocate_ip_from_pool" do
|
|
988
988
|
let(:server) { nil }
|
|
989
|
-
let(:pool) {
|
|
989
|
+
let(:pool) { "swimmers" }
|
|
990
990
|
let(:config) { { allocate_floating_ip: true } }
|
|
991
991
|
let(:network_id) { 123 }
|
|
992
|
-
let(:ip) {
|
|
992
|
+
let(:ip) { "1.1.1.1" }
|
|
993
993
|
let(:address) do
|
|
994
994
|
double(ip: ip, fixed_ip: nil, instance_id: nil, pool: pool)
|
|
995
995
|
end
|
|
996
996
|
let(:list_networks_response) do
|
|
997
|
-
double(body: {
|
|
997
|
+
double(body: { "networks" => [{ "name" => pool, "id" => network_id }] })
|
|
998
998
|
end
|
|
999
999
|
let(:create_ip_network_response) do
|
|
1000
|
-
double(body: {
|
|
1000
|
+
double(body: { "floatingip" => { "floating_ip_address" => ip } })
|
|
1001
1001
|
end
|
|
1002
1002
|
let(:network) { double(list_networks: list_networks_response, create_floating_ip: create_ip_network_response) } # rubocop:disable Metrics/LineLength
|
|
1003
1003
|
|
|
1004
1004
|
before(:each) do
|
|
1005
|
-
allow(driver).to receive(:attach_ip).with(server, ip).and_return(
|
|
1005
|
+
allow(driver).to receive(:attach_ip).with(server, ip).and_return("bing!")
|
|
1006
1006
|
allow(driver).to receive(:network).and_return(network)
|
|
1007
1007
|
end
|
|
1008
1008
|
|
|
1009
|
-
it
|
|
1010
|
-
expect(driver.send(:attach_ip_from_pool, server, pool)).to eq(
|
|
1009
|
+
it "determines an IP to attempt to attach" do
|
|
1010
|
+
expect(driver.send(:attach_ip_from_pool, server, pool)).to eq("bing!")
|
|
1011
1011
|
end
|
|
1012
1012
|
end
|
|
1013
1013
|
|
|
1014
|
-
describe
|
|
1015
|
-
let(:ip) {
|
|
1014
|
+
describe "#attach_ip" do
|
|
1015
|
+
let(:ip) { "1.1.1.1" }
|
|
1016
1016
|
let(:addresses) { {} }
|
|
1017
1017
|
let(:server) do
|
|
1018
|
-
s = double(
|
|
1018
|
+
s = double("server")
|
|
1019
1019
|
expect(s).to receive(:associate_address).with(ip).and_return(true)
|
|
1020
1020
|
allow(s).to receive(:addresses).and_return(addresses)
|
|
1021
1021
|
s
|
|
1022
1022
|
end
|
|
1023
1023
|
|
|
1024
|
-
it
|
|
1024
|
+
it "associates the IP address with the server" do
|
|
1025
1025
|
expect(driver.send(:attach_ip, server, ip)).to eq(true)
|
|
1026
1026
|
end
|
|
1027
1027
|
end
|
|
1028
1028
|
|
|
1029
|
-
describe
|
|
1029
|
+
describe "#get_ip" do
|
|
1030
1030
|
let(:addresses) { nil }
|
|
1031
1031
|
let(:public_ip_addresses) { nil }
|
|
1032
1032
|
let(:private_ip_addresses) { nil }
|
|
@@ -1045,71 +1045,71 @@ describe Kitchen::Driver::Openstack do
|
|
|
1045
1045
|
wait_for: { duration: 0 })
|
|
1046
1046
|
end
|
|
1047
1047
|
|
|
1048
|
-
context
|
|
1049
|
-
let(:public_ip_addresses) { %w
|
|
1050
|
-
let(:private_ip_addresses) { %w
|
|
1051
|
-
let(:parsed_ips) { [%w
|
|
1048
|
+
context "both public and private IPs" do
|
|
1049
|
+
let(:public_ip_addresses) { %w{1::1 1.2.3.4} }
|
|
1050
|
+
let(:private_ip_addresses) { %w{5.5.5.5} }
|
|
1051
|
+
let(:parsed_ips) { [%w{1.2.3.4}, %w{5.5.5.5}] }
|
|
1052
1052
|
|
|
1053
|
-
it
|
|
1054
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1053
|
+
it "returns a public IPv4 address" do
|
|
1054
|
+
expect(driver.send(:get_ip, server)).to eq("1.2.3.4")
|
|
1055
1055
|
end
|
|
1056
1056
|
end
|
|
1057
1057
|
|
|
1058
|
-
context
|
|
1059
|
-
let(:public_ip_addresses) { %w
|
|
1060
|
-
let(:parsed_ips) { [%w
|
|
1058
|
+
context "only public IPs" do
|
|
1059
|
+
let(:public_ip_addresses) { %w{4.3.2.1 2::1} }
|
|
1060
|
+
let(:parsed_ips) { [%w{4.3.2.1}, []] }
|
|
1061
1061
|
|
|
1062
|
-
it
|
|
1063
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1062
|
+
it "returns a public IPv4 address" do
|
|
1063
|
+
expect(driver.send(:get_ip, server)).to eq("4.3.2.1")
|
|
1064
1064
|
end
|
|
1065
1065
|
end
|
|
1066
1066
|
|
|
1067
|
-
context
|
|
1068
|
-
let(:private_ip_addresses) { %w
|
|
1069
|
-
let(:parsed_ips) { [[], %w
|
|
1067
|
+
context "only private IPs" do
|
|
1068
|
+
let(:private_ip_addresses) { %w{3::1 5.5.5.5} }
|
|
1069
|
+
let(:parsed_ips) { [[], %w{5.5.5.5}] }
|
|
1070
1070
|
|
|
1071
|
-
it
|
|
1072
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1071
|
+
it "returns a private IPv4 address" do
|
|
1072
|
+
expect(driver.send(:get_ip, server)).to eq("5.5.5.5")
|
|
1073
1073
|
end
|
|
1074
1074
|
end
|
|
1075
1075
|
|
|
1076
|
-
context
|
|
1077
|
-
let(:ip_addresses) { %w
|
|
1078
|
-
let(:parsed_ips) { [[], %w
|
|
1076
|
+
context "no predictable network name" do
|
|
1077
|
+
let(:ip_addresses) { %w{3::1 5.5.5.5} }
|
|
1078
|
+
let(:parsed_ips) { [[], %w{5.5.5.5}] }
|
|
1079
1079
|
|
|
1080
|
-
it
|
|
1081
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1080
|
+
it "returns the first IP that matches the IP version" do
|
|
1081
|
+
expect(driver.send(:get_ip, server)).to eq("5.5.5.5")
|
|
1082
1082
|
end
|
|
1083
1083
|
end
|
|
1084
1084
|
|
|
1085
|
-
context
|
|
1086
|
-
let(:config) { { openstack_network_name:
|
|
1085
|
+
context "IPs in user-defined network group" do
|
|
1086
|
+
let(:config) { { openstack_network_name: "mynetwork" } }
|
|
1087
1087
|
let(:addresses) do
|
|
1088
1088
|
{
|
|
1089
|
-
|
|
1090
|
-
{
|
|
1091
|
-
{
|
|
1092
|
-
]
|
|
1089
|
+
"mynetwork" => [
|
|
1090
|
+
{ "addr" => "7.7.7.7" },
|
|
1091
|
+
{ "addr" => "4::1" },
|
|
1092
|
+
],
|
|
1093
1093
|
}
|
|
1094
1094
|
end
|
|
1095
1095
|
|
|
1096
|
-
it
|
|
1097
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1096
|
+
it "returns a IPv4 address in user-defined network group" do
|
|
1097
|
+
expect(driver.send(:get_ip, server)).to eq("7.7.7.7")
|
|
1098
1098
|
end
|
|
1099
1099
|
end
|
|
1100
1100
|
|
|
1101
|
-
context
|
|
1102
|
-
let(:config) { { floating_ip:
|
|
1101
|
+
context "when a floating ip is provided" do
|
|
1102
|
+
let(:config) { { floating_ip: "1.2.3.4" } }
|
|
1103
1103
|
|
|
1104
|
-
it
|
|
1104
|
+
it "returns the floating ip and skips reloading" do
|
|
1105
1105
|
allow(driver).to receive(:config).and_return(config)
|
|
1106
1106
|
|
|
1107
1107
|
expect(server).to_not receive(:wait_for)
|
|
1108
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1108
|
+
expect(driver.send(:get_ip, server)).to eq("1.2.3.4")
|
|
1109
1109
|
end
|
|
1110
1110
|
end
|
|
1111
1111
|
|
|
1112
|
-
context
|
|
1112
|
+
context "an OpenStack deployment without the floating IP extension" do
|
|
1113
1113
|
before do
|
|
1114
1114
|
allow(server).to receive(:public_ip_addresses).and_raise(
|
|
1115
1115
|
Fog::Compute::OpenStack::NotFound
|
|
@@ -1119,216 +1119,216 @@ describe Kitchen::Driver::Openstack do
|
|
|
1119
1119
|
)
|
|
1120
1120
|
end
|
|
1121
1121
|
|
|
1122
|
-
context
|
|
1122
|
+
context "both public and private IPs in the addresses hash" do
|
|
1123
1123
|
let(:addresses) do
|
|
1124
1124
|
{
|
|
1125
|
-
|
|
1126
|
-
|
|
1125
|
+
"public" => [{ "addr" => "6.6.6.6" }, { "addr" => "7.7.7.7" }],
|
|
1126
|
+
"private" => [{ "addr" => "8.8.8.8" }, { "addr" => "9.9.9.9" }],
|
|
1127
1127
|
}
|
|
1128
1128
|
end
|
|
1129
|
-
let(:parsed_ips) { [%w
|
|
1129
|
+
let(:parsed_ips) { [%w{6.6.6.6 7.7.7.7}, %w{8.8.8.8 9.9.9.9}] }
|
|
1130
1130
|
|
|
1131
|
-
it
|
|
1132
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1131
|
+
it "selects the first public IP" do
|
|
1132
|
+
expect(driver.send(:get_ip, server)).to eq("6.6.6.6")
|
|
1133
1133
|
end
|
|
1134
1134
|
end
|
|
1135
1135
|
|
|
1136
|
-
context
|
|
1136
|
+
context "when openstack_network_name is provided" do
|
|
1137
1137
|
let(:addresses) do
|
|
1138
1138
|
{
|
|
1139
|
-
|
|
1140
|
-
|
|
1139
|
+
"public" => [{ "addr" => "6.6.6.6" }, { "addr" => "7.7.7.7" }],
|
|
1140
|
+
"private" => [{ "addr" => "8.8.8.8" }, { "addr" => "9.9.9.9" }],
|
|
1141
1141
|
}
|
|
1142
1142
|
end
|
|
1143
|
-
let(:config) { { openstack_network_name:
|
|
1143
|
+
let(:config) { { openstack_network_name: "public" } }
|
|
1144
1144
|
|
|
1145
|
-
it
|
|
1145
|
+
it "should respond with the first address from the addresses" do
|
|
1146
1146
|
allow(driver).to receive(:config).and_return(config)
|
|
1147
1147
|
|
|
1148
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1148
|
+
expect(driver.send(:get_ip, server)).to eq("6.6.6.6")
|
|
1149
1149
|
end
|
|
1150
1150
|
end
|
|
1151
1151
|
|
|
1152
|
-
context
|
|
1152
|
+
context "when openstack_network_name is provided and use_ipv6 is false" do
|
|
1153
1153
|
let(:addresses) do
|
|
1154
1154
|
{
|
|
1155
|
-
|
|
1156
|
-
|
|
1155
|
+
"public" => [{ "addr" => "4::1" }, { "addr" => "7.7.7.7" }],
|
|
1156
|
+
"private" => [{ "addr" => "5::1" }, { "addr" => "9.9.9.9" }],
|
|
1157
1157
|
}
|
|
1158
1158
|
end
|
|
1159
|
-
let(:config) { { openstack_network_name:
|
|
1159
|
+
let(:config) { { openstack_network_name: "public" } }
|
|
1160
1160
|
|
|
1161
|
-
it
|
|
1161
|
+
it "should respond with the first IPv4 address from the addresses" do
|
|
1162
1162
|
allow(driver).to receive(:config).and_return(config)
|
|
1163
1163
|
|
|
1164
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1164
|
+
expect(driver.send(:get_ip, server)).to eq("7.7.7.7")
|
|
1165
1165
|
end
|
|
1166
1166
|
end
|
|
1167
1167
|
|
|
1168
|
-
context
|
|
1168
|
+
context "when openstack_network_name is provided and use_ipv6 is true" do
|
|
1169
1169
|
let(:addresses) do
|
|
1170
1170
|
{
|
|
1171
|
-
|
|
1172
|
-
|
|
1171
|
+
"public" => [{ "addr" => "4::1" }, { "addr" => "7.7.7.7" }],
|
|
1172
|
+
"private" => [{ "addr" => "5::1" }, { "addr" => "9.9.9.9" }],
|
|
1173
1173
|
}
|
|
1174
1174
|
end
|
|
1175
|
-
let(:config) { { openstack_network_name:
|
|
1175
|
+
let(:config) { { openstack_network_name: "public", use_ipv6: true } }
|
|
1176
1176
|
|
|
1177
|
-
it
|
|
1177
|
+
it "should respond with the first IPv6 address from the addresses" do
|
|
1178
1178
|
allow(driver).to receive(:config).and_return(config)
|
|
1179
1179
|
|
|
1180
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1180
|
+
expect(driver.send(:get_ip, server)).to eq("4::1")
|
|
1181
1181
|
end
|
|
1182
1182
|
end
|
|
1183
1183
|
|
|
1184
|
-
context
|
|
1184
|
+
context "only public IPs in the address hash" do
|
|
1185
1185
|
let(:addresses) do
|
|
1186
|
-
{
|
|
1186
|
+
{ "public" => [{ "addr" => "6.6.6.6" }, { "addr" => "7.7.7.7" }] }
|
|
1187
1187
|
end
|
|
1188
|
-
let(:parsed_ips) { [%w
|
|
1188
|
+
let(:parsed_ips) { [%w{6.6.6.6 7.7.7.7}, []] }
|
|
1189
1189
|
|
|
1190
|
-
it
|
|
1191
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1190
|
+
it "selects the first public IP" do
|
|
1191
|
+
expect(driver.send(:get_ip, server)).to eq("6.6.6.6")
|
|
1192
1192
|
end
|
|
1193
1193
|
end
|
|
1194
1194
|
|
|
1195
|
-
context
|
|
1195
|
+
context "only private IPs in the address hash" do
|
|
1196
1196
|
let(:addresses) do
|
|
1197
|
-
{
|
|
1197
|
+
{ "private" => [{ "addr" => "8.8.8.8" }, { "addr" => "9.9.9.9" }] }
|
|
1198
1198
|
end
|
|
1199
|
-
let(:parsed_ips) { [[], %w
|
|
1199
|
+
let(:parsed_ips) { [[], %w{8.8.8.8 9.9.9.9}] }
|
|
1200
1200
|
|
|
1201
|
-
it
|
|
1202
|
-
expect(driver.send(:get_ip, server)).to eq(
|
|
1201
|
+
it "selects the first private IP" do
|
|
1202
|
+
expect(driver.send(:get_ip, server)).to eq("8.8.8.8")
|
|
1203
1203
|
end
|
|
1204
1204
|
end
|
|
1205
1205
|
end
|
|
1206
1206
|
|
|
1207
|
-
context
|
|
1208
|
-
it
|
|
1207
|
+
context "no IP addresses whatsoever" do
|
|
1208
|
+
it "raises an exception" do
|
|
1209
1209
|
expected = Kitchen::ActionFailed
|
|
1210
1210
|
expect { driver.send(:get_ip, server) }.to raise_error(expected)
|
|
1211
1211
|
end
|
|
1212
1212
|
end
|
|
1213
1213
|
|
|
1214
|
-
context
|
|
1214
|
+
context "when network information is not found" do
|
|
1215
1215
|
before do
|
|
1216
1216
|
allow(server).to receive(:wait_for).and_raise(Fog::Errors::TimeoutError)
|
|
1217
1217
|
end
|
|
1218
1218
|
|
|
1219
|
-
it
|
|
1219
|
+
it "raises an exception" do
|
|
1220
1220
|
expected = Kitchen::ActionFailed
|
|
1221
1221
|
expect { driver.send(:get_ip, server) }.to raise_error(expected)
|
|
1222
1222
|
end
|
|
1223
1223
|
end
|
|
1224
1224
|
end
|
|
1225
1225
|
|
|
1226
|
-
describe
|
|
1227
|
-
let(:pub_v4) { %w
|
|
1228
|
-
let(:pub_v6) { %w
|
|
1229
|
-
let(:priv_v4) { %w
|
|
1230
|
-
let(:priv_v6) { %w
|
|
1226
|
+
describe "#parse_ips" do
|
|
1227
|
+
let(:pub_v4) { %w{1.1.1.1 2.2.2.2} }
|
|
1228
|
+
let(:pub_v6) { %w{1::1 2::2} }
|
|
1229
|
+
let(:priv_v4) { %w{3.3.3.3 4.4.4.4} }
|
|
1230
|
+
let(:priv_v6) { %w{3::3 4::4} }
|
|
1231
1231
|
let(:pub) { pub_v4 + pub_v6 }
|
|
1232
1232
|
let(:priv) { priv_v4 + priv_v6 }
|
|
1233
1233
|
|
|
1234
|
-
context
|
|
1235
|
-
context
|
|
1236
|
-
it
|
|
1234
|
+
context "both public and private IPs" do
|
|
1235
|
+
context "IPv4 (default)" do
|
|
1236
|
+
it "returns only the v4 IPs" do
|
|
1237
1237
|
expect(driver.send(:parse_ips, pub, priv)).to eq([pub_v4, priv_v4])
|
|
1238
1238
|
end
|
|
1239
1239
|
end
|
|
1240
1240
|
|
|
1241
|
-
context
|
|
1241
|
+
context "IPv6" do
|
|
1242
1242
|
let(:config) { { use_ipv6: true } }
|
|
1243
1243
|
|
|
1244
|
-
it
|
|
1244
|
+
it "returns only the v6 IPs" do
|
|
1245
1245
|
expect(driver.send(:parse_ips, pub, priv)).to eq([pub_v6, priv_v6])
|
|
1246
1246
|
end
|
|
1247
1247
|
end
|
|
1248
1248
|
end
|
|
1249
1249
|
|
|
1250
|
-
context
|
|
1250
|
+
context "only public IPs" do
|
|
1251
1251
|
let(:priv) { nil }
|
|
1252
1252
|
|
|
1253
|
-
context
|
|
1254
|
-
it
|
|
1253
|
+
context "IPv4 (default)" do
|
|
1254
|
+
it "returns only the v4 IPs" do
|
|
1255
1255
|
expect(driver.send(:parse_ips, pub, priv)).to eq([pub_v4, []])
|
|
1256
1256
|
end
|
|
1257
1257
|
end
|
|
1258
1258
|
|
|
1259
|
-
context
|
|
1259
|
+
context "IPv6" do
|
|
1260
1260
|
let(:config) { { use_ipv6: true } }
|
|
1261
1261
|
|
|
1262
|
-
it
|
|
1262
|
+
it "returns only the v6 IPs" do
|
|
1263
1263
|
expect(driver.send(:parse_ips, pub, priv)).to eq([pub_v6, []])
|
|
1264
1264
|
end
|
|
1265
1265
|
end
|
|
1266
1266
|
end
|
|
1267
1267
|
|
|
1268
|
-
context
|
|
1268
|
+
context "only private IPs" do
|
|
1269
1269
|
let(:pub) { nil }
|
|
1270
1270
|
|
|
1271
|
-
context
|
|
1272
|
-
it
|
|
1271
|
+
context "IPv4 (default)" do
|
|
1272
|
+
it "returns only the v4 IPs" do
|
|
1273
1273
|
expect(driver.send(:parse_ips, pub, priv)).to eq([[], priv_v4])
|
|
1274
1274
|
end
|
|
1275
1275
|
end
|
|
1276
1276
|
|
|
1277
|
-
context
|
|
1277
|
+
context "IPv6" do
|
|
1278
1278
|
let(:config) { { use_ipv6: true } }
|
|
1279
1279
|
|
|
1280
|
-
it
|
|
1280
|
+
it "returns only the v6 IPs" do
|
|
1281
1281
|
expect(driver.send(:parse_ips, pub, priv)).to eq([[], priv_v6])
|
|
1282
1282
|
end
|
|
1283
1283
|
end
|
|
1284
1284
|
end
|
|
1285
1285
|
|
|
1286
|
-
context
|
|
1286
|
+
context "no IPs whatsoever" do
|
|
1287
1287
|
let(:pub) { nil }
|
|
1288
1288
|
let(:priv) { nil }
|
|
1289
1289
|
|
|
1290
|
-
context
|
|
1291
|
-
it
|
|
1290
|
+
context "IPv4 (default)" do
|
|
1291
|
+
it "returns empty lists" do
|
|
1292
1292
|
expect(driver.send(:parse_ips, pub, priv)).to eq([[], []])
|
|
1293
1293
|
end
|
|
1294
1294
|
end
|
|
1295
1295
|
|
|
1296
|
-
context
|
|
1296
|
+
context "IPv6" do
|
|
1297
1297
|
let(:config) { { use_ipv6: true } }
|
|
1298
1298
|
|
|
1299
|
-
it
|
|
1299
|
+
it "returns empty lists" do
|
|
1300
1300
|
expect(driver.send(:parse_ips, nil, nil)).to eq([[], []])
|
|
1301
1301
|
end
|
|
1302
1302
|
end
|
|
1303
1303
|
end
|
|
1304
1304
|
end
|
|
1305
1305
|
|
|
1306
|
-
describe
|
|
1307
|
-
let(:state) { { hostname:
|
|
1306
|
+
describe "#add_ohai_hint" do
|
|
1307
|
+
let(:state) { { hostname: "host" } }
|
|
1308
1308
|
let(:ssh) do
|
|
1309
|
-
s = double(
|
|
1309
|
+
s = double("ssh")
|
|
1310
1310
|
allow(s).to receive(:run) { |args| args }
|
|
1311
1311
|
s
|
|
1312
1312
|
end
|
|
1313
|
-
it
|
|
1313
|
+
it "opens an SSH session to the server" do
|
|
1314
1314
|
driver.send(:add_ohai_hint, state)
|
|
1315
1315
|
end
|
|
1316
1316
|
|
|
1317
|
-
it
|
|
1317
|
+
it "opens an Winrm session to the server" do
|
|
1318
1318
|
allow(driver).to receive(:bourne_shell?).and_return(false)
|
|
1319
1319
|
allow(driver).to receive(:windows_os?).and_return(true)
|
|
1320
1320
|
driver.send(:add_ohai_hint, state)
|
|
1321
1321
|
end
|
|
1322
1322
|
end
|
|
1323
1323
|
|
|
1324
|
-
describe
|
|
1325
|
-
it
|
|
1324
|
+
describe "#disable_ssl_validation" do
|
|
1325
|
+
it "turns off Excon SSL cert validation" do
|
|
1326
1326
|
expect(driver.send(:disable_ssl_validation)).to eq(false)
|
|
1327
1327
|
end
|
|
1328
1328
|
end
|
|
1329
1329
|
|
|
1330
|
-
describe
|
|
1331
|
-
it
|
|
1330
|
+
describe "#countdown" do
|
|
1331
|
+
it "counts down to future time with 0 seconds with almost no time" do
|
|
1332
1332
|
current = Time.now
|
|
1333
1333
|
driver.send(:countdown, 0)
|
|
1334
1334
|
after = Time.now
|
|
@@ -1336,7 +1336,7 @@ describe Kitchen::Driver::Openstack do
|
|
|
1336
1336
|
expect(after - current).to be < 10
|
|
1337
1337
|
end
|
|
1338
1338
|
|
|
1339
|
-
it
|
|
1339
|
+
it "counts down to future time with 1 seconds with at least 9 seconds" do
|
|
1340
1340
|
current = Time.now
|
|
1341
1341
|
driver.send(:countdown, 1)
|
|
1342
1342
|
after = Time.now
|
|
@@ -1344,15 +1344,15 @@ describe Kitchen::Driver::Openstack do
|
|
|
1344
1344
|
end
|
|
1345
1345
|
end
|
|
1346
1346
|
|
|
1347
|
-
describe
|
|
1347
|
+
describe "#wait_for_server" do
|
|
1348
1348
|
let(:config) { { server_wait: 0 } }
|
|
1349
|
-
let(:state) { { hostname:
|
|
1349
|
+
let(:state) { { hostname: "host" } }
|
|
1350
1350
|
|
|
1351
|
-
it
|
|
1351
|
+
it "waits for connection to be available" do
|
|
1352
1352
|
expect(driver.send(:wait_for_server, state)).to be(nil)
|
|
1353
1353
|
end
|
|
1354
1354
|
|
|
1355
|
-
it
|
|
1355
|
+
it "Fails when calling transport but still destroys the created system" do
|
|
1356
1356
|
allow(instance.transport).to receive(:connection).and_raise(ArgumentError)
|
|
1357
1357
|
expect(driver).to receive(:destroy)
|
|
1358
1358
|
|
|
@@ -1361,47 +1361,47 @@ describe Kitchen::Driver::Openstack do
|
|
|
1361
1361
|
end
|
|
1362
1362
|
end
|
|
1363
1363
|
|
|
1364
|
-
describe
|
|
1364
|
+
describe "#get_bdm" do
|
|
1365
1365
|
let(:logger) { Logger.new(logged_output) }
|
|
1366
1366
|
let(:config) do
|
|
1367
1367
|
{
|
|
1368
|
-
openstack_username:
|
|
1369
|
-
openstack_api_key:
|
|
1370
|
-
openstack_auth_url:
|
|
1371
|
-
openstack_tenant:
|
|
1372
|
-
openstack_region:
|
|
1373
|
-
openstack_service_name:
|
|
1374
|
-
image_ref:
|
|
1375
|
-
flavor_ref:
|
|
1376
|
-
username:
|
|
1377
|
-
port:
|
|
1378
|
-
server_name:
|
|
1379
|
-
server_name_prefix:
|
|
1380
|
-
floating_ip_pool:
|
|
1381
|
-
floating_ip:
|
|
1382
|
-
network_ref:
|
|
1368
|
+
openstack_username: "a",
|
|
1369
|
+
openstack_api_key: "b",
|
|
1370
|
+
openstack_auth_url: "http://",
|
|
1371
|
+
openstack_tenant: "me",
|
|
1372
|
+
openstack_region: "ORD",
|
|
1373
|
+
openstack_service_name: "stack",
|
|
1374
|
+
image_ref: "22",
|
|
1375
|
+
flavor_ref: "33",
|
|
1376
|
+
username: "admin",
|
|
1377
|
+
port: "2222",
|
|
1378
|
+
server_name: "puppy",
|
|
1379
|
+
server_name_prefix: "parsnip",
|
|
1380
|
+
floating_ip_pool: "swimmers",
|
|
1381
|
+
floating_ip: "11111",
|
|
1382
|
+
network_ref: "0xCAFFE",
|
|
1383
1383
|
block_device_mapping: {
|
|
1384
|
-
volume_id:
|
|
1385
|
-
volume_size:
|
|
1386
|
-
device_name:
|
|
1387
|
-
delete_on_termination: true
|
|
1388
|
-
}
|
|
1384
|
+
volume_id: "55",
|
|
1385
|
+
volume_size: "5",
|
|
1386
|
+
device_name: "vda",
|
|
1387
|
+
delete_on_termination: true,
|
|
1388
|
+
},
|
|
1389
1389
|
}
|
|
1390
1390
|
end
|
|
1391
|
-
it
|
|
1391
|
+
it "returns just the BDM config" do
|
|
1392
1392
|
expect(driver.send(:get_bdm, config)).to eq(config[:block_device_mapping])
|
|
1393
1393
|
end
|
|
1394
1394
|
end
|
|
1395
1395
|
|
|
1396
|
-
describe
|
|
1396
|
+
describe "#config_server_name" do
|
|
1397
1397
|
let(:config) do
|
|
1398
1398
|
{
|
|
1399
|
-
server_name_prefix:
|
|
1399
|
+
server_name_prefix: "parsnip",
|
|
1400
1400
|
}
|
|
1401
1401
|
end
|
|
1402
1402
|
|
|
1403
|
-
it
|
|
1404
|
-
expect(driver.send(:config_server_name)).to include(
|
|
1403
|
+
it "returns random string prefixed by servername_prefix attribute" do
|
|
1404
|
+
expect(driver.send(:config_server_name)).to include("parsnip")
|
|
1405
1405
|
end
|
|
1406
1406
|
end
|
|
1407
1407
|
end
|