kitchen-azurerm 0.15.2 → 1.2.0

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: 48df20f4bbd7b6087cfde1ec03770f559f0fbd45e01bc01834e95e95d8f9c3b6
4
- data.tar.gz: 6cc4e949b4fbc6bf173664fb4ee5f7aa3eb9bcfa5254c70a6642767c53425ce6
3
+ metadata.gz: 8615b3c50c7c88dc0167c2b0daebd1c66c1fec9bd05d1c169223c30fc00a7cc2
4
+ data.tar.gz: 769a0df10ad7af7a1215066955eba46717e16358f83ad176df6954d4f2e43d49
5
5
  SHA512:
6
- metadata.gz: 71daccd76e78290d7c601b293d3e54c8a9fc4f1fd06a7d754d8dc0ea900c516424d05dbe50d1c5011a52862a5ac8a6f738cb183fd31ca280fe8637cf6fe3ba01
7
- data.tar.gz: acadd9d7ea7152cac675428e0203a12d6d79b187d7ae4603be1795edbe3498c7b3ccffec5457f22e864bc1623b203d58ba666f522c3a1f65dd8331cdd70d6c79
6
+ metadata.gz: 48a2d37a873c8d2b842dc20e0c2e40cc9b349faed29d0c1f9bbc12ccb53097e0df0a06884f29c840b2e2f72a3deef6a0ab2244ef037a9c1aa24397524f756747
7
+ data.tar.gz: b3538aa314c217566e22a359655aee67eedb88cff3d2ea2f35e17445db4fe5821b57d5beb183f8ec77ac077ed58f88f275fd011fbdaa162a3b17def168c2c99e
data/LICENSE CHANGED
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright 2017 Pendrica Ltd.
189
+ Copyright [yyyy] [name of copyright owner]
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
data/README.md CHANGED
@@ -1,24 +1,43 @@
1
1
  # kitchen-azurerm
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/kitchen-azurerm.svg)](http://badge.fury.io/rb/kitchen-azurerm) [![Build Status](https://travis-ci.org/test-kitchen/kitchen-azurerm.svg)](https://travis-ci.org/test-kitchen/kitchen-azurerm)
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)
4
4
 
