kitchen-azurerm 1.1.0 → 1.5.1

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: c53c5b50e83af16c56722ecbc2baa30b5a28621cc17f4edde82a59b22420812f
4
- data.tar.gz: cd39338fdf0d29d39780e93b6a9fc8c27cd955daf59b6fc79f3be56801c7d891
3
+ metadata.gz: 83ff621acb68f00027da706be0a8cbcc9d1913ea0972a57596180d9d2cadc399
4
+ data.tar.gz: e32b5481b1ca6bec77dbe2f1da1f2be2d4c7236c8d35d6dd676e06979cdd69db
5
5
  SHA512:
6
- metadata.gz: d62cae11a2fa2a679657fc9c81e6b03547802cd7773f6b801b644388beb09b6fe44de2f0d5f2e9a1601cf3eee92b7a2d86e1f29e7dd86b09e3e6445fdceaebd5
7
- data.tar.gz: 8bbccc8d27fef365420257f9a11d89cd8b326cf6e60c97e737c1fe304b14f28ee543793c314e9e638096b606c6ccc64986e7d4db94345d53463981b84eadc931
6
+ metadata.gz: 6dd5a780356dc995c62ebc6f8cd91038b8c02a670af1de28e43090011df9e48d2a96c59702353802b4f9719c3722dba9f83a30af0545305b966df4c7bc7f76c8
7
+ data.tar.gz: 5e69a4e0b62d614c4aab4d86e46a4ab18e4aba6366bdc0f92d6afa8e0e466c1ac57911b4cf1787b4f68294ab674916dbc6b5621a8603f3ab5a00a286f6d131d3
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,9 +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.
715
+
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.
676
717
 
