knife-azure 1.7.0 → 1.8.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/README.md +12 -14
- data/lib/azure/resource_management/ARM_deployment_template.rb +94 -14
- data/lib/azure/resource_management/ARM_interface.rb +83 -83
- data/lib/azure/resource_management/vnet_config.rb +6 -6
- data/lib/azure/resource_management/windows_credentials.rb +1 -1
- data/lib/chef/knife/azure_base.rb +1 -0
- data/lib/chef/knife/azure_server_create.rb +19 -5
- data/lib/chef/knife/azure_server_delete.rb +1 -1
- data/lib/chef/knife/azurerm_base.rb +81 -2
- data/lib/chef/knife/azurerm_server_create.rb +13 -34
- data/lib/chef/knife/bootstrap/bootstrap_options.rb +10 -3
- data/lib/chef/knife/bootstrap/bootstrapper.rb +24 -13
- data/lib/chef/knife/bootstrap/common_bootstrap_options.rb +10 -3
- data/lib/chef/knife/bootstrap_azurerm.rb +4 -4
- data/lib/knife-azure/version.rb +1 -1
- metadata +15 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea0e76928647e01eb3f500a3a8d907c9445545ac
|
4
|
+
data.tar.gz: 986e61a68caaa29728a7f3293cbfa39f958ebcd9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35b24edba5370648f1377069c2d1c497373467ec15526125749dacdc37260eeefada00acdfe0ff581ee06f72ae4a73e5fed4285e8fbd02ca2d526d8caaef2df0
|
7
|
+
data.tar.gz: 93bf2f05f813fd46e94acb8d3f5293874026437e6b8a92327bd31e46f51264924e219bbb99fd08ea89aff90304c6a1e0880a991fb245edadc4871af53d8c7946
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
A [knife] (<http://docs.chef.io/knife.html>) plugin to create, delete, and enumerate [Microsoft Azure] (<https://azure.microsoft.com>) resources to be managed by Chef.
|
8
8
|
|
9
|
-
NOTE: You may also want to consider using the [
|
9
|
+
NOTE: You may also want to consider using the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli), this application is written by the Azure team and has many other integrations with Azure. If click [here](https://github.com/chef-partners/azure-chef-extension/blob/master/examples/azure-xplat-cli-examples.md) you'll see deeper examples of using the Chef extension and Azure.
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
@@ -26,31 +26,29 @@ Depending on your system's configuration, you may need to run this command with
|
|
26
26
|
|
27
27
|
## Modes
|
28
28
|
|
29
|
-
`knife-azure 1.6.0` onwards
|
29
|
+
`knife-azure 1.6.0` onwards supports Azure Resource Manager (preferred). You can easily switch between:
|
30
30
|
|
31
|
-
- Service management: commands using the Azure service management API
|
32
31
|
- Resource manager: commands using the Azure Resource Manager API
|
32
|
+
- Service management: commands using the Azure service management API
|
33
33
|
|
34
|
-
They are not designed to work together. Commands starting with `knife
|
35
|
-
|
36
|
-
PLEASE NOTE that `Azuererm` subcommands are experimental and of alpha quality. Not suitable for production use. Please use ASM subcommands for production.
|
34
|
+
They are not designed to work together. Commands starting with `knife azurerm` use ARM mode, while commands starting with `knife azure` use ASM mode.
|
37
35
|
|
38
36
|
## Configuration
|
39
37
|
|
40
|
-
1. [
|
41
|
-
|
38
|
+
1. [ARM Configuration](docs/configuration.md#arm-mode)
|
39
|
+
1. [ASM Configuration](docs/configuration.md#asm-mode)
|
42
40
|
|
43
41
|
## Detailed Usage
|
44
42
|
|
45
|
-
1. [
|
46
|
-
|
43
|
+
1. [ARM Mode](docs/ARM.md)
|
44
|
+
1. [ASM Mode](docs/ASM.md)
|
47
45
|
|
48
|
-
## Bootstrap existing VM to install the chef-client using chef-extension
|
46
|
+
## Bootstrap existing VM to install the chef-client using chef-extension
|
49
47
|
|
50
|
-
We have added a utility in
|
48
|
+
We have added a utility in ARM and ASM to bootstrap existing VM. This will install the chef-client using chef extension on your VM.
|
51
49
|
|
52
|
-
1. [Bootstrap Doc for
|
53
|
-
|
50
|
+
1. [Bootstrap Doc for ARM Mode](docs/bootstrap.md#arm-mode)
|
51
|
+
1. [Bootstrap Doc for ASM Mode](docs/bootstrap.md#asm-mode)
|
54
52
|
|
55
53
|
## Contributing
|
56
54
|
|
@@ -78,6 +78,7 @@ module Azure::ARM
|
|
78
78
|
def create_deployment_template(params)
|
79
79
|
if params[:chef_extension_public_param][:bootstrap_options][:chef_node_name]
|
80
80
|
chef_node_name = "[concat(parameters('chef_node_name'),copyIndex())]"
|
81
|
+
chef_node_name = "[parameters('chef_node_name')]" if params[:server_count].to_i==1
|
81
82
|
end
|
82
83
|
|
83
84
|
if(params[:server_count].to_i > 1)
|
@@ -160,6 +161,15 @@ module Azure::ARM
|
|
160
161
|
"description"=> "Password for the Virtual Machine."
|
161
162
|
}
|
162
163
|
},
|
164
|
+
"availabilitySetName" => {
|
165
|
+
"type" => "string"
|
166
|
+
},
|
167
|
+
"availabilitySetPlatformFaultDomainCount" => {
|
168
|
+
"type" => "string"
|
169
|
+
},
|
170
|
+
"availabilitySetPlatformUpdateDomainCount" => {
|
171
|
+
"type" => "string"
|
172
|
+
},
|
163
173
|
"numberOfInstances" => {
|
164
174
|
"type" => "int",
|
165
175
|
"defaultValue" => 1,
|
@@ -192,12 +202,7 @@ module Azure::ARM
|
|
192
202
|
"description"=> "JSON Escaped Validation Key"
|
193
203
|
}
|
194
204
|
},
|
195
|
-
|
196
|
-
"type"=> "string",
|
197
|
-
"metadata"=> {
|
198
|
-
"description"=> "Required for validtorless bootstrap."
|
199
|
-
}
|
200
|
-
},
|
205
|
+
|
201
206
|
"chef_server_crt" => {
|
202
207
|
"type"=> "string",
|
203
208
|
"metadata"=> {
|
@@ -221,6 +226,12 @@ module Azure::ARM
|
|
221
226
|
"metadata"=> {
|
222
227
|
"description"=> "Optional Run List to Execute"
|
223
228
|
}
|
229
|
+
},
|
230
|
+
"environment"=> {
|
231
|
+
"type"=> "string",
|
232
|
+
"metadata"=> {
|
233
|
+
"description"=> "Chef environment for the node (VM) in the Chef Organization"
|
234
|
+
}
|
224
235
|
},
|
225
236
|
"chef_node_name" => {
|
226
237
|
"type" => "string",
|
@@ -466,7 +477,8 @@ module Azure::ARM
|
|
466
477
|
"bootstrap_version" => "[parameters('bootstrap_version')]",
|
467
478
|
"node_ssl_verify_mode" => "[parameters('node_ssl_verify_mode')]",
|
468
479
|
"node_verify_api_cert" => "[parameters('node_verify_api_cert')]",
|
469
|
-
"bootstrap_proxy" => "[parameters('bootstrap_proxy')]"
|
480
|
+
"bootstrap_proxy" => "[parameters('bootstrap_proxy')]",
|
481
|
+
"environment" => "[parameters('environment')]"
|
470
482
|
},
|
471
483
|
"runlist" => "[parameters('runlist')]",
|
472
484
|
"validation_key_format" => "[parameters('validation_key_format')]",
|
@@ -476,7 +488,6 @@ module Azure::ARM
|
|
476
488
|
},
|
477
489
|
"protectedSettings" => {
|
478
490
|
"validation_key" => "[parameters('validation_key')]",
|
479
|
-
"client_pem" => "[parameters('client_pem')]",
|
480
491
|
"chef_server_crt" => "[parameters('chef_server_crt')]",
|
481
492
|
"encrypted_data_bag_secret" => "[parameters('encrypted_data_bag_secret')]"
|
482
493
|
}
|
@@ -485,6 +496,28 @@ module Azure::ARM
|
|
485
496
|
]
|
486
497
|
}
|
487
498
|
|
499
|
+
if params[:azure_availability_set]
|
500
|
+
set_val = {
|
501
|
+
"name" => "[parameters('availabilitySetName')]",
|
502
|
+
"type" => "Microsoft.Compute/availabilitySets",
|
503
|
+
"apiVersion" => "[variables('apiVersion')]",
|
504
|
+
"location" => "[resourceGroup().location]",
|
505
|
+
"properties" => {
|
506
|
+
"platformFaultDomainCount" => "[parameters('availabilitySetPlatformFaultDomainCount')]",
|
507
|
+
"platformUpdateDomainCount" => "[parameters('availabilitySetPlatformUpdateDomainCount')]"
|
508
|
+
}
|
509
|
+
}
|
510
|
+
|
511
|
+
length = template['resources'].length.to_i - 1
|
512
|
+
for i in 0..length do
|
513
|
+
if template['resources'][i]['type'] == "Microsoft.Compute/virtualMachines"
|
514
|
+
template['resources'][i]['dependsOn'] << "[concat('Microsoft.Compute/availabilitySets/', parameters('availabilitySetName'))]"
|
515
|
+
template['resources'][i]['properties'].merge!({"availabilitySet" => { "id" => "[resourceId('Microsoft.Compute/availabilitySets', parameters('availabilitySetName'))]"}})
|
516
|
+
end
|
517
|
+
end
|
518
|
+
template['resources'].insert(length, set_val)
|
519
|
+
end
|
520
|
+
|
488
521
|
if params[:tcp_endpoints]
|
489
522
|
sec_grp_json = tcp_ports(params[:tcp_endpoints], params[:azure_vm_name])
|
490
523
|
template['resources'].insert(1,sec_grp_json)
|
@@ -507,14 +540,40 @@ module Azure::ARM
|
|
507
540
|
end
|
508
541
|
end
|
509
542
|
|
510
|
-
if params[:chef_extension_public_param][:
|
543
|
+
if params[:chef_extension_public_param][:chef_daemon_interval]
|
511
544
|
template['resources'].each do |resource|
|
512
545
|
if resource['type'] == 'Microsoft.Compute/virtualMachines/extensions'
|
513
|
-
resource['properties']['settings']['
|
546
|
+
resource['properties']['settings']['chef_daemon_interval'] = params[:chef_extension_public_param][:chef_daemon_interval]
|
514
547
|
end
|
515
548
|
end
|
516
549
|
end
|
517
550
|
|
551
|
+
if params[:chef_extension_public_param][:daemon]
|
552
|
+
template['resources'].each do |resource|
|
553
|
+
if resource['type'] == 'Microsoft.Compute/virtualMachines/extensions'
|
554
|
+
resource['properties']['settings']['daemon'] = params[:chef_extension_public_param][:daemon]
|
555
|
+
end
|
556
|
+
end
|
557
|
+
end
|
558
|
+
if params[:server_count].to_i > 1 && params[:chef_extension_private_param][:validation_key].nil?
|
559
|
+
template["resources"].last["properties"]["protectedSettings"]["client_pem"] = "[parameters(concat('client_pem',copyIndex()))]"
|
560
|
+
0.upto (params[:server_count].to_i-1) do |count|
|
561
|
+
template["parameters"]["client_pem" + count.to_s] = {
|
562
|
+
"type"=> "string",
|
563
|
+
"metadata"=> {
|
564
|
+
"description"=> "Required for validtorless bootstrap."
|
565
|
+
}
|
566
|
+
}
|
567
|
+
end
|
568
|
+
else
|
569
|
+
template["resources"].last["properties"]["protectedSettings"]["client_pem"] = "[parameters('client_pem')]"
|
570
|
+
template["parameters"]["client_pem"] = {
|
571
|
+
"type"=> "string",
|
572
|
+
"metadata"=> {
|
573
|
+
"description"=> "Required for validtorless bootstrap."
|
574
|
+
}
|
575
|
+
}
|
576
|
+
end
|
518
577
|
template
|
519
578
|
end
|
520
579
|
|
@@ -534,6 +593,15 @@ module Azure::ARM
|
|
534
593
|
"adminPassword"=> {
|
535
594
|
"value"=> "#{admin_password}"
|
536
595
|
},
|
596
|
+
"availabilitySetName" => {
|
597
|
+
"value" => "#{params[:azure_availability_set]}"
|
598
|
+
},
|
599
|
+
"availabilitySetPlatformFaultDomainCount" => {
|
600
|
+
"value" => "2"
|
601
|
+
},
|
602
|
+
"availabilitySetPlatformUpdateDomainCount" => {
|
603
|
+
"value" => "5"
|
604
|
+
},
|
537
605
|
"dnsLabelPrefix"=> {
|
538
606
|
"value"=> "#{params[:azure_vm_name]}"
|
539
607
|
},
|
@@ -546,9 +614,7 @@ module Azure::ARM
|
|
546
614
|
"validation_key"=> {
|
547
615
|
"value"=> "#{params[:chef_extension_private_param][:validation_key]}"
|
548
616
|
},
|
549
|
-
|
550
|
-
"value" => "#{params[:chef_extension_private_param][:client_pem]}"
|
551
|
-
},
|
617
|
+
|
552
618
|
"chef_server_crt" => {
|
553
619
|
"value" => "#{params[:chef_extension_private_param][:chef_server_crt]}"
|
554
620
|
},
|
@@ -573,6 +639,9 @@ module Azure::ARM
|
|
573
639
|
"runlist" => {
|
574
640
|
"value" => "#{params[:chef_extension_public_param][:runlist]}"
|
575
641
|
},
|
642
|
+
"environment" => {
|
643
|
+
"value" => "#{params[:chef_extension_public_param][:bootstrap_options][:environment]}"
|
644
|
+
},
|
576
645
|
"chef_node_name" => {
|
577
646
|
"value"=> "#{params[:chef_extension_public_param][:bootstrap_options][:chef_node_name]}"
|
578
647
|
},
|
@@ -592,7 +661,18 @@ module Azure::ARM
|
|
592
661
|
"value" => "#{params[:disablePasswordAuthentication]}"
|
593
662
|
}
|
594
663
|
}
|
664
|
+
if params[:server_count].to_i > 1 && params[:chef_extension_private_param][:validation_key].nil?
|
665
|
+
0.upto (params[:server_count].to_i-1) do |count|
|
666
|
+
parameters["client_pem#{count.to_s}"] = {
|
667
|
+
"value" => "#{params[:chef_extension_private_param][("client_pem" + count.to_s).to_sym]}"
|
668
|
+
}
|
669
|
+
end
|
670
|
+
else
|
671
|
+
parameters["client_pem"] = {
|
672
|
+
"value" => "#{params[:chef_extension_private_param][:client_pem]}"
|
673
|
+
}
|
674
|
+
end
|
675
|
+
parameters
|
595
676
|
end
|
596
|
-
|
597
677
|
end
|
598
678
|
end
|
@@ -91,9 +91,9 @@ module Azure
|
|
91
91
|
|
92
92
|
def list_servers(resource_group_name = nil)
|
93
93
|
if resource_group_name.nil?
|
94
|
-
servers = compute_management_client.virtual_machines.list_all
|
94
|
+
servers = compute_management_client.virtual_machines.list_all
|
95
95
|
else
|
96
|
-
servers = compute_management_client.virtual_machines.list(resource_group_name)
|
96
|
+
servers = compute_management_client.virtual_machines.list(resource_group_name)
|
97
97
|
end
|
98
98
|
|
99
99
|
cols = ['VM Name', 'Resource Group Name', 'Location', 'Provisioning State', 'OS Type']
|
@@ -104,7 +104,7 @@ module Azure
|
|
104
104
|
rows << server.id.split('/')[4].downcase
|
105
105
|
rows << server.location.to_s
|
106
106
|
rows << begin
|
107
|
-
state = server.
|
107
|
+
state = server.provisioning_state.to_s.downcase
|
108
108
|
case state
|
109
109
|
when 'failed'
|
110
110
|
ui.color(state, :red)
|
@@ -114,7 +114,7 @@ module Azure
|
|
114
114
|
ui.color(state, :yellow)
|
115
115
|
end
|
116
116
|
end
|
117
|
-
rows << server.
|
117
|
+
rows << server.storage_profile.os_disk.os_type.to_s
|
118
118
|
end
|
119
119
|
display_list(ui, cols, rows)
|
120
120
|
end
|
@@ -124,8 +124,8 @@ module Azure
|
|
124
124
|
if server && server.name == vm_name
|
125
125
|
puts "\n\n"
|
126
126
|
msg_pair(ui, 'VM Name', server.name)
|
127
|
-
msg_pair(ui, 'VM Size', server.
|
128
|
-
msg_pair(ui, 'VM OS', server.
|
127
|
+
msg_pair(ui, 'VM Size', server.hardware_profile.vm_size)
|
128
|
+
msg_pair(ui, 'VM OS', server.storage_profile.os_disk.os_type)
|
129
129
|
puts "\n"
|
130
130
|
|
131
131
|
begin
|
@@ -139,7 +139,7 @@ module Azure
|
|
139
139
|
|
140
140
|
begin
|
141
141
|
server_detail = compute_management_client.virtual_machines.delete(resource_group_name, vm_name)
|
142
|
-
end until server_detail.
|
142
|
+
end until server_detail.nil?
|
143
143
|
|
144
144
|
puts "\n"
|
145
145
|
ui.warn "Deleted server #{vm_name}"
|
@@ -149,9 +149,9 @@ module Azure
|
|
149
149
|
def show_server(name, resource_group)
|
150
150
|
server = find_server(resource_group, name)
|
151
151
|
if server
|
152
|
-
network_interface_name = server.
|
152
|
+
network_interface_name = server.network_profile.network_interfaces[0].id.split('/')[-1]
|
153
153
|
network_interface_data = network_resource_client.network_interfaces.get(resource_group, network_interface_name)
|
154
|
-
public_ip_id_data = network_interface_data.
|
154
|
+
public_ip_id_data = network_interface_data.ip_configurations[0].public_ipaddress
|
155
155
|
unless public_ip_id_data.nil?
|
156
156
|
public_ip_name = public_ip_id_data.id.split('/')[-1]
|
157
157
|
public_ip_data = network_resource_client.public_ipaddresses.get(resource_group, public_ip_name)
|
@@ -164,39 +164,39 @@ module Azure
|
|
164
164
|
details << server.name
|
165
165
|
|
166
166
|
details << ui.color('Size', :bold, :cyan)
|
167
|
-
details << server.
|
167
|
+
details << server.hardware_profile.vm_size
|
168
168
|
|
169
169
|
details << ui.color('Provisioning State', :bold, :cyan)
|
170
|
-
details << server.
|
170
|
+
details << server.provisioning_state
|
171
171
|
|
172
172
|
details << ui.color('Location', :bold, :cyan)
|
173
173
|
details << server.location
|
174
174
|
|
175
175
|
details << ui.color('Publisher', :bold, :cyan)
|
176
|
-
details << server.
|
176
|
+
details << server.storage_profile.image_reference.publisher
|
177
177
|
|
178
178
|
details << ui.color('Offer', :bold, :cyan)
|
179
|
-
details << server.
|
179
|
+
details << server.storage_profile.image_reference.offer
|
180
180
|
|
181
181
|
details << ui.color('Sku', :bold, :cyan)
|
182
|
-
details << server.
|
182
|
+
details << server.storage_profile.image_reference.sku
|
183
183
|
|
184
184
|
details << ui.color('Version', :bold, :cyan)
|
185
|
-
details << server.
|
185
|
+
details << server.storage_profile.image_reference.version
|
186
186
|
|
187
187
|
details << ui.color('OS Type', :bold, :cyan)
|
188
|
-
details << server.
|
188
|
+
details << server.storage_profile.os_disk.os_type
|
189
189
|
|
190
190
|
details << ui.color('Public IP address', :bold, :cyan)
|
191
191
|
unless public_ip_data.nil?
|
192
|
-
details << public_ip_data.
|
192
|
+
details << public_ip_data.ip_address
|
193
193
|
else
|
194
194
|
details << ' -- '
|
195
195
|
end
|
196
196
|
|
197
197
|
details << ui.color('FQDN', :bold, :cyan)
|
198
|
-
unless public_ip_data.nil? or public_ip_data.
|
199
|
-
details << public_ip_data.
|
198
|
+
unless public_ip_data.nil? or public_ip_data.dns_settings.nil?
|
199
|
+
details << public_ip_data.dns_settings.fqdn
|
200
200
|
else
|
201
201
|
details << ' -- '
|
202
202
|
end
|
@@ -210,37 +210,37 @@ module Azure
|
|
210
210
|
end
|
211
211
|
|
212
212
|
def virtual_machine_exist?(resource_group_name, vm_name)
|
213
|
-
begin
|
214
|
-
compute_management_client.virtual_machines.get(resource_group_name, vm_name)
|
215
|
-
return true
|
216
|
-
rescue MsRestAzure::AzureOperationError => error
|
217
|
-
if error.body
|
218
|
-
err_json = JSON.parse(error.response.body)
|
219
|
-
if err_json['error']['code'] == "ResourceNotFound"
|
220
|
-
return false
|
221
|
-
else
|
222
|
-
raise error
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
def security_group_exist?(resource_group_name, security_group_name)
|
229
|
-
begin
|
230
|
-
network_resource_client.network_security_groups.get(resource_group_name, security_group_name)
|
231
|
-
return true
|
232
|
-
rescue MsRestAzure::AzureOperationError => error
|
233
|
-
if error.body
|
234
|
-
err_json = JSON.parse(error.response.body)
|
235
|
-
if err_json['error']['code'] == "ResourceNotFound"
|
236
|
-
return false
|
237
|
-
else
|
238
|
-
raise error
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
213
|
+
begin
|
214
|
+
compute_management_client.virtual_machines.get(resource_group_name, vm_name)
|
215
|
+
return true
|
216
|
+
rescue MsRestAzure::AzureOperationError => error
|
217
|
+
if error.body
|
218
|
+
err_json = JSON.parse(error.response.body)
|
219
|
+
if err_json['error']['code'] == "ResourceNotFound"
|
220
|
+
return false
|
221
|
+
else
|
222
|
+
raise error
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def security_group_exist?(resource_group_name, security_group_name)
|
229
|
+
begin
|
230
|
+
network_resource_client.network_security_groups.get(resource_group_name, security_group_name)
|
231
|
+
return true
|
232
|
+
rescue MsRestAzure::AzureOperationError => error
|
233
|
+
if error.body
|
234
|
+
err_json = JSON.parse(error.response.body)
|
235
|
+
if err_json['error']['code'] == "ResourceNotFound"
|
236
|
+
return false
|
237
|
+
else
|
238
|
+
raise error
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
244
|
def resource_group_exist?(resource_group_name)
|
245
245
|
resource_management_client.resource_groups.check_existence(resource_group_name)
|
246
246
|
end
|
@@ -266,8 +266,8 @@ module Azure
|
|
266
266
|
virtual_machine_name,
|
267
267
|
chef_extension_name,
|
268
268
|
'instanceView'
|
269
|
-
).
|
270
|
-
|
269
|
+
).instance_view.substatuses
|
270
|
+
|
271
271
|
return nil if substatuses.nil?
|
272
272
|
|
273
273
|
substatuses.each do |substatus|
|
@@ -332,7 +332,7 @@ module Azure
|
|
332
332
|
Chef::Log.info("Resource Group name is: #{resource_group.name}")
|
333
333
|
Chef::Log.info("Resource Group ID is: #{resource_group.id}")
|
334
334
|
end
|
335
|
-
|
335
|
+
|
336
336
|
# virtual machine creation
|
337
337
|
if virtual_machine_exist?(params[:azure_resource_group_name], params[:azure_vm_name])
|
338
338
|
ui.log("INFO:Virtual Machine #{params[:azure_vm_name]} already exist under the Resource Group #{params[:azure_resource_group_name]}. Exiting for now.")
|
@@ -344,24 +344,24 @@ module Azure
|
|
344
344
|
params[:azure_vnet_name],
|
345
345
|
params[:azure_vnet_subnet_name]
|
346
346
|
)
|
347
|
-
if params[:tcp_endpoints]
|
348
|
-
if @platform == 'Windows'
|
349
|
-
params[:tcp_endpoints] = params[:tcp_endpoints] + ",3389"
|
350
|
-
else
|
351
|
-
params[:tcp_endpoints] = params[:tcp_endpoints] + ",22,16001"
|
352
|
-
end
|
353
|
-
random_no = rand(100..1000)
|
354
|
-
params[:azure_sec_group_name] = params[:azure_vm_name] + '_sec_grp_' + random_no.to_s
|
355
|
-
if security_group_exist?(params[:azure_resource_group_name], params[:azure_sec_group_name])
|
356
|
-
random_no = rand(100..1000)
|
357
|
-
params[:azure_sec_group_name] = params[:azure_vm_name] + '_sec_grp_' + random_no.to_s
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
347
|
+
if params[:tcp_endpoints]
|
348
|
+
if @platform == 'Windows'
|
349
|
+
params[:tcp_endpoints] = params[:tcp_endpoints] + ",3389"
|
350
|
+
else
|
351
|
+
params[:tcp_endpoints] = params[:tcp_endpoints] + ",22,16001"
|
352
|
+
end
|
353
|
+
random_no = rand(100..1000)
|
354
|
+
params[:azure_sec_group_name] = params[:azure_vm_name] + '_sec_grp_' + random_no.to_s
|
355
|
+
if security_group_exist?(params[:azure_resource_group_name], params[:azure_sec_group_name])
|
356
|
+
random_no = rand(100..1000)
|
357
|
+
params[:azure_sec_group_name] = params[:azure_vm_name] + '_sec_grp_' + random_no.to_s
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
361
|
ui.log("Creating Virtual Machine....")
|
362
362
|
deployment = create_virtual_machine_using_template(params)
|
363
363
|
ui.log("Virtual Machine creation successfull.") unless deployment.nil?
|
364
|
-
|
364
|
+
|
365
365
|
unless deployment.nil?
|
366
366
|
ui.log("Deployment name is: #{deployment.name}")
|
367
367
|
ui.log("Deployment ID is: #{deployment.id}")
|
@@ -428,31 +428,27 @@ module Azure
|
|
428
428
|
deploy_params = Deployment.new
|
429
429
|
deploy_params.properties = deploy_prop
|
430
430
|
|
431
|
-
deployment = resource_management_client.deployments.create_or_update(params[:azure_resource_group_name], "#{params[:azure_vm_name]}_deploy", deploy_params)
|
431
|
+
deployment = resource_management_client.deployments.create_or_update(params[:azure_resource_group_name], "#{params[:azure_vm_name]}_deploy", deploy_params)
|
432
432
|
deployment
|
433
433
|
end
|
434
434
|
|
435
435
|
def create_vm_extension(params)
|
436
|
-
vm_ext_props = VirtualMachineExtensionProperties.new
|
437
|
-
vm_ext_props.publisher = params[:chef_extension_publisher]
|
438
|
-
vm_ext_props.type = params[:chef_extension]
|
439
|
-
vm_ext_props.type_handler_version = params[:chef_extension_version].nil? ? get_latest_chef_extension_version(params) : params[:chef_extension_version]
|
440
|
-
vm_ext_props.auto_upgrade_minor_version = false
|
441
|
-
vm_ext_props.settings = params[:chef_extension_public_param]
|
442
|
-
vm_ext_props.protected_settings = params[:chef_extension_private_param]
|
443
|
-
|
444
436
|
vm_ext = VirtualMachineExtension.new
|
445
437
|
vm_ext.name = params[:chef_extension]
|
446
438
|
vm_ext.location = params[:azure_service_location]
|
447
|
-
vm_ext.
|
448
|
-
|
439
|
+
vm_ext.publisher = params[:chef_extension_publisher]
|
440
|
+
vm_ext.virtual_machine_extension_type = params[:chef_extension]
|
441
|
+
vm_ext.type_handler_version = params[:chef_extension_version].nil? ? get_latest_chef_extension_version(params) : params[:chef_extension_version]
|
442
|
+
vm_ext.auto_upgrade_minor_version = false
|
443
|
+
vm_ext.settings = params[:chef_extension_public_param]
|
444
|
+
vm_ext.protected_settings = params[:chef_extension_private_param]
|
449
445
|
begin
|
450
446
|
vm_extension = compute_management_client.virtual_machine_extensions.create_or_update(
|
451
447
|
params[:azure_resource_group_name],
|
452
448
|
params[:azure_vm_name],
|
453
449
|
vm_ext.name,
|
454
450
|
vm_ext
|
455
|
-
)
|
451
|
+
)
|
456
452
|
rescue Exception => error
|
457
453
|
Chef::Log.error("Failed to create the Virtual Machine Extension -- exception being rescued.")
|
458
454
|
common_arm_rescue_block(error)
|
@@ -463,7 +459,7 @@ module Azure
|
|
463
459
|
|
464
460
|
def extension_already_installed?(server)
|
465
461
|
server.resources.each do |extension|
|
466
|
-
return true if (extension.
|
462
|
+
return true if (extension.virtual_machine_extension_type == "ChefClient" || extension.virtual_machine_extension_type == "LinuxChefClient")
|
467
463
|
end if server.resources
|
468
464
|
false
|
469
465
|
end
|
@@ -483,7 +479,7 @@ module Azure
|
|
483
479
|
|
484
480
|
begin
|
485
481
|
server = resource_management_client.resource_groups.delete(resource_group_name)
|
486
|
-
end until server.
|
482
|
+
end until server.nil?
|
487
483
|
puts "\n"
|
488
484
|
end
|
489
485
|
|
@@ -493,7 +489,11 @@ module Azure
|
|
493
489
|
err_details = err_json["error"]["details"] if err_json["error"]
|
494
490
|
if err_details
|
495
491
|
err_details.each do |err|
|
496
|
-
|
492
|
+
begin
|
493
|
+
ui.error(JSON.parse(err["message"])["error"]["message"])
|
494
|
+
rescue JSON::ParserError => e
|
495
|
+
ui.error(err["message"])
|
496
|
+
end
|
497
497
|
end
|
498
498
|
else
|
499
499
|
ui.error(err_json["error"]["message"])
|
@@ -27,7 +27,7 @@ module Azure::ARM
|
|
27
27
|
list = []
|
28
28
|
address_space = IPAddress(address_prefix)
|
29
29
|
subnets_list.each do |sbn|
|
30
|
-
subnet_address_prefix = IPAddress(sbn.
|
30
|
+
subnet_address_prefix = IPAddress(sbn.address_prefix)
|
31
31
|
|
32
32
|
## check if the subnet belongs to this address space or not ##
|
33
33
|
list << sbn if address_space.include? subnet_address_prefix
|
@@ -53,7 +53,7 @@ module Azure::ARM
|
|
53
53
|
|
54
54
|
## lists all subnets under a virtual network or lists subnets of only a particular address space ##
|
55
55
|
def subnets_list(resource_group_name, vnet_name, address_prefix = nil)
|
56
|
-
list = network_resource_client.subnets.list(resource_group_name, vnet_name)
|
56
|
+
list = network_resource_client.subnets.list(resource_group_name, vnet_name)
|
57
57
|
!address_prefix.nil? && !list.empty? ? subnets_list_for_specific_address_space(address_prefix, list) : list
|
58
58
|
end
|
59
59
|
|
@@ -69,12 +69,12 @@ module Azure::ARM
|
|
69
69
|
|
70
70
|
## return all the address prefixes under a virtual network ##
|
71
71
|
def vnet_address_spaces(vnet)
|
72
|
-
vnet.
|
72
|
+
vnet.address_space.address_prefixes
|
73
73
|
end
|
74
74
|
|
75
75
|
## return address prefix of a subnet ##
|
76
76
|
def subnet_address_prefix(subnet)
|
77
|
-
subnet.
|
77
|
+
subnet.address_prefix
|
78
78
|
end
|
79
79
|
|
80
80
|
## sort available networks pool in ascending order based on the network's
|
@@ -87,14 +87,14 @@ module Azure::ARM
|
|
87
87
|
## sort existing subnets in ascending order based on their cidr prefix or
|
88
88
|
## netmask to have subnets with larger networks on the top ##
|
89
89
|
def sort_subnets_by_cidr_prefix(subnets)
|
90
|
-
subnets.sort_by { |sbn| [
|
90
|
+
subnets.sort_by.with_index { |sbn, i| [subnet_address_prefix(sbn).split("/")[1].to_i, i] }
|
91
91
|
end
|
92
92
|
|
93
93
|
## sort used networks pool in descending order based on the number of hosts
|
94
94
|
## it contains, this helps to keep larger networks on top thereby eliminating
|
95
95
|
## more number of entries in available_networks_pool at a faster pace ##
|
96
96
|
def sort_used_networks_by_hosts_size(used_network)
|
97
|
-
used_network.sort_by { |nwrk| -nwrk.hosts.size }
|
97
|
+
used_network.sort_by.with_index { |nwrk, i| [-nwrk.hosts.size, i] }
|
98
98
|
end
|
99
99
|
|
100
100
|
## return the cidr prefix or netmask of the given subnet ##
|
@@ -194,6 +194,7 @@ class Chef
|
|
194
194
|
def parse_azure_profile(filename, errors)
|
195
195
|
require 'openssl'
|
196
196
|
require 'uri'
|
197
|
+
errors = [] if errors.nil?
|
197
198
|
azure_profile = File.read(File.expand_path(filename))
|
198
199
|
azure_profile = JSON.parse(azure_profile)
|
199
200
|
default_subscription = get_default_subscription(azure_profile)
|
@@ -374,7 +374,7 @@ class Chef
|
|
374
374
|
extension_status[:status] = :extension_status_not_detected
|
375
375
|
end
|
376
376
|
# This fix is for linux waagent issue: api unable to deserialize the waagent status.
|
377
|
-
elsif role.at_css('GuestAgentStatus Status').text == 'NotReady'
|
377
|
+
elsif (role.at_css('GuestAgentStatus Status').text == 'NotReady') && (waagent_status_msg == lnx_waagent_fail_msg)
|
378
378
|
extension_status[:status] = :extension_ready
|
379
379
|
else
|
380
380
|
extension_status[:status] = :wagent_provisioning
|
@@ -424,12 +424,12 @@ class Chef
|
|
424
424
|
end
|
425
425
|
|
426
426
|
def validate_params!
|
427
|
-
if locate_config_value(:winrm_password)
|
427
|
+
if locate_config_value(:winrm_password) && (locate_config_value(:winrm_password).length <= 6 && locate_config_value(:winrm_password).length >= 72)
|
428
428
|
ui.error("The supplied password must be 6-72 characters long and meet password complexity requirements")
|
429
429
|
exit 1
|
430
430
|
end
|
431
431
|
|
432
|
-
if locate_config_value(:ssh_password)
|
432
|
+
if locate_config_value(:ssh_password) && (locate_config_value(:ssh_password).length <= 6 && locate_config_value(:ssh_password).length >= 72)
|
433
433
|
ui.error("The supplied password must be 6-72 characters long and meet password complexity requirements")
|
434
434
|
exit 1
|
435
435
|
end
|
@@ -458,8 +458,8 @@ class Chef
|
|
458
458
|
end
|
459
459
|
|
460
460
|
# Validate join domain requirements.
|
461
|
-
if locate_config_value(:azure_domain_name)
|
462
|
-
if locate_config_value(:azure_domain_user).nil?
|
461
|
+
if locate_config_value(:azure_domain_name) || locate_config_value(:azure_domain_user)
|
462
|
+
if locate_config_value(:azure_domain_user).nil? || locate_config_value(:azure_domain_passwd).nil?
|
463
463
|
ui.error("Must specify both --azure-domain-user and --azure-domain-passwd.")
|
464
464
|
exit 1
|
465
465
|
end
|
@@ -474,6 +474,20 @@ class Chef
|
|
474
474
|
ui.error("--extended-logs option works with --bootstrap-protocol cloud-api")
|
475
475
|
exit 1
|
476
476
|
end
|
477
|
+
|
478
|
+
if locate_config_value(:daemon)
|
479
|
+
unless is_image_windows?
|
480
|
+
raise ArgumentError, "The daemon option is only support for Windows nodes."
|
481
|
+
end
|
482
|
+
|
483
|
+
unless locate_config_value(:bootstrap_protocol) == 'cloud-api'
|
484
|
+
raise ArgumentError, "--daemon option works with --bootstrap-protocol cloud-api"
|
485
|
+
end
|
486
|
+
|
487
|
+
unless %w{none service task}.include?(locate_config_value(:daemon))
|
488
|
+
raise ArgumentError, "Invalid value for --daemon option. Use valid daemon values i.e 'none', 'service' and 'task'."
|
489
|
+
end
|
490
|
+
end
|
477
491
|
end
|
478
492
|
|
479
493
|
def create_server_def
|
@@ -89,7 +89,7 @@ class Chef
|
|
89
89
|
object.destroy
|
90
90
|
ui.warn("Deleted #{type_name} #{name}")
|
91
91
|
rescue Net::HTTPServerException
|
92
|
-
ui.warn("Could not find a #{type_name} named #{name} to delete
|
92
|
+
ui.warn("Could not find a #{type_name} named #{name} to delete. Please provide --node-name option and it's value")
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -20,12 +20,18 @@
|
|
20
20
|
require 'chef/knife'
|
21
21
|
require 'azure/resource_management/ARM_interface'
|
22
22
|
require 'mixlib/shellout'
|
23
|
+
require 'chef/mixin/shell_out'
|
23
24
|
require 'time'
|
24
25
|
require 'json'
|
25
26
|
|
26
27
|
class Chef
|
27
28
|
class Knife
|
28
29
|
module AzurermBase
|
30
|
+
include Chef::Mixin::ShellOut
|
31
|
+
|
32
|
+
## azure-xplat-cli versio that introduced deprecation of Windows Credentials
|
33
|
+
## Manager (WCM) usage for authentication credentials storage purpose ##
|
34
|
+
XPLAT_VERSION_WITH_WCM_DEPRECATED ||= "0.10.5"
|
29
35
|
|
30
36
|
if Chef::Platform.windows?
|
31
37
|
require 'azure/resource_management/windows_credentials'
|
@@ -65,7 +71,6 @@ class Chef
|
|
65
71
|
|
66
72
|
# validates ARM mandatory keys
|
67
73
|
def validate_arm_keys!(*keys)
|
68
|
-
Chef::Log.warn('Azurerm subcommands are experimental and of alpha quality. Not suitable for production use. Please use ASM subcommands for production.')
|
69
74
|
parse_publish_settings_file(locate_config_value(:azure_publish_settings_file)) if(locate_config_value(:azure_publish_settings_file) != nil)
|
70
75
|
keys.push(:azure_subscription_id)
|
71
76
|
|
@@ -98,7 +103,31 @@ class Chef
|
|
98
103
|
token_details
|
99
104
|
end
|
100
105
|
|
106
|
+
def current_xplat_cli_version
|
107
|
+
shell_out!("azure -v", { returns: [0] }).stdout
|
108
|
+
end
|
109
|
+
|
110
|
+
def is_old_xplat?
|
111
|
+
Gem::Version.new(current_xplat_cli_version) < Gem::Version.new(XPLAT_VERSION_WITH_WCM_DEPRECATED)
|
112
|
+
end
|
113
|
+
|
114
|
+
def is_WCM_env_var_set?
|
115
|
+
ENV['AZURE_USE_SECURE_TOKEN_STORAGE'].nil? ? false : true
|
116
|
+
end
|
117
|
+
|
118
|
+
def token_details_for_windows
|
119
|
+
if is_old_xplat?
|
120
|
+
token_details_from_WCM
|
121
|
+
else
|
122
|
+
is_WCM_env_var_set? ? token_details_from_WCM : token_details_from_accessToken_file
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
101
126
|
def token_details_for_linux
|
127
|
+
token_details_from_accessToken_file
|
128
|
+
end
|
129
|
+
|
130
|
+
def token_details_from_accessToken_file
|
102
131
|
home_dir = File.expand_path('~')
|
103
132
|
file = File.read(home_dir + '/.azure/accessTokens.json')
|
104
133
|
file = JSON.parse(file)
|
@@ -146,7 +175,12 @@ class Chef
|
|
146
175
|
|
147
176
|
def validate_azure_login
|
148
177
|
err_string = "Please run XPLAT's 'azure login' command OR specify azure_tenant_id, azure_subscription_id, azure_client_id, azure_client_secret in your knife.rb"
|
149
|
-
|
178
|
+
|
179
|
+
## Older versions of the Azure CLI on Windows stored credentials in a unique way
|
180
|
+
## in Windows Credentails Manager (WCM).
|
181
|
+
## Newer versions use the same pattern across platforms where credentials gets
|
182
|
+
## stored in ~/.azure/accessTokens.json file.
|
183
|
+
if Chef::Platform.windows? && (is_old_xplat? || is_WCM_env_var_set?)
|
150
184
|
# cmdkey command is used for accessing windows credential manager
|
151
185
|
xplat_creds_cmd = Mixlib::ShellOut.new("cmdkey /list | findstr AzureXplatCli")
|
152
186
|
result = xplat_creds_cmd.run_command
|
@@ -256,6 +290,51 @@ class Chef
|
|
256
290
|
end
|
257
291
|
puts "\n"
|
258
292
|
end
|
293
|
+
|
294
|
+
def validate_params!
|
295
|
+
if locate_config_value(:azure_vnet_subnet_name) && !locate_config_value(:azure_vnet_name)
|
296
|
+
raise ArgumentError, "When --azure-vnet-subnet-name is specified, the --azure-vnet-name must also be specified."
|
297
|
+
end
|
298
|
+
|
299
|
+
if locate_config_value(:azure_vnet_subnet_name) == 'GatewaySubnet'
|
300
|
+
raise ArgumentError, 'GatewaySubnet cannot be used as the name for --azure-vnet-subnet-name option. GatewaySubnet can only be used for virtual network gateways.'
|
301
|
+
end
|
302
|
+
|
303
|
+
if locate_config_value(:node_ssl_verify_mode) && !["none", "peer"].include?(locate_config_value(:node_ssl_verify_mode))
|
304
|
+
raise ArgumentError, "Invalid value '#{locate_config_value(:node_ssl_verify_mode)}' for --node-ssl-verify-mode. Use Valid values i.e 'none', 'peer'."
|
305
|
+
end
|
306
|
+
|
307
|
+
if is_image_windows?
|
308
|
+
if locate_config_value(:winrm_user).nil? || locate_config_value(:winrm_password).nil?
|
309
|
+
raise ArgumentError, "Please provide --winrm-user and --winrm-password options for Windows option."
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
if !is_image_windows?
|
314
|
+
if (locate_config_value(:azure_vm_name).match /^(?=.*[a-zA-Z-])([a-zA-z0-9-]{1,64})$/).nil?
|
315
|
+
raise ArgumentError, "VM name can only contain alphanumeric and hyphen(-) characters and maximun length cannot exceed 64 charachters."
|
316
|
+
end
|
317
|
+
elsif (locate_config_value(:azure_vm_name).match /^(?=.*[a-zA-Z-])([a-zA-z0-9-]{1,15})$/).nil?
|
318
|
+
raise ArgumentError, "VM name can only contain alphanumeric and hyphen(-) characters and maximun length cannot exceed 15 charachters."
|
319
|
+
end
|
320
|
+
|
321
|
+
if locate_config_value(:server_count).to_i > 5
|
322
|
+
raise ArgumentError, "Maximum allowed value of --server-count is 5."
|
323
|
+
end
|
324
|
+
|
325
|
+
if locate_config_value(:daemon)
|
326
|
+
unless is_image_windows?
|
327
|
+
raise ArgumentError, "The daemon option is only support for Windows nodes."
|
328
|
+
end
|
329
|
+
|
330
|
+
unless %w{none service task}.include?(locate_config_value(:daemon))
|
331
|
+
raise ArgumentError, "Invalid value for --daemon option. Use valid daemon values i.e 'none', 'service' and 'task'."
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
config[:ohai_hints] = format_ohai_hints(locate_config_value(:ohai_hints))
|
336
|
+
validate_ohai_hints if ! locate_config_value(:ohai_hints).casecmp('default').zero?
|
337
|
+
end
|
259
338
|
end
|
260
339
|
end
|
261
340
|
end
|
@@ -49,6 +49,10 @@ class Chef
|
|
49
49
|
:long => "--ssh-port PORT",
|
50
50
|
:description => "The ssh port. Default is 22."
|
51
51
|
|
52
|
+
option :node_ssl_verify_mode,
|
53
|
+
:long => "--node-ssl-verify-mode [peer|none]",
|
54
|
+
:description => "Whether or not to verify the SSL cert for all HTTPS requests."
|
55
|
+
|
52
56
|
option :winrm_user,
|
53
57
|
:short => "-x USERNAME",
|
54
58
|
:long => "--winrm-user USERNAME",
|
@@ -130,6 +134,10 @@ class Chef
|
|
130
134
|
:default => 'Small',
|
131
135
|
:proc => Proc.new { |si| Chef::Config[:knife][:azure_vm_size] = si }
|
132
136
|
|
137
|
+
option :azure_availability_set,
|
138
|
+
:long => "--azure-availability-set NAME",
|
139
|
+
:description => "Optional. Name of availability set to add virtual machine into."
|
140
|
+
|
133
141
|
option :azure_vnet_name,
|
134
142
|
:long => "--azure-vnet-name VNET_NAME",
|
135
143
|
:description => "Optional. Specifies the virtual network name.
|
@@ -221,6 +229,7 @@ class Chef
|
|
221
229
|
:azure_image_reference_sku => locate_config_value(:azure_image_reference_sku),
|
222
230
|
:azure_image_reference_version => locate_config_value(:azure_image_reference_version),
|
223
231
|
:winrm_user => locate_config_value(:winrm_user),
|
232
|
+
:azure_availability_set => locate_config_value(:azure_availability_set),
|
224
233
|
:azure_vnet_name => locate_config_value(:azure_vnet_name),
|
225
234
|
:azure_vnet_subnet_name => locate_config_value(:azure_vnet_subnet_name),
|
226
235
|
:ssl_cert_fingerprint => locate_config_value(:thumbprint),
|
@@ -230,9 +239,10 @@ class Chef
|
|
230
239
|
:server_count => locate_config_value(:server_count)
|
231
240
|
}
|
232
241
|
|
233
|
-
if locate_config_value(:tcp_endpoints)
|
234
|
-
|
235
|
-
|
242
|
+
server_def[:tcp_endpoints] = locate_config_value(:tcp_endpoints) if locate_config_value(:tcp_endpoints)
|
243
|
+
|
244
|
+
# We assign azure_vm_name to chef_node_name If node name is nill because storage account name is combination of hash value and node name.
|
245
|
+
config[:chef_node_name] ||= locate_config_value(:azure_vm_name)
|
236
246
|
|
237
247
|
server_def[:azure_storage_account] = locate_config_value(:azure_vm_name) if server_def[:azure_storage_account].nil?
|
238
248
|
server_def[:azure_storage_account] = server_def[:azure_storage_account].gsub(/[!@#$%^&*()_-]/,'')
|
@@ -291,37 +301,6 @@ class Chef
|
|
291
301
|
end
|
292
302
|
end
|
293
303
|
|
294
|
-
def validate_params!
|
295
|
-
if locate_config_value(:azure_vnet_subnet_name) && !locate_config_value(:azure_vnet_name)
|
296
|
-
raise ArgumentError, "When --azure-vnet-subnet-name is specified, the --azure-vnet-name must also be specified."
|
297
|
-
end
|
298
|
-
|
299
|
-
if locate_config_value(:azure_vnet_subnet_name) == 'GatewaySubnet'
|
300
|
-
raise ArgumentError, 'GatewaySubnet cannot be used as the name for --azure-vnet-subnet-name option. GatewaySubnet can only be used for virtual network gateways.'
|
301
|
-
end
|
302
|
-
|
303
|
-
if is_image_windows?
|
304
|
-
if locate_config_value(:winrm_user).nil? || locate_config_value(:winrm_password).nil?
|
305
|
-
raise ArgumentError, "Please provide --winrm-user and --winrm-password options for Windows option."
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
if !is_image_windows?
|
310
|
-
if (locate_config_value(:azure_vm_name).match /^(?=.*[a-zA-Z-])([a-zA-z0-9-]{1,64})$/).nil?
|
311
|
-
raise ArgumentError, "VM name can only contain alphanumeric and hyphen(-) characters and maximun length cannot exceed 64 charachters."
|
312
|
-
end
|
313
|
-
elsif (locate_config_value(:azure_vm_name).match /^(?=.*[a-zA-Z-])([a-zA-z0-9-]{1,15})$/).nil?
|
314
|
-
raise ArgumentError, "VM name can only contain alphanumeric and hyphen(-) characters and maximun length cannot exceed 15 charachters."
|
315
|
-
end
|
316
|
-
|
317
|
-
if locate_config_value(:server_count).to_i > 5
|
318
|
-
raise ArgumentError, "Maximum allowed value of --server-count is 5."
|
319
|
-
end
|
320
|
-
|
321
|
-
config[:ohai_hints] = format_ohai_hints(locate_config_value(:ohai_hints))
|
322
|
-
validate_ohai_hints if ! locate_config_value(:ohai_hints).casecmp('default').zero?
|
323
|
-
end
|
324
|
-
|
325
304
|
private
|
326
305
|
|
327
306
|
def ssh_override_winrm
|
@@ -84,14 +84,21 @@ class Chef
|
|
84
84
|
:default => false,
|
85
85
|
:description => "Optional. Provide this option when --bootstrap-protocol is set to 'cloud-api'. It shows chef converge logs in detail."
|
86
86
|
|
87
|
-
option :
|
88
|
-
:long => "--chef-
|
87
|
+
option :chef_daemon_interval,
|
88
|
+
:long => "--chef-daemon-interval INTERVAL",
|
89
89
|
:description => "Optional. Provide this option when --bootstrap-protocol is set to 'cloud-api'.
|
90
90
|
It specifies the frequency (in minutes) at which the chef-service runs.
|
91
91
|
Pass 0 if you don't want the chef-service to be installed on the target machine."
|
92
92
|
|
93
|
+
option :daemon,
|
94
|
+
:long => "--daemon DAEMON",
|
95
|
+
:description => "Optional. Configures the chef-client service for unattended execution. Requires --bootstrap-protocol to be 'cloud-api' and the node platform to be Windows.
|
96
|
+
Options: 'none' or 'service' or 'task'.
|
97
|
+
none - Currently prevents the chef-client service from being configured as a service.
|
98
|
+
service - Configures the chef-client to run automatically in the background as a service.
|
99
|
+
task - Configures the chef-client to run automatically in the background as a scheduled task."
|
93
100
|
end
|
94
|
-
|
101
|
+
end
|
95
102
|
end
|
96
103
|
end
|
97
104
|
end
|
@@ -284,7 +284,8 @@ class Chef
|
|
284
284
|
pub_config[:custom_json_attr] = locate_config_value(:json_attributes) || {}
|
285
285
|
pub_config[:extendedLogs] = locate_config_value(:extended_logs) ? "true" : "false"
|
286
286
|
pub_config[:hints] = ohai_hints if @service.instance_of?(Azure::ResourceManagement::ARMInterface) && !locate_config_value(:ohai_hints).nil?
|
287
|
-
pub_config[:
|
287
|
+
pub_config[:chef_daemon_interval] = locate_config_value(:chef_daemon_interval) if locate_config_value(:chef_daemon_interval)
|
288
|
+
pub_config[:daemon] = locate_config_value(:daemon) if locate_config_value(:daemon)
|
288
289
|
|
289
290
|
# bootstrap attributes
|
290
291
|
pub_config[:bootstrap_options] = {}
|
@@ -296,7 +297,6 @@ class Chef
|
|
296
297
|
pub_config[:bootstrap_options][:bootstrap_version] = locate_config_value(:bootstrap_version) if locate_config_value(:bootstrap_version)
|
297
298
|
pub_config[:bootstrap_options][:node_ssl_verify_mode] = locate_config_value(:node_ssl_verify_mode) if locate_config_value(:node_ssl_verify_mode)
|
298
299
|
pub_config[:bootstrap_options][:bootstrap_proxy] = locate_config_value(:bootstrap_proxy) if locate_config_value(:bootstrap_proxy)
|
299
|
-
|
300
300
|
pub_config
|
301
301
|
end
|
302
302
|
|
@@ -317,26 +317,37 @@ class Chef
|
|
317
317
|
cli_secret_file || cli_secret || knife_secret_file || knife_secret
|
318
318
|
end
|
319
319
|
|
320
|
+
def create_node_and_client_pem
|
321
|
+
client_builder = Chef::Knife::Bootstrap::ClientBuilder.new(
|
322
|
+
chef_config: Chef::Config,
|
323
|
+
knife_config: config,
|
324
|
+
ui: ui,
|
325
|
+
)
|
326
|
+
client_builder.run
|
327
|
+
client_builder.client_path
|
328
|
+
end
|
329
|
+
|
320
330
|
def get_chef_extension_private_params
|
321
331
|
pri_config = Hash.new
|
322
332
|
|
323
333
|
# validator less bootstrap support for bootstrap protocol cloud-api
|
324
334
|
if (Chef::Config[:validation_key] && !File.exist?(File.expand_path(Chef::Config[:validation_key])))
|
325
|
-
|
326
335
|
if Chef::VERSION.split('.').first.to_i == 11
|
327
336
|
ui.error('Unable to find validation key. Please verify your configuration file for validation_key config value.')
|
328
337
|
exit 1
|
329
338
|
end
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
339
|
+
if config[:server_count].to_i > 1
|
340
|
+
node_name = config[:chef_node_name]
|
341
|
+
0.upto (config[:server_count].to_i-1) do |count|
|
342
|
+
config[:chef_node_name] = node_name + count.to_s
|
343
|
+
key_path = create_node_and_client_pem
|
344
|
+
pri_config[("client_pem" + count.to_s).to_sym] = File.read(key_path)
|
345
|
+
end
|
346
|
+
config[:chef_node_name] = node_name
|
347
|
+
else
|
348
|
+
key_path = create_node_and_client_pem
|
349
|
+
pri_config[:client_pem] = File.read(key_path)
|
350
|
+
end
|
340
351
|
else
|
341
352
|
pri_config[:validation_key] = File.read(Chef::Config[:validation_key])
|
342
353
|
end
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
#
|
20
|
-
# Bootstrap options listed here are supported only for cloud-api protocol.
|
20
|
+
# Bootstrap options listed here are supported only for cloud-api protocol ARM mode.
|
21
21
|
#
|
22
22
|
|
23
23
|
class Chef
|
@@ -99,11 +99,18 @@ class Chef
|
|
99
99
|
:default => false,
|
100
100
|
:description => "Optional. It shows chef convergence logs in detail."
|
101
101
|
|
102
|
-
option :
|
103
|
-
:long => "--chef-
|
102
|
+
option :chef_daemon_interval,
|
103
|
+
:long => "--chef-daemon-interval INTERVAL",
|
104
104
|
:description => "Optional. It specifies the frequency (in minutes) at which the chef-service runs.
|
105
105
|
Pass 0 if you don't want the chef-service to be installed on the target machine."
|
106
106
|
|
107
|
+
option :daemon,
|
108
|
+
:long => "--daemon DAEMON",
|
109
|
+
:description => "Optional. Configures the chef-client service for unattended execution. Requires --bootstrap-protocol to be 'cloud-api' and the node platform to be Windows.
|
110
|
+
Options: 'none' or 'service' or 'task'.
|
111
|
+
none - Currently prevents the chef-client service from being configured as a service.
|
112
|
+
service - Configures the chef-client to run automatically in the background as a service.
|
113
|
+
task - Configures the chef-client to run automatically in the background as a scheduled task."
|
107
114
|
end
|
108
115
|
end
|
109
116
|
end
|
@@ -73,17 +73,17 @@ class Chef
|
|
73
73
|
raise "Virtual machine #{server.name} already has Chef extension installed on it."
|
74
74
|
else
|
75
75
|
ext_params = Hash.new
|
76
|
-
case server.
|
76
|
+
case server.storage_profile.os_disk.os_type.downcase
|
77
77
|
when 'windows'
|
78
78
|
ext_params[:chef_extension] = 'ChefClient'
|
79
79
|
when 'linux'
|
80
|
-
if ['ubuntu', 'debian', 'rhel', 'centos'].any? { |platform| server.
|
80
|
+
if ['ubuntu', 'debian', 'rhel', 'centos'].any? { |platform| server.storage_profile.image_reference.offer.downcase.include? platform }
|
81
81
|
ext_params[:chef_extension] = 'LinuxChefClient'
|
82
82
|
else
|
83
|
-
raise "Offer #{server.
|
83
|
+
raise "Offer #{server.storage_profile.image_reference.offer} is not supported in the extension."
|
84
84
|
end
|
85
85
|
else
|
86
|
-
raise "OS type #{server.
|
86
|
+
raise "OS type #{server.storage_profile.os_disk.os_type} is not supported."
|
87
87
|
end
|
88
88
|
|
89
89
|
ext_params[:azure_resource_group_name] = locate_config_value(:azure_resource_group_name)
|
data/lib/knife-azure/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-azure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Barry Davis
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2017-09-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -45,70 +45,70 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - '='
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: 0.
|
48
|
+
version: 0.9.0
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - '='
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: 0.
|
55
|
+
version: 0.9.0
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: azure_mgmt_compute
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - '='
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: 0.
|
62
|
+
version: 0.9.0
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - '='
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 0.
|
69
|
+
version: 0.9.0
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: azure_mgmt_storage
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
74
|
- - '='
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: 0.
|
76
|
+
version: 0.9.0
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - '='
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: 0.
|
83
|
+
version: 0.9.0
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: azure_mgmt_network
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
88
|
- - '='
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: 0.
|
90
|
+
version: 0.9.0
|
91
91
|
type: :runtime
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - '='
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: 0.
|
97
|
+
version: 0.9.0
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: listen
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
|
-
- -
|
102
|
+
- - "~>"
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version: 3.0
|
104
|
+
version: '3.0'
|
105
105
|
type: :runtime
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
|
-
- -
|
109
|
+
- - "~>"
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version: 3.0
|
111
|
+
version: '3.0'
|
112
112
|
- !ruby/object:Gem::Dependency
|
113
113
|
name: ipaddress
|
114
114
|
requirement: !ruby/object:Gem::Requirement
|
@@ -141,9 +141,6 @@ dependencies:
|
|
141
141
|
name: chef
|
142
142
|
requirement: !ruby/object:Gem::Requirement
|
143
143
|
requirements:
|
144
|
-
- - "~>"
|
145
|
-
- !ruby/object:Gem::Version
|
146
|
-
version: '12.0'
|
147
144
|
- - ">="
|
148
145
|
- !ruby/object:Gem::Version
|
149
146
|
version: 12.2.1
|
@@ -151,9 +148,6 @@ dependencies:
|
|
151
148
|
prerelease: false
|
152
149
|
version_requirements: !ruby/object:Gem::Requirement
|
153
150
|
requirements:
|
154
|
-
- - "~>"
|
155
|
-
- !ruby/object:Gem::Version
|
156
|
-
version: '12.0'
|
157
151
|
- - ">="
|
158
152
|
- !ruby/object:Gem::Version
|
159
153
|
version: 12.2.1
|
@@ -288,7 +282,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
288
282
|
version: '0'
|
289
283
|
requirements: []
|
290
284
|
rubyforge_project:
|
291
|
-
rubygems_version: 2.6.
|
285
|
+
rubygems_version: 2.6.10
|
292
286
|
signing_key:
|
293
287
|
specification_version: 4
|
294
288
|
summary: A plugin to the Chef knife tool for creating instances on the Microsoft Azure
|