kitchen-google 3.0.0 → 3.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c6f8ac82e7287b315c4983229aad826ffc6dc2616d7b94c0f1887c3f3fbfdd4
4
- data.tar.gz: 15e6f00245977ef5f27fa4c9fb09ee81e320534e2b2757ab6f812cb43f2d5e03
3
+ metadata.gz: 7bb68767fd70358c97f209575379ad984b9aab4fd4b3f0377cf1e77b5167796a
4
+ data.tar.gz: 83f5317efdf99856679a51a88a95c5d5601dc220989285c54e5771b290b90393
5
5
  SHA512:
6
- metadata.gz: 813a82a35180d748b4d629b71e9ff9204a31a4482443e70e49830a1457ff545d7b7542ecfea6644991a864a5052f3cf3ef905276cfd171e0248b62327072d6f0
7
- data.tar.gz: ddbdb11f5bf6420395f772189ce8145f65120c01aee09a065702c735fae641f75a809875713dd6a525eaf0d1ecb53724d5fe5fe48fc246ca21d9268393f0235f
6
+ metadata.gz: 59c12a1a8494f2c99df3a5ddb5b68bcb34fde00815e3ed25df084b4e1cb7b96057f030486350870b694ac2cd827fdffc47f94a421c7586118d9338dc7c5870e7
7
+ data.tar.gz: 5e1f05a0b84feab76831418aeff5b5900d84a8285fbe3bf0b7b9c046ec958e9e6d46027bb47e493842c3e84f91d2398f094f23058b6f97b82be23a06b86e36bd
@@ -89,7 +89,10 @@ module Kitchen
89
89
  default_config :tags, []
90
90
  default_config :preemptible, false
91
91
  default_config :auto_restart, false
92
- default_config :auto_migrate, false
92
+ # Matches GCE's own default for onHostMaintenance. Several machine
93
+ # families, E2 among them, reject TERMINATE unless the instance is
94
+ # preemptible, so defaulting this off makes them unusable.
95
+ default_config :auto_migrate, true
93
96
  default_config :image_family, nil
94
97
  default_config :image_name, nil
95
98
  default_config :image_project, nil
@@ -125,13 +128,35 @@ module Kitchen
125
128
 
126
129
  # Configuration applied to every disk before the user's own settings.
127
130
  #
131
+ # Deliberately sets no `disk_type`. GCE derives an omitted disk type from
132
+ # the instance's machine series -- pd-standard on first- and
133
+ # second-generation series such as N1 and N2, pd-balanced on C3, C3D and
134
+ # M3, and hyperdisk-balanced on C4, N4 and newer -- so leaving it unset is
135
+ # the only default that is compatible with every machine type. Naming one
136
+ # here would fail outright on the families that no longer accept it.
137
+ #
128
138
  # @return [Hash] the per-disk defaults
129
139
  DISK_DEFAULT_CONFIG = {
130
140
  autodelete_disk: true,
131
141
  disk_size: 10,
132
- disk_type: "pd-standard",
133
142
  }.freeze
134
143
 
144
+ # Local Windows account Test Kitchen's WinRM transport defaults to, and
145
+ # which Google's Windows images ship disabled.
146
+ #
147
+ # @return [String] the built-in administrator account name
148
+ BUILTIN_ADMINISTRATOR = "administrator".freeze
149
+
150
+ # Told to the user when they are about to wait out a WinRM timeout for a
151
+ # reason the driver can see coming.
152
+ #
153
+ # @return [String] the warning text
154
+ BUILTIN_ADMINISTRATOR_WARNING =
155
+ "The WinRM transport is connecting as the built-in Administrator account, which is " \
156
+ "disabled on Google's Windows images. The guest agent resets its password without " \
157
+ "enabling it, so the login will be refused. Set transport.username to any other name " \
158
+ "and the agent will create that account instead.".freeze
159
+
135
160
  # Human-readable driver name shown in Test Kitchen output.
136
161
  #
137
162
  # @return [String] the driver's display name
@@ -164,13 +189,17 @@ module Kitchen
164
189
  info("Creating GCE instance <#{server_name}> in project #{project}, zone #{zone}...")
165
190
  operation = connection.insert_instance(project, zone, create_instance_object(server_name))
166
191
 
167
- wait_for_operation(operation)
168
-
169
- server = server_instance(server_name)
192
+ # GCE starts billing for the instance as soon as the insert is
193
+ # accepted, so record it before waiting on the operation. Anything that
194
+ # goes wrong from here on can then be torn down by the rescue below,
195
+ # and by `kitchen destroy` if the process does not survive to run it.
170
196
  state[:server_name] = server_name
171
- state[:hostname] = ip_address_for(server)
172
197
  state[:zone] = zone
173
198
 
199
+ wait_for_operation(operation)
200
+
201
+ state[:hostname] = ip_address_for(server_instance(server_name))
202
+
174
203
  info("Server <#{server_name}> created.")
