knife-azure 1.3.0 → 1.4.0.rc.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 +8 -8
- data/README.md +3 -3
- data/lib/azure/certificate.rb +20 -11
- data/lib/azure/deploy.rb +5 -1
- data/lib/azure/image.rb +34 -6
- data/lib/azure/rest.rb +1 -1
- data/lib/azure/role.rb +143 -88
- data/lib/chef/knife/azure_image_list.rb +3 -3
- data/lib/chef/knife/azure_server_create.rb +236 -39
- data/lib/knife-azure/version.rb +1 -1
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NDRlZjIwNmQwNWU1NzVlYzA4NGI3MzNjZTJlNmZkMmNlZmEwZDZiNg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDgxYzQ2YTU2NGFlZDA0ZmE3MmM0M2UzM2NkNzFlZGZkNWU3MzQyYg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MGIxZTg3ZDEzN2ZlNmIzMzhlYTRhZjdlYjY5OTVkMzRkZDNjMWYzZDBiZjFh
|
10
|
+
NzlhNjRlMTE3ZTQwMGUwYjQxNTc4NDY3ZDNhZDVkZThjMmFlODgwNGZiYWM0
|
11
|
+
MDY0YWRiMmQ5OTYwNjBmZGE3YWY3ZGU2OGFmMWRmZGNjOGM5YWE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTlkMTM2Mjc3NDQ3ZmNmNmZlOGQwYzk2MGJhM2EyYWIxMjljYzNiMzIxMWU2
|
14
|
+
NTY0NDE3MTk2MjBhOGVmZTA5MzY0YWZiMWJjY2E0MmJmNTBiY2IyMzNmZDlm
|
15
|
+
ZjQ4YWQxYTAxMDZlMWYwYjhiYTdmMGFhZTEwNTcxZjMzZWY2MzY=
|
data/README.md
CHANGED
@@ -48,7 +48,7 @@ location in your knife.rb:
|
|
48
48
|
$ knife azure server list
|
49
49
|
|
50
50
|
# Create and bootstrap an Ubuntu VM over ssh
|
51
|
-
$ knife azure server create -N MyNewNode --azure-vm-size Medium
|
51
|
+
$ knife azure server create -N MyNewNode --azure-vm-size Medium -I b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04_1-LTS-amd64-server-20140927-en-us-30GB -m 'West US' --ssh-user myuser --identity-file ~/.ssh/myprivatekey_rsa
|
52
52
|
|
53
53
|
# Create and bootstrap a Windows VM over winrm
|
54
54
|
$ knife azure server create --azure-dns-name MyNewServerName --azure-vm-size Medium --azure-source-image 8fcc3d_Win2012-amd64-30GB --azure-service-location 'West US' --winrm-user myuser --winrm-password 'mypassword' --bootstrap-protocol winrm --distro 'windows-chef-client-msi'
|
@@ -182,8 +182,8 @@ These options may also be configured from knife.rb, as in this example:
|
|
182
182
|
knife[:identity_file]='/path/to/RSA/private/key'
|
183
183
|
knife[:azure_storage_account]='auxpreview104'
|
184
184
|
knife[:azure_os_disk_name]='disk107'
|
185
|
-
knife[:
|
186
|
-
knife[:
|
185
|
+
knife[:tcp-endpoints]='80:80,3389:5678'
|
186
|
+
knife[:udp-endpoints]='123:123'
|
187
187
|
|
188
188
|
#### Options for Bootstrapping a Windows Node in Azure
|
189
189
|
|
data/lib/azure/certificate.rb
CHANGED
@@ -25,6 +25,10 @@ class Azure
|
|
25
25
|
certificate = Certificate.new(@connection)
|
26
26
|
certificate.create(params)
|
27
27
|
end
|
28
|
+
def add(certificate_data, certificate_password, certificate_format, dns_name)
|
29
|
+
certificate = Certificate.new(@connection)
|
30
|
+
certificate.add_certificate certificate_data, certificate_password, certificate_format, dns_name
|
31
|
+
end
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
@@ -41,17 +45,7 @@ class Azure
|
|
41
45
|
# public part of the key
|
42
46
|
@cert_data = generate_public_key_certificate_data({:ssh_key => params[:identity_file],
|
43
47
|
:ssh_key_passphrase => params[:identity_file_passphrase]})
|
44
|
-
|
45
|
-
# Add certificate to the hosted service
|
46
|
-
builder = Nokogiri::XML::Builder.new do |xml|
|
47
|
-
xml.CertificateFile('xmlns'=>'http://schemas.microsoft.com/windowsazure') {
|
48
|
-
xml.Data @cert_data
|
49
|
-
xml.CertificateFormat 'pfx'
|
50
|
-
xml.Password 'knifeazure'
|
51
|
-
}
|
52
|
-
end
|
53
|
-
# Windows Azure API call
|
54
|
-
@connection.query_azure("hostedservices/#{params[:azure_dns_name]}/certificates", "post", builder.to_xml)
|
48
|
+
add_certificate @cert_data, 'knifeazure', 'pfx', params[:azure_dns_name]
|
55
49
|
# Return the fingerprint to be used while adding role
|
56
50
|
@fingerprint
|
57
51
|
end
|
@@ -83,5 +77,20 @@ class Azure
|
|
83
77
|
# Encode the pfx format - upload this certificate
|
84
78
|
Base64.strict_encode64(pfx.to_der)
|
85
79
|
end
|
80
|
+
|
81
|
+
def add_certificate certificate_data, certificate_password, certificate_format, dns_name
|
82
|
+
# Generate XML to call the API
|
83
|
+
# Add certificate to the hosted service
|
84
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
85
|
+
xml.CertificateFile('xmlns'=>'http://schemas.microsoft.com/windowsazure') {
|
86
|
+
xml.Data certificate_data
|
87
|
+
xml.CertificateFormat certificate_format
|
88
|
+
xml.Password certificate_password
|
89
|
+
}
|
90
|
+
end
|
91
|
+
# Windows Azure API call
|
92
|
+
@connection.query_azure("hostedservices/#{dns_name}/certificates", "post", builder.to_xml)
|
93
|
+
end
|
94
|
+
|
86
95
|
end
|
87
96
|
end
|
data/lib/azure/deploy.rb
CHANGED
@@ -78,6 +78,10 @@ class Azure
|
|
78
78
|
if params[:identity_file]
|
79
79
|
params[:fingerprint] = @connection.certificates.create(params)
|
80
80
|
end
|
81
|
+
if params[:cert_path]
|
82
|
+
cert_data = File.read (params[:cert_path])
|
83
|
+
@connection.certificates.add cert_data, params[:cert_password], 'pfx', params[:azure_dns_name]
|
84
|
+
end
|
81
85
|
params['deploy_name'] = get_deploy_name_for_hostedservice(params[:azure_dns_name])
|
82
86
|
|
83
87
|
if params['deploy_name'] != nil
|
@@ -99,7 +103,7 @@ class Azure
|
|
99
103
|
end
|
100
104
|
def delete(rolename)
|
101
105
|
end
|
102
|
-
|
106
|
+
|
103
107
|
def queryDeploy(hostedservicename)
|
104
108
|
deploy = Deploy.new(@connection)
|
105
109
|
deploy.retrieve(hostedservicename)
|
data/lib/azure/image.rb
CHANGED
@@ -23,23 +23,51 @@ class Azure
|
|
23
23
|
end
|
24
24
|
def load
|
25
25
|
@images ||= begin
|
26
|
-
|
26
|
+
osimages = self.get_images("OSImage") #get OSImages
|
27
|
+
vmimages = self.get_images("VMImage") #get VMImages
|
28
|
+
|
29
|
+
all_images = osimages.merge(vmimages)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def all
|
34
|
+
self.load.values
|
35
|
+
end
|
36
|
+
|
37
|
+
# img_type = OSImages or VMImage
|
38
|
+
def get_images(img_type)
|
39
|
+
images = Hash.new
|
40
|
+
|
41
|
+
if(img_type == "OSImage")
|
27
42
|
response = @connection.query_azure('images')
|
28
|
-
|
43
|
+
elsif(img_type == "VMImage")
|
44
|
+
response = @connection.query_azure('vmimages')
|
45
|
+
end
|
46
|
+
|
47
|
+
unless response.to_s.empty?
|
48
|
+
osimages = response.css(img_type)
|
49
|
+
|
29
50
|
osimages.each do |image|
|
30
51
|
item = Image.new(image)
|
31
52
|
images[item.name] = item
|
32
53
|
end
|
33
|
-
images
|
34
54
|
end
|
55
|
+
|
56
|
+
images
|
35
57
|
end
|
36
58
|
|
37
|
-
def
|
38
|
-
self.
|
59
|
+
def is_os_image(image_name)
|
60
|
+
os_images = self.get_images("OSImage").values
|
61
|
+
os_images.detect {|img| img.name == image_name} ? true : false
|
62
|
+
end
|
63
|
+
|
64
|
+
def is_vm_image(image_name)
|
65
|
+
vm_images = self.get_images("VMImage").values
|
66
|
+
vm_images.detect {|img| img.name == image_name} ? true : false
|
39
67
|
end
|
40
68
|
|
41
69
|
def exists?(name)
|
42
|
-
self.all.
|
70
|
+
self.all.detect {|img| img.name == name} ? true : false
|
43
71
|
end
|
44
72
|
|
45
73
|
def find(name)
|
data/lib/azure/rest.rb
CHANGED
@@ -97,7 +97,7 @@ module AzureAPI
|
|
97
97
|
request = Net::HTTP::Put.new(uri.request_uri)
|
98
98
|
end
|
99
99
|
text = verb == 'put'
|
100
|
-
request["x-ms-version"] = "
|
100
|
+
request["x-ms-version"] = "2014-04-01"
|
101
101
|
request["content-type"] = text ? "text/plain" : "application/xml"
|
102
102
|
request["accept"] = "application/xml"
|
103
103
|
request["accept-charset"] = "utf-8"
|
data/lib/azure/role.rb
CHANGED
@@ -16,6 +16,7 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
require 'securerandom'
|
19
|
+
|
19
20
|
class Azure
|
20
21
|
class Roles
|
21
22
|
include AzureUtility
|
@@ -100,7 +101,7 @@ class Azure
|
|
100
101
|
if alone_on_hostedservice(role)
|
101
102
|
if !params[:preserve_azure_dns_name] && compmedia
|
102
103
|
servicecall = "hostedservices/#{role.hostedservicename}"
|
103
|
-
else
|
104
|
+
else
|
104
105
|
servicecall = "hostedservices/#{role.hostedservicename}/deployments/#{role.deployname}"
|
105
106
|
end
|
106
107
|
else
|
@@ -127,7 +128,7 @@ class Azure
|
|
127
128
|
for attempt in 0..12
|
128
129
|
break if @connection.query_azure(servicecall, "get").search("AttachedTo").text == ""
|
129
130
|
if attempt == 12 then puts "The associated disk could not be deleted due to time out." else sleep 25 end
|
130
|
-
end
|
131
|
+
end
|
131
132
|
unless params[:preserve_azure_vhd]
|
132
133
|
@connection.query_azure(servicecall, 'delete', '', 'comp=media', wait=params[:wait])
|
133
134
|
else
|
@@ -142,7 +143,7 @@ class Azure
|
|
142
143
|
roles_using_same_service = find_roles_within_hostedservice(params[:azure_dns_name])
|
143
144
|
if roles_using_same_service.size <= 1
|
144
145
|
servicecall = "hostedservices/" + params[:azure_dns_name]
|
145
|
-
@connection.query_azure(servicecall, "delete")
|
146
|
+
@connection.query_azure(servicecall, "delete")
|
146
147
|
end
|
147
148
|
end
|
148
149
|
end
|
@@ -219,122 +220,176 @@ class Azure
|
|
219
220
|
xml.RoleName {xml.text params[:azure_vm_name]}
|
220
221
|
xml.OsVersion('i:nil' => 'true')
|
221
222
|
xml.RoleType 'PersistentVMRole'
|
223
|
+
xml.VMImageName params[:azure_source_image] if params[:is_vm_image]
|
224
|
+
|
222
225
|
xml.ConfigurationSets {
|
223
226
|
if params[:os_type] == 'Linux'
|
224
|
-
|
225
227
|
xml.ConfigurationSet('i:type' => 'LinuxProvisioningConfigurationSet') {
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
228
|
+
xml.ConfigurationSetType 'LinuxProvisioningConfiguration'
|
229
|
+
xml.HostName params[:azure_vm_name]
|
230
|
+
xml.UserName params[:ssh_user]
|
231
|
+
unless params[:identity_file].nil?
|
232
|
+
xml.DisableSshPasswordAuthentication 'true'
|
233
|
+
xml.SSH {
|
234
|
+
xml.PublicKeys {
|
235
|
+
xml.PublicKey {
|
236
|
+
xml.Fingerprint params[:fingerprint].to_s.upcase
|
237
|
+
xml.Path '/home/' + params[:ssh_user] + '/.ssh/authorized_keys'
|
238
|
+
}
|
236
239
|
}
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
end
|
240
|
+
}
|
241
|
+
else
|
242
|
+
xml.UserPassword params[:ssh_password]
|
243
|
+
xml.DisableSshPasswordAuthentication 'false'
|
244
|
+
end
|
243
245
|
}
|
244
246
|
elsif params[:os_type] == 'Windows'
|
245
247
|
xml.ConfigurationSet('i:type' => 'WindowsProvisioningConfigurationSet') {
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
248
|
+
xml.ConfigurationSetType 'WindowsProvisioningConfiguration'
|
249
|
+
xml.ComputerName params[:azure_vm_name]
|
250
|
+
xml.AdminPassword params[:admin_password]
|
251
|
+
xml.ResetPasswordOnFirstLogon 'false'
|
252
|
+
xml.EnableAutomaticUpdates 'false'
|
253
|
+
if params[:bootstrap_proto].downcase == 'winrm'
|
254
|
+
if params[:ssl_cert_fingerprint]
|
255
|
+
xml.StoredCertificateSettings {
|
256
|
+
xml.CertificateSetting {
|
257
|
+
xml.StoreLocation "LocalMachine"
|
258
|
+
xml.StoreName "My"
|
259
|
+
xml.Thumbprint params[:ssl_cert_fingerprint]
|
260
|
+
}
|
261
|
+
}
|
262
|
+
end
|
263
|
+
xml.WinRM {
|
264
|
+
xml.Listeners {
|
265
|
+
if params[:ssl_cert_fingerprint]
|
266
|
+
xml.Listener {
|
267
|
+
xml.CertificateThumbprint params[:ssl_cert_fingerprint]
|
268
|
+
xml.Protocol 'Https'
|
269
|
+
}
|
270
|
+
else
|
271
|
+
xml.Listener {
|
272
|
+
xml.Protocol 'Http'
|
273
|
+
}
|
274
|
+
end
|
275
|
+
}
|
257
276
|
}
|
258
|
-
|
259
|
-
|
260
|
-
end
|
277
|
+
end
|
278
|
+
xml.AdminUsername params[:winrm_user]
|
261
279
|
}
|
262
280
|
end
|
263
281
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
xml.Name 'SSH'
|
271
|
-
xml.Port params[:port]
|
272
|
-
xml.Protocol 'TCP'
|
273
|
-
}
|
274
|
-
elsif params[:bootstrap_proto].downcase == 'winrm' and params[:os_type] == 'Windows'
|
275
|
-
xml.InputEndpoint {
|
282
|
+
xml.ConfigurationSet('i:type' => 'NetworkConfigurationSet') {
|
283
|
+
xml.ConfigurationSetType 'NetworkConfiguration'
|
284
|
+
xml.InputEndpoints {
|
285
|
+
|
286
|
+
if params[:os_type] == 'Windows' and (params[:bootstrap_proto].downcase == 'winrm' or params[:bootstrap_proto].downcase == 'cloud-api')
|
287
|
+
xml.InputEndpoint {
|
276
288
|
xml.LocalPort '5985'
|
277
289
|
xml.Name 'WinRM'
|
278
290
|
xml.Port params[:port]
|
279
291
|
xml.Protocol 'TCP'
|
280
292
|
}
|
281
|
-
|
282
|
-
|
283
|
-
if params[:tcp_endpoints]
|
284
|
-
params[:tcp_endpoints].split(',').each do |endpoint|
|
285
|
-
ports = endpoint.split(':')
|
286
|
-
if !(ports.length > 1 && ports[1] == params[:port] || ports.length == 1 && ports[0] == params[:port])
|
293
|
+
else
|
287
294
|
xml.InputEndpoint {
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
295
|
+
xml.LocalPort '22'
|
296
|
+
xml.Name 'SSH'
|
297
|
+
xml.Port params[:port]
|
298
|
+
xml.Protocol 'TCP'
|
299
|
+
}
|
300
|
+
end
|
301
|
+
|
302
|
+
if params[:tcp_endpoints]
|
303
|
+
params[:tcp_endpoints].split(',').each do |endpoint|
|
304
|
+
ports = endpoint.split(':')
|
305
|
+
if !(ports.length > 1 && ports[1] == params[:port] || ports.length == 1 && ports[0] == params[:port])
|
306
|
+
xml.InputEndpoint {
|
307
|
+
xml.LocalPort ports[0]
|
308
|
+
xml.Name 'tcpport_' + ports[0] + '_' + params[:azure_vm_name]
|
309
|
+
if ports.length > 1
|
310
|
+
xml.Port ports[1]
|
311
|
+
else
|
312
|
+
xml.Port ports[0]
|
313
|
+
end
|
314
|
+
xml.Protocol 'TCP'
|
315
|
+
}
|
292
316
|
else
|
293
|
-
|
317
|
+
warn_message = ports.length > 1 ? "#{ports.join(':')} because this ports are" : "#{ports[0]} because this port is"
|
318
|
+
puts("Skipping tcp-endpoints: #{warn_message} already in use by ssh/winrm endpoint in current VM.")
|
294
319
|
end
|
295
|
-
|
296
|
-
}
|
297
|
-
else
|
298
|
-
warn_message = ports.length > 1 ? "#{ports.join(':')} because this ports are" : "#{ports[0]} because this port is"
|
299
|
-
puts("Skipping tcp-endpoints: #{warn_message} already in use by ssh/winrm endpoint in current VM.")
|
320
|
+
end
|
300
321
|
end
|
301
|
-
end
|
302
|
-
end
|
303
322
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
323
|
+
if params[:udp_endpoints]
|
324
|
+
params[:udp_endpoints].split(',').each do |endpoint|
|
325
|
+
ports = endpoint.split(':')
|
326
|
+
xml.InputEndpoint {
|
327
|
+
xml.LocalPort ports[0]
|
328
|
+
xml.Name 'udpport_' + ports[0] + '_' + params[:azure_vm_name]
|
329
|
+
if ports.length > 1
|
330
|
+
xml.Port ports[1]
|
331
|
+
else
|
332
|
+
xml.Port ports[0]
|
333
|
+
end
|
334
|
+
xml.Protocol 'UDP'
|
335
|
+
}
|
314
336
|
end
|
315
|
-
|
337
|
+
end
|
338
|
+
}
|
339
|
+
if params[:azure_subnet_name]
|
340
|
+
xml.SubnetNames {
|
341
|
+
xml.SubnetName params[:azure_subnet_name]
|
316
342
|
}
|
317
343
|
end
|
318
|
-
end
|
319
344
|
}
|
320
|
-
if params[:azure_subnet_name]
|
321
|
-
xml.SubnetNames {
|
322
|
-
xml.SubnetName params[:azure_subnet_name]
|
323
|
-
}
|
324
|
-
end
|
325
|
-
}
|
326
345
|
}
|
346
|
+
|
327
347
|
if params[:azure_availability_set]
|
328
348
|
xml.AvailabilitySetName params[:azure_availability_set]
|
329
349
|
end
|
350
|
+
# Azure resource extension support
|
351
|
+
if params[:bootstrap_proto] == 'cloud-api'
|
352
|
+
xml.ResourceExtensionReferences {
|
353
|
+
xml.ResourceExtensionReference {
|
354
|
+
xml.ReferenceName params[:chef_extension]
|
355
|
+
xml.Publisher params[:chef_extension_publisher]
|
356
|
+
xml.Name params[:chef_extension]
|
357
|
+
xml.Version params[:chef_extension_version]
|
358
|
+
xml.ResourceExtensionParameterValues {
|
359
|
+
if params[:chef_extension_public_param]
|
360
|
+
xml.ResourceExtensionParameterValue {
|
361
|
+
xml.Key "PublicParams"
|
362
|
+
xml.Value params[:chef_extension_public_param]
|
363
|
+
xml.Type "Public"
|
364
|
+
}
|
365
|
+
end
|
366
|
+
if params[:chef_extension_private_param]
|
367
|
+
xml.ResourceExtensionParameterValue {
|
368
|
+
xml.Key "PrivateParams"
|
369
|
+
xml.Value params[:chef_extension_private_param]
|
370
|
+
xml.Type "Private"
|
371
|
+
}
|
372
|
+
end
|
373
|
+
}
|
374
|
+
xml.State "Enable"
|
375
|
+
}
|
376
|
+
}
|
377
|
+
end
|
378
|
+
|
330
379
|
xml.Label Base64.encode64(params[:azure_vm_name]).strip
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
xml.
|
335
|
-
|
336
|
-
|
380
|
+
|
381
|
+
#OSVirtualHardDisk not required in case azure_source_image is a VMImage
|
382
|
+
unless(params[:is_vm_image])
|
383
|
+
xml.OSVirtualHardDisk {
|
384
|
+
disk_name = params[:azure_os_disk_name] || "disk_" + SecureRandom.uuid
|
385
|
+
xml.DiskName disk_name
|
386
|
+
xml.MediaLink 'http://' + params[:azure_storage_account] + '.blob.core.windows.net/vhds/' + disk_name + '.vhd'
|
387
|
+
xml.SourceImageName params[:azure_source_image]
|
388
|
+
}
|
389
|
+
end
|
390
|
+
|
337
391
|
xml.RoleSize params[:azure_vm_size]
|
392
|
+
xml.ProvisionGuestAgent true if params[:bootstrap_proto] == 'cloud-api'
|
338
393
|
}
|
339
394
|
end
|
340
395
|
builder.doc
|
@@ -44,8 +44,8 @@ class Chef
|
|
44
44
|
|
45
45
|
validate!
|
46
46
|
|
47
|
-
image_labels = !locate_config_value(:show_all_fields) ? ['Name', 'OS', 'Location'] : ['Name', 'Category', 'Label', 'OS', 'Location']
|
48
|
-
image_list = image_labels.map {|label| ui.color(label, :bold)}
|
47
|
+
image_labels = !locate_config_value(:show_all_fields) ? ['Name', 'OS', 'Location'] : ['Name', 'Category', 'Label', 'OS', 'Location']
|
48
|
+
image_list = image_labels.map {|label| ui.color(label, :bold)}
|
49
49
|
items = connection.images.all
|
50
50
|
|
51
51
|
image_items = image_labels.map {|item| item.downcase }
|
@@ -54,7 +54,7 @@ class Chef
|
|
54
54
|
end
|
55
55
|
|
56
56
|
puts "\n"
|
57
|
-
puts h.list(image_list, :uneven_columns_across, !locate_config_value(:show_all_fields) ? 3 : 5)
|
57
|
+
puts h.list(image_list, :uneven_columns_across, !locate_config_value(:show_all_fields) ? 3 : 5)
|
58
58
|
|
59
59
|
end
|
60
60
|
end
|
@@ -40,7 +40,6 @@ class Chef
|
|
40
40
|
|
41
41
|
def load_winrm_deps
|
42
42
|
require 'winrm'
|
43
|
-
require 'em-winrm'
|
44
43
|
require 'chef/knife/winrm'
|
45
44
|
require 'chef/knife/bootstrap_windows_winrm'
|
46
45
|
end
|
@@ -51,7 +50,7 @@ class Chef
|
|
51
50
|
|
52
51
|
option :bootstrap_protocol,
|
53
52
|
:long => "--bootstrap-protocol protocol",
|
54
|
-
:description => "Protocol to bootstrap windows servers. options: winrm
|
53
|
+
:description => "Protocol to bootstrap windows servers. options: 'winrm' or 'ssh' or 'cloud-api'.",
|
55
54
|
:default => "winrm"
|
56
55
|
|
57
56
|
option :chef_node_name,
|
@@ -62,7 +61,8 @@ class Chef
|
|
62
61
|
option :ssh_user,
|
63
62
|
:short => "-x USERNAME",
|
64
63
|
:long => "--ssh-user USERNAME",
|
65
|
-
:description => "The ssh username"
|
64
|
+
:description => "The ssh username",
|
65
|
+
:default => "root"
|
66
66
|
|
67
67
|
option :ssh_password,
|
68
68
|
:short => "-P PASSWORD",
|
@@ -167,12 +167,12 @@ class Chef
|
|
167
167
|
option :tcp_endpoints,
|
168
168
|
:short => "-t PORT_LIST",
|
169
169
|
:long => "--tcp-endpoints PORT_LIST",
|
170
|
-
:description => "Comma
|
170
|
+
:description => "Comma-separated list of TCP local and public ports to open e.g. '80:80,433:5000'"
|
171
171
|
|
172
172
|
option :udp_endpoints,
|
173
173
|
:short => "-u PORT_LIST",
|
174
174
|
:long => "--udp-endpoints PORT_LIST",
|
175
|
-
:description => "Comma
|
175
|
+
:description => "Comma-separated list of UDP local and public ports to open e.g. '80:80,433:5000'"
|
176
176
|
|
177
177
|
option :azure_connect_to_existing_dns,
|
178
178
|
:short => "-c",
|
@@ -213,6 +213,18 @@ class Chef
|
|
213
213
|
:description => "A JSON string to be added to the first run of chef-client",
|
214
214
|
:proc => lambda { |o| JSON.parse(o) }
|
215
215
|
|
216
|
+
option :thumbprint,
|
217
|
+
:long => "--thumbprint THUMBPRINT",
|
218
|
+
:description => "The thumprint of the ssl certificate"
|
219
|
+
|
220
|
+
option :cert_passphrase,
|
221
|
+
:long => "--cert-passphrase PASSWORD",
|
222
|
+
:description => "SSL Certificate Password"
|
223
|
+
|
224
|
+
option :cert_path,
|
225
|
+
:long => "--cert-path PATH",
|
226
|
+
:description => "SSL Certificate Path"
|
227
|
+
|
216
228
|
def strip_non_ascii(string)
|
217
229
|
string.gsub(/[^0-9a-z ]/i, '')
|
218
230
|
end
|
@@ -222,6 +234,7 @@ class Chef
|
|
222
234
|
end
|
223
235
|
|
224
236
|
def wait_until_virtual_machine_ready(retry_interval_in_seconds = 30)
|
237
|
+
|
225
238
|
vm_status = nil
|
226
239
|
puts
|
227
240
|
|
@@ -230,6 +243,24 @@ class Chef
|
|
230
243
|
if vm_status != :vm_status_ready
|
231
244
|
wait_for_virtual_machine_state(:vm_status_ready, 15, retry_interval_in_seconds)
|
232
245
|
end
|
246
|
+
|
247
|
+
msg_server_summary(get_role_server())
|
248
|
+
|
249
|
+
if locate_config_value(:bootstrap_protocol) == "cloud-api"
|
250
|
+
extension_status = wait_for_resource_extension_state(:wagent_provisioning, 5, retry_interval_in_seconds)
|
251
|
+
|
252
|
+
if extension_status != :extension_installing
|
253
|
+
extension_status = wait_for_resource_extension_state(:extension_installing, 5, retry_interval_in_seconds)
|
254
|
+
end
|
255
|
+
|
256
|
+
if extension_status != :extension_provisioning
|
257
|
+
extension_status = wait_for_resource_extension_state(:extension_provisioning, 10, retry_interval_in_seconds)
|
258
|
+
end
|
259
|
+
|
260
|
+
if extension_status != :extension_ready
|
261
|
+
wait_for_resource_extension_state(:extension_ready, 5, retry_interval_in_seconds)
|
262
|
+
end
|
263
|
+
end
|
233
264
|
rescue Exception => e
|
234
265
|
Chef::Log.error("#{e.to_s}")
|
235
266
|
raise 'Verify connectivity to Azure and subscription resource limit compliance (e.g. maximum CPU core limits) and try again.'
|
@@ -265,6 +296,37 @@ class Chef
|
|
265
296
|
vm_status
|
266
297
|
end
|
267
298
|
|
299
|
+
def wait_for_resource_extension_state(extension_status_goal, total_wait_time_in_minutes, retry_interval_in_seconds)
|
300
|
+
|
301
|
+
extension_status_ordering = {:extension_status_not_detected => 0, :wagent_provisioning => 1, :extension_installing => 2, :extension_provisioning => 3, :extension_ready => 4}
|
302
|
+
|
303
|
+
status_description = {:extension_status_not_detected => 'any', :wagent_provisioning => 'wagent provisioning', :extension_installing => "installing", :extension_provisioning => "provisioning", :extension_ready => "ready" }
|
304
|
+
|
305
|
+
print ui.color("Waiting for Resource Extension to reach status '#{status_description[extension_status_goal]}'", :magenta)
|
306
|
+
|
307
|
+
max_polling_attempts = (total_wait_time_in_minutes * 60) / retry_interval_in_seconds
|
308
|
+
polling_attempts = 0
|
309
|
+
|
310
|
+
wait_start_time = Time.now
|
311
|
+
|
312
|
+
begin
|
313
|
+
extension_status = get_extension_status()
|
314
|
+
extension_ready = extension_status_ordering[extension_status[:status]] >= extension_status_ordering[extension_status_goal]
|
315
|
+
print '.'
|
316
|
+
sleep retry_interval_in_seconds if !extension_ready
|
317
|
+
polling_attempts += 1
|
318
|
+
end until extension_ready || polling_attempts >= max_polling_attempts
|
319
|
+
|
320
|
+
if ! extension_ready
|
321
|
+
raise Chef::Exceptions::CommandTimeout, "Resource extension state '#{status_description[extension_status_goal]}' not reached after #{total_wait_time_in_minutes} minutes. #{extension_status[:message]}"
|
322
|
+
end
|
323
|
+
|
324
|
+
elapsed_time_in_minutes = ((Time.now - wait_start_time) / 60).round(2)
|
325
|
+
print ui.color("Resource extension state '#{status_description[extension_status_goal]}' reached after #{elapsed_time_in_minutes} minutes.\n", :cyan)
|
326
|
+
|
327
|
+
extension_status[:status]
|
328
|
+
end
|
329
|
+
|
268
330
|
def get_virtual_machine_status()
|
269
331
|
role = get_role_server()
|
270
332
|
unless role.nil?
|
@@ -280,6 +342,53 @@ class Chef
|
|
280
342
|
return :vm_status_not_detected
|
281
343
|
end
|
282
344
|
|
345
|
+
def get_extension_status()
|
346
|
+
deployment_name = connection.deploys.get_deploy_name_for_hostedservice(locate_config_value(:azure_dns_name))
|
347
|
+
deployment = connection.query_azure("hostedservices/#{locate_config_value(:azure_dns_name)}/deployments/#{deployment_name}")
|
348
|
+
extension_status = Hash.new
|
349
|
+
|
350
|
+
if deployment.at_css('Deployment Name') != nil
|
351
|
+
role_list_xml = deployment.css('RoleInstanceList RoleInstance')
|
352
|
+
role_list_xml.each do |role|
|
353
|
+
if role.at_css("RoleName").text == locate_config_value(:azure_vm_name)
|
354
|
+
lnx_waagent_fail_msg = "Failed to deserialize the status reported by the Guest Agent"
|
355
|
+
waagent_status_msg = role.at_css("GuestAgentStatus FormattedMessage Message").text
|
356
|
+
|
357
|
+
if role.at_css("GuestAgentStatus Status").text == "Ready"
|
358
|
+
extn_status = role.at_css("ResourceExtensionStatusList Status").text
|
359
|
+
|
360
|
+
Chef::Log.debug("Resource extension status is #{extn_status}")
|
361
|
+
|
362
|
+
if extn_status == "Installing"
|
363
|
+
extension_status[:status] = :extension_installing
|
364
|
+
extension_status[:message] = role.at_css("ResourceExtensionStatusList FormattedMessage Message").text
|
365
|
+
elsif extn_status == "NotReady"
|
366
|
+
extension_status[:status] = :extension_provisioning
|
367
|
+
extension_status[:message] = role.at_css("ResourceExtensionStatusList FormattedMessage Message").text
|
368
|
+
elsif extn_status == "Ready"
|
369
|
+
extension_status[:status] = :extension_ready
|
370
|
+
extension_status[:message] = role.at_css("ResourceExtensionStatusList FormattedMessage Message").text
|
371
|
+
else
|
372
|
+
extension_status[:status] = :extension_status_not_detected
|
373
|
+
end
|
374
|
+
# This fix is for linux waagent issue: api unable to deserialize the waagent status.
|
375
|
+
elsif role.at_css("GuestAgentStatus Status").text == "NotReady" and waagent_status_msg == lnx_waagent_fail_msg
|
376
|
+
extension_status[:status] = :extension_ready
|
377
|
+
else
|
378
|
+
extension_status[:status] = :wagent_provisioning
|
379
|
+
extension_status[:message] = role.at_css("GuestAgentStatus Message").text
|
380
|
+
end
|
381
|
+
else
|
382
|
+
extension_status[:status] = :extension_status_not_detected
|
383
|
+
end
|
384
|
+
end
|
385
|
+
else
|
386
|
+
extension_status[:status] = :extension_status_not_detected
|
387
|
+
end
|
388
|
+
|
389
|
+
return extension_status
|
390
|
+
end
|
391
|
+
|
283
392
|
def get_role_server()
|
284
393
|
deploy = connection.deploys.queryDeploy(locate_config_value(:azure_dns_name))
|
285
394
|
deploy.find_role(locate_config_value(:azure_vm_name))
|
@@ -341,6 +450,8 @@ class Chef
|
|
341
450
|
Chef::Log.info("validating...")
|
342
451
|
validate!
|
343
452
|
|
453
|
+
ssh_override_winrm if %w(ssh cloud-api).include?(locate_config_value(:bootstrap_protocol)) and !is_image_windows?
|
454
|
+
|
344
455
|
Chef::Log.info("creating...")
|
345
456
|
|
346
457
|
config[:azure_dns_name] = get_dns_name(locate_config_value(:azure_dns_name))
|
@@ -352,7 +463,7 @@ class Chef
|
|
352
463
|
if connection.hosts.exists?(locate_config_value(:azure_dns_name))
|
353
464
|
remove_hosted_service_on_failure = nil
|
354
465
|
end
|
355
|
-
|
466
|
+
|
356
467
|
#If Storage Account is not specified, check if the geographic location has one to re-use
|
357
468
|
if not locate_config_value(:azure_storage_account)
|
358
469
|
storage_accts = connection.storageaccounts.all
|
@@ -369,14 +480,13 @@ class Chef
|
|
369
480
|
remove_storage_service_on_failure = nil
|
370
481
|
else
|
371
482
|
remove_storage_service_on_failure = locate_config_value(:azure_storage_account)
|
372
|
-
end
|
483
|
+
end
|
373
484
|
end
|
374
485
|
|
375
486
|
begin
|
376
487
|
connection.deploys.create(create_server_def)
|
377
488
|
wait_until_virtual_machine_ready()
|
378
489
|
server = get_role_server()
|
379
|
-
fqdn = server.publicipaddress
|
380
490
|
rescue Exception => e
|
381
491
|
Chef::Log.error("Failed to create the server -- exception being rescued: #{e.to_s}")
|
382
492
|
backtrace_message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
@@ -386,6 +496,12 @@ class Chef
|
|
386
496
|
|
387
497
|
msg_server_summary(server)
|
388
498
|
|
499
|
+
bootstrap_exec(server) unless locate_config_value(:bootstrap_protocol) == 'cloud-api'
|
500
|
+
end
|
501
|
+
|
502
|
+
def bootstrap_exec(server)
|
503
|
+
fqdn = server.publicipaddress
|
504
|
+
|
389
505
|
if is_image_windows?
|
390
506
|
# Set distro to windows-chef-client-msi
|
391
507
|
config[:distro] = "windows-chef-client-msi" if (config[:distro].nil? || config[:distro] == "chef-full")
|
@@ -409,7 +525,7 @@ class Chef
|
|
409
525
|
puts("done")
|
410
526
|
}
|
411
527
|
end
|
412
|
-
|
528
|
+
|
413
529
|
puts("\n")
|
414
530
|
bootstrap_for_windows_node(server,fqdn, port).run
|
415
531
|
else
|
@@ -461,7 +577,6 @@ class Chef
|
|
461
577
|
bootstrap
|
462
578
|
end
|
463
579
|
|
464
|
-
|
465
580
|
def bootstrap_for_windows_node(server, fqdn, port)
|
466
581
|
if locate_config_value(:bootstrap_protocol) == 'winrm'
|
467
582
|
|
@@ -523,15 +638,31 @@ class Chef
|
|
523
638
|
:azure_source_image,
|
524
639
|
:azure_vm_size,
|
525
640
|
])
|
641
|
+
|
642
|
+
if locate_config_value(:winrm_password) and (locate_config_value(:winrm_password).length <= 6 and locate_config_value(:winrm_password).length >= 72)
|
643
|
+
ui.error("The supplied password must be 6-72 characters long and meet password complexity requirements")
|
644
|
+
exit 1
|
645
|
+
end
|
646
|
+
|
647
|
+
if locate_config_value(:ssh_password) and (locate_config_value(:ssh_password).length <= 6 and locate_config_value(:ssh_password).length >= 72)
|
648
|
+
ui.error("The supplied password must be 6-72 characters long and meet password complexity requirements")
|
649
|
+
exit 1
|
650
|
+
end
|
651
|
+
|
526
652
|
if locate_config_value(:azure_connect_to_existing_dns) && locate_config_value(:azure_vm_name).nil?
|
527
653
|
ui.error("Specify the VM name using --azure-vm-name option, since you are connecting to existing dns")
|
528
654
|
exit 1
|
529
655
|
end
|
530
656
|
if locate_config_value(:azure_service_location) && locate_config_value(:azure_affinity_group)
|
531
|
-
ui.error("Cannot specify both --
|
657
|
+
ui.error("Cannot specify both --azure-service-location and --azure-affinity-group, use one or the other.")
|
532
658
|
exit 1
|
533
659
|
elsif locate_config_value(:azure_service_location).nil? && locate_config_value(:azure_affinity_group).nil?
|
534
|
-
ui.error("Must specify either --
|
660
|
+
ui.error("Must specify either --azure-service-location or --azure-affinity-group.")
|
661
|
+
exit 1
|
662
|
+
end
|
663
|
+
|
664
|
+
if !(connection.images.exists?(locate_config_value(:azure_source_image)))
|
665
|
+
ui.error("Image provided is invalid")
|
535
666
|
exit 1
|
536
667
|
end
|
537
668
|
end
|
@@ -553,58 +684,101 @@ class Chef
|
|
553
684
|
:azure_availability_set => locate_config_value(:azure_availability_set),
|
554
685
|
:azure_affinity_group => locate_config_value(:azure_affinity_group),
|
555
686
|
:azure_network_name => locate_config_value(:azure_network_name),
|
556
|
-
:azure_subnet_name => locate_config_value(:azure_subnet_name)
|
687
|
+
:azure_subnet_name => locate_config_value(:azure_subnet_name),
|
688
|
+
:ssl_cert_fingerprint => locate_config_value(:thumbprint),
|
689
|
+
:cert_path => locate_config_value(:cert_path),
|
690
|
+
:cert_password => locate_config_value(:cert_passphrase)
|
557
691
|
}
|
558
692
|
# If user is connecting a new VM to an existing dns, then
|
559
693
|
# the VM needs to have a unique public port. Logic below takes care of this.
|
560
694
|
if !is_image_windows? or locate_config_value(:bootstrap_protocol) == 'ssh'
|
561
695
|
port = locate_config_value(:ssh_port) || '22'
|
562
696
|
if locate_config_value(:azure_connect_to_existing_dns) && (port == '22')
|
563
|
-
|
697
|
+
port = Random.rand(64000) + 1000
|
564
698
|
end
|
565
699
|
else
|
566
700
|
port = locate_config_value(:winrm_port) || '5985'
|
567
701
|
if locate_config_value(:azure_connect_to_existing_dns) && (port == '5985')
|
568
|
-
|
702
|
+
port = Random.rand(64000) + 1000
|
569
703
|
end
|
570
704
|
end
|
705
|
+
|
571
706
|
server_def[:port] = port
|
572
707
|
|
708
|
+
if locate_config_value(:bootstrap_protocol) == 'cloud-api'
|
709
|
+
server_def[:chef_extension] = get_chef_extension_name
|
710
|
+
server_def[:chef_extension_publisher] = get_chef_extension_publisher
|
711
|
+
server_def[:chef_extension_version] = get_chef_extension_version
|
712
|
+
server_def[:chef_extension_public_param] = get_chef_extension_public_params
|
713
|
+
server_def[:chef_extension_private_param] = get_chef_extension_private_params
|
714
|
+
else
|
715
|
+
if is_image_windows?
|
716
|
+
if not locate_config_value(:winrm_password) or not locate_config_value(:bootstrap_protocol)
|
717
|
+
ui.error("WinRM Password and Bootstrapping Protocol are compulsory parameters")
|
718
|
+
exit 1
|
719
|
+
end
|
720
|
+
# We can specify the AdminUsername after API version 2013-03-01. However, in this API version,
|
721
|
+
# the AdminUsername is a required parameter.
|
722
|
+
# Also, the user name cannot be Administrator, Admin, Admin1 etc, for enhanced security (provided by Azure)
|
723
|
+
if locate_config_value(:winrm_user).nil? || locate_config_value(:winrm_user).downcase =~ /admin*/
|
724
|
+
ui.error("WinRM User is compulsory parameter and it cannot be named 'admin*'")
|
725
|
+
exit 1
|
726
|
+
end
|
727
|
+
else
|
728
|
+
if not locate_config_value(:ssh_user)
|
729
|
+
ui.error("SSH User is compulsory parameter")
|
730
|
+
exit 1
|
731
|
+
end
|
732
|
+
unless locate_config_value(:ssh_password) or locate_config_value(:identity_file)
|
733
|
+
ui.error("Specify either SSH Key or SSH Password")
|
734
|
+
exit 1
|
735
|
+
end
|
736
|
+
end
|
737
|
+
end
|
573
738
|
if is_image_windows?
|
574
739
|
server_def[:os_type] = 'Windows'
|
575
|
-
if not locate_config_value(:winrm_password) or not locate_config_value(:bootstrap_protocol)
|
576
|
-
ui.error("WinRM Password and Bootstrapping Protocol are compulsory parameters")
|
577
|
-
exit 1
|
578
|
-
end
|
579
|
-
# We can specify the AdminUsername after API version 2013-03-01. However, in this API version,
|
580
|
-
# the AdminUsername is a required parameter.
|
581
|
-
# Also, the user name cannot be Administrator, Admin, Admin1 etc, for enhanced security (provided by Azure)
|
582
|
-
if locate_config_value(:winrm_user).nil? || locate_config_value(:winrm_user).downcase =~ /admin*/
|
583
|
-
ui.error("WinRM User is compulsory parameter and it cannot be named 'admin*'")
|
584
|
-
exit
|
585
|
-
end
|
586
740
|
server_def[:admin_password] = locate_config_value(:winrm_password)
|
587
741
|
server_def[:bootstrap_proto] = locate_config_value(:bootstrap_protocol)
|
588
742
|
else
|
589
743
|
server_def[:os_type] = 'Linux'
|
590
|
-
server_def[:bootstrap_proto] = 'ssh'
|
591
|
-
if not locate_config_value(:ssh_user)
|
592
|
-
ui.error("SSH User is compulsory parameter")
|
593
|
-
exit 1
|
594
|
-
end
|
595
|
-
unless locate_config_value(:ssh_password) or locate_config_value(:identity_file)
|
596
|
-
ui.error("Specify either SSH Key or SSH Password")
|
597
|
-
exit 1
|
598
|
-
end
|
599
|
-
|
744
|
+
server_def[:bootstrap_proto] = locate_config_value(:bootstrap_protocol) || 'ssh'
|
600
745
|
server_def[:ssh_user] = locate_config_value(:ssh_user)
|
601
746
|
server_def[:ssh_password] = locate_config_value(:ssh_password)
|
602
747
|
server_def[:identity_file] = locate_config_value(:identity_file)
|
603
748
|
server_def[:identity_file_passphrase] = locate_config_value(:identity_file_passphrase)
|
604
749
|
end
|
750
|
+
|
751
|
+
server_def[:is_vm_image] = connection.images.is_vm_image(locate_config_value(:azure_source_image))
|
605
752
|
server_def
|
606
753
|
end
|
607
754
|
|
755
|
+
def get_chef_extension_name
|
756
|
+
extension_name = is_image_windows? ? "ChefClient" : "LinuxChefClient"
|
757
|
+
end
|
758
|
+
|
759
|
+
def get_chef_extension_publisher
|
760
|
+
publisher = "Chef.Bootstrap.WindowsAzure"
|
761
|
+
end
|
762
|
+
|
763
|
+
# get latest version
|
764
|
+
def get_chef_extension_version
|
765
|
+
extensions = @connection.query_azure("resourceextensions/#{get_chef_extension_publisher}/#{get_chef_extension_name}")
|
766
|
+
extensions.css("Version").max.text.to_f
|
767
|
+
end
|
768
|
+
|
769
|
+
def get_chef_extension_public_params
|
770
|
+
pub_config = Hash.new
|
771
|
+
pub_config[:client_rb] = "chef_server_url \t #{Chef::Config[:chef_server_url].to_json}\nvalidation_client_name\t#{Chef::Config[:validation_client_name].to_json}"
|
772
|
+
pub_config[:runlist] = locate_config_value(:run_list).empty? ? "" : locate_config_value(:run_list).join(",").to_json
|
773
|
+
Base64.encode64(pub_config.to_json)
|
774
|
+
end
|
775
|
+
|
776
|
+
def get_chef_extension_private_params
|
777
|
+
pri_config = Hash.new
|
778
|
+
pri_config[:validation_key] = File.read(Chef::Config[:validation_key])
|
779
|
+
Base64.encode64(pri_config.to_json)
|
780
|
+
end
|
781
|
+
|
608
782
|
def cleanup_and_exit(remove_hosted_service_on_failure, remove_storage_service_on_failure)
|
609
783
|
ui.warn("Cleaning up resources...")
|
610
784
|
|
@@ -619,8 +793,32 @@ class Chef
|
|
619
793
|
end
|
620
794
|
exit 1
|
621
795
|
end
|
622
|
-
|
796
|
+
|
623
797
|
private
|
798
|
+
|
799
|
+
def ssh_override_winrm
|
800
|
+
# unchanged ssh_user and changed winrm_user, override ssh_user
|
801
|
+
if locate_config_value(:ssh_user).eql?(options[:ssh_user][:default]) &&
|
802
|
+
!locate_config_value(:winrm_user).eql?(options[:winrm_user][:default])
|
803
|
+
config[:ssh_user] = locate_config_value(:winrm_user)
|
804
|
+
end
|
805
|
+
# unchanged ssh_port and changed winrm_port, override ssh_port
|
806
|
+
if locate_config_value(:ssh_port).eql?(options[:ssh_port][:default]) &&
|
807
|
+
!locate_config_value(:winrm_port).eql?(options[:winrm_port][:default])
|
808
|
+
config[:ssh_port] = locate_config_value(:winrm_port)
|
809
|
+
end
|
810
|
+
# unset ssh_password and set winrm_password, override ssh_password
|
811
|
+
if locate_config_value(:ssh_password).nil? &&
|
812
|
+
!locate_config_value(:winrm_password).nil?
|
813
|
+
config[:ssh_password] = locate_config_value(:winrm_password)
|
814
|
+
end
|
815
|
+
# unset identity_file and set kerberos_keytab_file, override identity_file
|
816
|
+
if locate_config_value(:identity_file).nil? &&
|
817
|
+
!locate_config_value(:kerberos_keytab_file).nil?
|
818
|
+
config[:identity_file] = locate_config_value(:kerberos_keytab_file)
|
819
|
+
end
|
820
|
+
end
|
821
|
+
|
624
822
|
# This is related to Windows VM's specifically and computer name
|
625
823
|
# length limits for legacy computer accounts
|
626
824
|
MAX_VM_NAME_CHARACTERS = 15
|
@@ -631,10 +829,9 @@ class Chef
|
|
631
829
|
if locate_config_value(:azure_vm_name).nil?
|
632
830
|
azure_dns_name = prefix + SecureRandom.hex(( MAX_VM_NAME_CHARACTERS - prefix.length)/2)
|
633
831
|
else
|
634
|
-
azure_dns_name =
|
832
|
+
azure_dns_name = locate_config_value(:azure_vm_name)
|
635
833
|
end
|
636
834
|
end
|
637
|
-
|
638
835
|
end
|
639
836
|
end
|
640
837
|
end
|
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.4.0.rc.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: 2014-
|
12
|
+
date: 2014-12-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -31,14 +31,14 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - ! '>='
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 0.
|
34
|
+
version: 0.8.2
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - ! '>='
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 0.
|
41
|
+
version: 0.8.2
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: chef
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,6 +81,20 @@ dependencies:
|
|
81
81
|
- - ~>
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: 0.2.9
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: knife-cloud
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 1.0.0
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 1.0.0
|
84
98
|
description: A plugin to the Chef knife tool for creating instances on the Microsoft
|
85
99
|
Azure platform
|
86
100
|
email: oss@getchef.com
|