5
- **kitchen-azurerm** is a driver for the popular test harness [Test Kitchen](http://kitchen.ci) that allows Microsoft Azure resources to be provisioned prior to 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).
5
+ **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
6
 
7
- This version has been tested on Windows, OS/X and Ubuntu. If you encounter a problem on your platform, please raise an issue.
7
+ This version has been tested on Windows, macOS, and Ubuntu. If you encounter a problem on your platform, please raise an issue.
8
8
 
9
9
  ## Quick-start
10
10
 
11
11
  ### Installation
12
12
 
13
- This plugin is distributed as a [Ruby Gem](https://rubygems.org/gems/kitchen-azurerm). To install it, run:
13
+ This plugin ships in Chef Workstation out of the box so there is no need to install it when using Chef Workstation[https://downloads.chef.io/products/workstation].
14
14
 
15
- ```$ gem install kitchen-azurerm```
15
+ If you're not using Chef Workstation and need to install the plugin as a gem run:
16
16
 
17
- Note if you are running the ChefDK you may need to prefix the command with chef, i.e. ```$ chef gem install kitchen-azurerm```
17
+ ```$ gem install kitchen-azurerm```
18
18
 
19
19
  ### Configuration
20
20
 
21
- For the driver to interact with the Microsoft Azure Resource management REST API, a Service Principal needs to be configured with Contributor rights against the specific subscription being targeted. Using an Organizational (AAD) account and related password is no longer supported. To create a Service Principal and apply the correct permissions, you will need to [create and authenticate a service principal](https://azure.microsoft.com/en-us/documentation/articles/resource-group-authenticate-service-principal/#authenticate-service-principal-with-password---azure-cli) using the [Azure CLI](https://azure.microsoft.com/en-us/documentation/articles/xplat-cli-install/). Make sure you stay within the section titled 'Authenticate service principal with password - Azure CLI'.
21
+ For the driver to interact with the Microsoft Azure Resource management REST API, a Service Principal needs to be configured with Contributor rights against the specific subscription being targeted. Using an Organizational (AAD) account and related password is no longer supported. To create a Service Principal and apply the correct permissions, you will need to [create an Azure service principal with the Azure CLI](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest#create-a-service-principal) using the [Azure CLI](https://azure.microsoft.com/en-us/documentation/articles/xplat-cli-install/). Make sure you stay within the section titled 'Authenticate service principal with password - Azure CLI'.
22
+
23
+ If the above is TLDR then try this after `az login` using your target subscription ID and the desired SP name:
24
+
25
+ ```bash
26
+ # Create a Service Principal using the desired subscription id from the command above
27
+ az ad sp create-for-rbac --name="kitchen-azurerm" --role="Contributor" --scopes="/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
28
+
29
+ #Output
30
+ #
31
+ #{
32
+ # "appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", <- Also known as the Client ID
33
+ # "displayName": "azure-cli-2018-12-12-14-15-39",
34
+ # "name": "http://azure-cli-2018-12-12-14-15-39",
35
+ # "password": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
36
+ # "tenant": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
37
+ #}
38
+ ```
39
+
40
+ NOTE: Don't forget to save the values from the output -- most importantly the `password`.
22
41
 
23
42
  You will also need to ensure you have an active Azure subscription (you can get started [for free](https://azure.microsoft.com/en-us/free/) or use your [MSDN Subscription](https://azure.microsoft.com/en-us/pricing/member-offers/msdn-benefits/)).
24
43
 
@@ -29,25 +48,34 @@ You are now ready to configure kitchen-azurerm to use the credentials from the s
29
48
  3. **Client Secret/Password**: this will be the password you supplied in the command in step 2.
30
49
  4. **Tenant ID**: use the command detailed in "Manually provide credentials through Azure CLI" step 1 to get the TenantId.
31
50
 
32
- Using a text editor, open or create the file ```~/.azure/credentials``` and add the following section, noting there is one section per Subscription ID. **Make sure you save the file with UTF-8 encoding**
51
+ Using a text editor, open or create the file ```~/.azure/credentials``` and add the following section, noting there is one section per Subscription ID. **Make sure you save the file with UTF-8 encoding**
33
52
 
34
53
  ```ruby
35
- [abcd1234-YOUR-SUBSCRIPTION-ID-HERE-abcdef123456]
36
- client_id = "48b9bba3-YOUR-GUID-HERE-90f0b68ce8ba"
54
+ [ADD-YOUR-AZURE-SUBSCRIPTION-ID-HERE-IN-SQUARE-BRACKET]
55
+ client_id = "your-azure-client-id-here"
37
56
  client_secret = "your-client-secret-here"
38
- tenant_id = "9c117323-YOUR-GUID-HERE-9ee430723ba3"
57
+ tenant_id = "your-azure-tenant-id-here"
39
58
  ```
40
59
 
41
60
  If preferred, you may also set the following environment variables, however this would be incompatible with supporting multiple Azure subscriptions.
42
61
 
43
62
  ```ruby
44
- AZURE_CLIENT_ID="48b9bba3-YOUR-GUID-HERE-90f0b68ce8ba"
63
+ AZURE_CLIENT_ID="your-azure-client-id-here"
45
64
  AZURE_CLIENT_SECRET="your-client-secret-here"
46
- AZURE_TENANT_ID="9c117323-YOUR-GUID-HERE-9ee430723ba3"
65
+ AZURE_TENANT_ID="your-azure-tenant-id-here"
47
66
  ```
48
67
 
49
68
  Note that the environment variables, if set, take preference over the values in a configuration file.
50
69
 
70
+ After adjusting your ```~/.azure/credentials``` file you will need to adjust your ```kitchen.yml``` file to leverage the azurerm driver. Use the following examples to achieve this, then check your configuration with standard kitchen commands. For example,
71
+
72
+ ```bash
73
+ % kitchen list
74
+ Instance Driver Provisioner Verifier Transport Last Action Last Error
75
+ wsus-windows-2019 Azurerm ChefZero Inspec Winrm <Not Created> <None>
76
+ wsus-windows-2016 Azurerm ChefZero Inspec Winrm <Not Created> <None>
77
+ ```
78
+
51
79
  ### .kitchen.yml example 1 - Linux/Ubuntu
52
80
 
53
81
  Here's an example ```.kitchen.yml``` file that provisions an Ubuntu Server, using Chef Zero as the provisioner and SSH as the transport. Note that if the key does not exist at the specified location, it will be created. Also note that if ```ssh_key``` is supplied, Test Kitchen will use this in preference to any default/configured passwords that are supplied.
@@ -56,7 +84,7 @@ Here's an example ```.kitchen.yml``` file that provisions an Ubuntu Server, usin
56
84
  ---
57
85
  driver:
58
86
  name: azurerm
59
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
87
+ subscription_id: 'your-azure-subscription-id-here'
60
88
  location: 'West Europe'
61
89
  machine_size: 'Standard_D1'
62
90
 
@@ -71,9 +99,6 @@ platforms:
71
99
  driver:
72
100
  image_urn: Canonical:UbuntuServer:14.04.4-LTS:latest
73
101
  vm_name: trusty-vm
74
- vm_tags:
75
- ostype: linux
76
- distro: ubuntu
77
102
 
78
103
  suites:
79
104
  - name: default
@@ -84,7 +109,7 @@ suites:
84
109
 
85
110
  ### Concurrent execution
86
111
 
87
- Concurrent execution of create/converge/destroy is supported via the --concurrency parameter. Each machine is created in it's own Azure Resource Group so has no shared lifecycle with the other machines in the test run. To take advantage of parallel execution use the following command:
112
+ Concurrent execution of create/converge/destroy is supported via the --concurrency parameter. Each machine is created in its own Azure Resource Group so it has no shared lifecycle with the other machines in the test run. To take advantage of parallel execution use the following command:
88
113
 
89
114
  ```kitchen test --concurrency <n>```
90
115
 
@@ -98,7 +123,7 @@ Here's a further example ```.kitchen.yml``` file that will provision a Windows S
98
123
  ---
99
124
  driver:
100
125
  name: azurerm
101
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
126
+ subscription_id: 'your-subscription-id-here'
102
127
  location: 'West Europe'
103
128
  machine_size: 'Standard_DS2_v2'
104
129
 
@@ -113,6 +138,9 @@ platforms:
113
138
  resource_group_tags:
114
139
  project: 'My Cool Project'
115
140
  contact: 'me@somewhere.com'
141
+ vm_tags:
142
+ my_tag: its value
143
+ another_tag: its awesome value
116
144
  transport:
117
145
  name: winrm
118
146
  suites:
@@ -125,16 +153,16 @@ suites:
125
153
  ### .kitchen.yml example 3 - "pre-deployment" ARM template
126
154
 
127
155
  The following example introduces the ```pre_deployment_template``` and ```pre_deployment_parameters``` properties in the configuration file.
128
- You can use this capability to execute an ARM template containing Azure resources to provision before the system under test is created.
156
+ You can use this capability to execute an ARM template containing Azure resources to provision before the system under test is created.
129
157
 
130
- In the example the ARM template in the file ```predeploy.json``` would be executed with the parameters that are specified under ```pre_deployment_parameters```.
158
+ In the example the ARM template in the file ```predeploy.json``` would be executed with the parameters that are specified under ```pre_deployment_parameters```.
131
159
  These resources will be created in the same Azure Resource Group as the VM under test, and therefore will be destroyed when you type ```kitchen destroy```.
132
160
 
133
161
  ```yaml
134
162
  ---
135
163
  driver:
136
164
  name: azurerm
137
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
165
+ subscription_id: 'your-azure-subscription-id-here'
138
166
  location: 'West Europe'
139
167
  machine_size: 'Standard_D1'
140
168
  pre_deployment_template: predeploy.json
@@ -198,7 +226,7 @@ Example predeploy.json:
198
226
 
199
227
  ### .kitchen.yml example 4 - deploy VM to existing virtual network/subnet (use for ExpressRoute/VPN scenarios)
200
228
 
201
- 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.
229
+ 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.
202
230
  You can use this capability to create the VM on an existing virtual network and subnet created in a different resource group.
203
231
 
204
232
  In this case, the public IP address is not used unless ```public_ip``` is set to ```true```
@@ -207,7 +235,7 @@ In this case, the public IP address is not used unless ```public_ip``` is set to
207
235
  ---
208
236
  driver:
209
237
  name: azurerm
210
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
238
+ subscription_id: 'your-azure-subscription-id-here'
211
239
  location: 'West Europe'
212
240
  machine_size: 'Standard_D1'
213
241
 
@@ -241,7 +269,7 @@ Note: The image must be available first. On deletion the disk and everything is
241
269
  ---
242
270
  driver:
243
271
  name: azurerm
244
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
272
+ subscription_id: 'your-azure-subscription-id-here'
245
273
  location: 'West Europe'
246
274
  machine_size: 'Standard_D1'
247
275
 
@@ -270,7 +298,7 @@ suites:
270
298
 
271
299
  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.
272
300
 
273
- Note: When the resource group ís deleted, the os disk is left in the extsing storage account blob. You must cleanup manually.
301
+ Note: When the resource group ís deleted, the os disk is left in the existing storage account blob. You must clean up manually.
274
302
 
275
303
  This example will:
276
304
 
@@ -282,7 +310,7 @@ This example will:
282
310
  ---
283
311
  driver:
284
312
  name: azurerm
285
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
313
+ subscription_id: 'your-azure-subscription-id-here'
286
314
  location: 'West Europe'
287
315
  machine_size: 'Standard_D1'
288
316
 
@@ -319,7 +347,7 @@ Note: Custom data can be custom data or a file to custom data. Please also note
319
347
  ---
320
348
  driver:
321
349
  name: azurerm
322
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
350
+ subscription_id: 'your-azure-subscription-id-here'
323
351
  location: 'West Europe'
324
352
  machine_size: 'Standard_D1'
325
353
 
@@ -358,13 +386,13 @@ suites:
358
386
 
359
387
  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.
360
388
 
361
- Note the availability of a `format_data_disks` option (default: `false`). When set to true, a PowerShell script will execute at first boot to initialize and format the disks with an NTFS filesystem. This option has no effect on Linux machines.
389
+ Note the availability of a `format_data_disks` option (default: `false`). When set to true, a PowerShell script will execute at first boot to initialize and format the disks with an NTFS filesystem. This option does not affect Linux machines.
362
390
 
363
391
  ```yaml
364
392
  ---
365
393
  driver:
366
394
  name: azurerm
367
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
395
+ subscription_id: 'your-azure-subscription-id-here'
368
396
  location: 'West Europe'
369
397
  machine_size: 'Standard_F2s'
370
398
 
@@ -394,16 +422,16 @@ suites:
394
422
  ### .kitchen.yml example 9 - "post-deployment" ARM template with MSI authentication
395
423
 
396
424
  The following example introduces the ```post_deployment_template``` and ```post_deployment_parameters``` properties in the configuration file.
397
- You can use this capability to execute an ARM template containing Azure resources to provision after the system under test is created.
425
+ You can use this capability to execute an ARM template containing Azure resources to provision after the system under test is created.
398
426
 
399
- In the example the ARM template in the file ```postdeploy.json``` would be executed with the parameters that are specified under ```post_deployment_parameters```.
427
+ In the example the ARM template in the file ```postdeploy.json``` would be executed with the parameters that are specified under ```post_deployment_parameters```.
400
428
  These resources will be created in the same Azure Resource Group as the VM under test, and therefore will be destroyed when you type ```kitchen destroy```.
401
429
 
402
430
  ```yaml
403
431
  ---
404
432
  driver:
405
433
  name: azurerm
406
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
434
+ subscription_id: 'your-azure-subscription-id-here'
407
435
  location: 'West Europe'
408
436
  machine_size: 'Standard_D1'
409
437
  post_deployment_template: postdeploy.json
@@ -488,7 +516,7 @@ See the [Managed identities for Azure resources](https://docs.microsoft.com/en-u
488
516
  ---
489
517
  driver:
490
518
  name: azurerm
491
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
519
+ subscription_id: 'your-azure-subscription-id-here'
492
520
  location: 'West Europe'
493
521
  machine_size: 'Standard_D1'
494
522
 
@@ -521,7 +549,7 @@ This following example introduces ```secret_url```, ```vault_name```, and ```vau
521
549
  ---
522
550
  driver:
523
551
  name: azurerm
524
- subscription_id: '4801fa9d-YOUR-GUID-HERE-b265ff49ce21'
552
+ subscription_id: 'your-azure-subscription-id-here'
525
553
  location: 'CentralUS'
526
554
  machine_size: 'Standard_D2s_v3'
527
555
  secret_url: 'https://YOUR-SECRET-PATH'
@@ -546,7 +574,7 @@ suites:
546
574
 
547
575
  ## Support for Government and Sovereign Clouds (China and Germany)
548
576
 
549
- Starting with v0.9.0 this driver has support for Azure Government and Sovereign Clouds via the use of the ```azure_environment``` setting. Valid Azure environments are ```Azure```, ```AzureUSGovernment```, ```AzureChina``` and ```AzureGermanCloud```
577
+ Starting with v0.9.0 this driver has support for Azure Government and Sovereign Clouds via the use of the ```azure_environment``` setting. Valid Azure environments are ```Azure```, ```AzureUSGovernment```, ```AzureChina``` and ```AzureGermanCloud```
550
578
 
551
579
  Note that the ```use_managed_disks``` option should be set to false until supported by AzureUSGovernment.
552
580
 
@@ -556,7 +584,7 @@ Note that the ```use_managed_disks``` option should be set to false until suppor
556
584
  ---
557
585
  driver:
558
586
  name: azurerm
559
- subscription_id: 'abcdabcd-YOUR-GUID-HERE-abcdabcdabcd'
587
+ subscription_id: 'your-azure-subscription-id-here'
560
588
  azure_environment: 'AzureUSGovernment'
561
589
  location: 'US Gov Iowa'
562
590
  machine_size: 'Standard_D2_v2_Promo'
@@ -616,9 +644,9 @@ data: Canonical UbuntuServer 15.10-DAILY 15.10.201509220 westeurope
616
644
  info: vm image list command OK
617
645
  ```
618
646
 
619
- ### Additional parameters that can be specified
647
+ ### Additional parameters that can be specified in your `kitchen.yml` or added to your personal `kitchen.local.yml`
620
648
 
621
- * Note that the ```driver``` section can also takes a ```username``` and ```password```. The default username is "azure" and the password is a randomly generated 12 character password that can be found in your local kitchen state file (typically .kitchen/<instance-name>.yml) if you require it for any reason.
649
+ * Note that the ```driver``` section can also take explicit values for ```username``` and ```password```. Otherwise, the default username is "azure" and the password is a randomly generated 24 character password that can be found in your local kitchen state file (typically `.kitchen/<instance-name>.yml`) if you require it for any reason.
622
650
 
623
651
  * The ```storage_account_type``` parameter defaults to 'Standard_LRS' and allows you to switch to premium storage (e.g. 'Premium_LRS')
624
652
 
@@ -626,6 +654,8 @@ info: vm image list command OK
626
654
 
627
655
  * The optional ```vm_tags``` parameter allows you to define key:value pairs to tag VMs with on creation.
628
656
 
657
+ * The optional ```plan``` parameter allows you to define plan information when creating VMs from Marketplace images. Please refer to [Deploy an image with Marketplace terms](https://aka.ms/azuremarketplaceapideployment) for more details. Not all Marketplace images support programmatic deployment, and support is controlled by the image publisher.
658
+
629
659
  * Managed disks are now enabled by default, to use the Storage account set ```use_managed_disks``` (default: true).
630
660
 
631
661
  * The ```image_url``` (unmanaged disks only) parameter can be used to specify a custom vhd (This VHD must be in the same storage account as the disks of the VM, therefore ```existing_storage_account_blob_url``` must also be set and ```use_managed_disks``` must be set to false)
@@ -640,10 +670,12 @@ info: vm image list command OK
640
670
 
641
671
  * The ```azure_resource_group_prefix``` and ```azure_resource_group_suffix``` can be used to further disambiguate Azure resource group names created by the driver.
642
672
 
643
- * 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"] %>```
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"] %>```
644
674
 
645
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.
646
676
 
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.
678
+
647
679
  ```yaml
648
680
  ---
649
681
  driver:
@@ -683,3 +715,25 @@ Contributions to the project are welcome via submitting Pull Requests.
683
715
  3. Commit your changes (`git commit -am 'Add some feature'`)
684
716
  4. Push to the branch (`git push origin my-new-feature`)
685
717
  5. Create a new Pull Request
718
+
719
+ ## Author
720
+
721
+ Stuart Preston
722
+
723
+ ## License and Copyright
724
+
725
+ Copyright 2015-2020, Chef Software, Inc.
726
+
727
+ ```
728
+ Licensed under the Apache License, Version 2.0 (the "License");
729
+ you may not use this file except in compliance with the License.
730
+ You may obtain a copy of the License at
731
+
732
+ http://www.apache.org/licenses/LICENSE-2.0
733
+
734
+ Unless required by applicable law or agreed to in writing, software
735
+ distributed under the License is distributed on an "AS IS" BASIS,
736
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
737
+ See the License for the specific language governing permissions and
738
+ limitations under the License.
739
+ ```
@@ -1,4 +1,5 @@
1
1
  require "inifile"
2
+ require "kitchen/logging"
2
3
 
3
4
  module Kitchen
4
5
  module Driver
@@ -6,6 +7,8 @@ module Kitchen
6
7
  # AzureCredentials
7
8
  #
8
9
  class AzureCredentials
10
+ include Kitchen::Logging
11
+
9
12
  CONFIG_PATH = "#{ENV["HOME"]}/.azure/credentials".freeze
10
13
 
11
14
  #
@@ -24,12 +27,6 @@ module Kitchen
24
27
  def initialize(subscription_id:, environment: "Azure")
25
28
  @subscription_id = subscription_id
26
29
  @environment = environment
27
- config_file = ENV["AZURE_CONFIG_FILE"] || File.expand_path(CONFIG_PATH)
28
- if File.file?(config_file)
29
- @credentials = IniFile.load(File.expand_path(config_file))
30
- else
31
- warn "#{CONFIG_PATH} was not found or not accessible."
32
- end
33
30
  end
34
31
 
35
32
  #
@@ -38,33 +35,65 @@ module Kitchen
38
35
  # @return [Object] Object that can be supplied along with all Azure client requests.
39
36
  #
40
37
  def azure_options
41
- options = { tenant_id: tenant_id,
42
- client_id: client_id,
43
- client_secret: client_secret,
38
+ options = { tenant_id: tenant_id!,
44
39
  subscription_id: subscription_id,
45
40
  credentials: ::MsRest::TokenCredentials.new(token_provider),
46
41
  active_directory_settings: ad_settings,
47
42
  base_url: endpoint_settings.resource_manager_endpoint_url }
48
-
43
+ options[:client_id] = client_id if client_id
44
+ options[:client_secret] = client_secret if client_secret
49
45
  options
50
46
  end
51
47
 
52
48
  private
53
49
 
50
+ def logger
51
+ Kitchen.logger
52
+ end
53
+
54
+ def config_path
55
+ @config_path ||= File.expand_path(ENV["AZURE_CONFIG_FILE"] || CONFIG_PATH)
56
+ end
57
+
58
+ def credentials
59
+ @credentials ||= begin
60
+ if File.file?(config_path)
61
+ IniFile.load(config_path)
62
+ else
63
+ warn "#{config_path} was not found or not accessible. Will attempt to use Managed Identity."
64
+ {}
65
+ end
66
+ end
67
+ end
68
+
69
+ def credentials_property(property)
70
+ credentials[subscription_id]&.[](property)
71
+ end
72
+
73
+ 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
+ end
76
+
54
77
  def tenant_id
55
- ENV["AZURE_TENANT_ID"] || @credentials[subscription_id]["tenant_id"]
78
+ ENV["AZURE_TENANT_ID"] || credentials_property("tenant_id")
56
79
  end
57
80
 
58
81
  def client_id
59
- ENV["AZURE_CLIENT_ID"] || @credentials[subscription_id]["client_id"]
82
+ ENV["AZURE_CLIENT_ID"] || credentials_property("client_id")
60
83
  end
61
84
 
62
85
  def client_secret
63
- ENV["AZURE_CLIENT_SECRET"] || @credentials[subscription_id]["client_secret"]
86
+ ENV["AZURE_CLIENT_SECRET"] || credentials_property("client_secret")
64
87
  end
65
88
 
66
89
  def token_provider
67
- ::MsRestAzure::ApplicationTokenProvider.new(tenant_id, client_id, client_secret, ad_settings)
90
+ if client_id && client_secret
91
+ ::MsRestAzure::ApplicationTokenProvider.new(tenant_id, client_id, client_secret, ad_settings)
92
+ elsif client_id
93
+ ::MsRestAzure::MSITokenProvider.new(50342, ad_settings, { client_id: client_id })
94
+ else
95
+ ::MsRestAzure::MSITokenProvider.new(50342, ad_settings)
96
+ end
68
97
  end
69
98
 
70
99
  #
@@ -1,15 +1,15 @@
1
1
  require "kitchen"
2
2
  require_relative "azure_credentials"
3
- require "securerandom"
3
+ require "securerandom" unless defined?(SecureRandom)
4
4
  require "azure_mgmt_resources"
5
5
  require "azure_mgmt_network"
6
- require "base64"
6
+ require "base64" unless defined?(Base64)
7
7
  require "sshkey"
8
- require "fileutils"
9
- require "erb"
10
- require "ostruct"
11
- require "json"
12
- require "faraday"
8
+ require "fileutils" unless defined?(FileUtils)
9
+ require "erb" unless defined?(Erb)
10
+ require "ostruct" unless defined?(OpenStruct)
11
+ require "json" unless defined?(JSON)
12
+ require "faraday" unless defined?(Faraday)
13
13
 
14
14
  module Kitchen
15
15
  module Driver
@@ -20,6 +20,8 @@ module Kitchen
20
20
  attr_accessor :resource_management_client
21
21
  attr_accessor :network_management_client
22
22
 
23
+ kitchen_driver_api_version 2
24
+
23
25
  default_config(:azure_resource_group_prefix) do |_config|
24
26
  "kitchen-"
25
27
  end
@@ -73,7 +75,7 @@ module Kitchen
73
75
  end
74
76
 
75
77
  default_config(:password) do |_config|
76
- SecureRandom.base64(12)
78
+ SecureRandom.base64(25)
77
79
  end
78
80
 
79
81
  default_config(:vm_name) do |_config|
@@ -132,6 +134,10 @@ module Kitchen
132
134
  {}
133
135
  end
134
136
 
137
+ default_config(:plan) do |_config|
138
+ {}
139
+ end
140
+
135
141
  default_config(:vm_tags) do |_config|
136
142
  {}
137
143
  end
@@ -168,6 +174,10 @@ module Kitchen
168
174
  true
169
175
  end
170
176
 
177
+ default_config(:destroy_explicit_resource_group_tags) do |_config|
178
+ true
179
+ end
180
+
171
181
  default_config(:destroy_resource_group_contents) do |_config|
172
182
  false
173
183
  end
@@ -208,7 +218,7 @@ module Kitchen
208
218
  dnsNameForPublicIP: "kitchen-#{state[:uuid]}",
209
219
  vmName: state[:vm_name],
210
220
  systemAssignedIdentity: config[:system_assigned_identity],
211
- userAssignedIdentities: config[:user_assigned_identities],
221
+ userAssignedIdentities: config[:user_assigned_identities].map { |identity| [identity, {}] }.to_h,
212
222
  secretUrl: config[:secret_url],
213
223
  vaultName: config[:vault_name],
214
224
  vaultResourceGroup: config[:vault_resource_group],
@@ -219,7 +229,7 @@ module Kitchen
219
229
  end
220
230
 
221
231
  if config[:subscription_id].to_s == ""
222
- raise "A subscription_id config value was not detected and kitchen-azurerm cannot continue. Please check your .kitchen.yml configuration. Exiting."
232
+ raise "A subscription_id config value was not detected and kitchen-azurerm cannot continue. Please check your kitchen.yml configuration. Exiting."
223
233
  end
224
234
 
225
235
  if config[:nic_name].to_s == ""
@@ -271,12 +281,9 @@ module Kitchen
271
281
  @resource_management_client = ::Azure::Resources::Profiles::Latest::Mgmt::Client.new(options)
272
282
 
273
283
  # Create Resource Group
274
- resource_group = ::Azure::Resources::Profiles::Latest::Mgmt::Models::ResourceGroup.new
275
- resource_group.location = config[:location]
276
- resource_group.tags = config[:resource_group_tags]
277
284
  begin
278
285
  info "Creating Resource Group: #{state[:azure_resource_group_name]}"
279
- create_resource_group(state[:azure_resource_group_name], resource_group)
286
+ create_resource_group(state[:azure_resource_group_name], get_resource_group)
280
287
  rescue ::MsRestAzure::AzureOperationError => operation_error
281
288
  error operation_error.body
282
289
  raise operation_error
@@ -528,6 +535,35 @@ module Kitchen
528
535
  info "Creating deployment: #{empty_deployment_name}"
529
536
  create_deployment_async(state[:azure_resource_group_name], empty_deployment_name, empty_deployment).value!
530
537
  follow_deployment_until_end_state(state[:azure_resource_group_name], empty_deployment_name)
538
+
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().
557
+ resource_group = get_resource_group
558
+ 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
565
+ end
566
+
531
567
  rescue ::MsRestAzure::AzureOperationError => operation_error
532
568
  error operation_error.body
533
569
  raise operation_error
@@ -643,13 +679,25 @@ module Kitchen
643
679
 
644
680
  def virtual_machine_deployment_template
645
681
  if config[:vnet_id] == ""
646
- 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])
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)
647
683
  else
648
684
  info "Using custom vnet: #{config[:vnet_id]}"
649
- 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])
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)
650
686
  end
651
687
  end
652
688
 
689
+ def plan_json
690
+ return nil if config[:plan].empty?
691
+
692
+ plan = {}
693
+ plan["name"] = config[:plan][:name] if config[:plan][:name]
694
+ plan["product"] = config[:plan][:product] if config[:plan][:product]
695
+ plan["promotionCode"] = config[:plan][:promotion_code] if config[:plan][:promotion_code]
696
+ plan["publisher"] = config[:plan][:publisher] if config[:plan][:publisher]
697
+
698
+ plan.to_json
699
+ end
700
+
653
701
  def virtual_machine_deployment_template_file(template_file, data = {})
654
702
  template = File.read(File.expand_path(File.join(__dir__, "../../../templates", template_file)))
655
703
  render_binding = OpenStruct.new(data)
@@ -688,6 +736,16 @@ module Kitchen
688
736
  # Wrapper methods for the Azure API calls to retry the calls when getting timeouts.
689
737
  #
690
738
 
739
+ # Create a new resource group object and set the location and tags attributes then return it.
740
+ #
741
+ # @return [::Azure::Resources::Profiles::Latest::Mgmt::Models::ResourceGroup] A new resource group object.
742
+ def get_resource_group
743
+ resource_group = ::Azure::Resources::Profiles::Latest::Mgmt::Models::ResourceGroup.new
744
+ resource_group.location = config[:location]
745
+ resource_group.tags = config[:resource_group_tags]
746
+ resource_group
747
+ end
748
+
691
749
  def create_resource_group(resource_group_name, resource_group)
692
750
  retries = config[:azure_api_retries]
693
751
  begin
@@ -178,10 +178,10 @@
178
178
  }
179
179
  },
180
180
  "userAssignedIdentities": {
181
- "type": "array",
182
- "defaultValue": [],
181
+ "type": "object",
182
+ "defaultValue": {},
183
183
  "metadata": {
184
- "description": "A list of resource IDs for user identities to associate with the Virtual Machine, or empty to disable user assigned identities."
184
+ "description": "An object whose keys are resource IDs for user identities to associate with the Virtual Machine and whose values are empty objects, or empty to disable user assigned identities."
185
185
  }
186
186
  },
187
187
  "bootDiagnosticsEnabled": {
@@ -410,9 +410,12 @@
410
410
  <%- end -%>
411
411
  }
412
412
  },
413
+ <%- unless plan_json.nil? -%>
414
+ "plan": <%= plan_json %>,
415
+ <%- end -%>
413
416
  "identity": {
414
417
  "type": "[variables('vmIdentityType')]",
415
- "identityIds": "[if(empty(parameters('userAssignedIdentities')), json('null'), parameters('userAssignedIdentities'))]"
418
+ "userAssignedIdentities": "[if(empty(parameters('userAssignedIdentities')), json('null'), parameters('userAssignedIdentities'))]"
416
419
  },
417
420
  "tags": {
418
421
  <%= vm_tags unless vm_tags.empty? %>
@@ -178,10 +178,10 @@
178
178
  }
179
179
  },
180
180
  "userAssignedIdentities": {
181
- "type": "array",
182
- "defaultValue": [],
181
+ "type": "object",
182
+ "defaultValue": {},
183
183
  "metadata": {
184
- "description": "A list of resource IDs for user identities to associate with the Virtual Machine, or empty to disable user assigned identities."
184
+ "description": "An object whose keys are resource IDs for user identities to associate with the Virtual Machine and whose values are empty objects, or empty to disable user assigned identities."
185
185
  }
186
186
  },
187
187
  "bootDiagnosticsEnabled": {
@@ -429,9 +429,12 @@
429
429
  <%- end -%>
430
430
  }
431
431
  },
432
+ <%- unless plan_json.nil? -%>
433
+ "plan": <%= plan_json %>,
434
+ <%- end -%>
432
435
  "identity": {
433
436
  "type": "[variables('vmIdentityType')]",
434
- "identityIds": "[if(empty(parameters('userAssignedIdentities')), json('null'), parameters('userAssignedIdentities'))]"
437
+ "userAssignedIdentities": "[if(empty(parameters('userAssignedIdentities')), json('null'), parameters('userAssignedIdentities'))]"
435
438
  },
436
439
  "tags": {
437
440
  <%= vm_tags unless vm_tags.empty? %>
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: 0.15.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stuart Preston
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-23 00:00:00.000000000 Z
11
+ date: 2020-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: azure_mgmt_network
@@ -91,19 +91,25 @@ dependencies:
91
91
  - !ruby/object:Gem::Version
92
92
  version: '3'
93
93
  - !ruby/object:Gem::Dependency
94
- name: bundler
94
+ name: test-kitchen
95
95
  requirement: !ruby/object:Gem::Requirement
96
96
  requirements:
97
97
  - - ">="
98
98
  - !ruby/object:Gem::Version
99
- version: '0'
100
- type: :development
99
+ version: '1.20'
100
+ - - "<"
101
+ - !ruby/object:Gem::Version
102
+ version: '3.0'
103
+ type: :runtime
101
104
  prerelease: false
102
105
  version_requirements: !ruby/object:Gem::Requirement
103
106
  requirements:
104
107
  - - ">="
105
108
  - !ruby/object:Gem::Version
106
- version: '0'
109
+ version: '1.20'
110
+ - - "<"
111
+ - !ruby/object:Gem::Version
112
+ version: '3.0'
107
113
  - !ruby/object:Gem::Dependency
108
114
  name: rake
109
115
  requirement: !ruby/object:Gem::Requirement
@@ -122,16 +128,72 @@ dependencies:
122
128
  name: chefstyle
123
129
  requirement: !ruby/object:Gem::Requirement
124
130
  requirements:
125
- - - ">="
131
+ - - '='
126
132
  - !ruby/object:Gem::Version
127
- version: '0'
133
+ version: 1.2.1
128
134
  type: :development
129
135
  prerelease: false
130
136
  version_requirements: !ruby/object:Gem::Requirement
131
137
  requirements:
132
- - - ">="
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
+ - - "~>"
133
195
  - !ruby/object:Gem::Version
134
- version: '0'
196
+ version: 1.3.0
135
197
  description: Test Kitchen driver for the Microsoft Azure Resource Manager (ARM) API
136
198
  email:
137
199
  - stuart@chef.io
@@ -150,7 +212,7 @@ homepage: https://github.com/test-kitchen/kitchen-azurerm
150
212
  licenses:
151
213
  - Apache-2.0
152
214
  metadata: {}
153
- post_install_message:
215
+ post_install_message:
154
216
  rdoc_options: []
155
217
  require_paths:
156
218
  - lib
@@ -166,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
228
  version: '0'
167
229
  requirements: []
168
230
  rubygems_version: 3.1.2
169
- signing_key:
231
+ signing_key:
170
232
  specification_version: 4
171
233
  summary: Test Kitchen driver for Azure Resource Manager.
172
234
  test_files: []