knife-azure 1.7.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|