kitchen-azurerm 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4f839405ed54ecf3a21f74e5b121312d6a392ebb
4
+ data.tar.gz: 9ea5501228c5845968582bfb7a7de47f33f9665c
5
+ SHA512:
6
+ metadata.gz: 1bc408f53fb2ee9da320b0b4ee540c7e5ed6f218abaeecc32feebbf6830a9bb1124285f1f3397e84f110b1dc79e912fedf047e3fdb6df67ab365765a8b50b133
7
+ data.tar.gz: 9c392729a184e55754e6f8cfed7b9724cead235ef90237842973a7cdc7be97b350c5b3356bccd20f2bc0b2b8cb5c08b543cf570e01c15b2bf3461e6a5fa13ac8
data/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "{}"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright {yyyy} {name of copyright owner}
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
202
+
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # kitchen-azurerm
2
+ A driver for Test Kitchen that works with Azure Resource Manager
@@ -0,0 +1,536 @@
1
+ require 'kitchen'
2
+ require 'kitchen/driver/credentials'
3
+ require 'securerandom'
4
+ require 'azure_mgmt_resources'
5
+ require 'azure_mgmt_network'
6
+
7
+ module Kitchen
8
+ module Driver
9
+ #
10
+ # AzureRM
11
+ #
12
+ class AzureRM < Kitchen::Driver::Base
13
+ attr_accessor :resource_management_client
14
+
15
+ default_config(:azure_resource_group_name) do |config|
16
+ "kitchen-#{config.instance.name}"
17
+ end
18
+
19
+ def create(state)
20
+ puts 'in kitchen create'
21
+ state[:uuid] = "#{SecureRandom.hex(8)}"
22
+ state[:azure_resource_group_name] = "#{config[:azure_resource_group_name]}-#{state[:uuid]}"
23
+ state[:subscription_id] = config[:subscription_id]
24
+ state[:username] = 'azure'
25
+ state[:password] = 'P2ssw0rd'
26
+
27
+ credentials = Kitchen::Driver::Credentials.new.azure_credentials_for_subscription(config[:subscription_id])
28
+ @resource_management_client = ::Azure::ARM::Resources::ResourceManagementClient.new(credentials)
29
+ @resource_management_client.subscription_id = config[:subscription_id]
30
+
31
+ # Create Resource Group
32
+ resource_group = ::Azure::ARM::Resources::Models::ResourceGroup.new
33
+ resource_group.location = config[:location]
34
+ begin
35
+ puts "Creating Resource Group: #{state[:azure_resource_group_name]}"
36
+ resource_management_client.resource_groups.create_or_update(state[:azure_resource_group_name], resource_group).value!
37
+ rescue ::MsRestAzure::AzureOperationError => operation_error
38
+ puts operation_error.body['error']
39
+ raise operation_error
40
+ end
41
+
42
+ # Create Deployment Template
43
+ parameters = {
44
+ location: config[:location],
45
+ vmSize: config[:machine_size],
46
+ newStorageAccountName: "storage#{state[:uuid]}",
47
+ adminUsername: state[:username],
48
+ adminPassword: state[:password],
49
+ dnsNameForPublicIP: "publicip#{state[:uuid]}",
50
+ ubuntuOSVersion: '14.04.2-LTS'
51
+ }
52
+
53
+ begin
54
+ deployment_name = "deploy#{state[:uuid]}"
55
+ puts "Creating Deployment: #{deployment_name}"
56
+ resource_management_client.deployments.create_or_update(state[:azure_resource_group_name], deployment_name, deployment(linux_virtual_machine_deployment_template, parameters)).value!
57
+ rescue ::MsRestAzure::AzureOperationError => operation_error
58
+ puts operation_error.body['error']
59
+ raise operation_error
60
+ end
61
+
62
+ follow_deployment_until_end_state(state[:azure_resource_group_name], deployment_name)
63
+
64
+ # Now retrieve the public IP from the resource group:
65
+ network_management_client = ::Azure::ARM::Network::NetworkResourceProviderClient.new(credentials)
66
+ network_management_client.subscription_id = config[:subscription_id]
67
+ result = network_management_client.public_ip_addresses.get(state[:azure_resource_group_name], 'myPublicIP').value!
68
+ puts "IP Address is: #{result.body.properties.ip_address} [#{result.body.properties.dns_settings.fqdn}]"
69
+ state[:server_id] = "vm#{state[:uuid]}"
70
+ state[:hostname] = result.body.properties.ip_address
71
+ end
72
+
73
+ def deployment(template, parameters)
74
+ deployment = ::Azure::ARM::Resources::Models::Deployment.new
75
+ deployment.properties = ::Azure::ARM::Resources::Models::DeploymentProperties.new
76
+ deployment.properties.mode = Azure::ARM::Resources::Models::DeploymentMode::Incremental
77
+ deployment.properties.template = JSON.parse(template)
78
+ deployment.properties.parameters = parameters_in_values_format(parameters)
79
+ deployment
80
+ end
81
+
82
+ def parameters_in_values_format(parameters_in)
83
+ parameters = parameters_in.map do |key, value|
84
+ { key.to_sym => { 'value' => value } }
85
+ end
86
+ parameters.reduce(:merge!)
87
+ end
88
+
89
+ def follow_deployment_until_end_state(resource_group, deployment_name)
90
+ end_provisioning_states = 'Canceled,Failed,Deleted,Succeeded'
91
+ end_provisioning_state_reached = false
92
+ until end_provisioning_state_reached
93
+ list_outstanding_deployment_operations(resource_group, deployment_name)
94
+ sleep 10
95
+ deployment_provisioning_state = deployment_state(resource_group, deployment_name)
96
+ end_provisioning_state_reached = end_provisioning_states.split(',').include?(deployment_provisioning_state)
97
+ end
98
+ puts "Resource Template deployment reached end state of '#{deployment_provisioning_state}'."
99
+ end
100
+
101
+ def list_outstanding_deployment_operations(resource_group, deployment_name)
102
+ end_operation_states = 'Failed,Succeeded'
103
+ deployment_operations = resource_management_client.deployment_operations.list(resource_group, deployment_name).value!
104
+ deployment_operations.body.value.each do |val|
105
+ resource_provisioning_state = val.properties.provisioning_state
106
+ resource_name = val.properties.target_resource.resource_name
107
+ resource_type = val.properties.target_resource.resource_type
108
+ end_operation_state_reached = end_operation_states.split(',').include?(resource_provisioning_state)
109
+ unless end_operation_state_reached
110
+ puts "Resource #{resource_type} '#{resource_name}' provisioning status is #{resource_provisioning_state}"
111
+ end
112
+ end
113
+ end
114
+
115
+ def deployment_state(resource_group, deployment_name)
116
+ deployments = resource_management_client.deployments.get(resource_group, deployment_name).value!
117
+ deployments.body.properties.provisioning_state
118
+ end
119
+
120
+ def destroy(state)
121
+ return if state[:server_id].nil?
122
+ credentials = Kitchen::Driver::Credentials.new.azure_credentials_for_subscription(state[:subscription_id])
123
+ resource_management_client = ::Azure::ARM::Resources::ResourceManagementClient.new(credentials)
124
+ resource_management_client.subscription_id = state[:subscription_id]
125
+ begin
126
+ puts "Destroying Resource Group: #{state[:azure_resource_group_name]}"
127
+ resource_management_client.resource_groups.delete(state[:azure_resource_group_name]).value
128
+ puts 'Destroy operation will continue in the background.'
129
+ rescue ::MsRestAzure::AzureOperationError => operation_error
130
+ puts operation_error.body['error']
131
+ raise operation_error
132
+ end
133
+ state.delete(:server_id)
134
+ state.delete(:hostname)
135
+ state.delete(:username)
136
+ state.delete(:password)
137
+ end
138
+
139
+ def windows_virtual_machine_deployment_template
140
+ # as per: https://github.com/Azure/azure-quickstart-templates/blob/master/101-simple-windows-vm/azuredeploy.json
141
+ <<-EOH
142
+ {
143
+ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
144
+ "contentVersion": "1.0.0.0",
145
+ "parameters": {
146
+ "location": {
147
+ "type": "string",
148
+ "metadata": {
149
+ "description": "The location where the resources will be created."
150
+ }
151
+ },
152
+ "vmSize": {
153
+ "type": "string",
154
+ "metadata": {
155
+ "description": "The size of the VM to be created"
156
+ }
157
+ },
158
+ "newStorageAccountName": {
159
+ "type": "string",
160
+ "metadata": {
161
+ "description": "Unique DNS Name for the Storage Account where the Virtual Machine's disks will be placed."
162
+ }
163
+ },
164
+ "adminUsername": {
165
+ "type": "string",
166
+ "metadata": {
167
+ "description": "Username for the Virtual Machine."
168
+ }
169
+ },
170
+ "adminPassword": {
171
+ "type": "securestring",
172
+ "metadata": {
173
+ "description": "Password for the Virtual Machine."
174
+ }
175
+ },
176
+ "dnsNameForPublicIP": {
177
+ "type": "string",
178
+ "metadata": {
179
+ "description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
180
+ }
181
+ },
182
+ "windowsOSVersion": {
183
+ "type": "string",
184
+ "defaultValue": "2012-R2-Datacenter",
185
+ "allowedValues": [
186
+ "2008-R2-SP1",
187
+ "2012-Datacenter",
188
+ "2012-R2-Datacenter"
189
+ ],
190
+ "metadata": {
191
+ "description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version. Allowed values: 2008-R2-SP1, 2012-Datacenter, 2012-R2-Datacenter."
192
+ }
193
+ }
194
+ },
195
+ "variables": {
196
+ "location": "[parameters('location')]",
197
+ "imagePublisher": "MicrosoftWindowsServer",
198
+ "imageOffer": "WindowsServer",
199
+ "OSDiskName": "osdiskforwindowssimple",
200
+ "nicName": "myVMNic",
201
+ "addressPrefix": "10.0.0.0/16",
202
+ "subnetName": "Subnet",
203
+ "subnetPrefix": "10.0.0.0/24",
204
+ "storageAccountType": "Standard_LRS",
205
+ "publicIPAddressName": "myPublicIP",
206
+ "publicIPAddressType": "Dynamic",
207
+ "vmStorageAccountContainerName": "vhds",
208
+ "vmName": "windows-vm",
209
+ "vmSize": "[parameters('vmSize')]",
210
+ "virtualNetworkName": "MyVNET",
211
+ "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]",
212
+ "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]"
213
+ },
214
+ "resources": [
215
+ {
216
+ "type": "Microsoft.Storage/storageAccounts",
217
+ "name": "[parameters('newStorageAccountName')]",
218
+ "apiVersion": "2015-05-01-preview",
219
+ "location": "[variables('location')]",
220
+ "properties": {
221
+ "accountType": "[variables('storageAccountType')]"
222
+ }
223
+ },
224
+ {
225
+ "apiVersion": "2015-05-01-preview",
226
+ "type": "Microsoft.Network/publicIPAddresses",
227
+ "name": "[variables('publicIPAddressName')]",
228
+ "location": "[variables('location')]",
229
+ "properties": {
230
+ "publicIPAllocationMethod": "[variables('publicIPAddressType')]",
231
+ "dnsSettings": {
232
+ "domainNameLabel": "[parameters('dnsNameForPublicIP')]"
233
+ }
234
+ }
235
+ },
236
+ {
237
+ "apiVersion": "2015-05-01-preview",
238
+ "type": "Microsoft.Network/virtualNetworks",
239
+ "name": "[variables('virtualNetworkName')]",
240
+ "location": "[variables('location')]",
241
+ "properties": {
242
+ "addressSpace": {
243
+ "addressPrefixes": [
244
+ "[variables('addressPrefix')]"
245
+ ]
246
+ },
247
+ "subnets": [
248
+ {
249
+ "name": "[variables('subnetName')]",
250
+ "properties": {
251
+ "addressPrefix": "[variables('subnetPrefix')]"
252
+ }
253
+ }
254
+ ]
255
+ }
256
+ },
257
+ {
258
+ "apiVersion": "2015-05-01-preview",
259
+ "type": "Microsoft.Network/networkInterfaces",
260
+ "name": "[variables('nicName')]",
261
+ "location": "[variables('location')]",
262
+ "dependsOn": [
263
+ "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
264
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
265
+ ],
266
+ "properties": {
267
+ "ipConfigurations": [
268
+ {
269
+ "name": "ipconfig1",
270
+ "properties": {
271
+ "privateIPAllocationMethod": "Dynamic",
272
+ "publicIPAddress": {
273
+ "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]"
274
+ },
275
+ "subnet": {
276
+ "id": "[variables('subnetRef')]"
277
+ }
278
+ }
279
+ }
280
+ ]
281
+ }
282
+ },
283
+ {
284
+ "apiVersion": "2015-06-15",
285
+ "type": "Microsoft.Compute/virtualMachines",
286
+ "name": "[variables('vmName')]",
287
+ "location": "[variables('location')]",
288
+ "dependsOn": [
289
+ "[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]",
290
+ "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
291
+ ],
292
+ "properties": {
293
+ "hardwareProfile": {
294
+ "vmSize": "[variables('vmSize')]"
295
+ },
296
+ "osProfile": {
297
+ "computername": "[variables('vmName')]",
298
+ "adminUsername": "[parameters('adminUsername')]",
299
+ "adminPassword": "[parameters('adminPassword')]"
300
+ },
301
+ "storageProfile": {
302
+ "imageReference": {
303
+ "publisher": "[variables('imagePublisher')]",
304
+ "offer": "[variables('imageOffer')]",
305
+ "sku": "[parameters('windowsOSVersion')]",
306
+ "version": "latest"
307
+ },
308
+ "osDisk": {
309
+ "name": "osdisk",
310
+ "vhd": {
311
+ "uri": "[concat('http://',parameters('newStorageAccountName'),'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]"
312
+ },
313
+ "caching": "ReadWrite",
314
+ "createOption": "FromImage"
315
+ }
316
+ },
317
+ "networkProfile": {
318
+ "networkInterfaces": [
319
+ {
320
+ "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]"
321
+ }
322
+ ]
323
+ },
324
+ "diagnosticsProfile": {
325
+ "bootDiagnostics": {
326
+ "enabled": "true",
327
+ "storageUri": "[concat('http://',parameters('newStorageAccountName'),'.blob.core.windows.net')]"
328
+ }
329
+ }
330
+ }
331
+ }
332
+ ]
333
+ }
334
+ EOH
335
+ end
336
+
337
+ def linux_virtual_machine_deployment_template
338
+ # as per: https://github.com/Azure/azure-quickstart-templates/blob/master/101-simple-linux-vm/azuredeploy.json
339
+ <<-EOH
340
+ {
341
+ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
342
+ "contentVersion": "1.0.0.0",
343
+ "parameters": {
344
+ "location": {
345
+ "type": "string",
346
+ "metadata": {
347
+ "description": "The location where the resources will be created."
348
+ }
349
+ },
350
+ "vmSize": {
351
+ "type": "string",
352
+ "metadata": {
353
+ "description": "The size of the VM to be created"
354
+ }
355
+ },
356
+ "newStorageAccountName": {
357
+ "type": "string",
358
+ "metadata": {
359
+ "description": "Unique DNS Name for the Storage Account where the Virtual Machine's disks will be placed."
360
+ }
361
+ },
362
+ "adminUsername": {
363
+ "type": "string",
364
+ "metadata": {
365
+ "description": "User name for the Virtual Machine."
366
+ }
367
+ },
368
+ "adminPassword": {
369
+ "type": "securestring",
370
+ "metadata": {
371
+ "description": "Password for the Virtual Machine."
372
+ }
373
+ },
374
+ "dnsNameForPublicIP": {
375
+ "type": "string",
376
+ "metadata": {
377
+ "description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
378
+ }
379
+ },
380
+ "ubuntuOSVersion": {
381
+ "type": "string",
382
+ "defaultValue": "14.04.2-LTS",
383
+ "allowedValues": [
384
+ "12.04.5-LTS",
385
+ "14.04.2-LTS",
386
+ "15.04"
387
+ ],
388
+ "metadata": {
389
+ "description": "The Ubuntu version for the VM. This will pick a fully patched image of this given Ubuntu version. Allowed values: 12.04.5-LTS, 14.04.2-LTS, 15.04."
390
+ }
391
+ }
392
+ },
393
+ "variables": {
394
+ "location": "[parameters('location')]",
395
+ "imagePublisher": "Canonical",
396
+ "imageOffer": "UbuntuServer",
397
+ "OSDiskName": "osdiskforlinuxsimple",
398
+ "nicName": "myVMNic",
399
+ "addressPrefix": "10.0.0.0/16",
400
+ "subnetName": "Subnet",
401
+ "subnetPrefix": "10.0.0.0/24",
402
+ "storageAccountType": "Standard_LRS",
403
+ "publicIPAddressName": "myPublicIP",
404
+ "publicIPAddressType": "Dynamic",
405
+ "vmStorageAccountContainerName": "vhds",
406
+ "vmName": "linux-vm",
407
+ "vmSize": "[parameters('vmSize')]",
408
+ "virtualNetworkName": "MyVNET",
409
+ "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]",
410
+ "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]"
411
+ },
412
+ "resources": [
413
+ {
414
+ "type": "Microsoft.Storage/storageAccounts",
415
+ "name": "[parameters('newStorageAccountName')]",
416
+ "apiVersion": "2015-05-01-preview",
417
+ "location": "[variables('location')]",
418
+ "properties": {
419
+ "accountType": "[variables('storageAccountType')]"
420
+ }
421
+ },
422
+ {
423
+ "apiVersion": "2015-05-01-preview",
424
+ "type": "Microsoft.Network/publicIPAddresses",
425
+ "name": "[variables('publicIPAddressName')]",
426
+ "location": "[variables('location')]",
427
+ "properties": {
428
+ "publicIPAllocationMethod": "[variables('publicIPAddressType')]",
429
+ "dnsSettings": {
430
+ "domainNameLabel": "[parameters('dnsNameForPublicIP')]"
431
+ }
432
+ }
433
+ },
434
+ {
435
+ "apiVersion": "2015-05-01-preview",
436
+ "type": "Microsoft.Network/virtualNetworks",
437
+ "name": "[variables('virtualNetworkName')]",
438
+ "location": "[variables('location')]",
439
+ "properties": {
440
+ "addressSpace": {
441
+ "addressPrefixes": [
442
+ "[variables('addressPrefix')]"
443
+ ]
444
+ },
445
+ "subnets": [
446
+ {
447
+ "name": "[variables('subnetName')]",
448
+ "properties": {
449
+ "addressPrefix": "[variables('subnetPrefix')]"
450
+ }
451
+ }
452
+ ]
453
+ }
454
+ },
455
+ {
456
+ "apiVersion": "2015-05-01-preview",
457
+ "type": "Microsoft.Network/networkInterfaces",
458
+ "name": "[variables('nicName')]",
459
+ "location": "[variables('location')]",
460
+ "dependsOn": [
461
+ "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
462
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
463
+ ],
464
+ "properties": {
465
+ "ipConfigurations": [
466
+ {
467
+ "name": "ipconfig1",
468
+ "properties": {
469
+ "privateIPAllocationMethod": "Dynamic",
470
+ "publicIPAddress": {
471
+ "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]"
472
+ },
473
+ "subnet": {
474
+ "id": "[variables('subnetRef')]"
475
+ }
476
+ }
477
+ }
478
+ ]
479
+ }
480
+ },
481
+ {
482
+ "apiVersion": "2015-06-15",
483
+ "type": "Microsoft.Compute/virtualMachines",
484
+ "name": "[variables('vmName')]",
485
+ "location": "[variables('location')]",
486
+ "dependsOn": [
487
+ "[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]",
488
+ "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
489
+ ],
490
+ "properties": {
491
+ "hardwareProfile": {
492
+ "vmSize": "[variables('vmSize')]"
493
+ },
494
+ "osProfile": {
495
+ "computername": "[variables('vmName')]",
496
+ "adminUsername": "[parameters('adminUsername')]",
497
+ "adminPassword": "[parameters('adminPassword')]"
498
+ },
499
+ "storageProfile": {
500
+ "imageReference": {
501
+ "publisher": "[variables('imagePublisher')]",
502
+ "offer": "[variables('imageOffer')]",
503
+ "sku": "[parameters('ubuntuOSVersion')]",
504
+ "version": "latest"
505
+ },
506
+ "osDisk": {
507
+ "name": "osdisk",
508
+ "vhd": {
509
+ "uri": "[concat('http://',parameters('newStorageAccountName'),'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]"
510
+ },
511
+ "caching": "ReadWrite",
512
+ "createOption": "FromImage"
513
+ }
514
+ },
515
+ "networkProfile": {
516
+ "networkInterfaces": [
517
+ {
518
+ "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]"
519
+ }
520
+ ]
521
+ },
522
+ "diagnosticsProfile": {
523
+ "bootDiagnostics": {
524
+ "enabled": "false",
525
+ "storageUri": "[concat('http://',parameters('newStorageAccountName'),'.blob.core.windows.net')]"
526
+ }
527
+ }
528
+ }
529
+ }
530
+ ]
531
+ }
532
+ EOH
533
+ end
534
+ end
535
+ end
536
+ end
@@ -0,0 +1,42 @@
1
+ require 'inifile'
2
+
3
+ module Kitchen
4
+ module Driver
5
+ #
6
+ # Credentials
7
+ #
8
+ class Credentials
9
+ CONFIG_PATH = "#{ENV['HOME']}/.azure/credentials"
10
+
11
+ #
12
+ # Creates and initializes a new instance of the Credentials class.
13
+ #
14
+ def initialize
15
+ config_file = ENV['AZURE_CONFIG_FILE'] || File.expand_path(CONFIG_PATH)
16
+ if File.file?(config_file)
17
+ @credentials = IniFile.load(File.expand_path(config_file))
18
+ else
19
+ Chef::Log.warn "#{CONFIG_PATH} was not found or not accessible." unless File.file?(config_file)
20
+ end
21
+ end
22
+
23
+ #
24
+ # Retrieves a [MsRest::TokenCredentials] object representing a token for the given Service Principal.
25
+ # @param subscription_id [String] The subscription_id to retrieve a token for
26
+ #
27
+ # @return [MsRest::TokenCredentials] TokenCredentials object to be passed in with each subsequent request.
28
+ #
29
+ def azure_credentials_for_subscription(subscription_id)
30
+ tenant_id = ENV['AZURE_TENANT_ID'] || @credentials[subscription_id]['tenant_id']
31
+ client_id = ENV['AZURE_CLIENT_ID'] || @credentials[subscription_id]['client_id']
32
+ client_secret = ENV['AZURE_CLIENT_SECRET'] || @credentials[subscription_id]['client_secret']
33
+ token_provider = ::MsRestAzure::ApplicationTokenProvider.new(tenant_id, client_id, client_secret)
34
+ ::MsRest::TokenCredentials.new(token_provider)
35
+ end
36
+
37
+ def self.singleton
38
+ @credentials ||= Credentials.new
39
+ end
40
+ end
41
+ end
42
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kitchen-azurerm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - Stuart Preston
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: inifile
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: azure_mgmt_resources
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: azure_mgmt_storage
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: azure_mgmt_compute
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.1.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: azure_mgmt_network
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 0.1.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 0.1.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.7'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.7'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ description: Test Kitchen driver for the Microsoft Azure Resource Manager (ARM) API
112
+ email:
113
+ - stuart@pendrica.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - LICENSE
119
+ - README.md
120
+ - lib/kitchen/driver/azurerm.rb
121
+ - lib/kitchen/driver/credentials.rb
122
+ homepage: https://github.com/pendrica/kitchen-azurerm
123
+ licenses:
124
+ - Apache-2.0
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">"
138
+ - !ruby/object:Gem::Version
139
+ version: 1.3.1
140
+ requirements: []
141
+ rubyforge_project:
142
+ rubygems_version: 2.4.4
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: Test Kitchen driver for Azure Resource Manager.
146
+ test_files: []
147
+ has_rdoc: