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 +4 -4
- data/LICENSE +1 -1
- data/README.md +94 -40
- data/lib/kitchen/driver/azure_credentials.rb +43 -14
- data/lib/kitchen/driver/azurerm.rb +74 -16
- data/templates/internal.erb +7 -4
- data/templates/public.erb +7 -4
- metadata +75 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8615b3c50c7c88dc0167c2b0daebd1c66c1fec9bd05d1c169223c30fc00a7cc2
|
4
|
+
data.tar.gz: 769a0df10ad7af7a1215066955eba46717e16358f83ad176df6954d4f2e43d49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
[](http://badge.fury.io/rb/kitchen-azurerm)
|
3
|
+
[](http://badge.fury.io/rb/kitchen-azurerm) 
|
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
|
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,
|
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
|
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
|
-
|
15
|
+
If you're not using Chef Workstation and need to install the plugin as a gem run:
|
16
16
|
|
17
|
-
|
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.
|
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.
|
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
|
-
[
|
36
|
-
client_id = "
|
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 = "
|
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="
|
63
|
+
AZURE_CLIENT_ID="your-azure-client-id-here"
|
45
64
|
AZURE_CLIENT_SECRET="your-client-secret-here"
|
46
|
-
AZURE_TENANT_ID="
|
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: '
|
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
|
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: '
|
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: '
|
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.
|
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: '
|
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: '
|
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
|
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: '
|
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: '
|
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`).
|
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: '
|
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: '
|
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: '
|
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: '
|
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.
|
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: '
|
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
|
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.
|
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"] ||
|
78
|
+
ENV["AZURE_TENANT_ID"] || credentials_property("tenant_id")
|
56
79
|
end
|
57
80
|
|
58
81
|
def client_id
|
59
|
-
ENV["AZURE_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"] ||
|
86
|
+
ENV["AZURE_CLIENT_SECRET"] || credentials_property("client_secret")
|
64
87
|
end
|
65
88
|
|
66
89
|
def token_provider
|
67
|
-
|
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(
|
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
|
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],
|
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
|
data/templates/internal.erb
CHANGED
@@ -178,10 +178,10 @@
|
|
178
178
|
}
|
179
179
|
},
|
180
180
|
"userAssignedIdentities": {
|
181
|
-
"type": "
|
182
|
-
"defaultValue":
|
181
|
+
"type": "object",
|
182
|
+
"defaultValue": {},
|
183
183
|
"metadata": {
|
184
|
-
"description": "
|
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
|
-
"
|
418
|
+
"userAssignedIdentities": "[if(empty(parameters('userAssignedIdentities')), json('null'), parameters('userAssignedIdentities'))]"
|
416
419
|
},
|
417
420
|
"tags": {
|
418
421
|
<%= vm_tags unless vm_tags.empty? %>
|
data/templates/public.erb
CHANGED
@@ -178,10 +178,10 @@
|
|
178
178
|
}
|
179
179
|
},
|
180
180
|
"userAssignedIdentities": {
|
181
|
-
"type": "
|
182
|
-
"defaultValue":
|
181
|
+
"type": "object",
|
182
|
+
"defaultValue": {},
|
183
183
|
"metadata": {
|
184
|
-
"description": "
|
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
|
-
"
|
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:
|
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-
|
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:
|
94
|
+
name: test-kitchen
|
95
95
|
requirement: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
97
|
- - ">="
|
98
98
|
- !ruby/object:Gem::Version
|
99
|
-
version: '
|
100
|
-
|
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: '
|
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:
|
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:
|
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: []
|