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 +4 -4
- data/README.md +53 -10
- data/lib/kitchen/driver/azure_credentials.rb +30 -5
- data/lib/kitchen/driver/azurerm.rb +140 -22
- data/templates/internal.erb +27 -9
- metadata +4 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83ff621acb68f00027da706be0a8cbcc9d1913ea0972a57596180d9d2cadc399
|
4
|
+
data.tar.gz: e32b5481b1ca6bec77dbe2f1da1f2be2d4c7236c8d35d6dd676e06979cdd69db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6dd5a780356dc995c62ebc6f8cd91038b8c02a670af1de28e43090011df9e48d2a96c59702353802b4f9719c3722dba9f83a30af0545305b966df4c7bc7f76c8
|
7
|
+
data.tar.gz: 5e69a4e0b62d614c4aab4d86e46a4ab18e4aba6366bdc0f92d6afa8e0e466c1ac57911b4cf1787b4f68294ab674916dbc6b5621a8603f3ab5a00a286f6d131d3
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# kitchen-azurerm
|
2
2
|
|
3
|
-
[](
|
3
|
+
[](https://badge.fury.io/rb/kitchen-azurerm)
|
4
|
+

|
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)
|
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
|
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
|
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
|
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
|
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
|
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
|
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.
|
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 ||
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
require "
|
9
|
-
|
10
|
-
require "
|
11
|
-
require "
|
12
|
-
require "
|
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:
|
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[
|
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],
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/templates/internal.erb
CHANGED
@@ -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": "
|
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": "[
|
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
|
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:
|
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: '
|
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.
|
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.
|