kitchen-azurerm 1.2.0 → 1.5.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: 8615b3c50c7c88dc0167c2b0daebd1c66c1fec9bd05d1c169223c30fc00a7cc2
4
- data.tar.gz: 769a0df10ad7af7a1215066955eba46717e16358f83ad176df6954d4f2e43d49
3
+ metadata.gz: 20aa37ca60b29d9b0902d8741de326baa5fbe19fde0d37a9874dac2191b97b1f
4
+ data.tar.gz: f219f48b5b966faf7033fe0f78d8dd2f7638c77118c66f8c6bbae7c53e9f939c
5
5
  SHA512:
6
- metadata.gz: 48a2d37a873c8d2b842dc20e0c2e40cc9b349faed29d0c1f9bbc12ccb53097e0df0a06884f29c840b2e2f72a3deef6a0ab2244ef037a9c1aa24397524f756747
7
- data.tar.gz: b3538aa314c217566e22a359655aee67eedb88cff3d2ea2f35e17445db4fe5821b57d5beb183f8ec77ac077ed58f88f275fd011fbdaa162a3b17def168c2c99e
6
+ metadata.gz: 1ca9ed3f8eb461263d65f752299e46aded16a7e9b4fd3b73a06f66bacabd7ad5c7e566be1bfc299ed9abb0514ad386807b713bdf3740969883595a64a6afb7a0
7
+ data.tar.gz: 95988ebe08533122dc27d847cc817e799f07b72e4e13666170d6515bd9b9db5e37d6568722892f30388713ce9227653e04b72899c8d7f8d657fc83f078ca12b9
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # kitchen-azurerm
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/kitchen-azurerm.svg)](http://badge.fury.io/rb/kitchen-azurerm) ![CI](https://github.com/test-kitchen/kitchen-azurerm/workflows/CI/badge.svg?branch=master)
3
+ [![Gem Version](https://badge.fury.io/rb/kitchen-azurerm.svg)](https://badge.fury.io/rb/kitchen-azurerm)
4
+ ![CI](https://github.com/test-kitchen/kitchen-azurerm/workflows/CI/badge.svg?branch=master)
4
5
 
5
6
  **kitchen-azurerm** is a driver for the popular test harness [Test Kitchen](http://kitchen.ci) that allows Microsoft Azure resources to be provisioned before testing. This driver uses the new Microsoft Azure Resource Management REST API via the [azure-sdk-for-ruby](https://github.com/azure/azure-sdk-for-ruby).
6
7
 
@@ -259,7 +260,45 @@ suites:
259
260
  attributes:
260
261
  ```
261
262
 
262
- ### .kitchen.yml example 5 - deploy VM to existing virtual network/subnet (use for ExpressRoute/VPN scenarios) with Private Managed Image
263
+ ### .kitchen.yml example 5 - deploy VM to existing virtual network/subnet with a Standard SKU public IP (use for ExpressRoute/VPN scenarios)
264
+
265
+ The following example introduces the ```vnet_id``` and ```subnet_id``` properties under "driver" in the configuration file. This can be applied at the top level, or per platform.
266
+ You can use this capability to create the VM on an existing virtual network and subnet created in a different resource group.
267
+
268
+ This enables scenarios that require a Standard SKU public IP resource, for example when a NAT gateway is present on the target subnet.
269
+
270
+
271
+ ```yaml
272
+ ---
273
+ driver:
274
+ name: azurerm
275
+ subscription_id: 'your-azure-subscription-id-here'
276
+ location: 'West Europe'
277
+ machine_size: 'Standard_D1'
278
+
279
+ transport:
280
+ ssh_key: ~/.ssh/id_kitchen-azurerm
281
+
282
+ provisioner:
283
+ name: chef_zero
284
+
285
+ platforms:
286
+ - name: ubuntu-1404
287
+ driver:
288
+ image_urn: Canonical:UbuntuServer:14.04.4-LTS:latest
289
+ vnet_id: /subscriptions/b6e7eee9-YOUR-GUID-HERE-03ab624df016/resourceGroups/pendrica-infrastructure/providers/Microsoft.Network/virtualNetworks/pendrica-arm-vnet
290
+ subnet_id: subnet-10.1.0
291
+ public_ip: true
292
+ public_ip_sku: Standard
293
+
294
+ suites:
295
+ - name: default
296
+ run_list:
297
+ - recipe[kitchen-azurerm-demo::default]
298
+ attributes:
299
+ ```
300
+
301
+ ### .kitchen.yml example 6 - deploy VM to existing virtual network/subnet (use for ExpressRoute/VPN scenarios) with Private Managed Image
263
302
 
264
303
  This example is the same as above, but uses a private managed image to provision the vm.
265
304
 
@@ -294,7 +333,7 @@ suites:
294
333
  attributes:
295
334
  ```
296
335
 
297
- ### .kitchen.yml example 6 - deploy VM to existing virtual network/subnet (use for ExpressRoute/VPN scenarios) with Private Classic OS Image
336
+ ### .kitchen.yml example 7 - deploy VM to existing virtual network/subnet (use for ExpressRoute/VPN scenarios) with Private Classic OS Image
298
337
 
299
338
  This example a classic Custom VM Image (aka a VHD file) is used. As the Image VHD must be in the same storage account then the disk of the instance, the os disk is created in an existing image account.
300
339
 
@@ -337,7 +376,7 @@ suites:
337
376
  attributes:
338
377
  ```
339
378
 
340
- ### .kitchen.yml example 7 - deploy VM to existing virtual network/subnet (use for ExpressRoute/VPN scenarios) with Private Classic OS Image and providing custom data and extra large os disk
379
+ ### .kitchen.yml example 8 - deploy VM to existing virtual network/subnet (use for ExpressRoute/VPN scenarios) with Private Classic OS Image and providing custom data and extra large os disk
341
380
 
342
381
  This is the same as above, but uses custom data to customize the instance.
343
382
 
@@ -382,7 +421,7 @@ suites:
382
421
  attributes:
383
422
  ```
384
423
 
385
- ### .kitchen.yml example 8 - Windows 2016 VM with additional data disks
424
+ ### .kitchen.yml example 9 - Windows 2016 VM with additional data disks
386
425
 
387
426
  This example demonstrates how to add 3 additional Managed data disks to a Windows Server 2016 VM. Not supported with legacy (pre-managed disk) storage accounts.
388
427
 
@@ -419,7 +458,7 @@ suites:
419
458
  attributes:
420
459
  ```
421
460
 
422
- ### .kitchen.yml example 9 - "post-deployment" ARM template with MSI authentication
461
+ ### .kitchen.yml example 10 - "post-deployment" ARM template with MSI authentication
423
462
 
424
463
  The following example introduces the ```post_deployment_template``` and ```post_deployment_parameters``` properties in the configuration file.
425
464
  You can use this capability to execute an ARM template containing Azure resources to provision after the system under test is created.
@@ -505,7 +544,7 @@ Example postdeploy.json to enable MSI extention on VM:
505
544
  }
506
545
  ```
507
546
 
508
- ### .kitchen.yml example 10 - Enabling Managed Service Identities
547
+ ### .kitchen.yml example 11 - Enabling Managed Service Identities
509
548
 
510
549
  This example demonstrates how to enable a System Assigned Identity and User Assigned Identities on a Kitchen VM.
511
550
  Any combination of System and User assigned identities may be enabled, and multiple User Assigned Identities can be supplied.
@@ -541,7 +580,7 @@ suites:
541
580
  attributes:
542
581
  ```
543
582
 
544
- ### .kitchen.yml example 11 - deploy VM with key vault certificate
583
+ ### .kitchen.yml example 12 - deploy VM with key vault certificate
545
584
 
546
585
  This following example introduces ```secret_url```, ```vault_name```, and ```vault_resource_group``` properties under "driver" in the configuration file. You can use this capability to create a VM with a specified key vault certificate.
547
586
 
@@ -670,11 +709,11 @@ info: vm image list command OK
670
709
 
671
710
  * The ```azure_resource_group_prefix``` and ```azure_resource_group_suffix``` can be used to further disambiguate Azure resource group names created by the driver.
672
711
 
673
- * The ```explicit_resource_group_name``` and ```destroy_explicit_resource_group``` (default: "true") parameters can be used in scenarios where you are provided a pre-created Resource Group. Example usage: ```explicit_resource_group_name: kitchen-<%= ENV["USERNAME"] %>```
712
+ * The ```explicit_resource_group_name``` and ```destroy_explicit_resource_group``` (default: "true") parameters can be used in scenarios where you are provided a pre-created Resource Group. Example usage: ```explicit_resource_group_name: kitchen-<%= ENV["USERNAME"] %>```. The ```destroy_explicit_resource_group``` option can now be used after using the ```destroy_resource_group_contents``` option creates an empty resource group to destroy the resource group previously created.
674
713
 
675
- * The ```destroy_resource_group_contents``` (default: "false") parameter can be used when you want to destroy the resources within a resource group without destroying the resource group itself. For example, the following configuration options used in combination would use an existing resource group (or create one if it doesn't exist) and will destroy the contents of the resource group in the ```kitchen destroy``` phase.
714
+ * The ```destroy_resource_group_contents``` (default: "false") parameter can be used when you want to destroy the resources within a resource group without destroying the resource group itself. For example, the following configuration options used in combination would use an existing resource group (or create one if it doesn't exist) and will destroy the contents of the resource group in the ```kitchen destroy``` phase. If you wish to destroy the empty resource group created after you empty the resource group with this flag you can now set the ```destroy_explicit_resource_group``` to "true" to destroy the empty resource group.
676
715
 
677
- * The ```destroy_explicit_resource_group_tags``` (default: "true") parameter can be used when you want to remove tags associated with an explicit resource group. The default setting is set to `true` to remain consistent with previous behavior. This should be used in combination with an explicitly named resource group and will be honored during the ```kitchen destroy``` phase.
716
+ * The ```destroy_explicit_resource_group_tags``` (default: "true") parameter can be used when you want to remove tags associated with an explicit resource group. The default setting is set to "true" to remain consistent with previous behavior. This should be used in combination with an ```explicit_resource_group_name``` and will be honored during the ```kitchen destroy``` phase.
678
717
 
679
718
  ```yaml
680
719
  ---
@@ -688,6 +727,8 @@ driver:
688
727
 
689
728
  * The ```secret_url```, ```vault_name```, and ```vault_resource_group``` parameters can be used to deploy VM with specified key vault certificate.
690
729
 
730
+ * The ```use_fqdn_hostname``` (default: "false") parameter can be used to determine how kitchen communicates with the Virtual Machine. When true, Kitchen will use the FQDN that is assigned to the Virtual Machine. When false, kitchen will use the public IP address of the machine. This may overcome issues with Corporate firewalls or VPNs blocking Public IP addresses.
731
+
691
732
  ## Enabling alternative WinRM configurations
692
733
 
693
734
  * By default on Windows machines, a PowerShell script runs that enables WinRM over the SSL transport, for Basic, Negotiate and CredSSP connections. To supply your own PowerShell script (e.g. to enable HTTP), use the `winrm_powershell_script` parameter. Windows 2008 R2 example:
@@ -1,5 +1,6 @@
1
1
  require "inifile"
2
2
  require "kitchen/logging"
3
+ autoload :MsRest, "ms_rest"
3
4
 
4
5
  module Kitchen
5
6
  module Driver
@@ -60,7 +61,7 @@ module Kitchen
60
61
  if File.file?(config_path)
61
62
  IniFile.load(config_path)
62
63
  else
63
- warn "#{config_path} was not found or not accessible. Will attempt to use Managed Identity."
64
+ warn "#{config_path} was not found or not accessible."
64
65
  {}
65
66
  end
66
67
  end
@@ -71,7 +72,7 @@ module Kitchen
71
72
  end
72
73
 
73
74
  def tenant_id!
74
- tenant_id || raise("Must provide tenant id. Use AZURE_TENANT_ID environment variable or set it in credentials file (#{config_path})")
75
+ tenant_id || warn("(#{config_path}) does not contain tenant_id neither is the AZURE_TENANT_ID environment variable set.")
75
76
  end
76
77
 
77
78
  def tenant_id
@@ -86,13 +87,37 @@ module Kitchen
86
87
  ENV["AZURE_CLIENT_SECRET"] || credentials_property("client_secret")
87
88
  end
88
89
 
90
+ # Retrieve a token based upon the preferred authentication method.
91
+ #
92
+ # @return [::MsRest::TokenProvider] A new token provider object.
89
93
  def token_provider
90
- if client_id && client_secret
94
+ # Login with a credentials file or setting the environment variables
95
+ #
96
+ # Typically used with a service principal.
97
+ #
98
+ # SPN with client_id, client_secret and tenant_id
99
+ if client_id && client_secret && tenant_id
91
100
  ::MsRestAzure::ApplicationTokenProvider.new(tenant_id, client_id, client_secret, ad_settings)
92
- elsif client_id
101
+ # Login with a Managed Service Identity.
102
+ #
103
+ # Typically used with a Managed Service Identity when you have a particular object registered in a tenant.
104
+ #
105
+ # MSI with client_id and tenant_id (aka User Assigned Identity).
106
+ elsif client_id && tenant_id
93
107
  ::MsRestAzure::MSITokenProvider.new(50342, ad_settings, { client_id: client_id })
94
- else
108
+ # Default approach to inheriting existing object permissions (application or device this code is running on).
109
+ #
110
+ # Typically used when you want to inherit the permissions of the system you're running on that are in a tenant.
111
+ #
112
+ # MSI with just tenant_id (aka System Assigned Identity).
113
+ elsif tenant_id
95
114
  ::MsRestAzure::MSITokenProvider.new(50342, ad_settings)
115
+ # Login using the Azure CLI
116
+ #
117
+ # Typically used when you want to rely upon `az login` as your preferred authentication method.
118
+ else
119
+ warn("Using tenant id set through `az login`.")
120
+ ::MsRestAzure::AzureCliTokenProvider.new(ad_settings)
96
121
  end
97
122
  end
98
123
 
@@ -1,21 +1,27 @@
1
1
  require "kitchen"
2
+
3
+ autoload :MsRestAzure, "ms_rest_azure"
2
4
  require_relative "azure_credentials"
3
5
  require "securerandom" unless defined?(SecureRandom)
4
- require "azure_mgmt_resources"
5
- require "azure_mgmt_network"
6
+ module Azure
7
+ autoload :Resources, "azure_mgmt_resources"
8
+ autoload :Network, "azure_mgmt_network"
9
+ end
6
10
  require "base64" unless defined?(Base64)
7
- require "sshkey"
11
+ autoload :SSHKey, "sshkey"
8
12
  require "fileutils" unless defined?(FileUtils)
9
13
  require "erb" unless defined?(Erb)
10
14
  require "ostruct" unless defined?(OpenStruct)
11
15
  require "json" unless defined?(JSON)
12
- require "faraday" unless defined?(Faraday)
16
+ autoload :Faraday, "faraday"
13
17
 
14
18
  module Kitchen
15
19
  module Driver
16
20
  #
17
21
  # Azurerm
22
+ # Create a new resource group object and set the location and tags attributes then return it.
18
23
  #
24
+ # @return [::Azure::Resources::Profiles::Latest::Mgmt::Models::ResourceGroup] A new resource group object.
19
25
  class Azurerm < Kitchen::Driver::Base
20
26
  attr_accessor :resource_management_client
21
27
  attr_accessor :network_management_client
@@ -202,10 +208,18 @@ module Kitchen
202
208
  ENV["AZURE_SUBSCRIPTION_ID"]
203
209
  end
204
210
 
211
+ default_config(:public_ip_sku) do |_config|
212
+ "Basic"
213
+ end
214
+
205
215
  default_config(:azure_api_retries) do |_config|
206
216
  5
207
217
  end
208
218
 
219
+ default_config(:use_fqdn_hostname) do |_config|
220
+ false
221
+ end
222
+
209
223
  def create(state)
210
224
  state = validate_state(state)
211
225
  deployment_parameters = {
@@ -214,7 +228,7 @@ module Kitchen
214
228
  storageAccountType: config[:storage_account_type],
215
229
  bootDiagnosticsEnabled: config[:boot_diagnostics_enabled],
216
230
  newStorageAccountName: "storage#{state[:uuid]}",
217
- adminUsername: state[:username],
231
+ adminUsername: config[:username],
218
232
  dnsNameForPublicIP: "kitchen-#{state[:uuid]}",
219
233
  vmName: state[:vm_name],
220
234
  systemAssignedIdentity: config[:system_assigned_identity],
@@ -225,7 +239,13 @@ module Kitchen
225
239
  }
226
240
 
227
241
  if instance.transport[:ssh_key].nil?
228
- deployment_parameters["adminPassword"] = state[:password]
242
+ deployment_parameters[:adminPassword] = config[:password]
243
+ end
244
+
245
+ deployment_parameters[:publicIPSKU] = config[:public_ip_sku]
246
+
247
+ if config[:public_ip_sku] == "Standard"
248
+ deployment_parameters[:publicIPAddressType] = "Static"
229
249
  end
230
250
 
231
251
  if config[:subscription_id].to_s == ""
@@ -301,6 +321,9 @@ module Kitchen
301
321
  info "Creating deployment: #{deployment_name}"
302
322
  create_deployment_async(state[:azure_resource_group_name], deployment_name, deployment(deployment_parameters)).value!
303
323
  follow_deployment_until_end_state(state[:azure_resource_group_name], deployment_name)
324
+ state[:username] = deployment_parameters[:adminUsername] unless existing_state_value?(state, :username)
325
+ state[:password] = deployment_parameters[:adminPassword] unless existing_state_value?(state, :password) && instance.transport[:ssh_key].nil?
326
+
304
327
  if File.file?(config[:post_deployment_template])
305
328
  post_deployment_name = "post-deploy-#{state[:uuid]}"
306
329
  info "Creating deployment: #{post_deployment_name}"
@@ -326,6 +349,10 @@ module Kitchen
326
349
  result = get_public_ip(state[:azure_resource_group_name], "publicip")
327
350
  info "IP Address is: #{result.ip_address} [#{result.dns_settings.fqdn}]"
328
351
  state[:hostname] = result.ip_address
352
+ if config[:use_fqdn_hostname]
353
+ info "Using FQDN to communicate instead of IP"
354
+ state[:hostname] = result.dns_settings.fqdn
355
+ end
329
356
  else
330
357
  # Retrieve the internal IP from the resource group:
331
358
  result = get_network_interface(state[:azure_resource_group_name], vmnic.to_s)
@@ -334,15 +361,24 @@ module Kitchen
334
361
  end
335
362
  end
336
363
 
364
+ # Return a True of False if the state is already stored for a particular property.
365
+ #
366
+ # @param [Hash] Hash of existing state values.
367
+ # @param [String] A property to check
368
+ # @return [Boolean]
337
369
  def existing_state_value?(state, property)
338
370
  state.key?(property) && !state[property].nil?
339
371
  end
340
372
 
373
+ # Leverage existing state values or bring state into existence from a configuration file.
374
+ #
375
+ # @param [Hash] Existing Hash of state values.
376
+ # @return [Hash] Updated Hash of state values.
341
377
  def validate_state(state = {})
342
378
  state[:uuid] = SecureRandom.hex(8) unless existing_state_value?(state, :uuid)
343
379
  state[:server_id] = "vm#{state[:uuid]}" unless existing_state_value?(state, :server_id)
344
380
  state[:azure_resource_group_name] = azure_resource_group_name unless existing_state_value?(state, :azure_resource_group_name)
345
- %i{subscription_id username password vm_name azure_environment use_managed_disks}.each do |config_element|
381
+ %i{subscription_id vm_name azure_environment use_managed_disks}.each do |config_element|
346
382
  state[config_element] = config[config_element] unless existing_state_value?(state, config_element)
347
383
  end
348
384
  state.delete(:password) unless instance.transport[:ssh_key].nil?
@@ -523,11 +559,38 @@ module Kitchen
523
559
  end
524
560
 
525
561
  def destroy(state)
526
- return if state[:server_id].nil?
562
+ # TODO: We have some not so fun state issues we need to clean up
563
+ state[:azure_environment] = config[:azure_environment] unless state[:azure_environment]
564
+ state[:subscription_id] = config[:subscription_id] unless state[:subscription_id]
527
565
 
566
+ # Setup our authentication components for the SDK
528
567
  options = Kitchen::Driver::AzureCredentials.new(subscription_id: state[:subscription_id],
529
- environment: state[:azure_environment]).azure_options
568
+ environment: state[:azure_environment]).azure_options
530
569
  @resource_management_client = ::Azure::Resources::Profiles::Latest::Mgmt::Client.new(options)
570
+
571
+ # If we don't have any instances, let's check to see if the user wants to delete a resource group and if so let's delete!
572
+ if state[:server_id].nil? && state[:azure_resource_group_name].nil? && !config[:explicit_resource_group_name].nil? && config[:destroy_explicit_resource_group]
573
+ if resource_group_exists?(config[:explicit_resource_group_name])
574
+ info "This instance doesn't exist but you asked to delete the resource group."
575
+ begin
576
+ info "Destroying Resource Group: #{config[:explicit_resource_group_name]}"
577
+ delete_resource_group_async(config[:explicit_resource_group_name])
578
+ info "Destroy operation accepted and will continue in the background."
579
+ return
580
+ rescue ::MsRestAzure::AzureOperationError => operation_error
581
+ error operation_error.body
582
+ raise operation_error
583
+ end
584
+ end
585
+ end
586
+
587
+ # Our working environment
588
+ info "Azure environment: #{state[:azure_environment]}"
589
+
590
+ # Skip if we don't have any instances
591
+ return if state[:server_id].nil?
592
+
593
+ # Destroy resource group contents
531
594
  if config[:destroy_resource_group_contents] == true
532
595
  info "Destroying individual resources within the Resource Group."
533
596
  empty_deployment_name = "empty-deploy-#{state[:uuid]}"
@@ -536,32 +599,20 @@ module Kitchen
536
599
  create_deployment_async(state[:azure_resource_group_name], empty_deployment_name, empty_deployment).value!
537
600
  follow_deployment_until_end_state(state[:azure_resource_group_name], empty_deployment_name)
538
601
 
539
- # Maintain tags on the resource group
540
- if config[:destroy_explicit_resource_group_tags] == false
541
- warn 'The "destroy_explicit_resource_group_tags" setting value is set to "false". The tags on the resource group will NOT be removed.'
542
- # NOTE: We are using the internal wrapper function create_resource_group() which wraps the API
543
- # method of create_or_update().
544
- begin
545
- create_resource_group(state[:azure_resource_group_name], get_resource_group)
546
- rescue ::MsRestAzure::AzureOperationError => operation_error
547
- error operation_error.body
548
- raise operation_error
549
- end
550
- end
551
-
552
- # Corner case where we want to use kitchen to remove the tags
553
- if config[:destroy_explicit_resource_group_tags] == true
554
- warn 'The "destroy_explicit_resource_group_tags" setting value is set to "true". The tags on the resource group will be removed.'
555
- # NOTE: We are using the internal wrapper function create_resource_group() which wraps the API
556
- # method of create_or_update().
602
+ # NOTE: We are using the internal wrapper function create_resource_group() which wraps the API
603
+ # method of create_or_update()
604
+ begin
605
+ # Maintain tags on the resource group
606
+ create_resource_group(state[:azure_resource_group_name], get_resource_group) unless config[:destroy_explicit_resource_group_tags] == true
607
+ warn 'The "destroy_explicit_resource_group_tags" setting value is set to "false". The tags on the resource group will NOT be removed.' unless config[:destroy_explicit_resource_group_tags] == true
608
+ # Corner case where we want to use kitchen to remove the tags
557
609
  resource_group = get_resource_group
558
610
  resource_group.tags = {}
559
- begin
560
- create_resource_group(state[:azure_resource_group_name], resource_group)
561
- rescue ::MsRestAzure::AzureOperationError => operation_error
562
- error operation_error.body
563
- raise operation_error
564
- end
611
+ create_resource_group(state[:azure_resource_group_name], resource_group) unless config[:destroy_explicit_resource_group_tags] == false
612
+ warn 'The "destroy_explicit_resource_group_tags" setting value is set to "true". The tags on the resource group will be removed.' unless config[:destroy_explicit_resource_group_tags] == false
613
+ rescue ::MsRestAzure::AzureOperationError => operation_error
614
+ error operation_error.body
615
+ raise operation_error
565
616
  end
566
617
 
567
618
  rescue ::MsRestAzure::AzureOperationError => operation_error
@@ -569,20 +620,27 @@ module Kitchen
569
620
  raise operation_error
570
621
  end
571
622
  end
623
+
624
+ # Do not remove the explicitly named resource group
572
625
  if config[:destroy_explicit_resource_group] == false && !config[:explicit_resource_group_name].nil?
573
626
  warn 'The "destroy_explicit_resource_group" setting value is set to "false". The resource group will not be deleted.'
574
627
  warn 'Remember to manually destroy resources, or set "destroy_resource_group_contents: true" to save costs!' unless config[:destroy_resource_group_contents] == true
575
- return
628
+ return state
576
629
  end
577
- info "Azure environment: #{state[:azure_environment]}"
630
+
631
+ # Destroy the world
578
632
  begin
579
633
  info "Destroying Resource Group: #{state[:azure_resource_group_name]}"
580
634
  delete_resource_group_async(state[:azure_resource_group_name])
581
635
  info "Destroy operation accepted and will continue in the background."
636
+ # Remove resource group name from driver state
637
+ state.delete(:azure_resource_group_name)
582
638
  rescue ::MsRestAzure::AzureOperationError => operation_error
583
639
  error operation_error.body
584
640
  raise operation_error
585
641
  end
642
+
643
+ # Clear state of components
586
644
  state.delete(:server_id)
587
645
  state.delete(:hostname)
588
646
  state.delete(:username)
@@ -679,10 +737,10 @@ module Kitchen
679
737
 
680
738
  def virtual_machine_deployment_template
681
739
  if config[:vnet_id] == ""
682
- virtual_machine_deployment_template_file("public.erb", vm_tags: vm_tag_string(config[:vm_tags]), use_managed_disks: config[:use_managed_disks], image_url: config[:image_url], existing_storage_account_blob_url: config[:existing_storage_account_blob_url], image_id: config[:image_id], existing_storage_account_container: config[:existing_storage_account_container], custom_data: config[:custom_data], os_disk_size_gb: config[:os_disk_size_gb], data_disks_for_vm_json: data_disks_for_vm_json, use_ephemeral_osdisk: config[:use_ephemeral_osdisk], ssh_key: instance.transport[:ssh_key], plan_json: plan_json)
740
+ virtual_machine_deployment_template_file("public.erb", vm_tags: vm_tag_string(config[:vm_tags]), use_managed_disks: config[:use_managed_disks], image_url: config[:image_url], storage_account_type: config[:storage_account_type], existing_storage_account_blob_url: config[:existing_storage_account_blob_url], image_id: config[:image_id], existing_storage_account_container: config[:existing_storage_account_container], custom_data: config[:custom_data], os_disk_size_gb: config[:os_disk_size_gb], data_disks_for_vm_json: data_disks_for_vm_json, use_ephemeral_osdisk: config[:use_ephemeral_osdisk], ssh_key: instance.transport[:ssh_key], plan_json: plan_json)
683
741
  else
684
742
  info "Using custom vnet: #{config[:vnet_id]}"
685
- virtual_machine_deployment_template_file("internal.erb", vnet_id: config[:vnet_id], subnet_id: config[:subnet_id], public_ip: config[:public_ip], vm_tags: vm_tag_string(config[:vm_tags]), use_managed_disks: config[:use_managed_disks], image_url: config[:image_url], existing_storage_account_blob_url: config[:existing_storage_account_blob_url], image_id: config[:image_id], existing_storage_account_container: config[:existing_storage_account_container], custom_data: config[:custom_data], os_disk_size_gb: config[:os_disk_size_gb], data_disks_for_vm_json: data_disks_for_vm_json, use_ephemeral_osdisk: config[:use_ephemeral_osdisk], ssh_key: instance.transport[:ssh_key], plan_json: plan_json)
743
+ virtual_machine_deployment_template_file("internal.erb", vnet_id: config[:vnet_id], subnet_id: config[:subnet_id], public_ip: config[:public_ip], vm_tags: vm_tag_string(config[:vm_tags]), use_managed_disks: config[:use_managed_disks], image_url: config[:image_url], storage_account_type: config[:storage_account_type], existing_storage_account_blob_url: config[:existing_storage_account_blob_url], image_id: config[:image_id], existing_storage_account_container: config[:existing_storage_account_container], custom_data: config[:custom_data], os_disk_size_gb: config[:os_disk_size_gb], data_disks_for_vm_json: data_disks_for_vm_json, use_ephemeral_osdisk: config[:use_ephemeral_osdisk], ssh_key: instance.transport[:ssh_key], public_ip_sku: config[:public_ip_sku], plan_json: plan_json)
686
744
  end
687
745
  end
688
746
 
@@ -746,6 +804,26 @@ module Kitchen
746
804
  resource_group
747
805
  end
748
806
 
807
+ # Checks whether a resource group exists.
808
+ #
809
+ # @param resource_group_name [String] The name of the resource group to check.
810
+ # The name is case insensitive.
811
+ #
812
+ # @return [Boolean] operation results.
813
+ #
814
+ def resource_group_exists?(resource_group_name)
815
+ retries = config[:azure_api_retries]
816
+ begin
817
+ resource_management_client.resource_groups.check_existence(resource_group_name)
818
+ rescue Faraday::TimeoutError, Faraday::ClientError => exception
819
+ send_exception_message(exception, "while checking if resource group '#{resource_group_name}' exists. #{retries} retries left.")
820
+ raise if retries == 0
821
+
822
+ retries -= 1
823
+ retry
824
+ end
825
+ end
826
+
749
827
  def create_resource_group(resource_group_name, resource_group)
750
828
  retries = config[:azure_api_retries]
751
829
  begin
@@ -40,6 +40,22 @@
40
40
  "description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
41
41
  }
42
42
  },
43
+ <%- if public_ip_sku %>
44
+ "publicIPSKU": {
45
+ "type": "string",
46
+ "defaultValue": "Standard",
47
+ "metadata": {
48
+ "description": "SKU name for the Public IP used to access the Virtual Machine."
49
+ }
50
+ },
51
+ "publicIPAddressType": {
52
+ "type": "string",
53
+ "defaultValue": "Dynamic",
54
+ "metadata": {
55
+ "description": "SKU name for the Public IP used to access the Virtual Machine."
56
+ }
57
+ },
58
+ <%- end %>
43
59
  <%- unless os_disk_size_gb.to_s.empty? -%>
44
60
  "osDiskSizeGb": {
45
61
  "type": "int",
@@ -165,7 +181,7 @@
165
181
  },
166
182
  "storageAccountType": {
167
183
  "type": "string",
168
- "defaultValue": "Standard_LRS",
184
+ "defaultValue": "<%= storage_account_type %>",
169
185
  "metadata": {
170
186
  "description": "The type of storage to use (e.g. Standard_LRS or Premium_LRS)."
171
187
  }
@@ -201,7 +217,6 @@
201
217
  "subnetPrefix": "10.0.0.0/24",
202
218
  "storageAccountType": "[parameters('storageAccountType')]",
203
219
  "publicIPAddressName": "publicip",
204
- "publicIPAddressType": "Dynamic",
205
220
  "vmStorageAccountContainerName": "vhds",
206
221
  "vmName": "[parameters('vmName')]",
207
222
  "vmSize": "[parameters('vmSize')]",
@@ -242,12 +257,15 @@
242
257
  <%- end -%>
243
258
  <%- if public_ip -%>
244
259
  {
245
- "apiVersion": "2015-05-01-preview",
260
+ "apiVersion": "2017-08-01",
246
261
  "type": "Microsoft.Network/publicIPAddresses",
247
262
  "name": "[variables('publicIPAddressName')]",
248
263
  "location": "[variables('location')]",
264
+ "sku": {
265
+ "name": "[parameters('publicIPSKU')]"
266
+ },
249
267
  "properties": {
250
- "publicIPAllocationMethod": "[variables('publicIPAddressType')]",
268
+ "publicIPAllocationMethod": "[parameters('publicIPAddressType')]",
251
269
  "dnsSettings": {
252
270
  "domainNameLabel": "[parameters('dnsNameForPublicIP')]"
253
271
  }
@@ -343,12 +361,12 @@
343
361
  },
344
362
  <%- end -%>
345
363
  <%- if use_ephemeral_osdisk -%>
346
- "osDisk": {
347
- "diffDiskSettings": {
348
- "option": "Local"
349
- },
350
- "caching": "ReadOnly",
351
- "createOption": "FromImage"
364
+ "osDisk": {
365
+ "diffDiskSettings": {
366
+ "option": "Local"
367
+ },
368
+ "caching": "ReadOnly",
369
+ "createOption": "FromImage"
352
370
  }
353
371
  <%- elsif use_managed_disks -%>
354
372
  "osDisk": {
@@ -356,6 +374,9 @@
356
374
  <%- unless os_disk_size_gb.to_s.empty? -%>
357
375
  "diskSizeGB": "[parameters('osDiskSizeGB')]",
358
376
  <%- end -%>
377
+ "managedDisk": {
378
+ "storageAccountType": "[parameters('storageAccountType')]"
379
+ },
359
380
  "createOption": "FromImage"
360
381
  }
361
382
  <%- else -%>
data/templates/public.erb CHANGED
@@ -165,7 +165,7 @@
165
165
  },
166
166
  "storageAccountType": {
167
167
  "type": "string",
168
- "defaultValue": "Standard_LRS",
168
+ "defaultValue": "<%= storage_account_type %>",
169
169
  "metadata": {
170
170
  "description": "The type of storage to use (e.g. Standard_LRS or Premium_LRS)."
171
171
  }
@@ -375,6 +375,9 @@
375
375
  <%- unless os_disk_size_gb.to_s.empty? -%>
376
376
  "diskSizeGB": "[parameters('osDiskSizeGB')]",
377
377
  <%- end -%>
378
+ "managedDisk": {
379
+ "storageAccountType": "[parameters('storageAccountType')]"
380
+ },
378
381
  "createOption": "FromImage"
379
382
  }
380
383
  <%- else -%>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-azurerm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stuart Preston
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-20 00:00:00.000000000 Z
11
+ date: 2021-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: azure_mgmt_network
@@ -110,90 +110,6 @@ dependencies:
110
110
  - - "<"
111
111
  - !ruby/object:Gem::Version
112
112
  version: '3.0'
113
- - !ruby/object:Gem::Dependency
114
- name: rake
115
- requirement: !ruby/object:Gem::Requirement
116
- requirements:
117
- - - ">="
118
- - !ruby/object:Gem::Version
119
- version: '11.0'
120
- type: :development
121
- prerelease: false
122
- version_requirements: !ruby/object:Gem::Requirement
123
- requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- version: '11.0'
127
- - !ruby/object:Gem::Dependency
128
- name: chefstyle
129
- requirement: !ruby/object:Gem::Requirement
130
- requirements:
131
- - - '='
132
- - !ruby/object:Gem::Version
133
- version: 1.2.1
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- requirements:
138
- - - '='
139
- - !ruby/object:Gem::Version
140
- version: 1.2.1
141
- - !ruby/object:Gem::Dependency
142
- name: rspec
143
- requirement: !ruby/object:Gem::Requirement
144
- requirements:
145
- - - "~>"
146
- - !ruby/object:Gem::Version
147
- version: '3.5'
148
- type: :development
149
- prerelease: false
150
- version_requirements: !ruby/object:Gem::Requirement
151
- requirements:
152
- - - "~>"
153
- - !ruby/object:Gem::Version
154
- version: '3.5'
155
- - !ruby/object:Gem::Dependency
156
- name: rspec-mocks
157
- requirement: !ruby/object:Gem::Requirement
158
- requirements:
159
- - - "~>"
160
- - !ruby/object:Gem::Version
161
- version: '3.5'
162
- type: :development
163
- prerelease: false
164
- version_requirements: !ruby/object:Gem::Requirement
165
- requirements:
166
- - - "~>"
167
- - !ruby/object:Gem::Version
168
- version: '3.5'
169
- - !ruby/object:Gem::Dependency
170
- name: rspec-expectations
171
- requirement: !ruby/object:Gem::Requirement
172
- requirements:
173
- - - "~>"
174
- - !ruby/object:Gem::Version
175
- version: '3.5'
176
- type: :development
177
- prerelease: false
178
- version_requirements: !ruby/object:Gem::Requirement
179
- requirements:
180
- - - "~>"
181
- - !ruby/object:Gem::Version
182
- version: '3.5'
183
- - !ruby/object:Gem::Dependency
184
- name: rspec-its
185
- requirement: !ruby/object:Gem::Requirement
186
- requirements:
187
- - - "~>"
188
- - !ruby/object:Gem::Version
189
- version: 1.3.0
190
- type: :development
191
- prerelease: false
192
- version_requirements: !ruby/object:Gem::Requirement
193
- requirements:
194
- - - "~>"
195
- - !ruby/object:Gem::Version
196
- version: 1.3.0
197
113
  description: Test Kitchen driver for the Microsoft Azure Resource Manager (ARM) API
198
114
  email:
199
115
  - stuart@chef.io
@@ -220,14 +136,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
220
136
  requirements:
221
137
  - - ">="
222
138
  - !ruby/object:Gem::Version
223
- version: '0'
139
+ version: '2.5'
224
140
  required_rubygems_version: !ruby/object:Gem::Requirement
225
141
  requirements:
226
142
  - - ">="
227
143
  - !ruby/object:Gem::Version
228
144
  version: '0'
229
145
  requirements: []
230
- rubygems_version: 3.1.2
146
+ rubygems_version: 3.1.4
231
147
  signing_key:
232
148
  specification_version: 4
233
149
  summary: Test Kitchen driver for Azure Resource Manager.