kitchen-ec2 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.cane +2 -1
- data/.gitignore +2 -0
- data/.rspec +3 -0
- data/.rubocop.yml +9 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +60 -17
- data/Gemfile +3 -3
- data/README.md +241 -85
- data/Rakefile +30 -12
- data/data/amis.json +18 -0
- data/kitchen-ec2.gemspec +21 -10
- data/lib/kitchen/driver/aws/client.rb +110 -0
- data/lib/kitchen/driver/aws/instance_generator.rb +148 -0
- data/lib/kitchen/driver/ec2.rb +288 -88
- data/lib/kitchen/driver/ec2_version.rb +1 -1
- data/spec/kitchen/driver/ec2/client_spec.rb +119 -0
- data/spec/kitchen/driver/ec2/instance_generator_spec.rb +303 -0
- data/spec/kitchen/driver/ec2_spec.rb +82 -0
- data/spec/spec_helper.rb +104 -0
- metadata +131 -22
- data/.tailor +0 -106
- data/spec/create_spec.rb +0 -106
@@ -0,0 +1,119 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Tyler Ball (<tball@chef.io>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2015, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require "kitchen/driver/aws/client"
|
20
|
+
require "climate_control"
|
21
|
+
|
22
|
+
describe Kitchen::Driver::Aws::Client do
|
23
|
+
describe "::get_credentials" do
|
24
|
+
let(:shared) { instance_double(Aws::SharedCredentials) }
|
25
|
+
let(:iam) { instance_double(Aws::InstanceProfileCredentials) }
|
26
|
+
|
27
|
+
before do
|
28
|
+
expect(Aws::SharedCredentials).to \
|
29
|
+
receive(:new).with(:profile_name => "profile").and_return(shared)
|
30
|
+
end
|
31
|
+
|
32
|
+
# nothing else is set, so we default to this
|
33
|
+
it "loads IAM credentials last" do
|
34
|
+
expect(shared).to receive(:loadable?).and_return(false)
|
35
|
+
expect(Aws::InstanceProfileCredentials).to receive(:new).and_return(iam)
|
36
|
+
expect(Kitchen::Driver::Aws::Client.get_credentials("profile", nil, nil, nil)).to eq(iam)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "loads shared credentials second to last" do
|
40
|
+
expect(shared).to receive(:loadable?).and_return(true)
|
41
|
+
expect(Kitchen::Driver::Aws::Client.get_credentials("profile", nil, nil, nil)).to eq(shared)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "loads shared credentials third to last" do
|
45
|
+
expect(shared).to_not receive(:loadable?)
|
46
|
+
ClimateControl.modify(
|
47
|
+
"AWS_ACCESS_KEY_ID" => "key1",
|
48
|
+
"AWS_SECRET_ACCESS_KEY" => "value1",
|
49
|
+
"AWS_SESSION_TOKEN" => "token1"
|
50
|
+
) do
|
51
|
+
expect(Kitchen::Driver::Aws::Client.get_credentials("profile", nil, nil, nil)).to \
|
52
|
+
be_a(Aws::Credentials).and have_attributes(
|
53
|
+
:access_key_id => "key1",
|
54
|
+
:secret_access_key => "value1",
|
55
|
+
:session_token => "token1"
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it "loads deprecated credentials fourth to last" do
|
61
|
+
expect(shared).to_not receive(:loadable?)
|
62
|
+
ClimateControl.modify(
|
63
|
+
"AWS_ACCESS_KEY" => "key2",
|
64
|
+
"AWS_SECRET_KEY" => "value2",
|
65
|
+
"AWS_TOKEN" => "token2"
|
66
|
+
) do
|
67
|
+
expect(Kitchen::Driver::Aws::Client.get_credentials("profile", nil, nil, nil)).to \
|
68
|
+
be_a(Aws::Credentials).and have_attributes(
|
69
|
+
:access_key_id => "key2",
|
70
|
+
:secret_access_key => "value2",
|
71
|
+
:session_token => "token2"
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it "loads provided credentials first" do
|
77
|
+
expect(shared).to_not receive(:loadable?)
|
78
|
+
expect(Kitchen::Driver::Aws::Client.get_credentials("profile", "key3", "value3", nil)).to \
|
79
|
+
be_a(Aws::Credentials).and have_attributes(
|
80
|
+
:access_key_id => "key3",
|
81
|
+
:secret_access_key => "value3",
|
82
|
+
:session_token => nil
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "uses a session token if provided" do
|
87
|
+
expect(shared).to_not receive(:loadable?)
|
88
|
+
expect(Kitchen::Driver::Aws::Client.get_credentials("profile", "key3", "value3", "t")).to \
|
89
|
+
be_a(Aws::Credentials).and have_attributes(
|
90
|
+
:access_key_id => "key3",
|
91
|
+
:secret_access_key => "value3",
|
92
|
+
:session_token => "t"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
let(:client) { Kitchen::Driver::Aws::Client.new("us-west-1") }
|
98
|
+
|
99
|
+
describe "#initialize" do
|
100
|
+
|
101
|
+
it "successfully creates a client" do
|
102
|
+
expect(client).to be_a(Kitchen::Driver::Aws::Client)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "Sets the AWS config" do
|
106
|
+
client
|
107
|
+
expect(Aws.config[:region]).to eq("us-west-1")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it "returns a client" do
|
112
|
+
expect(client.client).to be_a(Aws::EC2::Client)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "returns a resource" do
|
116
|
+
expect(client.resource).to be_a(Aws::EC2::Resource)
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,303 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Tyler Ball (<tball@chef.io>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2015, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require "kitchen/driver/aws/instance_generator"
|
20
|
+
require "kitchen/driver/aws/client"
|
21
|
+
require "tempfile"
|
22
|
+
|
23
|
+
describe Kitchen::Driver::Aws::InstanceGenerator do
|
24
|
+
|
25
|
+
let(:config) { Hash.new }
|
26
|
+
|
27
|
+
let(:resource) { instance_double(Aws::EC2::Resource) }
|
28
|
+
|
29
|
+
let(:ec2) { instance_double(Kitchen::Driver::Aws::Client, :resource => resource) }
|
30
|
+
|
31
|
+
let(:generator) { Kitchen::Driver::Aws::InstanceGenerator.new(config, ec2) }
|
32
|
+
|
33
|
+
describe "#debug_if_root_device" do
|
34
|
+
let(:image_id) { "ami-123456" }
|
35
|
+
let(:config) { { :image_id => image_id } }
|
36
|
+
let(:image) { double("image") }
|
37
|
+
|
38
|
+
before do
|
39
|
+
expect(resource).to receive(:image).with(image_id).and_return(image)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns nil when the image cannot be found" do
|
43
|
+
expect(image).to receive(:root_device_name).and_raise(
|
44
|
+
::Aws::EC2::Errors::InvalidAMIIDNotFound.new({}, "")
|
45
|
+
)
|
46
|
+
expect(generator).to_not receive(:info)
|
47
|
+
expect(generator.debug_if_root_device({})).to eq(nil)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "logs an info message when the device mappings are overriding the root device" do
|
51
|
+
expect(image).to receive(:root_device_name).and_return("name")
|
52
|
+
expect(generator).to receive(:info)
|
53
|
+
expect(generator.debug_if_root_device([{ :device_name => "name" }])).to eq(nil)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#prepared_user_data" do
|
58
|
+
context "when config[:user_data] is a file" do
|
59
|
+
let(:tmp_file) { Tempfile.new("prepared_user_data_test") }
|
60
|
+
let(:config) { { :user_data => tmp_file.path } }
|
61
|
+
|
62
|
+
before do
|
63
|
+
tmp_file.write("foo\nbar")
|
64
|
+
tmp_file.rewind
|
65
|
+
end
|
66
|
+
|
67
|
+
after do
|
68
|
+
tmp_file.close
|
69
|
+
tmp_file.unlink
|
70
|
+
end
|
71
|
+
|
72
|
+
it "reads the file contents" do
|
73
|
+
expect(generator.prepared_user_data).to eq("foo\nbar")
|
74
|
+
end
|
75
|
+
|
76
|
+
it "memoizes the file contents" do
|
77
|
+
expect(generator.prepared_user_data).to eq("foo\nbar")
|
78
|
+
tmp_file.write("other\nvalue")
|
79
|
+
tmp_file.rewind
|
80
|
+
expect(generator.prepared_user_data).to eq("foo\nbar")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "block_device_mappings" do
|
86
|
+
before do
|
87
|
+
expect(generator).to receive(:debug_if_root_device)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "returns empty if nothing is provided" do
|
91
|
+
expect(generator.block_device_mappings).to eq([])
|
92
|
+
end
|
93
|
+
|
94
|
+
context "when populated with multiple mappings" do
|
95
|
+
let(:config) do
|
96
|
+
{ :block_device_mappings => [
|
97
|
+
{
|
98
|
+
:ebs_volume_size => 13,
|
99
|
+
:ebs_delete_on_termination => true,
|
100
|
+
:ebs_device_name => "/dev/sda1"
|
101
|
+
},
|
102
|
+
{
|
103
|
+
:ebs_volume_size => 15,
|
104
|
+
:ebs_delete_on_termination => false,
|
105
|
+
:ebs_device_name => "/dev/sda2",
|
106
|
+
:ebs_volume_type => "gp2",
|
107
|
+
:ebs_snapshot_id => "id",
|
108
|
+
:ebs_virtual_name => "test"
|
109
|
+
}
|
110
|
+
] }
|
111
|
+
end
|
112
|
+
|
113
|
+
it "returns the transformed mappings" do
|
114
|
+
expect(generator.block_device_mappings).to match(
|
115
|
+
[
|
116
|
+
{
|
117
|
+
:ebs => {
|
118
|
+
:volume_size => 13,
|
119
|
+
:delete_on_termination => true
|
120
|
+
},
|
121
|
+
:device_name => "/dev/sda1"
|
122
|
+
},
|
123
|
+
{
|
124
|
+
:ebs => {
|
125
|
+
:volume_size => 15,
|
126
|
+
:volume_type => "gp2",
|
127
|
+
:snapshot_id => "id",
|
128
|
+
:delete_on_termination => false
|
129
|
+
},
|
130
|
+
:device_name => "/dev/sda2",
|
131
|
+
:virtual_name => "test"
|
132
|
+
}
|
133
|
+
]
|
134
|
+
)
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
context "when populatd with deprecated configs" do
|
140
|
+
let(:config) do
|
141
|
+
{
|
142
|
+
:ebs_volume_size => 13,
|
143
|
+
:ebs_delete_on_termination => true,
|
144
|
+
:ebs_device_name => "/dev/sda1",
|
145
|
+
:ebs_volume_type => "gp2"
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
it "returns the transformed mappings" do
|
150
|
+
expect(generator.block_device_mappings).to match(
|
151
|
+
[
|
152
|
+
{
|
153
|
+
:ebs => {
|
154
|
+
:volume_size => 13,
|
155
|
+
:delete_on_termination => true,
|
156
|
+
:volume_type => "gp2"
|
157
|
+
},
|
158
|
+
:device_name => "/dev/sda1"
|
159
|
+
}
|
160
|
+
]
|
161
|
+
)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context "when populated with deprecated configs and new configs" do
|
166
|
+
let(:config) do
|
167
|
+
{
|
168
|
+
:ebs_volume_size => 13,
|
169
|
+
:ebs_delete_on_termination => true,
|
170
|
+
:ebs_device_name => "/dev/sda1",
|
171
|
+
:ebs_volume_type => "gp2",
|
172
|
+
:block_device_mappings => [
|
173
|
+
{
|
174
|
+
:ebs_volume_size => 15,
|
175
|
+
:ebs_delete_on_termination => false,
|
176
|
+
:ebs_device_name => "/dev/sda2",
|
177
|
+
:ebs_volume_type => "gp2",
|
178
|
+
:ebs_snapshot_id => "id",
|
179
|
+
:ebs_virtual_name => "test"
|
180
|
+
}
|
181
|
+
]
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
185
|
+
it "ignores the old configs" do
|
186
|
+
expect(generator.block_device_mappings).to match(
|
187
|
+
[
|
188
|
+
{
|
189
|
+
:ebs => {
|
190
|
+
:volume_size => 15,
|
191
|
+
:volume_type => "gp2",
|
192
|
+
:snapshot_id => "id",
|
193
|
+
:delete_on_termination => false
|
194
|
+
},
|
195
|
+
:device_name => "/dev/sda2",
|
196
|
+
:virtual_name => "test"
|
197
|
+
}
|
198
|
+
]
|
199
|
+
)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "#ec2_instance_data" do
|
205
|
+
before do
|
206
|
+
expect(generator).to receive(:debug_if_root_device)
|
207
|
+
end
|
208
|
+
|
209
|
+
it "returns empty on nil" do
|
210
|
+
expect(generator.ec2_instance_data).to eq(
|
211
|
+
:placement => { :availability_zone => nil },
|
212
|
+
:instance_type => nil,
|
213
|
+
:ebs_optimized => nil,
|
214
|
+
:image_id => nil,
|
215
|
+
:key_name => nil,
|
216
|
+
:subnet_id => nil,
|
217
|
+
:private_ip_address => nil
|
218
|
+
)
|
219
|
+
end
|
220
|
+
|
221
|
+
context "when populated with minimum requirements" do
|
222
|
+
let(:config) do
|
223
|
+
{
|
224
|
+
:availability_zone => "eu-west-1a",
|
225
|
+
:instance_type => "micro",
|
226
|
+
:ebs_optimized => true,
|
227
|
+
:image_id => "ami-123",
|
228
|
+
:aws_ssh_key_id => "key",
|
229
|
+
:subnet_id => "s-456",
|
230
|
+
:private_ip_address => "0.0.0.0"
|
231
|
+
}
|
232
|
+
end
|
233
|
+
|
234
|
+
it "returns the minimum data" do
|
235
|
+
expect(generator.ec2_instance_data).to eq(
|
236
|
+
:placement => { :availability_zone => "eu-west-1a" },
|
237
|
+
:instance_type => "micro",
|
238
|
+
:ebs_optimized => true,
|
239
|
+
:image_id => "ami-123",
|
240
|
+
:key_name => "key",
|
241
|
+
:subnet_id => "s-456",
|
242
|
+
:private_ip_address => "0.0.0.0"
|
243
|
+
)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
context "when provided the maximum config" do
|
248
|
+
let(:config) do
|
249
|
+
{
|
250
|
+
:availability_zone => "eu-west-1a",
|
251
|
+
:instance_type => "micro",
|
252
|
+
:ebs_optimized => true,
|
253
|
+
:image_id => "ami-123",
|
254
|
+
:aws_ssh_key_id => "key",
|
255
|
+
:subnet_id => "s-456",
|
256
|
+
:private_ip_address => "0.0.0.0",
|
257
|
+
:block_device_mappings => [
|
258
|
+
{
|
259
|
+
:ebs_volume_size => 15,
|
260
|
+
:ebs_delete_on_termination => false,
|
261
|
+
:ebs_device_name => "/dev/sda2",
|
262
|
+
:ebs_volume_type => "gp2",
|
263
|
+
:ebs_snapshot_id => "id",
|
264
|
+
:ebs_virtual_name => "test"
|
265
|
+
}
|
266
|
+
],
|
267
|
+
:security_group_ids => ["sg-789"],
|
268
|
+
:user_data => "foo",
|
269
|
+
:iam_instance_profile => "iam-123",
|
270
|
+
:associate_public_ip_address => true
|
271
|
+
}
|
272
|
+
end
|
273
|
+
|
274
|
+
it "returns the maximum data" do
|
275
|
+
expect(generator.ec2_instance_data).to eq(
|
276
|
+
:placement => { :availability_zone => "eu-west-1a" },
|
277
|
+
:instance_type => "micro",
|
278
|
+
:ebs_optimized => true,
|
279
|
+
:image_id => "ami-123",
|
280
|
+
:key_name => "key",
|
281
|
+
:subnet_id => "s-456",
|
282
|
+
:private_ip_address => "0.0.0.0",
|
283
|
+
:block_device_mappings => [
|
284
|
+
{
|
285
|
+
:ebs => {
|
286
|
+
:volume_size => 15,
|
287
|
+
:delete_on_termination => false,
|
288
|
+
:volume_type => "gp2",
|
289
|
+
:snapshot_id => "id"
|
290
|
+
},
|
291
|
+
:device_name => "/dev/sda2",
|
292
|
+
:virtual_name => "test"
|
293
|
+
}
|
294
|
+
],
|
295
|
+
:iam_instance_profile => { :name => nil },
|
296
|
+
:network_interfaces => [{ :device_index => 0, :associate_public_ip_address => true }],
|
297
|
+
:security_group_ids => ["sg-789"],
|
298
|
+
:user_data => "foo"
|
299
|
+
)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Tyler Ball (<tball@chef.io>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2015, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require "kitchen/driver/ec2"
|
20
|
+
require "kitchen/provisioner/dummy"
|
21
|
+
require "kitchen/transport/dummy"
|
22
|
+
require "kitchen/verifier/dummy"
|
23
|
+
|
24
|
+
describe Kitchen::Driver::Ec2 do
|
25
|
+
|
26
|
+
let(:logged_output) { StringIO.new }
|
27
|
+
let(:logger) { Logger.new(logged_output) }
|
28
|
+
let(:config) { { :aws_ssh_key_id => "key", :image_id => "ami-1234567" } }
|
29
|
+
let(:platform) { Kitchen::Platform.new(:name => "fooos-99") }
|
30
|
+
let(:suite) { Kitchen::Suite.new(:name => "suitey") }
|
31
|
+
let(:verifier) { Kitchen::Verifier::Dummy.new }
|
32
|
+
let(:provisioner) { Kitchen::Provisioner::Dummy.new }
|
33
|
+
let(:transport) { Kitchen::Transport::Dummy.new }
|
34
|
+
let(:state_file) { double("state_file") }
|
35
|
+
|
36
|
+
let(:driver) { Kitchen::Driver::Ec2.new(config) }
|
37
|
+
|
38
|
+
let(:instance) do
|
39
|
+
Kitchen::Instance.new(
|
40
|
+
:verifier => verifier,
|
41
|
+
:driver => driver,
|
42
|
+
:logger => logger,
|
43
|
+
:suite => suite,
|
44
|
+
:platform => platform,
|
45
|
+
:provisioner => provisioner,
|
46
|
+
:transport => transport,
|
47
|
+
:state_file => state_file
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "driver api_version is 2" do
|
52
|
+
expect(driver.diagnose_plugin[:api_version]).to eq(2)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "plugin_version is set to Kitchen::Vagrant::VERSION" do
|
56
|
+
expect(driver.diagnose_plugin[:version]).to eq(
|
57
|
+
Kitchen::Driver::EC2_VERSION)
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "configuration" do
|
61
|
+
let(:config) { {} }
|
62
|
+
it "requires :aws_ssh_key_id to be provided" do
|
63
|
+
expect { driver.finalize_config!(instance) }.to \
|
64
|
+
raise_error(Kitchen::UserError, /:aws_ssh_key_id/)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "requires :image_id to be provided" do
|
68
|
+
config[:aws_ssh_key_id] = "key"
|
69
|
+
expect { driver.finalize_config!(instance) }.to \
|
70
|
+
raise_error(Kitchen::UserError, /:image_id/)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "finalize_config!" do
|
75
|
+
it "defaults the availability zone if not provided" do
|
76
|
+
expect(config[:availability_zone]).to eq(nil)
|
77
|
+
driver.finalize_config!(instance)
|
78
|
+
expect(config[:availability_zone]).to eq("us-east-1b")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|