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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 82664c984b7db17f6d04c2844f382e18e87047d2
4
- data.tar.gz: a47939f2f42029ee55400669a5daee07848023b6
3
+ metadata.gz: 6201b751412eb2c2ee39e9e48044db20388eb210
4
+ data.tar.gz: 747394a1e962ca4780e91ccf20a3d3acade150d1
5
5
  SHA512:
6
- metadata.gz: 52267771b0165f69641258d29dd85603574e402b5c506dcae6a2c5e3b4a1332fce62cb31826ae6a22139e98d5792abcc5fccde5d14ff0be110cdb4964f44c7f8
7
- data.tar.gz: 7ff9cb61420f0d29c4f71b0dfe4678f5a76d755efa5e0a4b80f12efb496189c962f3b275ae801927cc3c0680d2765282e76f56f295d6ba42536db4d2d7ca9873
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
- **Required**. The name of the disk image to use as the source image for
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
- The GCP project specified with the `project` configuration parameter will
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
- You can override the project in which to search for the image with the
126
- `image_project` parameter.
139
+ This parameter will override `image_family` if they are both specified.
127
140
 
128
- Additionally, you can supply an image alias supported by the `gcloud compute instances create`
129
- command and kitchen-google will find the latest version of that image to use.
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
- image_name: centos-6-v20160219
306
+ image_project: ubuntu-os-cloud
307
+ image_family: ubuntu-1604-lts
291
308
  - name: windows
292
309
  driver:
293
- image_name: windows-server-2012-r2-dc-v20160112
310
+ image_project: windows-cloud
311
+ image_name: windows-server-2012-r2-dc-v20170117
294
312
  disk_size: 50
295
313
 
296
314
  suites:
@@ -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] and !valid_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.downcase == "winrm"
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?(image_project, image_name)
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 ||= disk_image_url
360
+ @boot_disk_source ||= image_url
370
361
  end
371
362
 
372
- def disk_image_url
373
- # if the user provided an image_project, assume they want it, no questions asked
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 image_alias_url
410
- image_alias = config[:image_name]
411
- return unless IMAGE_ALIAS_MAP.key?(image_alias)
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
@@ -18,6 +18,6 @@
18
18
 
19
19
  module Kitchen
20
20
  module Driver
21
- GCE_VERSION = "1.1.0".freeze
21
+ GCE_VERSION = "1.2.0".freeze
22
22
  end
23
23
  end
@@ -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 '#name' do
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 '#create' do
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 '#destroy' do
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 '#validate!' do
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 '#connection' do
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 '#authorization' do
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 '#winrm_transport?' do
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 '#update_windows_password' do
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 '#check_api_call' do
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 RuntimeError.new("whoops") } }.to raise_error(RuntimeError)
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 '#valid_machine_type?' do
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 '#valid_network?' do
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 '#valid_subnet?' do
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 '#valid_zone?' do
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 '#valid_region?' do
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 '#valid_disk_type?' do
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 '#image_exist?' do
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("image_project", "image_name")
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?("image_project", "image_name")).to eq(true)
445
+ expect(driver.image_exist?).to eq(true)
429
446
  end
430
447
  end
431
448
 
432
- describe '#server_exist?' do
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 '#project' do
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 '#region' do
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 '#region_for_zone' do
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 '#zone' do
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 '#find_zone' do
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 '#zones_in_region' do
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 '#server_instance' do
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 '#ip_address_for' do
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 '#private_ip_for' do
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 '#public_ip_for' do
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 '#generate_server_name' do
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 '#boot_disk' do
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(:disk_image_url).and_return("disk_image_url")
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 '#disk_type_url_for' do
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 '#disk_image_url' do
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 project" do
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 URL based on the image project" do
662
- expect(driver).to receive(:image_url_for).with("my_image_project", "my_image").and_return("image_url")
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 does not supply an image project" do
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
- it "returns the alias URL" do
673
- expect(driver).to receive(:image_alias_url).and_return("image_alias_url")
674
- expect(driver.disk_image_url).to eq("image_alias_url")
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 '#image_url_for' do
693
+ describe "#image_url" do
718
694
  it "returns nil if the image does not exist" do
719
- expect(driver).to receive(:image_exist?).with("image_project", "image_name").and_return(false)
720
- expect(driver.image_url_for("image_project", "image_name")).to eq(nil)
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?).with("image_project", "image_name").and_return(true)
725
- expect(driver.image_url_for("image_project", "image_name")).to eq("projects/image_project/global/images/image_name")
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 '#machine_type_url' do
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 '#instance_metadata' do
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 '#env_user' do
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 '#instance_network_interfaces' do
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 '#network_url' do
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 '#subnet_url_for' do
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 '#interface_access_configs' do
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 '#instance_scheduling' do
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 '#preemptible?' do
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 '#auto_migrate?' do
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 '#auto_restart?' do
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 '#migrate_setting' do
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 '#instance_service_accounts' do
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 '#service_account_scope_url' do
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 '#translate_scope_alias' do
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 '#instance_tags' do
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 '#wait_time' do
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 '#refresh_rate' do
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 '#wait_for_status' do
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 '#wait_for_operation' do
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 '#zone_operation' do
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 '#operation_errors' do
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.1.0
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.4.8
168
+ rubygems_version: 2.6.10
169
169
  signing_key:
170
170
  specification_version: 4
171
171
  summary: Kitchen::Driver::Gce