677
718
  ```yaml
678
719
  ---
@@ -686,6 +727,8 @@ driver:
686
727
 
687
728
  * The ```secret_url```, ```vault_name```, and ```vault_resource_group``` parameters can be used to deploy VM with specified key vault certificate.
688
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
+
689
732
  ## Enabling alternative WinRM configurations
690
733
 
691
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
- require "securerandom"
4
- require "azure_mgmt_resources"
5
- require "azure_mgmt_network"
6
- require "base64"
7
- require "sshkey"
8
- require "fileutils"
9
- require "erb"
10
- require "ostruct"
11
- require "json"
12
- require "faraday"
5
+ require "securerandom" unless defined?(SecureRandom)
6
+ module Azure
7
+ autoload :Resources, "azure_mgmt_resources"
8
+ autoload :Network, "azure_mgmt_network"
9
+ end
10
+ require "base64" unless defined?(Base64)
11
+ autoload :SSHKey, "sshkey"
12
+ require "fileutils" unless defined?(FileUtils)
13
+ require "erb" unless defined?(Erb)
14
+ require "ostruct" unless defined?(OpenStruct)
15
+ require "json" unless defined?(JSON)
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
@@ -174,6 +180,10 @@ module Kitchen
174
180
  true
175
181
  end
176
182
 
183
+ default_config(:destroy_explicit_resource_group_tags) do |_config|
184
+ true
185
+ end
186
+
177
187
  default_config(:destroy_resource_group_contents) do |_config|
178
188
  false
179
189
  end
@@ -198,10 +208,18 @@ module Kitchen
198
208
  ENV["AZURE_SUBSCRIPTION_ID"]
199
209
  end
200
210
 
211
+ default_config(:public_ip_sku) do |_config|
212
+ "Basic"
213
+ end
214
+
201
215
  default_config(:azure_api_retries) do |_config|
202
216
  5
203
217
  end
204
218
 
219
+ default_config(:use_fqdn_hostname) do |_config|
220
+ false
221
+ end
222
+
205
223
  def create(state)
206
224
  state = validate_state(state)
207
225
  deployment_parameters = {
@@ -210,7 +228,7 @@ module Kitchen
210
228
  storageAccountType: config[:storage_account_type],
211
229
  bootDiagnosticsEnabled: config[:boot_diagnostics_enabled],
212
230
  newStorageAccountName: "storage#{state[:uuid]}",
213
- adminUsername: state[:username],
231
+ adminUsername: config[:username],
214
232
  dnsNameForPublicIP: "kitchen-#{state[:uuid]}",
215
233
  vmName: state[:vm_name],
216
234
  systemAssignedIdentity: config[:system_assigned_identity],
@@ -221,7 +239,13 @@ module Kitchen
221
239
  }
222
240
 
223
241
  if instance.transport[:ssh_key].nil?
224
- 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"
225
249
  end
226
250
 
227
251
  if config[:subscription_id].to_s == ""
@@ -277,12 +301,9 @@ module Kitchen
277
301
  @resource_management_client = ::Azure::Resources::Profiles::Latest::Mgmt::Client.new(options)
278
302
 
279
303
  # Create Resource Group
280
- resource_group = ::Azure::Resources::Profiles::Latest::Mgmt::Models::ResourceGroup.new
281
- resource_group.location = config[:location]
282
- resource_group.tags = config[:resource_group_tags]
283
304
  begin
284
305
  info "Creating Resource Group: #{state[:azure_resource_group_name]}"
285
- create_resource_group(state[:azure_resource_group_name], resource_group)
306
+ create_resource_group(state[:azure_resource_group_name], get_resource_group)
286
307
  rescue ::MsRestAzure::AzureOperationError => operation_error
287
308
  error operation_error.body
288
309
  raise operation_error
@@ -300,6 +321,9 @@ module Kitchen
300
321
  info "Creating deployment: #{deployment_name}"
301
322
  create_deployment_async(state[:azure_resource_group_name], deployment_name, deployment(deployment_parameters)).value!
302
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
+
303
327
  if File.file?(config[:post_deployment_template])
304
328
  post_deployment_name = "post-deploy-#{state[:uuid]}"
305
329
  info "Creating deployment: #{post_deployment_name}"
@@ -325,6 +349,10 @@ module Kitchen
325
349
  result = get_public_ip(state[:azure_resource_group_name], "publicip")
326
350
  info "IP Address is: #{result.ip_address} [#{result.dns_settings.fqdn}]"
327
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
328
356
  else
329
357
  # Retrieve the internal IP from the resource group:
330
358
  result = get_network_interface(state[:azure_resource_group_name], vmnic.to_s)
@@ -333,15 +361,24 @@ module Kitchen
333
361
  end
334
362
  end
335
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]
336
369
  def existing_state_value?(state, property)
337
370
  state.key?(property) && !state[property].nil?
338
371
  end
339
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.
340
377
  def validate_state(state = {})
341
378
  state[:uuid] = SecureRandom.hex(8) unless existing_state_value?(state, :uuid)
342
379
  state[:server_id] = "vm#{state[:uuid]}" unless existing_state_value?(state, :server_id)
343
380
  state[:azure_resource_group_name] = azure_resource_group_name unless existing_state_value?(state, :azure_resource_group_name)
344
- %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|
345
382
  state[config_element] = config[config_element] unless existing_state_value?(state, config_element)
346
383
  end
347
384
  state.delete(:password) unless instance.transport[:ssh_key].nil?
@@ -522,11 +559,38 @@ module Kitchen
522
559
  end
523
560
 
524
561
  def destroy(state)
525
- 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]
526
565
 
566
+ # Setup our authentication components for the SDK
527
567
  options = Kitchen::Driver::AzureCredentials.new(subscription_id: state[:subscription_id],
528
- environment: state[:azure_environment]).azure_options
568
+ environment: state[:azure_environment]).azure_options
529
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
530
594
  if config[:destroy_resource_group_contents] == true
531
595
  info "Destroying individual resources within the Resource Group."
532
596
  empty_deployment_name = "empty-deploy-#{state[:uuid]}"
@@ -534,25 +598,49 @@ module Kitchen
534
598
  info "Creating deployment: #{empty_deployment_name}"
535
599
  create_deployment_async(state[:azure_resource_group_name], empty_deployment_name, empty_deployment).value!
536
600
  follow_deployment_until_end_state(state[:azure_resource_group_name], empty_deployment_name)
601
+
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
609
+ resource_group = get_resource_group
610
+ resource_group.tags = {}
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
616
+ end
617
+
537
618
  rescue ::MsRestAzure::AzureOperationError => operation_error
538
619
  error operation_error.body
539
620
  raise operation_error
540
621
  end
541
622
  end
623
+
624
+ # Do not remove the explicitly named resource group
542
625
  if config[:destroy_explicit_resource_group] == false && !config[:explicit_resource_group_name].nil?
543
626
  warn 'The "destroy_explicit_resource_group" setting value is set to "false". The resource group will not be deleted.'
544
627
  warn 'Remember to manually destroy resources, or set "destroy_resource_group_contents: true" to save costs!' unless config[:destroy_resource_group_contents] == true
545
- return
628
+ return state
546
629
  end
547
- info "Azure environment: #{state[:azure_environment]}"
630
+
631
+ # Destroy the world
548
632
  begin
549
633
  info "Destroying Resource Group: #{state[:azure_resource_group_name]}"
550
634
  delete_resource_group_async(state[:azure_resource_group_name])
551
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)
552
638
  rescue ::MsRestAzure::AzureOperationError => operation_error
553
639
  error operation_error.body
554
640
  raise operation_error
555
641
  end
642
+
643
+ # Clear state of components
556
644
  state.delete(:server_id)
557
645
  state.delete(:hostname)
558
646
  state.delete(:username)
@@ -652,7 +740,7 @@ module Kitchen
652
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], 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)
653
741
  else
654
742
  info "Using custom vnet: #{config[:vnet_id]}"
655
- 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], 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)
656
744
  end
657
745
  end
658
746
 
@@ -706,6 +794,36 @@ module Kitchen
706
794
  # Wrapper methods for the Azure API calls to retry the calls when getting timeouts.
707
795
  #
708
796
 
797
+ # Create a new resource group object and set the location and tags attributes then return it.
798
+ #
799
+ # @return [::Azure::Resources::Profiles::Latest::Mgmt::Models::ResourceGroup] A new resource group object.
800
+ def get_resource_group
801
+ resource_group = ::Azure::Resources::Profiles::Latest::Mgmt::Models::ResourceGroup.new
802
+ resource_group.location = config[:location]
803
+ resource_group.tags = config[:resource_group_tags]
804
+ resource_group
805
+ end
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
+
709
827
  def create_resource_group(resource_group_name, resource_group)
710
828
  retries = config[:azure_api_retries]
711
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",
@@ -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": {
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.1.0
4
+ version: 1.5.1
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-18 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: '0'
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- requirements:
138
- - - ">="
139
- - !ruby/object:Gem::Version
140
- version: '0'
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.