kitchen-azurerm 0.15.1 → 0.15.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/kitchen/driver/{credentials.rb → azure_credentials.rb} +42 -25
- data/lib/kitchen/driver/azurerm.rb +142 -25
- data/templates/internal.erb +6 -2
- data/templates/public.erb +6 -2
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48df20f4bbd7b6087cfde1ec03770f559f0fbd45e01bc01834e95e95d8f9c3b6
|
4
|
+
data.tar.gz: 6cc4e949b4fbc6bf173664fb4ee5f7aa3eb9bcfa5254c70a6642767c53425ce6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71daccd76e78290d7c601b293d3e54c8a9fc4f1fd06a7d754d8dc0ea900c516424d05dbe50d1c5011a52862a5ac8a6f738cb183fd31ca280fe8637cf6fe3ba01
|
7
|
+
data.tar.gz: acadd9d7ea7152cac675428e0203a12d6d79b187d7ae4603be1795edbe3498c7b3ccffec5457f22e864bc1623b203d58ba666f522c3a1f65dd8331cdd70d6c79
|
data/README.md
CHANGED
@@ -618,7 +618,7 @@ info: vm image list command OK
|
|
618
618
|
|
619
619
|
### Additional parameters that can be specified
|
620
620
|
|
621
|
-
* Note that the ```driver``` section also takes a ```username``` and ```password
|
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.
|
622
622
|
|
623
623
|
* The ```storage_account_type``` parameter defaults to 'Standard_LRS' and allows you to switch to premium storage (e.g. 'Premium_LRS')
|
624
624
|
|
@@ -3,15 +3,27 @@ require "inifile"
|
|
3
3
|
module Kitchen
|
4
4
|
module Driver
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# AzureCredentials
|
7
7
|
#
|
8
|
-
class
|
8
|
+
class AzureCredentials
|
9
9
|
CONFIG_PATH = "#{ENV["HOME"]}/.azure/credentials".freeze
|
10
10
|
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
attr_reader :subscription_id
|
15
|
+
|
16
|
+
#
|
17
|
+
# @return [String]
|
18
|
+
#
|
19
|
+
attr_reader :environment
|
20
|
+
|
11
21
|
#
|
12
22
|
# Creates and initializes a new instance of the Credentials class.
|
13
23
|
#
|
14
|
-
def initialize
|
24
|
+
def initialize(subscription_id:, environment: "Azure")
|
25
|
+
@subscription_id = subscription_id
|
26
|
+
@environment = environment
|
15
27
|
config_file = ENV["AZURE_CONFIG_FILE"] || File.expand_path(CONFIG_PATH)
|
16
28
|
if File.file?(config_file)
|
17
29
|
@credentials = IniFile.load(File.expand_path(config_file))
|
@@ -21,37 +33,47 @@ module Kitchen
|
|
21
33
|
end
|
22
34
|
|
23
35
|
#
|
24
|
-
# Retrieves an object containing options and credentials
|
25
|
-
# subscription_id and azure_environment.
|
26
|
-
#
|
27
|
-
# @param subscription_id [String] The subscription_id to retrieve a token for
|
28
|
-
# @param azure_environment [String] The azure_environment to use
|
36
|
+
# Retrieves an object containing options and credentials
|
29
37
|
#
|
30
38
|
# @return [Object] Object that can be supplied along with all Azure client requests.
|
31
39
|
#
|
32
|
-
def
|
33
|
-
tenant_id = ENV["AZURE_TENANT_ID"] || @credentials[subscription_id]["tenant_id"]
|
34
|
-
client_id = ENV["AZURE_CLIENT_ID"] || @credentials[subscription_id]["client_id"]
|
35
|
-
client_secret = ENV["AZURE_CLIENT_SECRET"] || @credentials[subscription_id]["client_secret"]
|
36
|
-
token_provider = ::MsRestAzure::ApplicationTokenProvider.new(tenant_id, client_id, client_secret, ad_settings_for_azure_environment(azure_environment))
|
40
|
+
def azure_options
|
37
41
|
options = { tenant_id: tenant_id,
|
38
42
|
client_id: client_id,
|
39
43
|
client_secret: client_secret,
|
40
44
|
subscription_id: subscription_id,
|
41
45
|
credentials: ::MsRest::TokenCredentials.new(token_provider),
|
42
|
-
active_directory_settings:
|
43
|
-
base_url:
|
46
|
+
active_directory_settings: ad_settings,
|
47
|
+
base_url: endpoint_settings.resource_manager_endpoint_url }
|
48
|
+
|
44
49
|
options
|
45
50
|
end
|
46
51
|
|
52
|
+
private
|
53
|
+
|
54
|
+
def tenant_id
|
55
|
+
ENV["AZURE_TENANT_ID"] || @credentials[subscription_id]["tenant_id"]
|
56
|
+
end
|
57
|
+
|
58
|
+
def client_id
|
59
|
+
ENV["AZURE_CLIENT_ID"] || @credentials[subscription_id]["client_id"]
|
60
|
+
end
|
61
|
+
|
62
|
+
def client_secret
|
63
|
+
ENV["AZURE_CLIENT_SECRET"] || @credentials[subscription_id]["client_secret"]
|
64
|
+
end
|
65
|
+
|
66
|
+
def token_provider
|
67
|
+
::MsRestAzure::ApplicationTokenProvider.new(tenant_id, client_id, client_secret, ad_settings)
|
68
|
+
end
|
69
|
+
|
47
70
|
#
|
48
71
|
# Retrieves a [MsRestAzure::ActiveDirectoryServiceSettings] object representing the AD settings for the given cloud.
|
49
|
-
# @param azure_environment [String] The Azure environment to retrieve settings for.
|
50
72
|
#
|
51
73
|
# @return [MsRestAzure::ActiveDirectoryServiceSettings] Settings to be used for subsequent requests
|
52
74
|
#
|
53
|
-
def
|
54
|
-
case
|
75
|
+
def ad_settings
|
76
|
+
case environment.downcase
|
55
77
|
when "azureusgovernment"
|
56
78
|
::MsRestAzure::ActiveDirectoryServiceSettings.get_azure_us_government_settings
|
57
79
|
when "azurechina"
|
@@ -65,12 +87,11 @@ module Kitchen
|
|
65
87
|
|
66
88
|
#
|
67
89
|
# Retrieves a [MsRestAzure::AzureEnvironment] object representing endpoint settings for the given cloud.
|
68
|
-
# @param azure_environment [String] The Azure environment to retrieve settings for.
|
69
90
|
#
|
70
91
|
# @return [MsRestAzure::AzureEnvironment] Settings to be used for subsequent requests
|
71
92
|
#
|
72
|
-
def
|
73
|
-
case
|
93
|
+
def endpoint_settings
|
94
|
+
case environment.downcase
|
74
95
|
when "azureusgovernment"
|
75
96
|
::MsRestAzure::AzureEnvironments::AzureUSGovernment
|
76
97
|
when "azurechina"
|
@@ -81,10 +102,6 @@ module Kitchen
|
|
81
102
|
::MsRestAzure::AzureEnvironments::AzureCloud
|
82
103
|
end
|
83
104
|
end
|
84
|
-
|
85
|
-
def self.singleton
|
86
|
-
@credentials ||= Credentials.new
|
87
|
-
end
|
88
105
|
end
|
89
106
|
end
|
90
107
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require "kitchen"
|
2
|
-
require_relative "
|
2
|
+
require_relative "azure_credentials"
|
3
3
|
require "securerandom"
|
4
4
|
require "azure_mgmt_resources"
|
5
5
|
require "azure_mgmt_network"
|
@@ -9,6 +9,7 @@ require "fileutils"
|
|
9
9
|
require "erb"
|
10
10
|
require "ostruct"
|
11
11
|
require "json"
|
12
|
+
require "faraday"
|
12
13
|
|
13
14
|
module Kitchen
|
14
15
|
module Driver
|
@@ -17,6 +18,7 @@ module Kitchen
|
|
17
18
|
#
|
18
19
|
class Azurerm < Kitchen::Driver::Base
|
19
20
|
attr_accessor :resource_management_client
|
21
|
+
attr_accessor :network_management_client
|
20
22
|
|
21
23
|
default_config(:azure_resource_group_prefix) do |_config|
|
22
24
|
"kitchen-"
|
@@ -71,7 +73,7 @@ module Kitchen
|
|
71
73
|
end
|
72
74
|
|
73
75
|
default_config(:password) do |_config|
|
74
|
-
|
76
|
+
SecureRandom.base64(12)
|
75
77
|
end
|
76
78
|
|
77
79
|
default_config(:vm_name) do |_config|
|
@@ -190,6 +192,10 @@ module Kitchen
|
|
190
192
|
ENV["AZURE_SUBSCRIPTION_ID"]
|
191
193
|
end
|
192
194
|
|
195
|
+
default_config(:azure_api_retries) do |_config|
|
196
|
+
5
|
197
|
+
end
|
198
|
+
|
193
199
|
def create(state)
|
194
200
|
state = validate_state(state)
|
195
201
|
deployment_parameters = {
|
@@ -199,7 +205,6 @@ module Kitchen
|
|
199
205
|
bootDiagnosticsEnabled: config[:boot_diagnostics_enabled],
|
200
206
|
newStorageAccountName: "storage#{state[:uuid]}",
|
201
207
|
adminUsername: state[:username],
|
202
|
-
adminPassword: state[:password] || "P2ssw0rd",
|
203
208
|
dnsNameForPublicIP: "kitchen-#{state[:uuid]}",
|
204
209
|
vmName: state[:vm_name],
|
205
210
|
systemAssignedIdentity: config[:system_assigned_identity],
|
@@ -209,6 +214,10 @@ module Kitchen
|
|
209
214
|
vaultResourceGroup: config[:vault_resource_group],
|
210
215
|
}
|
211
216
|
|
217
|
+
if instance.transport[:ssh_key].nil?
|
218
|
+
deployment_parameters["adminPassword"] = state[:password]
|
219
|
+
end
|
220
|
+
|
212
221
|
if config[:subscription_id].to_s == ""
|
213
222
|
raise "A subscription_id config value was not detected and kitchen-azurerm cannot continue. Please check your .kitchen.yml configuration. Exiting."
|
214
223
|
end
|
@@ -255,7 +264,8 @@ module Kitchen
|
|
255
264
|
deployment_parameters["imageVersion"] = image_version
|
256
265
|
end
|
257
266
|
|
258
|
-
options = Kitchen::Driver::
|
267
|
+
options = Kitchen::Driver::AzureCredentials.new(subscription_id: config[:subscription_id],
|
268
|
+
environment: config[:azure_environment]).azure_options
|
259
269
|
|
260
270
|
debug "Azure environment: #{config[:azure_environment]}"
|
261
271
|
@resource_management_client = ::Azure::Resources::Profiles::Latest::Mgmt::Client.new(options)
|
@@ -266,7 +276,7 @@ module Kitchen
|
|
266
276
|
resource_group.tags = config[:resource_group_tags]
|
267
277
|
begin
|
268
278
|
info "Creating Resource Group: #{state[:azure_resource_group_name]}"
|
269
|
-
|
279
|
+
create_resource_group(state[:azure_resource_group_name], resource_group)
|
270
280
|
rescue ::MsRestAzure::AzureOperationError => operation_error
|
271
281
|
error operation_error.body
|
272
282
|
raise operation_error
|
@@ -277,17 +287,17 @@ module Kitchen
|
|
277
287
|
if File.file?(config[:pre_deployment_template])
|
278
288
|
pre_deployment_name = "pre-deploy-#{state[:uuid]}"
|
279
289
|
info "Creating deployment: #{pre_deployment_name}"
|
280
|
-
|
290
|
+
create_deployment_async(state[:azure_resource_group_name], pre_deployment_name, pre_deployment(config[:pre_deployment_template], config[:pre_deployment_parameters])).value!
|
281
291
|
follow_deployment_until_end_state(state[:azure_resource_group_name], pre_deployment_name)
|
282
292
|
end
|
283
293
|
deployment_name = "deploy-#{state[:uuid]}"
|
284
294
|
info "Creating deployment: #{deployment_name}"
|
285
|
-
|
295
|
+
create_deployment_async(state[:azure_resource_group_name], deployment_name, deployment(deployment_parameters)).value!
|
286
296
|
follow_deployment_until_end_state(state[:azure_resource_group_name], deployment_name)
|
287
297
|
if File.file?(config[:post_deployment_template])
|
288
298
|
post_deployment_name = "post-deploy-#{state[:uuid]}"
|
289
299
|
info "Creating deployment: #{post_deployment_name}"
|
290
|
-
|
300
|
+
create_deployment_async(state[:azure_resource_group_name], post_deployment_name, post_deployment(config[:post_deployment_template], config[:post_deployment_parameters])).value!
|
291
301
|
follow_deployment_until_end_state(state[:azure_resource_group_name], post_deployment_name)
|
292
302
|
end
|
293
303
|
rescue ::MsRestAzure::AzureOperationError => operation_error
|
@@ -302,17 +312,16 @@ module Kitchen
|
|
302
312
|
end
|
303
313
|
end
|
304
314
|
|
305
|
-
network_management_client = ::Azure::Network::Profiles::Latest::Mgmt::Client.new(options)
|
315
|
+
@network_management_client = ::Azure::Network::Profiles::Latest::Mgmt::Client.new(options)
|
306
316
|
|
307
317
|
if config[:vnet_id] == "" || config[:public_ip]
|
308
318
|
# Retrieve the public IP from the resource group:
|
309
|
-
result =
|
319
|
+
result = get_public_ip(state[:azure_resource_group_name], "publicip")
|
310
320
|
info "IP Address is: #{result.ip_address} [#{result.dns_settings.fqdn}]"
|
311
321
|
state[:hostname] = result.ip_address
|
312
322
|
else
|
313
323
|
# Retrieve the internal IP from the resource group:
|
314
|
-
|
315
|
-
result = network_interfaces.get(state[:azure_resource_group_name], vmnic.to_s)
|
324
|
+
result = get_network_interface(state[:azure_resource_group_name], vmnic.to_s)
|
316
325
|
info "IP Address is: #{result.ip_configurations[0].private_ipaddress}"
|
317
326
|
state[:hostname] = result.ip_configurations[0].private_ipaddress
|
318
327
|
end
|
@@ -475,7 +484,7 @@ module Kitchen
|
|
475
484
|
until end_provisioning_state_reached
|
476
485
|
list_outstanding_deployment_operations(resource_group, deployment_name)
|
477
486
|
sleep config[:deployment_sleep]
|
478
|
-
deployment_provisioning_state =
|
487
|
+
deployment_provisioning_state = get_deployment_state(resource_group, deployment_name)
|
479
488
|
end_provisioning_state_reached = end_provisioning_states.split(",").include?(deployment_provisioning_state)
|
480
489
|
end
|
481
490
|
info "Resource Template deployment reached end state of '#{deployment_provisioning_state}'."
|
@@ -483,7 +492,7 @@ module Kitchen
|
|
483
492
|
end
|
484
493
|
|
485
494
|
def show_failed_operations(resource_group, deployment_name)
|
486
|
-
failed_operations =
|
495
|
+
failed_operations = list_deployment_operations(resource_group, deployment_name)
|
487
496
|
failed_operations.each do |val|
|
488
497
|
resource_code = val.properties.status_code
|
489
498
|
raise val.properties.status_message.inspect.to_s if resource_code != "OK"
|
@@ -492,7 +501,7 @@ module Kitchen
|
|
492
501
|
|
493
502
|
def list_outstanding_deployment_operations(resource_group, deployment_name)
|
494
503
|
end_operation_states = "Failed,Succeeded"
|
495
|
-
deployment_operations =
|
504
|
+
deployment_operations = list_deployment_operations(resource_group, deployment_name)
|
496
505
|
deployment_operations.each do |val|
|
497
506
|
resource_provisioning_state = val.properties.provisioning_state
|
498
507
|
unless val.properties.target_resource.nil?
|
@@ -506,22 +515,18 @@ module Kitchen
|
|
506
515
|
end
|
507
516
|
end
|
508
517
|
|
509
|
-
def deployment_state(resource_group, deployment_name)
|
510
|
-
deployments = resource_management_client.deployments.get(resource_group, deployment_name)
|
511
|
-
deployments.properties.provisioning_state
|
512
|
-
end
|
513
|
-
|
514
518
|
def destroy(state)
|
515
519
|
return if state[:server_id].nil?
|
516
520
|
|
517
|
-
options = Kitchen::Driver::
|
521
|
+
options = Kitchen::Driver::AzureCredentials.new(subscription_id: state[:subscription_id],
|
522
|
+
environment: state[:azure_environment]).azure_options
|
518
523
|
@resource_management_client = ::Azure::Resources::Profiles::Latest::Mgmt::Client.new(options)
|
519
524
|
if config[:destroy_resource_group_contents] == true
|
520
525
|
info "Destroying individual resources within the Resource Group."
|
521
526
|
empty_deployment_name = "empty-deploy-#{state[:uuid]}"
|
522
527
|
begin
|
523
528
|
info "Creating deployment: #{empty_deployment_name}"
|
524
|
-
|
529
|
+
create_deployment_async(state[:azure_resource_group_name], empty_deployment_name, empty_deployment).value!
|
525
530
|
follow_deployment_until_end_state(state[:azure_resource_group_name], empty_deployment_name)
|
526
531
|
rescue ::MsRestAzure::AzureOperationError => operation_error
|
527
532
|
error operation_error.body
|
@@ -536,7 +541,7 @@ module Kitchen
|
|
536
541
|
info "Azure environment: #{state[:azure_environment]}"
|
537
542
|
begin
|
538
543
|
info "Destroying Resource Group: #{state[:azure_resource_group_name]}"
|
539
|
-
|
544
|
+
delete_resource_group_async(state[:azure_resource_group_name])
|
540
545
|
info "Destroy operation accepted and will continue in the background."
|
541
546
|
rescue ::MsRestAzure::AzureOperationError => operation_error
|
542
547
|
error operation_error.body
|
@@ -638,10 +643,10 @@ module Kitchen
|
|
638
643
|
|
639
644
|
def virtual_machine_deployment_template
|
640
645
|
if config[:vnet_id] == ""
|
641
|
-
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])
|
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])
|
642
647
|
else
|
643
648
|
info "Using custom vnet: #{config[:vnet_id]}"
|
644
|
-
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])
|
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])
|
645
650
|
end
|
646
651
|
end
|
647
652
|
|
@@ -676,6 +681,118 @@ module Kitchen
|
|
676
681
|
end
|
677
682
|
end
|
678
683
|
end
|
684
|
+
|
685
|
+
private
|
686
|
+
|
687
|
+
#
|
688
|
+
# Wrapper methods for the Azure API calls to retry the calls when getting timeouts.
|
689
|
+
#
|
690
|
+
|
691
|
+
def create_resource_group(resource_group_name, resource_group)
|
692
|
+
retries = config[:azure_api_retries]
|
693
|
+
begin
|
694
|
+
resource_management_client.resource_groups.create_or_update(resource_group_name, resource_group)
|
695
|
+
rescue Faraday::TimeoutError, Faraday::ClientError => exception
|
696
|
+
send_exception_message(exception, "while creating resource group '#{resource_group_name}'. #{retries} retries left.")
|
697
|
+
raise if retries == 0
|
698
|
+
|
699
|
+
retries -= 1
|
700
|
+
retry
|
701
|
+
end
|
702
|
+
end
|
703
|
+
|
704
|
+
def create_deployment_async(resource_group, deployment_name, deployment)
|
705
|
+
retries = config[:azure_api_retries]
|
706
|
+
begin
|
707
|
+
resource_management_client.deployments.begin_create_or_update_async(resource_group, deployment_name, deployment)
|
708
|
+
rescue Faraday::TimeoutError, Faraday::ClientError => exception
|
709
|
+
send_exception_message(exception, "while sending deployment creation request for deployment '#{deployment_name}'. #{retries} retries left.")
|
710
|
+
raise if retries == 0
|
711
|
+
|
712
|
+
retries -= 1
|
713
|
+
retry
|
714
|
+
end
|
715
|
+
end
|
716
|
+
|
717
|
+
def get_public_ip(resource_group_name, public_ip_name)
|
718
|
+
retries = config[:azure_api_retries]
|
719
|
+
begin
|
720
|
+
network_management_client.public_ipaddresses.get(resource_group_name, public_ip_name)
|
721
|
+
rescue Faraday::TimeoutError, Faraday::ClientError => exception
|
722
|
+
send_exception_message(exception, "while fetching public ip '#{public_ip_name}' for resource group '#{resource_group_name}'. #{retries} retries left.")
|
723
|
+
raise if retries == 0
|
724
|
+
|
725
|
+
retries -= 1
|
726
|
+
retry
|
727
|
+
end
|
728
|
+
end
|
729
|
+
|
730
|
+
def get_network_interface(resource_group_name, network_interface_name)
|
731
|
+
retries = config[:azure_api_retries]
|
732
|
+
begin
|
733
|
+
network_interfaces = ::Azure::Network::Profiles::Latest::Mgmt::NetworkInterfaces.new(network_management_client)
|
734
|
+
network_interfaces.get(resource_group_name, network_interface_name)
|
735
|
+
rescue Faraday::TimeoutError, Faraday::ClientError => exception
|
736
|
+
send_exception_message(exception, "while fetching network interface '#{network_interface_name}' for resource group '#{resource_group_name}'. #{retries} retries left.")
|
737
|
+
raise if retries == 0
|
738
|
+
|
739
|
+
retries -= 1
|
740
|
+
retry
|
741
|
+
end
|
742
|
+
end
|
743
|
+
|
744
|
+
def list_deployment_operations(resource_group, deployment_name)
|
745
|
+
retries = config[:azure_api_retries]
|
746
|
+
begin
|
747
|
+
resource_management_client.deployment_operations.list(resource_group, deployment_name)
|
748
|
+
rescue Faraday::TimeoutError, Faraday::ClientError => exception
|
749
|
+
send_exception_message(exception, "while listing deployment operations for deployment '#{deployment_name}'. #{retries} retries left.")
|
750
|
+
raise if retries == 0
|
751
|
+
|
752
|
+
retries -= 1
|
753
|
+
retry
|
754
|
+
end
|
755
|
+
end
|
756
|
+
|
757
|
+
def get_deployment_state(resource_group, deployment_name)
|
758
|
+
retries = config[:azure_api_retries]
|
759
|
+
begin
|
760
|
+
deployments = resource_management_client.deployments.get(resource_group, deployment_name)
|
761
|
+
deployments.properties.provisioning_state
|
762
|
+
rescue Faraday::TimeoutError, Faraday::ClientError => exception
|
763
|
+
send_exception_message(exception, "while retrieving state for deployment '#{deployment_name}'. #{retries} retries left.")
|
764
|
+
raise if retries == 0
|
765
|
+
|
766
|
+
retries -= 1
|
767
|
+
retry
|
768
|
+
end
|
769
|
+
end
|
770
|
+
|
771
|
+
def delete_resource_group_async(resource_group_name)
|
772
|
+
retries = config[:azure_api_retries]
|
773
|
+
begin
|
774
|
+
resource_management_client.resource_groups.begin_delete(resource_group_name)
|
775
|
+
rescue Faraday::TimeoutError, Faraday::ClientError => exception
|
776
|
+
send_exception_message(exception, "while sending resource group deletion request for '#{resource_group_name}'. #{retries} retries left.")
|
777
|
+
raise if retries == 0
|
778
|
+
|
779
|
+
retries -= 1
|
780
|
+
retry
|
781
|
+
end
|
782
|
+
end
|
783
|
+
|
784
|
+
def send_exception_message(exception, message)
|
785
|
+
if exception.is_a?(Faraday::TimeoutError)
|
786
|
+
header = "Timed out"
|
787
|
+
elsif exception.is_a?(Faraday::ClientError)
|
788
|
+
header = "Connection reset by peer"
|
789
|
+
else
|
790
|
+
# Unhandled exception, return early
|
791
|
+
info "Unrecognized exception type."
|
792
|
+
return
|
793
|
+
end
|
794
|
+
info "#{header} #{message}"
|
795
|
+
end
|
679
796
|
end
|
680
797
|
end
|
681
798
|
end
|
data/templates/internal.erb
CHANGED
@@ -26,12 +26,14 @@
|
|
26
26
|
"description": "User name for the Virtual Machine."
|
27
27
|
}
|
28
28
|
},
|
29
|
+
<%- if ssh_key.nil? -%>
|
29
30
|
"adminPassword": {
|
30
31
|
"type": "securestring",
|
31
32
|
"metadata": {
|
32
33
|
"description": "Password for the Virtual Machine."
|
33
34
|
}
|
34
35
|
},
|
36
|
+
<%- end -%>
|
35
37
|
"dnsNameForPublicIP": {
|
36
38
|
"type": "string",
|
37
39
|
"metadata": {
|
@@ -322,8 +324,10 @@
|
|
322
324
|
]
|
323
325
|
],
|
324
326
|
<%- end -%>
|
325
|
-
|
326
|
-
"adminPassword": "[parameters('adminPassword')]"
|
327
|
+
<%- if ssh_key.nil? -%>
|
328
|
+
"adminPassword": "[parameters('adminPassword')]",
|
329
|
+
<%- end -%>
|
330
|
+
"adminUsername": "[parameters('adminUsername')]"
|
327
331
|
},
|
328
332
|
"storageProfile": {
|
329
333
|
<%- if image_url.empty? and image_id.empty? -%>
|
data/templates/public.erb
CHANGED
@@ -26,12 +26,14 @@
|
|
26
26
|
"description": "User name for the Virtual Machine."
|
27
27
|
}
|
28
28
|
},
|
29
|
+
<%- if ssh_key.nil? -%>
|
29
30
|
"adminPassword": {
|
30
31
|
"type": "securestring",
|
31
32
|
"metadata": {
|
32
33
|
"description": "Password for the Virtual Machine."
|
33
34
|
}
|
34
35
|
},
|
36
|
+
<%- end -%>
|
35
37
|
"dnsNameForPublicIP": {
|
36
38
|
"type": "string",
|
37
39
|
"metadata": {
|
@@ -341,8 +343,10 @@
|
|
341
343
|
]
|
342
344
|
],
|
343
345
|
<%- end -%>
|
344
|
-
|
345
|
-
"adminPassword": "[parameters('adminPassword')]"
|
346
|
+
<%- if ssh_key.nil? -%>
|
347
|
+
"adminPassword": "[parameters('adminPassword')]",
|
348
|
+
<%- end -%>
|
349
|
+
"adminUsername": "[parameters('adminUsername')]"
|
346
350
|
},
|
347
351
|
"storageProfile": {
|
348
352
|
<%- if image_url.empty? and image_id.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.
|
4
|
+
version: 0.15.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stuart Preston
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: azure_mgmt_network
|
@@ -54,22 +54,22 @@ dependencies:
|
|
54
54
|
name: inifile
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|
57
|
-
- - ">="
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: 3.0.0
|
60
57
|
- - "~>"
|
61
58
|
- !ruby/object:Gem::Version
|
62
59
|
version: '3.0'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 3.0.0
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- - ">="
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: 3.0.0
|
70
67
|
- - "~>"
|
71
68
|
- !ruby/object:Gem::Version
|
72
69
|
version: '3.0'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 3.0.0
|
73
73
|
- !ruby/object:Gem::Dependency
|
74
74
|
name: sshkey
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
@@ -141,8 +141,8 @@ extra_rdoc_files: []
|
|
141
141
|
files:
|
142
142
|
- LICENSE
|
143
143
|
- README.md
|
144
|
+
- lib/kitchen/driver/azure_credentials.rb
|
144
145
|
- lib/kitchen/driver/azurerm.rb
|
145
|
-
- lib/kitchen/driver/credentials.rb
|
146
146
|
- templates/empty.erb
|
147
147
|
- templates/internal.erb
|
148
148
|
- templates/public.erb
|
@@ -165,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
167
|
requirements: []
|
168
|
-
rubygems_version: 3.
|
168
|
+
rubygems_version: 3.1.2
|
169
169
|
signing_key:
|
170
170
|
specification_version: 4
|
171
171
|
summary: Test Kitchen driver for Azure Resource Manager.
|