kitchen-google 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +37 -19
- data/lib/kitchen/driver/gce.rb +22 -99
- data/lib/kitchen/driver/gce_version.rb +1 -1
- data/spec/kitchen/driver/gce_spec.rb +89 -185
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6201b751412eb2c2ee39e9e48044db20388eb210
|
4
|
+
data.tar.gz: 747394a1e962ca4780e91ccf20a3d3acade150d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 447bfea307fe118344d6a1d067ad4ed9cf76706104c1908462e20765b6ec94b18440cab65b74cb3423efc7c8602375c152e2f2ad6462a4c0f0e0e09b914a8e5a
|
7
|
+
data.tar.gz: 83afed3f0a3988504c3e4be89221c40a3520454107d0e8fbfa356efbc9979608d70bab6f46c8cd93b51c6577b1285cc1ea983f772f87a1d9ed5a532193b830d9
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ which to run your test-kitchen instances, create one, noting the
|
|
24
24
|
|
25
25
|
### Authentication and Authorization
|
26
26
|
|
27
|
-
The [underlying API](https://github.com/google/google-api-ruby-client) this plugin uses relies on the
|
27
|
+
The [underlying API](https://github.com/google/google-api-ruby-client) this plugin uses relies on the
|
28
28
|
[Google Auth Library](https://github.com/google/google-auth-library-ruby) to handle authentication to the
|
29
29
|
Google Cloud API. The auth library expects that there is a JSON credentials file located at:
|
30
30
|
|
@@ -39,7 +39,7 @@ If you already have a file you'd like to use that is in a different location, se
|
|
39
39
|
### SSH Keys
|
40
40
|
|
41
41
|
In order to bootstrap Linux nodes, you will first need to ensure your SSH
|
42
|
-
keys are set up correctly. Ensure your SSH public key is properly entered
|
42
|
+
keys are set up correctly. Ensure your SSH public key is properly entered
|
43
43
|
into your project's Metadata tab in the GCP Console. GCE will add your key
|
44
44
|
to the appropriate user's `~/.ssh/authorized_keys` file when Chef first
|
45
45
|
connects to perform the bootstrap process.
|
@@ -113,26 +113,38 @@ Note that this parameter requires the "Project ID", not the "Project Name."
|
|
113
113
|
|
114
114
|
Example: "funky-penguin-12345"
|
115
115
|
|
116
|
+
### `image_project`
|
117
|
+
|
118
|
+
The project ID of the GCP project to search for the configured image or image
|
119
|
+
family. This must be specified to find either public images or your own images
|
120
|
+
that exist in another project.
|
121
|
+
|
122
|
+
Example: "ubuntu-os-cloud"
|
123
|
+
|
124
|
+
### `image_family`
|
125
|
+
|
126
|
+
The family of the image to initialize your boot disk from, the latest
|
127
|
+
non-deprecated image will be used.
|
128
|
+
|
129
|
+
Note that this parameter will be ignored if `image_name` is also specified.
|
130
|
+
|
131
|
+
Example: "ubuntu-1604-lts"
|
132
|
+
|
116
133
|
### `image_name`
|
117
134
|
|
118
|
-
|
119
|
-
the boot disk. Example: `centos-6-v20160219`
|
135
|
+
The name of the disk image to use as the source image for the boot disk.
|
120
136
|
|
121
|
-
|
122
|
-
be searched first. If the image cannot be found and it looks like a common
|
123
|
-
public image, the appropriate public project will be searched.
|
137
|
+
Example: `centos-7-v20170124`
|
124
138
|
|
125
|
-
|
126
|
-
`image_project` parameter.
|
139
|
+
This parameter will override `image_family` if they are both specified.
|
127
140
|
|
128
|
-
|
129
|
-
|
130
|
-
For a full list of aliases, see the output of `gcloud compute instances create --help`.
|
141
|
+
If `image_project` is not specified, only the GCP project specified in `project`
|
142
|
+
will be searched.
|
131
143
|
|
132
144
|
### `zone`
|
133
145
|
|
134
146
|
**Required if `region` is left blank.** The name of the GCE zone in which to
|
135
|
-
launch your instances.
|
147
|
+
launch your instances.
|
136
148
|
|
137
149
|
Example: `us-east1-b`
|
138
150
|
|
@@ -166,7 +178,7 @@ to a host in the event of host maintenance. Default: `false`
|
|
166
178
|
Size, in gigabytes, of boot disk. Default: `10`.
|
167
179
|
|
168
180
|
Some images, such as windows images, have a larger source image size
|
169
|
-
and require the disk_size to be the same size or larger than the source.
|
181
|
+
and require the disk_size to be the same size or larger than the source.
|
170
182
|
An error message will be displayed to you indicating this requirement
|
171
183
|
if necessary.
|
172
184
|
|
@@ -194,8 +206,8 @@ GCE subnetwork that instance will be attached to. Only applies to custom network
|
|
194
206
|
### `preemptible`
|
195
207
|
|
196
208
|
If set to `true`, GCE instance will be brought up as a [preemptible](https://cloud.google.com/compute/docs/instances/preemptible) virtual machine,
|
197
|
-
that runs at a much lower price than normal instances. However, Compute
|
198
|
-
Engine might terminate (preempt) these instances if it requires access
|
209
|
+
that runs at a much lower price than normal instances. However, Compute
|
210
|
+
Engine might terminate (preempt) these instances if it requires access
|
199
211
|
to those resources for other tasks; default: `false`
|
200
212
|
|
201
213
|
### `service_account_name`
|
@@ -285,12 +297,18 @@ transport:
|
|
285
297
|
username: chefuser
|
286
298
|
|
287
299
|
platforms:
|
288
|
-
- name: centos
|
300
|
+
- name: centos-7
|
301
|
+
driver:
|
302
|
+
image_project: centos-cloud
|
303
|
+
image_name: centos-7-v20170124
|
304
|
+
- name: ubuntu-16.04
|
289
305
|
driver:
|
290
|
-
|
306
|
+
image_project: ubuntu-os-cloud
|
307
|
+
image_family: ubuntu-1604-lts
|
291
308
|
- name: windows
|
292
309
|
driver:
|
293
|
-
|
310
|
+
image_project: windows-cloud
|
311
|
+
image_name: windows-server-2012-r2-dc-v20170117
|
294
312
|
disk_size: 50
|
295
313
|
|
296
314
|
suites:
|
data/lib/kitchen/driver/gce.rb
CHANGED
@@ -53,32 +53,10 @@ module Kitchen
|
|
53
53
|
"userinfo-email" => "userinfo.email",
|
54
54
|
}
|
55
55
|
|
56
|
-
IMAGE_ALIAS_MAP = {
|
57
|
-
"centos-6" => { project: "centos-cloud", prefix: "centos-6" },
|
58
|
-
"centos-7" => { project: "centos-cloud", prefix: "centos-7" },
|
59
|
-
"container-vm" => { project: "google-containers", prefix: "container-vm" },
|
60
|
-
"coreos" => { project: "coreos-cloud", prefix: "coreos-stable" },
|
61
|
-
"debian-7" => { project: "debian-cloud", prefix: "debian-7-wheezy" },
|
62
|
-
"debian-7-backports" => { project: "debian-cloud", prefix: "backports-debian-7-wheezy" },
|
63
|
-
"debian-8" => { project: "debian-cloud", prefix: "debian-8-jessie" },
|
64
|
-
"opensuse-13" => { project: "opensuse-cloud", prefix: "opensuse-13" },
|
65
|
-
"rhel-6" => { project: "rhel-cloud", prefix: "rhel-6" },
|
66
|
-
"rhel-7" => { project: "rhel-cloud", prefix: "rhel-7" },
|
67
|
-
"sles-11" => { project: "suse-cloud", prefix: "sles-11" },
|
68
|
-
"sles-12" => { project: "suse-cloud", prefix: "sles-12" },
|
69
|
-
"ubuntu-12-04" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1204-precise" },
|
70
|
-
"ubuntu-14-04" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1404-trusty" },
|
71
|
-
"ubuntu-15-04" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1504-vivid" },
|
72
|
-
"ubuntu-15-10" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1510-wily" },
|
73
|
-
"windows-2008-r2" => { project: "windows-cloud", prefix: "windows-server-2008-r2" },
|
74
|
-
"windows-2012-r2" => { project: "windows-cloud", prefix: "windows-server-2012-r2" },
|
75
|
-
}
|
76
|
-
|
77
56
|
kitchen_driver_api_version 2
|
78
57
|
plugin_version Kitchen::Driver::GCE_VERSION
|
79
58
|
|
80
59
|
required_config :project
|
81
|
-
required_config :image_name
|
82
60
|
|
83
61
|
default_config :region, nil
|
84
62
|
default_config :zone, nil
|
@@ -96,6 +74,8 @@ module Kitchen
|
|
96
74
|
default_config :preemptible, false
|
97
75
|
default_config :auto_restart, false
|
98
76
|
default_config :auto_migrate, false
|
77
|
+
default_config :image_family, nil
|
78
|
+
default_config :image_name, nil
|
99
79
|
default_config :image_project, nil
|
100
80
|
default_config :email, nil
|
101
81
|
default_config :use_private_ip, false
|
@@ -166,12 +146,15 @@ module Kitchen
|
|
166
146
|
raise "Region #{config[:region]} is not a valid region" if config[:region] && !valid_region?
|
167
147
|
raise "Machine type #{config[:machine_type]} is not valid" unless valid_machine_type?
|
168
148
|
raise "Disk type #{config[:disk_type]} is not valid" unless valid_disk_type?
|
149
|
+
raise "Either image family or name must be specified" unless config[:image_family] || config[:image_name]
|
169
150
|
raise "Disk image #{config[:image_name]} is not valid - check your image name and image project" if boot_disk_source_image.nil?
|
170
151
|
raise "Network #{config[:network]} is not valid" unless valid_network?
|
171
|
-
raise "Subnet #{config[:subnet]} is not valid" if config[:subnet]
|
152
|
+
raise "Subnet #{config[:subnet]} is not valid" if config[:subnet] && !valid_subnet?
|
172
153
|
raise "Email address of GCE user is not set" if winrm_transport? && config[:email].nil?
|
173
154
|
|
174
155
|
warn("Both zone and region specified - region will be ignored.") if config[:zone] && config[:region]
|
156
|
+
warn("Both image family and name specified - image family will be ignored") if config[:image_family] && config[:image_name]
|
157
|
+
warn("Image project not specified - searching current project only") unless config[:image_project]
|
175
158
|
warn("Auto-migrate disabled for preemptible instance") if preemptible? && config[:auto_migrate]
|
176
159
|
warn("Auto-restart disabled for preemptible instance") if preemptible? && config[:auto_restart]
|
177
160
|
end
|
@@ -199,7 +182,7 @@ module Kitchen
|
|
199
182
|
end
|
200
183
|
|
201
184
|
def winrm_transport?
|
202
|
-
instance.transport.name.
|
185
|
+
instance.transport.name.casecmp("winrm") == 0
|
203
186
|
end
|
204
187
|
|
205
188
|
def update_windows_password(server_name)
|
@@ -263,7 +246,7 @@ module Kitchen
|
|
263
246
|
check_api_call { connection.get_disk_type(project, zone, config[:disk_type]) }
|
264
247
|
end
|
265
248
|
|
266
|
-
def image_exist?
|
249
|
+
def image_exist?
|
267
250
|
check_api_call { connection.get_image(image_project, image_name) }
|
268
251
|
end
|
269
252
|
|
@@ -275,6 +258,14 @@ module Kitchen
|
|
275
258
|
config[:project]
|
276
259
|
end
|
277
260
|
|
261
|
+
def image_name
|
262
|
+
@image_name ||= config[:image_name] || image_name_for_family(config[:image_family])
|
263
|
+
end
|
264
|
+
|
265
|
+
def image_project
|
266
|
+
config[:image_project].nil? ? project : config[:image_project]
|
267
|
+
end
|
268
|
+
|
278
269
|
def region
|
279
270
|
config[:region].nil? ? region_for_zone : config[:region]
|
280
271
|
end
|
@@ -366,84 +357,16 @@ module Kitchen
|
|
366
357
|
end
|
367
358
|
|
368
359
|
def boot_disk_source_image
|
369
|
-
@boot_disk_source ||=
|
360
|
+
@boot_disk_source ||= image_url
|
370
361
|
end
|
371
362
|
|
372
|
-
def
|
373
|
-
|
374
|
-
unless config[:image_project].nil?
|
375
|
-
debug("Searching project #{config[:image_project]} for image #{config[:image_name]}")
|
376
|
-
return image_url_for(config[:image_project], config[:image_name])
|
377
|
-
end
|
378
|
-
|
379
|
-
# No image project has been provided. Check to see if the image is a known alias.
|
380
|
-
alias_url = image_alias_url
|
381
|
-
unless alias_url.nil?
|
382
|
-
debug("Image #{config[:image_name]} is a known alias - using image URL: #{alias_url}")
|
383
|
-
return alias_url
|
384
|
-
end
|
385
|
-
|
386
|
-
# Doesn't match an alias. Let's check the user's project for the image.
|
387
|
-
url = image_url_for(project, config[:image_name])
|
388
|
-
unless url.nil?
|
389
|
-
debug("Located image #{config[:image_name]} in project #{project} - using image URL: #{url}")
|
390
|
-
return url
|
391
|
-
end
|
392
|
-
|
393
|
-
# Image not found in user's project. Is there a public project this image might exist in?
|
394
|
-
public_project = public_project_for_image(config[:image_name])
|
395
|
-
if public_project
|
396
|
-
debug("Searching public image project #{public_project} for image #{config[:image_name]}")
|
397
|
-
return image_url_for(public_project, config[:image_name])
|
398
|
-
end
|
399
|
-
|
400
|
-
# No image in user's project or public project, so it doesn't exist.
|
401
|
-
error("Image search failed for image #{config[:image_name]} - no suitable image found")
|
402
|
-
nil
|
403
|
-
end
|
404
|
-
|
405
|
-
def image_url_for(image_project, image_name)
|
406
|
-
return "projects/#{image_project}/global/images/#{image_name}" if image_exist?(image_project, image_name)
|
363
|
+
def image_url
|
364
|
+
return "projects/#{image_project}/global/images/#{image_name}" if image_exist?
|
407
365
|
end
|
408
366
|
|
409
|
-
def
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
image_project = IMAGE_ALIAS_MAP[image_alias][:project]
|
414
|
-
image_prefix = IMAGE_ALIAS_MAP[image_alias][:prefix]
|
415
|
-
|
416
|
-
latest_image = connection.list_images(image_project).items
|
417
|
-
.select { |image| image.name.start_with?(image_prefix) }
|
418
|
-
.sort { |a, b| a.name <=> b.name }
|
419
|
-
.last
|
420
|
-
|
421
|
-
return if latest_image.nil?
|
422
|
-
|
423
|
-
latest_image.self_link
|
424
|
-
end
|
425
|
-
|
426
|
-
def public_project_for_image(image)
|
427
|
-
case image
|
428
|
-
when /centos/
|
429
|
-
"centos-cloud"
|
430
|
-
when /container-vm/
|
431
|
-
"google-containers"
|
432
|
-
when /coreos/
|
433
|
-
"coreos-cloud"
|
434
|
-
when /debian/
|
435
|
-
"debian-cloud"
|
436
|
-
when /opensuse-cloud/
|
437
|
-
"opensuse-cloud"
|
438
|
-
when /rhel/
|
439
|
-
"rhel-cloud"
|
440
|
-
when /sles/
|
441
|
-
"suse-cloud"
|
442
|
-
when /ubuntu/
|
443
|
-
"ubuntu-os-cloud"
|
444
|
-
when /windows/
|
445
|
-
"windows-cloud"
|
446
|
-
end
|
367
|
+
def image_name_for_family(image_family)
|
368
|
+
image = connection.get_image_from_family(image_project, image_family)
|
369
|
+
image.name
|
447
370
|
end
|
448
371
|
|
449
372
|
def machine_type_url
|
@@ -78,13 +78,13 @@ describe Kitchen::Driver::Gce do
|
|
78
78
|
expect(driver.diagnose_plugin[:api_version]).to eq(2)
|
79
79
|
end
|
80
80
|
|
81
|
-
describe
|
81
|
+
describe "#name" do
|
82
82
|
it "has an overridden name" do
|
83
83
|
expect(driver.name).to eq("Google Compute (GCE)")
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
|
-
describe
|
87
|
+
describe "#create" do
|
88
88
|
let(:connection) { double("connection") }
|
89
89
|
let(:operation) { double("operation", name: "test_operation") }
|
90
90
|
let(:state) { {} }
|
@@ -151,7 +151,7 @@ describe Kitchen::Driver::Gce do
|
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
|
-
describe
|
154
|
+
describe "#destroy" do
|
155
155
|
let(:connection) { double("connection") }
|
156
156
|
let(:state) { { server_name: "server_1", hostname: "test_host", zone: "test_zone" } }
|
157
157
|
|
@@ -187,7 +187,7 @@ describe Kitchen::Driver::Gce do
|
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
190
|
-
describe
|
190
|
+
describe "#validate!" do
|
191
191
|
let(:config) do
|
192
192
|
{
|
193
193
|
project: "test_project",
|
@@ -217,14 +217,21 @@ describe Kitchen::Driver::Gce do
|
|
217
217
|
end
|
218
218
|
|
219
219
|
context "when neither zone nor region are specified" do
|
220
|
-
let(:config) { {} }
|
220
|
+
let(:config) { { image_name: "test_image" } }
|
221
221
|
it "raises an exception" do
|
222
222
|
expect { driver.validate! }.to raise_error(RuntimeError, "Either zone or region must be specified")
|
223
223
|
end
|
224
224
|
end
|
225
225
|
|
226
|
+
context "when neither image_family nor image_name are specified" do
|
227
|
+
let(:config) { { zone: "test_zone" } }
|
228
|
+
it "raises an exception" do
|
229
|
+
expect { driver.validate! }.to raise_error(RuntimeError, "Either image family or name must be specified")
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
226
233
|
context "when zone and region are both set" do
|
227
|
-
let(:config) { { zone: "test_zone", region: "test_region" } }
|
234
|
+
let(:config) { { zone: "test_zone", region: "test_region", image_project: "test_project", image_name: "test_image" } }
|
228
235
|
|
229
236
|
it "warns the user that the region will be ignored" do
|
230
237
|
expect(driver).to receive(:warn).with("Both zone and region specified - region will be ignored.")
|
@@ -232,6 +239,15 @@ describe Kitchen::Driver::Gce do
|
|
232
239
|
end
|
233
240
|
end
|
234
241
|
|
242
|
+
context "when image family and name are both set" do
|
243
|
+
let(:config) { { image_project: "test_project", image_name: "test_image", image_family: "test_image_family", zone: "test_zone" } }
|
244
|
+
|
245
|
+
it "warns the user that the image family will be ignored" do
|
246
|
+
expect(driver).to receive(:warn).with("Both image family and name specified - image family will be ignored")
|
247
|
+
driver.validate!
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
235
251
|
context "when region is set to 'any'" do
|
236
252
|
let(:config) { { region: "any" } }
|
237
253
|
it "raises an exception" do
|
@@ -262,6 +278,7 @@ describe Kitchen::Driver::Gce do
|
|
262
278
|
{
|
263
279
|
project: "test_project",
|
264
280
|
zone: "test_zone",
|
281
|
+
image_name: "test_image",
|
265
282
|
machine_type: "test_machine_type",
|
266
283
|
disk_type: "test_disk_type",
|
267
284
|
network: "test_network",
|
@@ -306,7 +323,7 @@ describe Kitchen::Driver::Gce do
|
|
306
323
|
end
|
307
324
|
end
|
308
325
|
|
309
|
-
describe
|
326
|
+
describe "#connection" do
|
310
327
|
it "returns a properly configured ComputeService" do
|
311
328
|
compute_service = double("compute_service")
|
312
329
|
client_options = double("client_options")
|
@@ -324,7 +341,7 @@ describe Kitchen::Driver::Gce do
|
|
324
341
|
end
|
325
342
|
end
|
326
343
|
|
327
|
-
describe
|
344
|
+
describe "#authorization" do
|
328
345
|
it "returns a Google::Auth authorization object" do
|
329
346
|
auth_object = double("auth_object")
|
330
347
|
expect(Google::Auth).to receive(:get_application_default).and_return(auth_object)
|
@@ -332,7 +349,7 @@ describe Kitchen::Driver::Gce do
|
|
332
349
|
end
|
333
350
|
end
|
334
351
|
|
335
|
-
describe
|
352
|
+
describe "#winrm_transport?" do
|
336
353
|
it "returns true if the transport name is Winrm" do
|
337
354
|
expect(transport).to receive(:name).and_return("Winrm")
|
338
355
|
expect(driver.winrm_transport?).to eq(true)
|
@@ -344,7 +361,7 @@ describe Kitchen::Driver::Gce do
|
|
344
361
|
end
|
345
362
|
end
|
346
363
|
|
347
|
-
describe
|
364
|
+
describe "#update_windows_password" do
|
348
365
|
it "does not attempt to reset the password if the transport is not WinRM" do
|
349
366
|
expect(driver).to receive(:winrm_transport?).and_return(false)
|
350
367
|
expect(GoogleComputeWindowsPassword).not_to receive(:new)
|
@@ -374,14 +391,14 @@ describe Kitchen::Driver::Gce do
|
|
374
391
|
end
|
375
392
|
end
|
376
393
|
|
377
|
-
describe
|
394
|
+
describe "#check_api_call" do
|
378
395
|
it "returns false and logs a debug message if the block raises a ClientError" do
|
379
396
|
expect(driver).to receive(:debug).with("API error: whoops")
|
380
397
|
expect(driver.check_api_call { raise Google::Apis::ClientError.new("whoops") }).to eq(false)
|
381
398
|
end
|
382
399
|
|
383
400
|
it "raises an exception if the block raises something other than a ClientError" do
|
384
|
-
expect { driver.check_api_call { raise
|
401
|
+
expect { driver.check_api_call { raise "whoops" } }.to raise_error(RuntimeError)
|
385
402
|
end
|
386
403
|
|
387
404
|
it "returns true if the block does not raise an exception" do
|
@@ -389,47 +406,47 @@ describe Kitchen::Driver::Gce do
|
|
389
406
|
end
|
390
407
|
end
|
391
408
|
|
392
|
-
describe
|
409
|
+
describe "#valid_machine_type?" do
|
393
410
|
subject { driver.valid_machine_type? }
|
394
411
|
it_behaves_like "a validity checker", :machine_type, :get_machine_type, "test_project", "test_zone"
|
395
412
|
end
|
396
413
|
|
397
|
-
describe
|
414
|
+
describe "#valid_network?" do
|
398
415
|
subject { driver.valid_network? }
|
399
416
|
it_behaves_like "a validity checker", :network, :get_network, "test_project"
|
400
417
|
end
|
401
418
|
|
402
|
-
describe
|
419
|
+
describe "#valid_subnet?" do
|
403
420
|
subject { driver.valid_subnet? }
|
404
421
|
it_behaves_like "a validity checker", :subnet, :get_subnetwork, "test_project", "test_region"
|
405
422
|
end
|
406
423
|
|
407
|
-
describe
|
424
|
+
describe "#valid_zone?" do
|
408
425
|
subject { driver.valid_zone? }
|
409
426
|
it_behaves_like "a validity checker", :zone, :get_zone, "test_project"
|
410
427
|
end
|
411
428
|
|
412
|
-
describe
|
429
|
+
describe "#valid_region?" do
|
413
430
|
subject { driver.valid_region? }
|
414
431
|
it_behaves_like "a validity checker", :region, :get_region, "test_project"
|
415
432
|
end
|
416
433
|
|
417
|
-
describe
|
434
|
+
describe "#valid_disk_type?" do
|
418
435
|
subject { driver.valid_disk_type? }
|
419
436
|
it_behaves_like "a validity checker", :disk_type, :get_disk_type, "test_project", "test_zone"
|
420
437
|
end
|
421
438
|
|
422
|
-
describe
|
439
|
+
describe "#image_exist?" do
|
423
440
|
it "checks the outcome of the API call" do
|
424
441
|
connection = double("connection")
|
425
442
|
expect(driver).to receive(:connection).and_return(connection)
|
426
|
-
expect(connection).to receive(:get_image).with("
|
443
|
+
expect(connection).to receive(:get_image).with("test_project", "test_image")
|
427
444
|
expect(driver).to receive(:check_api_call).and_call_original
|
428
|
-
expect(driver.image_exist?
|
445
|
+
expect(driver.image_exist?).to eq(true)
|
429
446
|
end
|
430
447
|
end
|
431
448
|
|
432
|
-
describe
|
449
|
+
describe "#server_exist?" do
|
433
450
|
it "checks the outcome of the API call" do
|
434
451
|
expect(driver).to receive(:server_instance).with("server_1")
|
435
452
|
expect(driver).to receive(:check_api_call).and_call_original
|
@@ -437,7 +454,7 @@ describe Kitchen::Driver::Gce do
|
|
437
454
|
end
|
438
455
|
end
|
439
456
|
|
440
|
-
describe
|
457
|
+
describe "#project" do
|
441
458
|
it "returns the project from the config" do
|
442
459
|
allow(driver).to receive(:project).and_call_original
|
443
460
|
expect(driver).to receive(:config).and_return(project: "my_project")
|
@@ -445,7 +462,7 @@ describe Kitchen::Driver::Gce do
|
|
445
462
|
end
|
446
463
|
end
|
447
464
|
|
448
|
-
describe
|
465
|
+
describe "#region" do
|
449
466
|
it "returns the region from the config if specified" do
|
450
467
|
allow(driver).to receive(:region).and_call_original
|
451
468
|
allow(driver).to receive(:config).and_return(region: "my_region")
|
@@ -460,7 +477,7 @@ describe Kitchen::Driver::Gce do
|
|
460
477
|
end
|
461
478
|
end
|
462
479
|
|
463
|
-
describe
|
480
|
+
describe "#region_for_zone" do
|
464
481
|
it "returns the region for a given zone" do
|
465
482
|
connection = double("connection")
|
466
483
|
zone_obj = double("zone_obj", region: "/path/to/test_region")
|
@@ -471,7 +488,7 @@ describe Kitchen::Driver::Gce do
|
|
471
488
|
end
|
472
489
|
end
|
473
490
|
|
474
|
-
describe
|
491
|
+
describe "#zone" do
|
475
492
|
before do
|
476
493
|
allow(driver).to receive(:zone).and_call_original
|
477
494
|
end
|
@@ -505,7 +522,7 @@ describe Kitchen::Driver::Gce do
|
|
505
522
|
end
|
506
523
|
end
|
507
524
|
|
508
|
-
describe
|
525
|
+
describe "#find_zone" do
|
509
526
|
let(:zones_in_region) { double("zones_in_region") }
|
510
527
|
|
511
528
|
before do
|
@@ -525,7 +542,7 @@ describe Kitchen::Driver::Gce do
|
|
525
542
|
end
|
526
543
|
end
|
527
544
|
|
528
|
-
describe
|
545
|
+
describe "#zones_in_region" do
|
529
546
|
it "returns a correct list of available zones" do
|
530
547
|
zone1 = double("zone1", status: "UP", region: "a/b/c/test_region")
|
531
548
|
zone2 = double("zone2", status: "UP", region: "a/b/c/test_region")
|
@@ -542,7 +559,7 @@ describe Kitchen::Driver::Gce do
|
|
542
559
|
end
|
543
560
|
end
|
544
561
|
|
545
|
-
describe
|
562
|
+
describe "#server_instance" do
|
546
563
|
it "returns the instance from the API" do
|
547
564
|
connection = double("connection")
|
548
565
|
expect(driver).to receive(:connection).and_return(connection)
|
@@ -551,7 +568,7 @@ describe Kitchen::Driver::Gce do
|
|
551
568
|
end
|
552
569
|
end
|
553
570
|
|
554
|
-
describe
|
571
|
+
describe "#ip_address_for" do
|
555
572
|
it "returns the private IP if use_private_ip is true" do
|
556
573
|
expect(driver).to receive(:config).and_return(use_private_ip: true)
|
557
574
|
expect(driver).to receive(:private_ip_for).with("server").and_return("1.2.3.4")
|
@@ -565,7 +582,7 @@ describe Kitchen::Driver::Gce do
|
|
565
582
|
end
|
566
583
|
end
|
567
584
|
|
568
|
-
describe
|
585
|
+
describe "#private_ip_for" do
|
569
586
|
it "returns the IP address if it exists" do
|
570
587
|
network_interface = double("network_interface", network_ip: "1.2.3.4")
|
571
588
|
server = double("server", network_interfaces: [network_interface])
|
@@ -581,7 +598,7 @@ describe Kitchen::Driver::Gce do
|
|
581
598
|
end
|
582
599
|
end
|
583
600
|
|
584
|
-
describe
|
601
|
+
describe "#public_ip_for" do
|
585
602
|
it "returns the IP address if it exists" do
|
586
603
|
access_config = double("access_config", nat_ip: "4.3.2.1")
|
587
604
|
network_interface = double("network_interface", access_configs: [access_config])
|
@@ -599,7 +616,7 @@ describe Kitchen::Driver::Gce do
|
|
599
616
|
end
|
600
617
|
end
|
601
618
|
|
602
|
-
describe
|
619
|
+
describe "#generate_server_name" do
|
603
620
|
it "generates and returns a server name" do
|
604
621
|
expect(instance).to receive(:name).and_return("ABC123")
|
605
622
|
expect(SecureRandom).to receive(:hex).with(3).and_return("abcdef")
|
@@ -615,7 +632,7 @@ describe Kitchen::Driver::Gce do
|
|
615
632
|
end
|
616
633
|
end
|
617
634
|
|
618
|
-
describe
|
635
|
+
describe "#boot_disk" do
|
619
636
|
it "sets up a disk object and returns it" do
|
620
637
|
disk = double("disk")
|
621
638
|
params = double("params")
|
@@ -628,7 +645,7 @@ describe Kitchen::Driver::Gce do
|
|
628
645
|
|
629
646
|
allow(driver).to receive(:config).and_return(config)
|
630
647
|
expect(driver).to receive(:disk_type_url_for).with("test_type").and_return("disk_url")
|
631
|
-
expect(driver).to receive(:
|
648
|
+
expect(driver).to receive(:image_url).and_return("disk_image_url")
|
632
649
|
|
633
650
|
expect(Google::Apis::ComputeV1::AttachedDisk).to receive(:new).and_return(disk)
|
634
651
|
expect(Google::Apis::ComputeV1::AttachedDiskInitializeParams).to receive(:new).and_return(params)
|
@@ -644,168 +661,55 @@ describe Kitchen::Driver::Gce do
|
|
644
661
|
end
|
645
662
|
end
|
646
663
|
|
647
|
-
describe
|
664
|
+
describe "#disk_type_url_for" do
|
648
665
|
it "returns a disk URL" do
|
649
666
|
expect(driver.disk_type_url_for("my_type")).to eq("zones/test_zone/diskTypes/my_type")
|
650
667
|
end
|
651
668
|
end
|
652
669
|
|
653
|
-
describe
|
670
|
+
describe "#image_name" do
|
654
671
|
before do
|
655
672
|
allow(driver).to receive(:config).and_return(config)
|
656
673
|
end
|
657
674
|
|
658
|
-
context "when the user supplies an image
|
675
|
+
context "when the user supplies an image name" do
|
659
676
|
let(:config) { { image_project: "my_image_project", image_name: "my_image" } }
|
660
677
|
|
661
|
-
it "returns the image
|
662
|
-
expect(driver).to
|
663
|
-
expect(driver.disk_image_url).to eq("image_url")
|
678
|
+
it "returns the image name supplied" do
|
679
|
+
expect(driver.image_name).to eq("my_image")
|
664
680
|
end
|
665
681
|
end
|
666
682
|
|
667
|
-
context "when the user
|
668
|
-
|
669
|
-
context "when the image provided is an alias" do
|
670
|
-
let(:config) { { image_name: "image_alias" } }
|
683
|
+
context "when the user supplies an image family" do
|
684
|
+
let(:config) { { image_project: "my_image_project", image_family: "my_image_family" } }
|
671
685
|
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
end
|
676
|
-
end
|
677
|
-
|
678
|
-
context "when the image provided is not an alias" do
|
679
|
-
let(:config) { { image_name: "my_image" } }
|
680
|
-
|
681
|
-
before do
|
682
|
-
expect(driver).to receive(:image_alias_url).and_return(nil)
|
683
|
-
end
|
684
|
-
|
685
|
-
context "when the image exists in the user's project" do
|
686
|
-
it "returns the image URL" do
|
687
|
-
expect(driver).to receive(:image_url_for).with(project, "my_image").and_return("image_url")
|
688
|
-
expect(driver.disk_image_url).to eq("image_url")
|
689
|
-
end
|
690
|
-
end
|
691
|
-
|
692
|
-
context "when the image does not exist in the user's project" do
|
693
|
-
before do
|
694
|
-
expect(driver).to receive(:image_url_for).with(project, "my_image").and_return(nil)
|
695
|
-
end
|
696
|
-
|
697
|
-
context "when the image matches a known public project" do
|
698
|
-
it "returns the image URL from the public project" do
|
699
|
-
expect(driver).to receive(:public_project_for_image).with("my_image").and_return("public_project")
|
700
|
-
expect(driver).to receive(:image_url_for).with("public_project", "my_image").and_return("image_url")
|
701
|
-
expect(driver.disk_image_url).to eq("image_url")
|
702
|
-
end
|
703
|
-
end
|
704
|
-
|
705
|
-
context "when the image does not match a known project" do
|
706
|
-
it "returns nil" do
|
707
|
-
expect(driver).to receive(:public_project_for_image).with("my_image").and_return(nil)
|
708
|
-
expect(driver).not_to receive(:image_url_for)
|
709
|
-
expect(driver.disk_image_url).to eq(nil)
|
710
|
-
end
|
711
|
-
end
|
712
|
-
end
|
686
|
+
it "returns the image found in the family" do
|
687
|
+
expect(driver).to receive(:image_name_for_family).with("my_image_family").and_return("my_image")
|
688
|
+
expect(driver.image_name).to eq("my_image")
|
713
689
|
end
|
714
690
|
end
|
715
691
|
end
|
716
692
|
|
717
|
-
describe
|
693
|
+
describe "#image_url" do
|
718
694
|
it "returns nil if the image does not exist" do
|
719
|
-
expect(driver).to receive(:image_exist?).
|
720
|
-
expect(driver.
|
695
|
+
expect(driver).to receive(:image_exist?).and_return(false)
|
696
|
+
expect(driver.image_url).to eq(nil)
|
721
697
|
end
|
722
698
|
|
723
699
|
it "returns a properly formatted image URL if the image exists" do
|
724
|
-
expect(driver).to receive(:image_exist?).
|
725
|
-
expect(driver.
|
726
|
-
end
|
727
|
-
end
|
728
|
-
|
729
|
-
describe '#image_alias_url' do
|
730
|
-
before do
|
731
|
-
allow(driver).to receive(:config).and_return(config)
|
732
|
-
end
|
733
|
-
|
734
|
-
context "when the image_alias is not a valid alias" do
|
735
|
-
let(:config) { { image_name: "fake_alias" } }
|
736
|
-
|
737
|
-
it "returns nil" do
|
738
|
-
expect(driver.image_alias_url).to eq(nil)
|
739
|
-
end
|
740
|
-
end
|
741
|
-
|
742
|
-
context "when the image_alias is a valid alias" do
|
743
|
-
let(:config) { { image_name: "centos-7" } }
|
744
|
-
let(:connection) { double("connection") }
|
745
|
-
|
746
|
-
before do
|
747
|
-
allow(driver).to receive(:connection).and_return(connection)
|
748
|
-
allow(connection).to receive(:list_images).and_return(response)
|
749
|
-
end
|
750
|
-
|
751
|
-
context "when the response contains no images" do
|
752
|
-
let(:response) { double("response", items: []) }
|
753
|
-
|
754
|
-
it "returns nil" do
|
755
|
-
expect(driver.image_alias_url).to eq(nil)
|
756
|
-
end
|
757
|
-
end
|
758
|
-
|
759
|
-
context "when the response contains images but none match the name" do
|
760
|
-
let(:image1) { double("image1", name: "centos-6-v20150101") }
|
761
|
-
let(:image2) { double("image2", name: "centos-6-v20150202") }
|
762
|
-
let(:image3) { double("image3", name: "ubuntu-14-v20150303") }
|
763
|
-
let(:response) { double("response", items: [ image1, image2, image3 ]) }
|
764
|
-
|
765
|
-
it "returns nil" do
|
766
|
-
expect(driver.image_alias_url).to eq(nil)
|
767
|
-
end
|
768
|
-
end
|
769
|
-
|
770
|
-
context "when the response contains images that match the name" do
|
771
|
-
let(:image1) { double("image1", name: "centos-7-v20160201", self_link: "image1_selflink") }
|
772
|
-
let(:image2) { double("image2", name: "centos-7-v20160301", self_link: "image2_selflink") }
|
773
|
-
let(:image3) { double("image3", name: "centos-6-v20160401", self_link: "image3_selflink") }
|
774
|
-
let(:response) { double("response", items: [ image1, image2, image3 ]) }
|
775
|
-
|
776
|
-
it "returns the link for image2 which is the most recent image" do
|
777
|
-
expect(driver.image_alias_url).to eq("image2_selflink")
|
778
|
-
end
|
779
|
-
end
|
780
|
-
end
|
781
|
-
end
|
782
|
-
|
783
|
-
describe '#public_project_for_image' do
|
784
|
-
{
|
785
|
-
"centos" => "centos-cloud",
|
786
|
-
"container-vm" => "google-containers",
|
787
|
-
"coreos" => "coreos-cloud",
|
788
|
-
"debian" => "debian-cloud",
|
789
|
-
"opensuse-cloud" => "opensuse-cloud",
|
790
|
-
"rhel" => "rhel-cloud",
|
791
|
-
"sles" => "suse-cloud",
|
792
|
-
"ubuntu" => "ubuntu-os-cloud",
|
793
|
-
"windows" => "windows-cloud",
|
794
|
-
}.each do |image_name, project_name|
|
795
|
-
it "returns project #{project_name} for an image named #{image_name}" do
|
796
|
-
expect(driver.public_project_for_image(image_name)).to eq(project_name)
|
797
|
-
end
|
700
|
+
expect(driver).to receive(:image_exist?).and_return(true)
|
701
|
+
expect(driver.image_url).to eq("projects/test_project/global/images/test_image")
|
798
702
|
end
|
799
703
|
end
|
800
704
|
|
801
|
-
describe
|
705
|
+
describe "#machine_type_url" do
|
802
706
|
it "returns a machine type URL" do
|
803
707
|
expect(driver).to receive(:config).and_return(machine_type: "machine_type")
|
804
708
|
expect(driver.machine_type_url).to eq("zones/test_zone/machineTypes/machine_type")
|
805
709
|
end
|
806
710
|
end
|
807
711
|
|
808
|
-
describe
|
712
|
+
describe "#instance_metadata" do
|
809
713
|
it "returns a properly-configured metadata object" do
|
810
714
|
item1 = double("item1")
|
811
715
|
item2 = double("item2")
|
@@ -830,7 +734,7 @@ describe Kitchen::Driver::Gce do
|
|
830
734
|
end
|
831
735
|
end
|
832
736
|
|
833
|
-
describe
|
737
|
+
describe "#env_user" do
|
834
738
|
it "returns the current user from the environment" do
|
835
739
|
expect(ENV).to receive(:[]).with("USER").and_return("test_user")
|
836
740
|
expect(driver.env_user).to eq("test_user")
|
@@ -842,7 +746,7 @@ describe Kitchen::Driver::Gce do
|
|
842
746
|
end
|
843
747
|
end
|
844
748
|
|
845
|
-
describe
|
749
|
+
describe "#instance_network_interfaces" do
|
846
750
|
let(:interface) { double("interface") }
|
847
751
|
|
848
752
|
before do
|
@@ -885,14 +789,14 @@ describe Kitchen::Driver::Gce do
|
|
885
789
|
end
|
886
790
|
end
|
887
791
|
|
888
|
-
describe
|
792
|
+
describe "#network_url" do
|
889
793
|
it "returns a network URL" do
|
890
794
|
expect(driver).to receive(:config).and_return(network: "test_network")
|
891
795
|
expect(driver.network_url).to eq("projects/test_project/global/networks/test_network")
|
892
796
|
end
|
893
797
|
end
|
894
798
|
|
895
|
-
describe
|
799
|
+
describe "#subnet_url_for" do
|
896
800
|
it "returns nil if no subnet is specified" do
|
897
801
|
expect(driver).to receive(:config).and_return({})
|
898
802
|
expect(driver.subnet_url).to eq(nil)
|
@@ -905,7 +809,7 @@ describe Kitchen::Driver::Gce do
|
|
905
809
|
end
|
906
810
|
end
|
907
811
|
|
908
|
-
describe
|
812
|
+
describe "#interface_access_configs" do
|
909
813
|
it "returns a properly-configured access config object" do
|
910
814
|
access_config = double("access_config")
|
911
815
|
|
@@ -923,7 +827,7 @@ describe Kitchen::Driver::Gce do
|
|
923
827
|
end
|
924
828
|
end
|
925
829
|
|
926
|
-
describe
|
830
|
+
describe "#instance_scheduling" do
|
927
831
|
it "returns a properly-configured scheduling object" do
|
928
832
|
scheduling = double("scheduling")
|
929
833
|
|
@@ -938,14 +842,14 @@ describe Kitchen::Driver::Gce do
|
|
938
842
|
end
|
939
843
|
end
|
940
844
|
|
941
|
-
describe
|
845
|
+
describe "#preemptible?" do
|
942
846
|
it "returns the preemptible setting from the config" do
|
943
847
|
expect(driver).to receive(:config).and_return(preemptible: "test_preempt")
|
944
848
|
expect(driver.preemptible?).to eq("test_preempt")
|
945
849
|
end
|
946
850
|
end
|
947
851
|
|
948
|
-
describe
|
852
|
+
describe "#auto_migrate?" do
|
949
853
|
it "returns false if the instance is preemptible" do
|
950
854
|
expect(driver).to receive(:preemptible?).and_return(true)
|
951
855
|
expect(driver.auto_migrate?).to eq(false)
|
@@ -958,7 +862,7 @@ describe Kitchen::Driver::Gce do
|
|
958
862
|
end
|
959
863
|
end
|
960
864
|
|
961
|
-
describe
|
865
|
+
describe "#auto_restart?" do
|
962
866
|
it "returns false if the instance is preemptible" do
|
963
867
|
expect(driver).to receive(:preemptible?).and_return(true)
|
964
868
|
expect(driver.auto_restart?).to eq(false)
|
@@ -971,7 +875,7 @@ describe Kitchen::Driver::Gce do
|
|
971
875
|
end
|
972
876
|
end
|
973
877
|
|
974
|
-
describe
|
878
|
+
describe "#migrate_setting" do
|
975
879
|
it "returns MIGRATE if auto_migrate is true" do
|
976
880
|
expect(driver).to receive(:auto_migrate?).and_return(true)
|
977
881
|
expect(driver.migrate_setting).to eq("MIGRATE")
|
@@ -983,7 +887,7 @@ describe Kitchen::Driver::Gce do
|
|
983
887
|
end
|
984
888
|
end
|
985
889
|
|
986
|
-
describe
|
890
|
+
describe "#instance_service_accounts" do
|
987
891
|
it "returns nil if service_account_scopes is nil" do
|
988
892
|
allow(driver).to receive(:config).and_return({})
|
989
893
|
expect(driver.instance_service_accounts).to eq(nil)
|
@@ -1011,7 +915,7 @@ describe Kitchen::Driver::Gce do
|
|
1011
915
|
end
|
1012
916
|
end
|
1013
917
|
|
1014
|
-
describe
|
918
|
+
describe "#service_account_scope_url" do
|
1015
919
|
it "returns the passed-in scope if it already looks like a scope URL" do
|
1016
920
|
scope = "https://www.googleapis.com/auth/fake_scope"
|
1017
921
|
expect(driver.service_account_scope_url(scope)).to eq(scope)
|
@@ -1023,7 +927,7 @@ describe Kitchen::Driver::Gce do
|
|
1023
927
|
end
|
1024
928
|
end
|
1025
929
|
|
1026
|
-
describe
|
930
|
+
describe "#translate_scope_alias" do
|
1027
931
|
it "returns a scope for a given alias" do
|
1028
932
|
expect(driver.translate_scope_alias("storage-rw")).to eq("devstorage.read_write")
|
1029
933
|
end
|
@@ -1033,7 +937,7 @@ describe Kitchen::Driver::Gce do
|
|
1033
937
|
end
|
1034
938
|
end
|
1035
939
|
|
1036
|
-
describe
|
940
|
+
describe "#instance_tags" do
|
1037
941
|
it "returns a properly-formatted tags object" do
|
1038
942
|
tags_obj = double("tags_obj")
|
1039
943
|
|
@@ -1045,21 +949,21 @@ describe Kitchen::Driver::Gce do
|
|
1045
949
|
end
|
1046
950
|
end
|
1047
951
|
|
1048
|
-
describe
|
952
|
+
describe "#wait_time" do
|
1049
953
|
it "returns the configured wait time" do
|
1050
954
|
expect(driver).to receive(:config).and_return(wait_time: 123)
|
1051
955
|
expect(driver.wait_time).to eq(123)
|
1052
956
|
end
|
1053
957
|
end
|
1054
958
|
|
1055
|
-
describe
|
959
|
+
describe "#refresh_rate" do
|
1056
960
|
it "returns the configured refresh rate" do
|
1057
961
|
expect(driver).to receive(:config).and_return(refresh_rate: 321)
|
1058
962
|
expect(driver.refresh_rate).to eq(321)
|
1059
963
|
end
|
1060
964
|
end
|
1061
965
|
|
1062
|
-
describe
|
966
|
+
describe "#wait_for_status" do
|
1063
967
|
let(:item) { double("item") }
|
1064
968
|
|
1065
969
|
before do
|
@@ -1103,7 +1007,7 @@ describe Kitchen::Driver::Gce do
|
|
1103
1007
|
end
|
1104
1008
|
end
|
1105
1009
|
|
1106
|
-
describe
|
1010
|
+
describe "#wait_for_operation" do
|
1107
1011
|
let(:operation) { double("operation", name: "operation-123") }
|
1108
1012
|
|
1109
1013
|
it "raises a properly-formatted exception when errors exist" do
|
@@ -1126,7 +1030,7 @@ describe Kitchen::Driver::Gce do
|
|
1126
1030
|
end
|
1127
1031
|
end
|
1128
1032
|
|
1129
|
-
describe
|
1033
|
+
describe "#zone_operation" do
|
1130
1034
|
it "fetches the operation from the API and returns it" do
|
1131
1035
|
connection = double("connection")
|
1132
1036
|
expect(driver).to receive(:connection).and_return(connection)
|
@@ -1135,7 +1039,7 @@ describe Kitchen::Driver::Gce do
|
|
1135
1039
|
end
|
1136
1040
|
end
|
1137
1041
|
|
1138
|
-
describe
|
1042
|
+
describe "#operation_errors" do
|
1139
1043
|
let(:operation) { double("operation") }
|
1140
1044
|
let(:error_obj) { double("error_obj") }
|
1141
1045
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kitchen-google
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Leonard
|
@@ -165,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
165
|
version: '0'
|
166
166
|
requirements: []
|
167
167
|
rubyforge_project:
|
168
|
-
rubygems_version: 2.
|
168
|
+
rubygems_version: 2.6.10
|
169
169
|
signing_key:
|
170
170
|
specification_version: 4
|
171
171
|
summary: Kitchen::Driver::Gce
|