175
204
 
176
205
  update_windows_password(server_name)
@@ -269,9 +298,12 @@ module Kitchen
269
298
  boot: true,
270
299
  autodelete_disk: config.fetch(:autodelete_disk, DISK_DEFAULT_CONFIG[:autodelete_disk]),
271
300
  disk_size: config.fetch(:disk_size, DISK_DEFAULT_CONFIG[:disk_size]),
272
- disk_type: config.fetch(:disk_type, DISK_DEFAULT_CONFIG[:disk_type]),
273
301
  }
274
302
 
303
+ # Carry the key only when the user set it, so that an unset type stays
304
+ # absent rather than becoming an explicit nil. See DISK_DEFAULT_CONFIG.
305
+ disk_config[:disk_type] = config[:disk_type] if config[:disk_type]
306
+
275
307
  raise "Disk type #{disk_config[:disk_type]} is not valid" unless valid_disk_type?(disk_config[:disk_type])
276
308
 
277
309
  disk_config
@@ -388,11 +420,13 @@ module Kitchen
388
420
  raise "You cannot use autodelete_disk, disk_size or disk_type with the new disks configuration" if old_disk_configuration_present? && new_disk_configuration_present?
389
421
  raise "Disk image #{config[:image_name]} is not valid - check your image name and image project" if boot_disk_source_image.nil?
390
422
 
423
+ warn(BUILTIN_ADMINISTRATOR_WARNING) if winrm_transport? && builtin_administrator?
391
424
  warn("Both zone and region specified - region will be ignored.") if config[:zone] && config[:region]
392
425
  warn("Both image family and name specified - image family will be ignored") if config[:image_family] && config[:image_name]
393
426
  warn("Image project not specified - searching current project only") unless config[:image_project]
394
427
  warn("Subnet project not specified - searching current project only") if config[:subnet] && !config[:subnet_project]
395
428
  warn("Auto-migrate disabled for preemptible instance") if preemptible? && config[:auto_migrate]
429
+ warn("Auto-migrate disabled for instance with guest accelerators") if guest_accelerators? && config[:auto_migrate]
396
430
  warn("Auto-restart disabled for preemptible instance") if preemptible? && config[:auto_restart]
397
431
  warn("These configs are deprecated - consider using new disks configuration") if old_disk_configuration_present?
398
432
  end
@@ -425,6 +459,14 @@ module Kitchen
425
459
  )
426
460
  end
427
461
 
462
+ # Whether the WinRM transport is configured to log in as the built-in
463
+ # Administrator account.
464
+ #
465
+ # @return [Boolean] true if the transport username is `administrator`
466
+ def builtin_administrator?
467
+ instance.transport[:username].to_s.casecmp?(BUILTIN_ADMINISTRATOR)
468
+ end
469
+
428
470
  # Whether the suite's transport is WinRM, implying a Windows guest.
429
471
  #
430
472
  # @return [Boolean] true when the transport is WinRM
@@ -525,10 +567,13 @@ module Kitchen
525
567
 
526
568
  # Whether a disk type exists in the target zone.
527
569
  #
570
+ # An unset type is valid: the driver sends no `diskType` at all and GCE
571
+ # substitutes the default for the instance's machine series.
572
+ #
528
573
  # @param disk_type [String, nil] the disk type to check
529
- # @return [Boolean] true if the disk type is valid
574
+ # @return [Boolean] true if the disk type is valid or unset
530
575
  def valid_disk_type?(disk_type)
531
- return false if disk_type.nil?
576
+ return true if disk_type.nil?
532
577
 
533
578
  check_api_call { connection.get_disk_type(project, zone, disk_type) }
534
579
  end
@@ -753,17 +798,19 @@ module Kitchen
753
798
  disk.boot = true if disk_config[:boot]
754
799
  disk.auto_delete = disk_config[:autodelete_disk]
755
800
  params.disk_size_gb = disk_config[:disk_size]
756
- params.disk_type = disk_type_url_for(disk_config[:disk_type])
801
+ params.disk_type = disk_type_url_for(disk_config[:disk_type]) if disk_config[:disk_type]
757
802
 
758
803
  if local_ssd?(disk_config)
759
804
  info("Creating a #{LOCAL_SSD_SIZE_GB} GB local ssd as scratch disk (https://cloud.google.com/compute/docs/disks/#localssds).")
760
805
  disk.type = "SCRATCH"
761
806
  elsif disk.boot
762
- info("Creating a #{disk_config[:disk_size]} GB boot disk named #{unique_disk_name} from image #{image_name}...")
807
+ params.disk_size_gb = disk_size_for_image(disk_config[:disk_size], image_name)
808
+ info("Creating a #{params.disk_size_gb} GB boot disk named #{unique_disk_name} from image #{image_name}...")
763
809
  params.source_image = boot_disk_source_image
764
810
  params.disk_name = unique_disk_name
765
811
  else
