knife-azure 1.4.0.rc.0 → 1.4.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +16 -12
- data/lib/azure/certificate.rb +114 -0
- data/lib/azure/deploy.rb +4 -0
- data/lib/azure/vnet.rb +43 -14
- data/lib/chef/knife/azure_server_create.rb +47 -13
- data/lib/chef/knife/azure_vnet_create.rb +6 -0
- data/lib/knife-azure/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzljMjVkNDdjMGI2MWJmMjBlZmU1ZWYxNTY4MDcxY2IxMDI1YzU3YQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDg0MDc2ZTcwMTA4MTViYzI0MWVhYTkwZmZjNzUyOGUxMDcxYzI1ZA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OWRhN2NiMjQ3ZjRlM2NiMDVhZTYwMjI5MGY3YjIwMmEyMTJjM2E2MGZkZTUw
|
10
|
+
YzU3NDU4ZDY3NjkzYzQwZjFlMmRjYTQyYzRkNWUyMzA3YjUzMjM4NzgwNGQ5
|
11
|
+
ZGZhMjdjYzY2YTZhZDZlYjYyZjgyMzJjNmQ5Zjk0YTQ3M2NkNzY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NjQ1NWFiYzZjMTU3ZWU0YmNlY2JmYzM0MDI2ZDdlZWNmZTJkZTcxY2IwYzU4
|
14
|
+
NGY0MzMyNTE5MjZlNmRlMjI4YmM1Y2RkOTNjZWQyMmE0NGYzNTY4YTE3YWNm
|
15
|
+
NDI5ODU3ZTllNWNkM2QwMTcyMGMwNzAyMjk2NWRhMjBiMzdhOWE=
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Knife Azure
|
2
2
|
|
3
3
|
## Description
|
4
|
-
A [knife] (http://docs.
|
4
|
+
A [knife] (http://docs.chef.io/knife.html) plugin to create,
|
5
5
|
delete, and enumerate
|
6
|
-
[
|
6
|
+
[Microsoft Azure] (https://azure.microsoft.com)
|
7
7
|
resources to be managed by Chef.
|
8
8
|
|
9
9
|
## Installation
|
@@ -46,13 +46,17 @@ location in your knife.rb:
|
|
46
46
|
|
47
47
|
# List all VM's (including those not be managed by Chef)
|
48
48
|
$ knife azure server list
|
49
|
-
|
49
|
+
|
50
|
+
# Create and bootstrap a Windows VM over winrm (winrm is the default for Windows)
|
51
|
+
$ knife azure server create --azure-dns-name MyNewServerName --azure-vm-size Medium -I a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-201412.01-en.us-127GB.vhd --azure-service-location 'West US' --winrm-user myuser --winrm-password 'mypassword'
|
52
|
+
|
50
53
|
# Create and bootstrap an Ubuntu VM over ssh
|
51
54
|
$ 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
|
-
|
53
|
-
# Create and bootstrap
|
54
|
-
|
55
|
-
|
55
|
+
|
56
|
+
# Create and bootstrap an Windows VM through the Azure API --
|
57
|
+
# No winrm or ssh transport or Internet access required
|
58
|
+
$ knife azure server create --azure-dns-name MyNewServerName --azure-vm-size Medium -I a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-201412.01-en.us-127GB.vhd --azure-service-location 'West US' --winrm-user myuser --winrm-password 'mypassword' --bootstrap-protocol winrm --bootstrap-protocol cloud-api
|
59
|
+
|
56
60
|
# Delete a server and purge it from the Chef server
|
57
61
|
$ knife azure server delete MyNewNode --purge -y
|
58
62
|
|
@@ -84,18 +88,18 @@ Outputs a list of all linux images that are available to use for provisioning. Y
|
|
84
88
|
This subcommand provisions a new server in Azure and then performs a Chef bootstrap. The goal of the bootstrap is to get Chef installed on the target system so it can run Chef Client with a Chef Server.
|
85
89
|
|
86
90
|
#### Windows Bootstrapping Requirements
|
87
|
-
knife-azure depends on knife-windows: https://github.com/
|
91
|
+
knife-azure depends on knife-windows: https://github.com/chef/knife-windows
|
88
92
|
to bootstrap Windows machines via winrm (Basic, NTLM and Kerberos authentication) or ssh.
|
89
93
|
|
90
|
-
The distro/template to be used for bootstrapping is: https://github.com/
|
94
|
+
The distro/template to be used for bootstrapping is: https://github.com/chef/knife-windows/blob/master/lib/chef/knife/bootstrap/windows-chef-client-msi.erb
|
91
95
|
|
92
96
|
Windows source images should have the WinRM service enabled and the
|
93
97
|
authentication should be set accordingly (Basic, NTLM and Kerberos). Firewall rules should be added accordingly to the source images. Refer to the link to configure this:
|
94
|
-
https://github.com/
|
98
|
+
https://github.com/chef/knife-windows#nodes
|
95
99
|
|
96
100
|
#### Azure-specific Options
|
97
101
|
:azure_dns_name Required. The DNS prefix name that can be used to access the cloud
|
98
|
-
service which is unique within
|
102
|
+
service which is unique within Microsoft Azure. If you want to add
|
99
103
|
new VM to an existing service/deployment, specify an exiting
|
100
104
|
dns-name, along with --azure-connect-to-existing-dns option. Otherwise
|
101
105
|
a new deployment is created.
|
@@ -105,7 +109,7 @@ https://github.com/opscode/knife-windows#nodes
|
|
105
109
|
:azure_source_image Required. Specifies the name of the disk image to use to create
|
106
110
|
the virtual machine. Do a "knife azure image list" to see a
|
107
111
|
list of available images.
|
108
|
-
:azure_storage_account A name for the storage account that is unique within
|
112
|
+
:azure_storage_account A name for the storage account that is unique within Microsoft Azure.
|
109
113
|
Storage account names must be between 3 and 24 characters in
|
110
114
|
length and use numbers and lower-case letters only. This name is
|
111
115
|
the DNS prefix name and can be used to access blobs, queues, and
|
data/lib/azure/certificate.rb
CHANGED
@@ -29,6 +29,13 @@ class Azure
|
|
29
29
|
certificate = Certificate.new(@connection)
|
30
30
|
certificate.add_certificate certificate_data, certificate_password, certificate_format, dns_name
|
31
31
|
end
|
32
|
+
|
33
|
+
def create_ssl_certificate(azure_dns_name)
|
34
|
+
cert_params = { output_file: 'winrm', key_length: 2048, cert_validity: 24,
|
35
|
+
azure_dns_name: azure_dns_name }
|
36
|
+
certificate = Certificate.new(@connection)
|
37
|
+
thumbprint = certificate.create_ssl_certificate(cert_params)
|
38
|
+
end
|
32
39
|
end
|
33
40
|
end
|
34
41
|
|
@@ -92,5 +99,112 @@ class Azure
|
|
92
99
|
@connection.query_azure("hostedservices/#{dns_name}/certificates", "post", builder.to_xml)
|
93
100
|
end
|
94
101
|
|
102
|
+
######## SSL certificate generation for knife-azure ssl bootstrap ######
|
103
|
+
|
104
|
+
def create_ssl_certificate cert_params
|
105
|
+
file_path = cert_params[:output_file].sub(/\.(\w+)$/,'')
|
106
|
+
path = prompt_for_file_path
|
107
|
+
file_path = File.join(path, file_path) unless path.empty?
|
108
|
+
cert_params[:domain] = prompt_for_domain
|
109
|
+
|
110
|
+
rsa_key = generate_keypair cert_params[:key_length]
|
111
|
+
cert = generate_certificate(rsa_key, cert_params)
|
112
|
+
write_certificate_to_file cert, file_path, rsa_key, cert_params
|
113
|
+
puts "*"*70
|
114
|
+
puts "Generated Certificates:"
|
115
|
+
puts "- #{file_path}.pfx - PKCS12 format keypair. Contains both the public and private keys, usually used on the server."
|
116
|
+
puts "- #{file_path}.b64 - Base64 encoded PKCS12 keypair. Contains both the public and private keys, for upload to the Azure REST API."
|
117
|
+
puts "- #{file_path}.pem - Base64 encoded public certificate only. Required by the client to connect to the server."
|
118
|
+
puts "Certificate Thumbprint: #{@thumbprint.to_s.upcase}"
|
119
|
+
puts "*"*70
|
120
|
+
|
121
|
+
Chef::Config[:knife][:ca_trust_file] = file_path + ".pem" if Chef::Config[:knife][:ca_trust_file].nil?
|
122
|
+
cert_data = File.read (file_path + ".b64")
|
123
|
+
add_certificate cert_data, @winrm_cert_passphrase, 'pfx', cert_params[:azure_dns_name]
|
124
|
+
@thumbprint
|
125
|
+
end
|
126
|
+
|
127
|
+
def generate_keypair key_length
|
128
|
+
OpenSSL::PKey::RSA.new(key_length.to_i)
|
129
|
+
end
|
130
|
+
|
131
|
+
def prompt_for_passphrase
|
132
|
+
passphrase = ""
|
133
|
+
begin
|
134
|
+
print "Passphrases do not match. Try again.\n" unless passphrase.empty?
|
135
|
+
print "Enter certificate passphrase (empty for no passphrase):"
|
136
|
+
passphrase = STDIN.gets
|
137
|
+
return passphrase.strip if passphrase == "\n"
|
138
|
+
print "Enter same passphrase again:"
|
139
|
+
confirm_passphrase = STDIN.gets
|
140
|
+
end until passphrase == confirm_passphrase
|
141
|
+
passphrase.strip
|
142
|
+
end
|
143
|
+
|
144
|
+
def prompt_for_file_path
|
145
|
+
file_path = ''
|
146
|
+
counter = 0
|
147
|
+
begin
|
148
|
+
print "Invalid location! \n" unless file_path.empty?
|
149
|
+
print 'Enter the file path for certificates e.g. C:\Windows (empty for current location):'
|
150
|
+
file_path = STDIN.gets
|
151
|
+
stripped_file_path = file_path.strip
|
152
|
+
return stripped_file_path if file_path == "\n"
|
153
|
+
counter += 1
|
154
|
+
exit(1) if counter == 3
|
155
|
+
end until File.directory?(stripped_file_path)
|
156
|
+
stripped_file_path
|
157
|
+
end
|
158
|
+
|
159
|
+
def prompt_for_domain
|
160
|
+
counter = 0
|
161
|
+
begin
|
162
|
+
print 'Enter the domain (mandatory):'
|
163
|
+
domain = STDIN.gets
|
164
|
+
domain = domain.strip
|
165
|
+
counter += 1
|
166
|
+
exit(1) if counter == 3
|
167
|
+
end until !domain.empty?
|
168
|
+
domain
|
169
|
+
end
|
170
|
+
|
171
|
+
def generate_certificate(rsa_key, cert_params)
|
172
|
+
@hostname = "*"
|
173
|
+
if cert_params[:domain]
|
174
|
+
@hostname = "*." + cert_params[:domain]
|
175
|
+
end
|
176
|
+
|
177
|
+
#Create a self-signed X509 certificate from the rsa_key (unencrypted)
|
178
|
+
cert = OpenSSL::X509::Certificate.new
|
179
|
+
cert.version = 2
|
180
|
+
cert.serial = Random.rand(65534) + 1 # 2 digit byte range random number for better security aspect
|
181
|
+
|
182
|
+
cert.subject = OpenSSL::X509::Name.parse "/CN=#{@hostname}"
|
183
|
+
cert.issuer = cert.subject
|
184
|
+
cert.public_key = rsa_key.public_key
|
185
|
+
cert.not_before = Time.now
|
186
|
+
cert.not_after = cert.not_before + 2 * 365 * cert_params[:cert_validity].to_i * 60 * 60 # 2 years validity
|
187
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
188
|
+
ef.subject_certificate = cert
|
189
|
+
ef.issuer_certificate = cert
|
190
|
+
cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
|
191
|
+
cert.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
|
192
|
+
cert.add_extension(ef.create_extension("extendedKeyUsage", "1.3.6.1.5.5.7.3.1", false))
|
193
|
+
cert.sign(rsa_key, OpenSSL::Digest::SHA1.new)
|
194
|
+
@thumbprint = OpenSSL::Digest::SHA1.new(cert.to_der)
|
195
|
+
cert
|
196
|
+
end
|
197
|
+
|
198
|
+
def write_certificate_to_file cert, file_path, rsa_key, cert_params
|
199
|
+
File.open(file_path + ".pem", "wb") { |f| f.print cert.to_pem }
|
200
|
+
@winrm_cert_passphrase = prompt_for_passphrase unless @winrm_cert_passphrase
|
201
|
+
pfx = OpenSSL::PKCS12.create("#{cert_params[:winrm_cert_passphrase]}", "winrmcert", rsa_key, cert)
|
202
|
+
File.open(file_path + ".pfx", "wb") { |f| f.print pfx.to_der }
|
203
|
+
File.open(file_path + ".b64", "wb") { |f| f.print Base64.strict_encode64(pfx.to_der) }
|
204
|
+
end
|
205
|
+
|
206
|
+
########## SSL certificate generation ends ###########
|
207
|
+
|
208
|
+
|
95
209
|
end
|
96
210
|
end
|
data/lib/azure/deploy.rb
CHANGED
@@ -81,7 +81,11 @@ class Azure
|
|
81
81
|
if params[:cert_path]
|
82
82
|
cert_data = File.read (params[:cert_path])
|
83
83
|
@connection.certificates.add cert_data, params[:cert_password], 'pfx', params[:azure_dns_name]
|
84
|
+
elsif(params[:winrm_transport] == "ssl")
|
85
|
+
thumbprint = @connection.certificates.create_ssl_certificate params[:azure_dns_name]
|
86
|
+
params[:ssl_cert_fingerprint] = thumbprint.to_s.upcase
|
84
87
|
end
|
88
|
+
|
85
89
|
params['deploy_name'] = get_deploy_name_for_hostedservice(params[:azure_dns_name])
|
86
90
|
|
87
91
|
if params['deploy_name'] != nil
|
data/lib/azure/vnet.rb
CHANGED
@@ -63,26 +63,55 @@ class Azure
|
|
63
63
|
|
64
64
|
def parse(image)
|
65
65
|
@name = image.at_css('Name').content
|
66
|
-
@affinity_group = image.at_css('AffinityGroup').content
|
66
|
+
@affinity_group = image.at_css('AffinityGroup') ? image.at_css('AffinityGroup').content : ""
|
67
67
|
@state = image.at_css('State').content
|
68
68
|
self
|
69
69
|
end
|
70
70
|
|
71
71
|
def create(params)
|
72
72
|
response = @connection.query_azure('networking/media')
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
73
|
+
if response.at_css("Error") && response.at_css('Code').text == "ResourceNotFound"
|
74
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
75
|
+
xml.NetworkConfiguration(
|
76
|
+
'xmlns'=>'http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration'
|
77
|
+
) {
|
78
|
+
|
79
|
+
xml.VirtualNetworkConfiguration {
|
80
|
+
xml.VirtualNetworkSites {
|
81
|
+
xml.VirtualNetworkSite('name' => params[:azure_vnet_name], 'AffinityGroup' => params[:azure_ag_name]) {
|
82
|
+
if params[:azure_address_space]
|
83
|
+
xml.AddressSpace {
|
84
|
+
xml.AddressPrefix params[:azure_address_space]
|
85
|
+
}
|
86
|
+
end
|
87
|
+
xml.Subnets{
|
88
|
+
xml.Subnet('name' => params[:azure_subnet_name]) {
|
89
|
+
xml.AddressPrefix params[:azure_address_space]
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
end
|
97
|
+
puts("Creating New Virtual Network: #{params[:azure_vnet_name]}...")
|
98
|
+
response = builder
|
99
|
+
else
|
100
|
+
vnets = response.css('VirtualNetworkSite')
|
101
|
+
vnet = nil
|
102
|
+
vnets.each { |vn| vnet = vn if vn['name'] == params[:azure_vnet_name] }
|
103
|
+
add = vnet.nil?
|
104
|
+
vnet = Nokogiri::XML::Node.new('VirtualNetworkSite', response) if add
|
105
|
+
vnet['name'] = params[:azure_vnet_name]
|
106
|
+
vnet['AffinityGroup'] = params[:azure_ag_name]
|
107
|
+
addr_space = Nokogiri::XML::Node.new('AddressSpace', response)
|
108
|
+
addr_prefix = Nokogiri::XML::Node.new('AddressPrefix', response)
|
109
|
+
addr_prefix.content = params[:azure_address_space]
|
110
|
+
addr_space.children = addr_prefix
|
111
|
+
vnet.children = addr_space
|
112
|
+
vnets.last.add_next_sibling(vnet) if add
|
113
|
+
puts("Updating existing Virtual Network: #{params[:azure_vnet_name]}...")
|
114
|
+
end
|
86
115
|
@connection.query_azure('networking/media', 'put', response.to_xml)
|
87
116
|
end
|
88
117
|
end
|
@@ -40,6 +40,7 @@ class Chef
|
|
40
40
|
|
41
41
|
def load_winrm_deps
|
42
42
|
require 'winrm'
|
43
|
+
require 'em-winrm'
|
43
44
|
require 'chef/knife/winrm'
|
44
45
|
require 'chef/knife/bootstrap_windows_winrm'
|
45
46
|
end
|
@@ -71,8 +72,7 @@ class Chef
|
|
71
72
|
|
72
73
|
option :ssh_port,
|
73
74
|
:long => "--ssh-port PORT",
|
74
|
-
:description => "The ssh port. Default is 22."
|
75
|
-
:default => '22'
|
75
|
+
:description => "The ssh port. Default is 22. If --azure-connect-to-existing-dns set then default SSH port is random"
|
76
76
|
|
77
77
|
option :prerelease,
|
78
78
|
:long => "--prerelease",
|
@@ -190,6 +190,16 @@ class Chef
|
|
190
190
|
:long => "--azure-subnet-name SUBNET_NAME",
|
191
191
|
:description => "Optional. Specifies the subnet of virtual machine"
|
192
192
|
|
193
|
+
option :azure_vm_startup_timeout,
|
194
|
+
:long => "--azure-vm-startup-timeout TIMEOUT",
|
195
|
+
:description => "The number of minutes that knife-azure will wait for the virtual machine to reach the 'provisioning' state. Default is 10.",
|
196
|
+
:default => 10
|
197
|
+
|
198
|
+
option :azure_vm_ready_timeout,
|
199
|
+
:long => "--azure-vm-ready-timeout TIMEOUT",
|
200
|
+
:description => "The number of minutes that knife-azure will wait for the virtual machine state to transition from 'provisioning' to 'ready'. Default is 15.",
|
201
|
+
:default => 15
|
202
|
+
|
193
203
|
option :identity_file,
|
194
204
|
:long => "--identity-file FILENAME",
|
195
205
|
:description => "SSH identity file for authentication, optional. It is the RSA private key path. Specify either ssh-password or identity-file"
|
@@ -225,6 +235,12 @@ class Chef
|
|
225
235
|
:long => "--cert-path PATH",
|
226
236
|
:description => "SSL Certificate Path"
|
227
237
|
|
238
|
+
option :auto_update_client,
|
239
|
+
:long => "--auto-update-client",
|
240
|
+
:boolean => true,
|
241
|
+
:default => false,
|
242
|
+
:description => "Set this flag to enable auto chef client update in azure chef extension. This flag should be used with cloud-api bootstrap protocol only"
|
243
|
+
|
228
244
|
def strip_non_ascii(string)
|
229
245
|
string.gsub(/[^0-9a-z ]/i, '')
|
230
246
|
end
|
@@ -236,12 +252,15 @@ class Chef
|
|
236
252
|
def wait_until_virtual_machine_ready(retry_interval_in_seconds = 30)
|
237
253
|
|
238
254
|
vm_status = nil
|
255
|
+
|
239
256
|
puts
|
240
257
|
|
241
258
|
begin
|
242
|
-
|
259
|
+
azure_vm_startup_timeout = locate_config_value(:azure_vm_startup_timeout).to_i
|
260
|
+
azure_vm_ready_timeout = locate_config_value(:azure_vm_ready_timeout).to_i
|
261
|
+
vm_status = wait_for_virtual_machine_state(:vm_status_provisioning, azure_vm_startup_timeout, retry_interval_in_seconds)
|
243
262
|
if vm_status != :vm_status_ready
|
244
|
-
wait_for_virtual_machine_state(:vm_status_ready,
|
263
|
+
wait_for_virtual_machine_state(:vm_status_ready, azure_vm_ready_timeout, retry_interval_in_seconds)
|
245
264
|
end
|
246
265
|
|
247
266
|
msg_server_summary(get_role_server())
|
@@ -590,7 +609,7 @@ class Chef
|
|
590
609
|
bootstrap.config[:winrm_user] = locate_config_value(:winrm_user) || 'Administrator'
|
591
610
|
bootstrap.config[:winrm_password] = locate_config_value(:winrm_password)
|
592
611
|
bootstrap.config[:winrm_transport] = locate_config_value(:winrm_transport)
|
593
|
-
|
612
|
+
bootstrap.config[:winrm_authentication_protocol] = locate_config_value(:winrm_authentication_protocol)
|
594
613
|
bootstrap.config[:winrm_port] = port
|
595
614
|
|
596
615
|
elsif locate_config_value(:bootstrap_protocol) == 'ssh'
|
@@ -653,6 +672,7 @@ class Chef
|
|
653
672
|
ui.error("Specify the VM name using --azure-vm-name option, since you are connecting to existing dns")
|
654
673
|
exit 1
|
655
674
|
end
|
675
|
+
|
656
676
|
if locate_config_value(:azure_service_location) && locate_config_value(:azure_affinity_group)
|
657
677
|
ui.error("Cannot specify both --azure-service-location and --azure-affinity-group, use one or the other.")
|
658
678
|
exit 1
|
@@ -661,6 +681,11 @@ class Chef
|
|
661
681
|
exit 1
|
662
682
|
end
|
663
683
|
|
684
|
+
if locate_config_value(:winrm_authentication_protocol) && ! %w{basic negotiate kerberos}.include?(locate_config_value(:winrm_authentication_protocol))
|
685
|
+
ui.error("Invalid value for --winrm-authentication-protocol option. Use valid protocol values i.e [basic, negotiate, kerberos]")
|
686
|
+
exit 1
|
687
|
+
end
|
688
|
+
|
664
689
|
if !(connection.images.exists?(locate_config_value(:azure_source_image)))
|
665
690
|
ui.error("Image provided is invalid")
|
666
691
|
exit 1
|
@@ -687,19 +712,22 @@ class Chef
|
|
687
712
|
:azure_subnet_name => locate_config_value(:azure_subnet_name),
|
688
713
|
:ssl_cert_fingerprint => locate_config_value(:thumbprint),
|
689
714
|
:cert_path => locate_config_value(:cert_path),
|
690
|
-
:cert_password => locate_config_value(:cert_passphrase)
|
715
|
+
:cert_password => locate_config_value(:cert_passphrase),
|
716
|
+
:winrm_transport => locate_config_value(:winrm_transport)
|
691
717
|
}
|
692
718
|
# If user is connecting a new VM to an existing dns, then
|
693
719
|
# the VM needs to have a unique public port. Logic below takes care of this.
|
694
720
|
if !is_image_windows? or locate_config_value(:bootstrap_protocol) == 'ssh'
|
695
|
-
|
696
|
-
|
697
|
-
|
721
|
+
if locate_config_value(:azure_connect_to_existing_dns)
|
722
|
+
port = locate_config_value(:ssh_port) || Random.rand(64000) + 1000
|
723
|
+
else
|
724
|
+
port = locate_config_value(:ssh_port) || '22'
|
698
725
|
end
|
699
726
|
else
|
700
|
-
|
701
|
-
|
702
|
-
|
727
|
+
if locate_config_value(:azure_connect_to_existing_dns)
|
728
|
+
port = locate_config_value(:winrm_port) || Random.rand(64000) + 1000
|
729
|
+
else
|
730
|
+
port = locate_config_value(:winrm_port) || '5985'
|
703
731
|
end
|
704
732
|
end
|
705
733
|
|
@@ -724,6 +752,11 @@ class Chef
|
|
724
752
|
ui.error("WinRM User is compulsory parameter and it cannot be named 'admin*'")
|
725
753
|
exit 1
|
726
754
|
end
|
755
|
+
# take cares of when user name contains domain
|
756
|
+
# azure add role api doesn't support '\\' in user name
|
757
|
+
if locate_config_value(:winrm_user) && locate_config_value(:winrm_user).split("\\").length.eql?(2)
|
758
|
+
server_def[:winrm_user] = locate_config_value(:winrm_user).split("\\")[1]
|
759
|
+
end
|
727
760
|
else
|
728
761
|
if not locate_config_value(:ssh_user)
|
729
762
|
ui.error("SSH User is compulsory parameter")
|
@@ -763,13 +796,14 @@ class Chef
|
|
763
796
|
# get latest version
|
764
797
|
def get_chef_extension_version
|
765
798
|
extensions = @connection.query_azure("resourceextensions/#{get_chef_extension_publisher}/#{get_chef_extension_name}")
|
766
|
-
extensions.css("Version").max.text.
|
799
|
+
extensions.css("Version").max.text.split(".").first + ".*"
|
767
800
|
end
|
768
801
|
|
769
802
|
def get_chef_extension_public_params
|
770
803
|
pub_config = Hash.new
|
771
804
|
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
805
|
pub_config[:runlist] = locate_config_value(:run_list).empty? ? "" : locate_config_value(:run_list).join(",").to_json
|
806
|
+
pub_config[:autoUpdateClient] = locate_config_value(:auto_update_client) ? "true" : "false"
|
773
807
|
Base64.encode64(pub_config.to_json)
|
774
808
|
end
|
775
809
|
|
@@ -42,6 +42,11 @@ class Chef
|
|
42
42
|
:description =>
|
43
43
|
'Specifies the address space of the vnet using CIDR notation.'
|
44
44
|
|
45
|
+
option :azure_subnet_name,
|
46
|
+
:long => '--azure-subnet-name CIDR',
|
47
|
+
:description =>
|
48
|
+
'Specifies the Subnet Name.'
|
49
|
+
|
45
50
|
def run
|
46
51
|
$stdout.sync = true
|
47
52
|
|
@@ -57,6 +62,7 @@ class Chef
|
|
57
62
|
azure_vnet_name: locate_config_value(:azure_network_name),
|
58
63
|
azure_ag_name: locate_config_value(:azure_affinity_group),
|
59
64
|
azure_address_space: locate_config_value(:azure_address_space),
|
65
|
+
azure_subnet_name: locate_config_value(:azure_subnet_name) || "Subnet-#{Random.rand(10)}"
|
60
66
|
}
|
61
67
|
|
62
68
|
rsp = connection.vnets.create(params)
|
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.0.rc.
|
4
|
+
version: 1.4.0.rc.1
|
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: 2015-02-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -46,6 +46,9 @@ dependencies:
|
|
46
46
|
- - ! '>='
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: 11.8.2
|
49
|
+
- - <
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '12'
|
49
52
|
type: :development
|
50
53
|
prerelease: false
|
51
54
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -53,6 +56,9 @@ dependencies:
|
|
53
56
|
- - ! '>='
|
54
57
|
- !ruby/object:Gem::Version
|
55
58
|
version: 11.8.2
|
59
|
+
- - <
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '12'
|
56
62
|
- !ruby/object:Gem::Dependency
|
57
63
|
name: mixlib-config
|
58
64
|
requirement: !ruby/object:Gem::Requirement
|