766
- info("Creating a #{disk_config[:disk_size]} GB extra disk named #{unique_disk_name} from image #{disk_config[:custom_image]}...")
812
+ params.disk_size_gb = disk_size_for_image(disk_config[:disk_size], disk_config[:custom_image])
813
+ info("Creating a #{params.disk_size_gb} GB extra disk named #{unique_disk_name} from image #{disk_config[:custom_image]}...")
767
814
  params.source_image = image_url(disk_config[:custom_image])
768
815
  params.disk_name = unique_disk_name
769
816
  end
@@ -771,6 +818,50 @@ module Kitchen
771
818
  disk
772
819
  end
773
820
 
821
+ # The size to request for a disk cloned from an image.
822
+ #
823
+ # GCE refuses to create a disk smaller than the image it is cloned from,
824
+ # and the driver's own 10 GB default is smaller than many stock images -
825
+ # every Windows image is 50 GB, and Rocky and CentOS are 20 GB. Rather
826
+ # than fail the run over a size the user never chose, raise the request
827
+ # to what the image needs and say so.
828
+ #
829
+ # @param requested [Integer, nil] the configured size in gigabytes
830
+ # @param image [String, nil] the image the disk is cloned from
831
+ # @return [Integer, nil] the size to request
832
+ # @api private
833
+ def disk_size_for_image(requested, image)
834
+ image_size = image_disk_size_gb(image)
835
+ return requested if image_size.nil? || (!requested.nil? && requested >= image_size)
836
+
837
+ warn("Requested disk size of #{requested} GB is smaller than image #{image} " \
838
+ "(#{image_size} GB) - creating a #{image_size} GB disk instead.")
839
+ image_size
840
+ end
841
+
842
+ # The size, in gigabytes, of an image in the image project.
843
+ #
844
+ # Memoised per image name, since the boot image is looked up more than
845
+ # once during a single action.
846
+ #
847
+ # @param image [String, nil] the image name
848
+ # @return [Integer, nil] the image's size, or nil if it cannot be read
849
+ # @api private
850
+ def image_disk_size_gb(image)
851
+ return if image.nil?
852
+
853
+ @image_disk_sizes ||= {}
854
+ return @image_disk_sizes[image] if @image_disk_sizes.key?(image)
855
+
856
+ @image_disk_sizes[image] =
857
+ begin
858
+ connection.get_image(image_project, image).disk_size_gb
859
+ rescue Google::Apis::ClientError => e
860
+ debug("Unable to read the size of image #{image}: #{e.message}")
861
+ nil
862
+ end
863
+ end
864
+
774
865
  # Creates a standalone persistent disk, waits for it to become ready, and
775
866
  # returns a reference attaching it to the instance.
776
867
  #
@@ -781,7 +872,7 @@ module Kitchen
781
872
  disk = Google::Apis::ComputeV1::Disk.new
782
873
  disk.name = unique_disk_name
783
874
  disk.size_gb = disk_config[:disk_size]
784
- disk.type = disk_type_url_for(disk_config[:disk_type])
875
+ disk.type = disk_type_url_for(disk_config[:disk_type]) if disk_config[:disk_type]
785
876
 
786
877
  info("Creating a #{disk_config[:disk_size]} GB disk named #{unique_disk_name}...")
787
878
  wait_for_operation(connection.insert_disk(project, zone, disk))
@@ -1019,16 +1110,24 @@ module Kitchen
1019
1110
  config[:preemptible] ? true : false
1020
1111
  end
1021
1112
 
1022
- # Whether the instance may live-migrate. Always false when preemptible,
1023
- # which GCE does not allow to migrate.
1113
+ # Whether the instance may live-migrate. Always false for preemptible
1114
+ # instances and for instances with guest accelerators attached, neither
1115
+ # of which GCE will migrate.
1024
1116
  #
1025
1117
  # @return [Boolean] true if live migration is enabled
1026
1118
  def auto_migrate?
1027
- return false if preemptible?
1119
+ return false if preemptible? || guest_accelerators?
1028
1120
 
1029
1121
  config[:auto_migrate] ? true : false
1030
1122
  end
1031
1123
 
1124
+ # Whether any guest accelerators are attached.
1125
+ #
1126
+ # @return [Boolean] true if the instance has at least one accelerator
1127
+ def guest_accelerators?
1128
+ !Array(config[:guest_accelerators]).empty?
1129
+ end
1130
+
1032
1131
  # Whether the instance should restart automatically. Always false when
1033
1132
  # preemptible, which GCE does not allow to auto-restart.
1034
1133
  #
@@ -28,6 +28,6 @@ module Kitchen
28
28
  # release. Keep it on one line.
29
29
  #
30
30
  # @return [String] the gem version
31
- GCE_VERSION = "3.0.0"
31
+ GCE_VERSION = "3.0.2"
32
32
  end
33
33
  end
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: 3.0.0
4
+ version: 3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Test Kitchen Team