knife-azure 1.9.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/azure/azure_interface.rb +2 -3
- data/lib/azure/custom_errors.rb +1 -1
- data/lib/azure/helpers.rb +1 -1
- data/lib/azure/resource_management/ARM_deployment_template.rb +157 -162
- data/lib/azure/resource_management/ARM_interface.rb +72 -73
- data/lib/azure/resource_management/vnet_config.rb +11 -10
- data/lib/azure/resource_management/windows_credentials.rb +19 -19
- data/lib/azure/service_management/ASM_interface.rb +6 -5
- data/lib/azure/service_management/ag.rb +11 -11
- data/lib/azure/service_management/certificate.rb +7 -5
- data/lib/azure/service_management/connection.rb +10 -10
- data/lib/azure/service_management/deploy.rb +12 -14
- data/lib/azure/service_management/disk.rb +4 -2
- data/lib/azure/service_management/host.rb +7 -4
- data/lib/azure/service_management/image.rb +4 -4
- data/lib/azure/service_management/loadbalancer.rb +2 -2
- data/lib/azure/service_management/rest.rb +9 -8
- data/lib/azure/service_management/role.rb +67 -70
- data/lib/azure/service_management/storageaccount.rb +5 -3
- data/lib/azure/service_management/utility.rb +1 -1
- data/lib/azure/service_management/vnet.rb +1 -1
- data/lib/chef/knife/azure_ag_create.rb +13 -13
- data/lib/chef/knife/azure_ag_list.rb +1 -1
- data/lib/chef/knife/azure_base.rb +49 -66
- data/lib/chef/knife/azure_image_list.rb +6 -6
- data/lib/chef/knife/azure_internal-lb_create.rb +14 -14
- data/lib/chef/knife/azure_internal-lb_list.rb +1 -1
- data/lib/chef/knife/azure_server_create.rb +233 -268
- data/lib/chef/knife/azure_server_delete.rb +31 -31
- data/lib/chef/knife/azure_server_list.rb +1 -1
- data/lib/chef/knife/azure_server_show.rb +1 -1
- data/lib/chef/knife/azure_vnet_create.rb +15 -19
- data/lib/chef/knife/azure_vnet_list.rb +1 -1
- data/lib/chef/knife/azurerm_base.rb +39 -28
- data/lib/chef/knife/azurerm_server_create.rb +112 -177
- data/lib/chef/knife/azurerm_server_delete.rb +13 -13
- data/lib/chef/knife/azurerm_server_list.rb +1 -1
- data/lib/chef/knife/azurerm_server_show.rb +1 -1
- data/lib/chef/knife/bootstrap/bootstrapper.rb +34 -238
- data/lib/chef/knife/bootstrap/common_bootstrap_options.rb +77 -76
- data/lib/chef/knife/bootstrap_azure.rb +56 -33
- data/lib/chef/knife/bootstrap_azurerm.rb +46 -29
- data/lib/knife-azure/version.rb +18 -1
- metadata +28 -16
- data/lib/chef/knife/bootstrap/bootstrap_options.rb +0 -105
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Mukta Aphale (mukta.aphale@clogeny.com)
|
3
|
-
# Copyright:: Copyright 2010-
|
3
|
+
# Copyright:: Copyright 2010-2019, Chef Software Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -58,8 +58,8 @@ module Azure
|
|
58
58
|
def create(params)
|
59
59
|
# If RSA private key has been specified, then generate an x 509 certificate from the
|
60
60
|
# public part of the key
|
61
|
-
@cert_data = generate_public_key_certificate_data({ :
|
62
|
-
:
|
61
|
+
@cert_data = generate_public_key_certificate_data({ ssh_key: params[:ssh_identity_file],
|
62
|
+
ssh_key_passphrase: params[:identity_file_passphrase] })
|
63
63
|
add_certificate @cert_data, "knifeazure", "pfx", params[:azure_dns_name]
|
64
64
|
|
65
65
|
# Return the fingerprint to be used while adding role
|
@@ -111,7 +111,7 @@ module Azure
|
|
111
111
|
for attempt in 0..4
|
112
112
|
Chef::Log.info "Waiting to get certificate ..."
|
113
113
|
res = get_certificate(dns_name, @fingerprint)
|
114
|
-
break
|
114
|
+
break unless res.empty?
|
115
115
|
if attempt == 4
|
116
116
|
raise "The certificate with thumbprint #{fingerprint} was not found."
|
117
117
|
else
|
@@ -159,6 +159,7 @@ module Azure
|
|
159
159
|
print "Enter certificate passphrase (empty for no passphrase):"
|
160
160
|
passphrase = STDIN.gets
|
161
161
|
return passphrase.strip if passphrase == "\n"
|
162
|
+
|
162
163
|
print "Enter same passphrase again:"
|
163
164
|
confirm_passphrase = STDIN.gets
|
164
165
|
end until passphrase == confirm_passphrase
|
@@ -174,6 +175,7 @@ module Azure
|
|
174
175
|
file_path = STDIN.gets
|
175
176
|
stripped_file_path = file_path.strip
|
176
177
|
return stripped_file_path if file_path == "\n"
|
178
|
+
|
177
179
|
counter += 1
|
178
180
|
exit(1) if counter == 3
|
179
181
|
end until File.directory?(stripped_file_path)
|
@@ -198,7 +200,7 @@ module Azure
|
|
198
200
|
@hostname = "*." + cert_params[:domain]
|
199
201
|
end
|
200
202
|
|
201
|
-
#Create a self-signed X509 certificate from the rsa_key (unencrypted)
|
203
|
+
# Create a self-signed X509 certificate from the rsa_key (unencrypted)
|
202
204
|
cert = OpenSSL::X509::Certificate.new
|
203
205
|
cert.version = 2
|
204
206
|
cert.serial = Random.rand(65534) + 1 # 2 digit byte range random number for better security aspect
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
-
# Copyright:: Copyright 2010-
|
3
|
+
# Copyright:: Copyright 2010-2019, Chef Software Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -33,7 +33,7 @@ module Azure
|
|
33
33
|
class Connection
|
34
34
|
include AzureUtility
|
35
35
|
attr_accessor :hosts, :rest, :images, :deploys, :roles,
|
36
|
-
|
36
|
+
:disks, :storageaccounts, :certificates, :ags, :vnets, :lbs
|
37
37
|
def initialize(rest)
|
38
38
|
@images = Images.new(self)
|
39
39
|
@roles = Roles.new(self)
|
@@ -49,12 +49,12 @@ module Azure
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def query_azure(service_name,
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
verb = "get",
|
53
|
+
body = "",
|
54
|
+
params = "",
|
55
|
+
wait = true,
|
56
|
+
services = true,
|
57
|
+
content_type = nil)
|
58
58
|
Chef::Log.info "calling " + verb + " " + service_name + (wait ? " synchronously" : " asynchronously")
|
59
59
|
Chef::Log.debug body unless body == ""
|
60
60
|
response = @rest.query_azure(service_name, verb, body, params, services, content_type)
|
@@ -64,7 +64,7 @@ module Azure
|
|
64
64
|
Chef::Log.debug "Request accepted in asynchronous mode"
|
65
65
|
ret_val = Nokogiri::XML response.body
|
66
66
|
elsif response.code.to_i >= 201 && response.code.to_i <= 299
|
67
|
-
ret_val = wait_for_completion
|
67
|
+
ret_val = wait_for_completion
|
68
68
|
else
|
69
69
|
if response.body
|
70
70
|
ret_val = Nokogiri::XML response.body
|
@@ -82,7 +82,7 @@ module Azure
|
|
82
82
|
status = "InProgress"
|
83
83
|
Chef::Log.info "Waiting while status returns InProgress"
|
84
84
|
while status == "InProgress"
|
85
|
-
response = @rest.query_for_completion
|
85
|
+
response = @rest.query_for_completion
|
86
86
|
ret_val = Nokogiri::XML response.body
|
87
87
|
status = xml_content(ret_val, "Status")
|
88
88
|
if status == "InProgress"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
-
# Copyright:: Copyright 2010-
|
3
|
+
# Copyright:: Copyright 2010-2019, Chef Software Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -26,9 +26,9 @@ module Azure
|
|
26
26
|
# force_load should be true when there is something in local cache and we want to reload
|
27
27
|
# first call is always load.
|
28
28
|
def load(force_load = false)
|
29
|
-
|
29
|
+
unless @deploys || force_load
|
30
30
|
@deploys = begin
|
31
|
-
deploys =
|
31
|
+
deploys = []
|
32
32
|
hosts = @connection.hosts.all
|
33
33
|
hosts.each do |host|
|
34
34
|
deploy = Deploy.new(@connection)
|
@@ -76,14 +76,14 @@ module Azure
|
|
76
76
|
unless @connection.storageaccounts.exists?(params[:azure_storage_account])
|
77
77
|
@connection.storageaccounts.create(params)
|
78
78
|
end
|
79
|
-
if params[:
|
79
|
+
if params[:ssh_identity_file]
|
80
80
|
params[:fingerprint] = @connection.certificates.create(params)
|
81
81
|
end
|
82
82
|
if params[:cert_path]
|
83
83
|
cert_data = File.read (params[:cert_path])
|
84
84
|
@connection.certificates.add cert_data, params[:cert_password], "pfx", params[:azure_dns_name]
|
85
|
-
elsif params[:
|
86
|
-
#TODO: generate certificates for ssl listener
|
85
|
+
elsif params[:winrm_ssl]
|
86
|
+
# TODO: generate certificates for ssl listener
|
87
87
|
end
|
88
88
|
|
89
89
|
params["deploy_name"] = get_deploy_name_for_hostedservice(params[:azure_dns_name])
|
@@ -106,8 +106,7 @@ module Azure
|
|
106
106
|
@connection.roles.find_in_hosted_service(params[:azure_vm_name], params[:azure_dns_name])
|
107
107
|
end
|
108
108
|
|
109
|
-
def delete(rolename)
|
110
|
-
end
|
109
|
+
def delete(rolename); end
|
111
110
|
|
112
111
|
def queryDeploy(hostedservicename)
|
113
112
|
deploy = Deploy.new(@connection)
|
@@ -131,7 +130,7 @@ module Azure
|
|
131
130
|
@name = xml_content(deployXML, "Deployment Name")
|
132
131
|
@status = xml_content(deployXML, "Deployment Status")
|
133
132
|
@url = xml_content(deployXML, "Deployment Url")
|
134
|
-
@roles =
|
133
|
+
@roles = {}
|
135
134
|
rolesXML = deployXML.css("Deployment RoleInstanceList RoleInstance")
|
136
135
|
rolesListXML = deployXML.css("Deployment RoleList Role")
|
137
136
|
rolesXML.zip(rolesListXML).each do |roleXML, roleListXML|
|
@@ -143,12 +142,12 @@ module Azure
|
|
143
142
|
role.parse_role_list_xml(roleListXML)
|
144
143
|
@roles[role.name] = role
|
145
144
|
end
|
146
|
-
@input_endpoints =
|
145
|
+
@input_endpoints = []
|
147
146
|
endpointsXML = deployXML.css("InputEndpoint")
|
148
147
|
endpointsXML.each do |endpointXML|
|
149
148
|
@input_endpoints << parse_endpoint(endpointXML)
|
150
149
|
end
|
151
|
-
@loadbalancers =
|
150
|
+
@loadbalancers = {}
|
152
151
|
lbsXML = deployXML.css("Deployment LoadBalancers LoadBalancer")
|
153
152
|
lbsXML.each do |lbXML|
|
154
153
|
loadbalancer = Loadbalancer.new(@connection)
|
@@ -161,7 +160,6 @@ module Azure
|
|
161
160
|
def setup(params)
|
162
161
|
role = Role.new(@connection)
|
163
162
|
roleXML = role.setup(params)
|
164
|
-
#roleXML = Nokogiri::XML role.setup(params)
|
165
163
|
builder = Nokogiri::XML::Builder.new do |xml|
|
166
164
|
xml.Deployment(
|
167
165
|
"xmlns" => "http://schemas.microsoft.com/windowsazure",
|
@@ -188,7 +186,7 @@ module Azure
|
|
188
186
|
# This parses endpoints from a RoleList-Role-InputEndpoint, NOT a RoleInstanceList-RoleInstance-InstanceEndpoint
|
189
187
|
# Refactor: make this an object rather than a hash..?
|
190
188
|
def parse_endpoint(inputendpoint_xml)
|
191
|
-
hash =
|
189
|
+
hash = {}
|
192
190
|
%w{LoadBalancedEndpointSetName LocalPort Name Port Protocol EnableDirectServerReturn LoadBalancerName IdleTimeoutInMinutes}.each do |key|
|
193
191
|
hash[key] = xml_content(inputendpoint_xml, key, nil)
|
194
192
|
end
|
@@ -198,7 +196,7 @@ module Azure
|
|
198
196
|
end
|
199
197
|
probe = inputendpoint_xml.css("LoadBalancerProbe")
|
200
198
|
if probe
|
201
|
-
hash["LoadBalancerProbe"] =
|
199
|
+
hash["LoadBalancerProbe"] = {}
|
202
200
|
%w{Path Port Protocol IntervalInSeconds TimeoutInSeconds}.each do |key|
|
203
201
|
hash["LoadBalancerProbe"][key] = xml_content(probe, key, nil)
|
204
202
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
-
# Copyright:: Copyright 2010-
|
3
|
+
# Copyright:: Copyright 2010-2019, Chef Software Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -23,7 +23,7 @@ module Azure
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def all
|
26
|
-
disks =
|
26
|
+
disks = []
|
27
27
|
response = @connection.query_azure("disks")
|
28
28
|
founddisks = response.css("Disk")
|
29
29
|
founddisks.each do |disk|
|
@@ -37,6 +37,7 @@ module Azure
|
|
37
37
|
founddisk = nil
|
38
38
|
all.each do |disk|
|
39
39
|
next unless disk.name == name
|
40
|
+
|
40
41
|
founddisk = disk
|
41
42
|
end
|
42
43
|
founddisk
|
@@ -49,6 +50,7 @@ module Azure
|
|
49
50
|
def clear_unattached
|
50
51
|
all.each do |disk|
|
51
52
|
next unless disk.attached == false
|
53
|
+
|
52
54
|
@connection.query_azure("disks/" + disk.name, "delete")
|
53
55
|
end
|
54
56
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
-
# Copyright:: Copyright 2010-
|
3
|
+
# Copyright:: Copyright 2010-2019, Chef Software Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -26,9 +26,9 @@ module Azure
|
|
26
26
|
# force_load should be true when there is something in local cache and we want to reload
|
27
27
|
# first call is always load.
|
28
28
|
def load(force_load = false)
|
29
|
-
|
29
|
+
unless @hosted_services || force_load
|
30
30
|
@hosted_services = begin
|
31
|
-
hosted_services =
|
31
|
+
hosted_services = {}
|
32
32
|
responseXML = @connection.query_azure("hostedservices")
|
33
33
|
servicesXML = responseXML.css("HostedServices HostedService")
|
34
34
|
servicesXML.each do |serviceXML|
|
@@ -48,6 +48,7 @@ module Azure
|
|
48
48
|
# first look up local cache if we have already loaded list.
|
49
49
|
def exists?(name)
|
50
50
|
return @hosted_services.key?(name) if @hosted_services
|
51
|
+
|
51
52
|
exists_on_cloud?(name)
|
52
53
|
end
|
53
54
|
|
@@ -66,6 +67,7 @@ module Azure
|
|
66
67
|
# first look up local cache if we have already loaded list.
|
67
68
|
def find(name)
|
68
69
|
return @hosted_services[name] if @hosted_services && @hosted_services.key?(name)
|
70
|
+
|
69
71
|
fetch_from_cloud(name)
|
70
72
|
end
|
71
73
|
|
@@ -105,7 +107,7 @@ module Azure
|
|
105
107
|
def initialize(connection)
|
106
108
|
@connection = connection
|
107
109
|
@deploys_loaded = false
|
108
|
-
@deploys =
|
110
|
+
@deploys = {}
|
109
111
|
end
|
110
112
|
|
111
113
|
def parse(serviceXML)
|
@@ -171,6 +173,7 @@ module Azure
|
|
171
173
|
|
172
174
|
def find_role(role_name, deploy_name = nil)
|
173
175
|
return @deploys[deploy_name].find_role(role_name) if deploy_name && deploys
|
176
|
+
|
174
177
|
# else lookup all deploys within hostedservice
|
175
178
|
deploys.each do |deploy|
|
176
179
|
role = deploy.find_role(role_name)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
-
# Copyright:: Copyright 2010-
|
3
|
+
# Copyright:: Copyright 2010-2019, Chef Software Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -24,8 +24,8 @@ module Azure
|
|
24
24
|
|
25
25
|
def load
|
26
26
|
@images ||= begin
|
27
|
-
osimages = get_images("OSImage") #get OSImages
|
28
|
-
vmimages = get_images("VMImage") #get VMImages
|
27
|
+
osimages = get_images("OSImage") # get OSImages
|
28
|
+
vmimages = get_images("VMImage") # get VMImages
|
29
29
|
|
30
30
|
all_images = osimages.merge(vmimages)
|
31
31
|
end
|
@@ -37,7 +37,7 @@ module Azure
|
|
37
37
|
|
38
38
|
# img_type = OSImages or VMImage
|
39
39
|
def get_images(img_type)
|
40
|
-
images =
|
40
|
+
images = {}
|
41
41
|
|
42
42
|
if img_type == "OSImage"
|
43
43
|
response = @connection.query_azure("images")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Aiman Alsari (aiman.alsari@gmail.com)
|
3
|
-
# Copyright:: Copyright
|
3
|
+
# Copyright:: Copyright 2010-2019, Chef Software Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -27,7 +27,7 @@ module Azure
|
|
27
27
|
|
28
28
|
def load
|
29
29
|
@lbs ||= begin
|
30
|
-
@lbs =
|
30
|
+
@lbs = {}
|
31
31
|
@connection.deploys.all.each do |deploy|
|
32
32
|
@lbs.merge!(deploy.loadbalancers)
|
33
33
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
-
# Copyright:: Copyright 2010-
|
3
|
+
# Copyright:: Copyright 2010-2019, Chef Software Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -15,6 +15,7 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
|
+
|
18
19
|
require "net/https"
|
19
20
|
require "uri"
|
20
21
|
require "nokogiri"
|
@@ -30,11 +31,11 @@ module AzureAPI
|
|
30
31
|
end
|
31
32
|
|
32
33
|
def query_azure(service_name,
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
verb = "get",
|
35
|
+
body = "",
|
36
|
+
params = "",
|
37
|
+
services = true,
|
38
|
+
content_type = nil)
|
38
39
|
svc_str = services ? "/services" : ""
|
39
40
|
uri = URI.parse("#{@host_name}/#{@subscription_id}#{svc_str}/#{service_name}")
|
40
41
|
scheme = !uri.scheme ? "https://" : ""
|
@@ -42,7 +43,7 @@ module AzureAPI
|
|
42
43
|
print "."
|
43
44
|
response = http_query(request_url, verb, body, params, content_type)
|
44
45
|
if response.code.to_i == 307
|
45
|
-
Chef::Log.debug "Redirect to #{response[
|
46
|
+
Chef::Log.debug "Redirect to #{response["Location"]}"
|
46
47
|
response = http_query(response["Location"], verb, body, params, content_type)
|
47
48
|
end
|
48
49
|
@last_request_id = response["x-ms-request-id"]
|
@@ -65,7 +66,7 @@ module AzureAPI
|
|
65
66
|
request_url = "#{scheme}#{@host_name}/#{@subscription_id}/operations/#{@last_request_id}"
|
66
67
|
response = http_query(request_url, "get", "", "")
|
67
68
|
if response.code.to_i == 307
|
68
|
-
Chef::Log.debug "Redirect to #{response[
|
69
|
+
Chef::Log.debug "Redirect to #{response["Location"]}"
|
69
70
|
response = http_query(response["Location"], "get", "", "")
|
70
71
|
end
|
71
72
|
response
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
-
# Copyright:: Copyright 2010-
|
3
|
+
# Copyright:: Copyright 2010-2019, Chef Software Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -15,6 +15,7 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
|
+
|
18
19
|
require "securerandom"
|
19
20
|
require "azure/service_management/utility"
|
20
21
|
|
@@ -29,7 +30,7 @@ module Azure
|
|
29
30
|
|
30
31
|
# do not use this unless you want a list of all roles(vms) in your subscription
|
31
32
|
def all
|
32
|
-
@roles =
|
33
|
+
@roles = []
|
33
34
|
@connection.deploys.all.each do |deploy|
|
34
35
|
deploy.roles.each do |role|
|
35
36
|
@roles << role
|
@@ -40,12 +41,13 @@ module Azure
|
|
40
41
|
|
41
42
|
def find_roles_within_hostedservice(hostedservicename)
|
42
43
|
host = @connection.hosts.find(hostedservicename)
|
43
|
-
|
44
|
+
host ? host.roles : nil # nil says invalid hosted service
|
44
45
|
end
|
45
46
|
|
46
47
|
def find_in_hosted_service(role_name, hostedservicename)
|
47
48
|
host = @connection.hosts.find(hostedservicename)
|
48
49
|
return nil if host.nil?
|
50
|
+
|
49
51
|
host.find_role(role_name)
|
50
52
|
end
|
51
53
|
|
@@ -56,20 +58,17 @@ module Azure
|
|
56
58
|
|
57
59
|
all if @roles.nil?
|
58
60
|
|
59
|
-
# TODO - optimize this lookup
|
61
|
+
# TODO: - optimize this lookup
|
60
62
|
@roles.each do |role|
|
61
|
-
if role.name == role_name
|
62
|
-
return role
|
63
|
-
end
|
63
|
+
return role if role.name == role_name
|
64
64
|
end
|
65
65
|
nil
|
66
66
|
end
|
67
67
|
|
68
68
|
def alone_on_hostedservice(found_role)
|
69
69
|
roles = find_roles_within_hostedservice(found_role.hostedservicename)
|
70
|
-
if roles && roles.length > 1
|
71
|
-
|
72
|
-
end
|
70
|
+
return false if roles && roles.length > 1
|
71
|
+
|
73
72
|
true
|
74
73
|
end
|
75
74
|
|
@@ -79,7 +78,7 @@ module Azure
|
|
79
78
|
|
80
79
|
def delete(params)
|
81
80
|
role = find(params[:name])
|
82
|
-
|
81
|
+
unless role.nil?
|
83
82
|
roleXML = nil
|
84
83
|
roleXML = @connection.query_azure("hostedservices/#{role.hostedservicename}", "get", "", "embed-detail=true")
|
85
84
|
osdisk = roleXML.css(roleXML, "OSVirtualHardDisk")
|
@@ -107,8 +106,8 @@ module Azure
|
|
107
106
|
servicecall = "hostedservices/#{role.hostedservicename}/deployments/#{role.deployname}"
|
108
107
|
end
|
109
108
|
else
|
110
|
-
servicecall = "hostedservices/#{role.hostedservicename}/deployments"
|
111
|
-
|
109
|
+
servicecall = "hostedservices/#{role.hostedservicename}/deployments" \
|
110
|
+
"/#{role.deployname}/roles/#{role.name}"
|
112
111
|
end
|
113
112
|
if compmedia
|
114
113
|
@connection.query_azure(servicecall, "delete", "", "comp=media", wait = params[:wait])
|
@@ -129,12 +128,13 @@ module Azure
|
|
129
128
|
# exit otherwise after 12 attempts.
|
130
129
|
for attempt in 0..12
|
131
130
|
break if @connection.query_azure(servicecall, "get").search("AttachedTo").text == ""
|
131
|
+
|
132
132
|
attempt == 12 ? (puts "The associated disk could not be deleted due to time out.") : (sleep 25)
|
133
133
|
end
|
134
|
-
|
135
|
-
@connection.query_azure(servicecall, "delete", "", "comp=media", wait = params[:wait])
|
136
|
-
else
|
134
|
+
if params[:preserve_azure_vhd]
|
137
135
|
@connection.query_azure(servicecall, "delete")
|
136
|
+
else
|
137
|
+
@connection.query_azure(servicecall, "delete", "", "comp=media", wait = params[:wait])
|
138
138
|
end
|
139
139
|
end
|
140
140
|
end
|
@@ -153,16 +153,17 @@ module Azure
|
|
153
153
|
|
154
154
|
def check_and_delete_storage(params, disk_name, storage_account_name)
|
155
155
|
if params[:delete_azure_storage_account]
|
156
|
-
|
156
|
+
# Iteratively check for disk deletion
|
157
157
|
for attempt in 0..12
|
158
158
|
break unless @connection.query_azure("disks").search("Name").text.include?(disk_name)
|
159
|
+
|
159
160
|
attempt == 12 ? (puts "The associated disk could not be deleted due to time out.") : (sleep 25)
|
160
161
|
end
|
161
162
|
begin
|
162
163
|
@connection.query_azure("storageservices/#{storage_account_name}", "delete")
|
163
164
|
rescue Exception => ex
|
164
|
-
ui.warn(
|
165
|
-
ui.warn(
|
165
|
+
ui.warn(ex.message.to_s)
|
166
|
+
ui.warn(ex.backtrace.join("\n").to_s)
|
166
167
|
end
|
167
168
|
end
|
168
169
|
end
|
@@ -174,7 +175,6 @@ module Azure
|
|
174
175
|
end
|
175
176
|
|
176
177
|
private :check_and_delete_role_and_resources, :check_and_delete_disks, :check_and_delete_service, :check_and_delete_storage
|
177
|
-
|
178
178
|
end
|
179
179
|
|
180
180
|
class Role
|
@@ -200,8 +200,7 @@ module Azure
|
|
200
200
|
"995" => "POP3S",
|
201
201
|
"993" => "IMAPS",
|
202
202
|
"1433" => "MSSQL",
|
203
|
-
"3306" => "MySQL"
|
204
|
-
}
|
203
|
+
"3306" => "MySQL" }.freeze
|
205
204
|
|
206
205
|
def initialize(connection)
|
207
206
|
@connection = connection
|
@@ -216,18 +215,18 @@ module Azure
|
|
216
215
|
@hostedservicename = hostedservicename
|
217
216
|
@deployname = deployname
|
218
217
|
@thumbprint = fetch_thumbprint
|
219
|
-
@tcpports =
|
220
|
-
@udpports =
|
218
|
+
@tcpports = []
|
219
|
+
@udpports = []
|
221
220
|
|
222
221
|
endpoints = roleXML.css("InstanceEndpoint")
|
223
|
-
@publicipaddress = xml_content(endpoints[0], "Vip")
|
222
|
+
@publicipaddress = xml_content(endpoints[0], "Vip") unless endpoints.empty?
|
224
223
|
endpoints.each do |endpoint|
|
225
224
|
if xml_content(endpoint, "Name").casecmp("ssh").zero?
|
226
225
|
@sshport = xml_content(endpoint, "PublicPort")
|
227
226
|
elsif xml_content(endpoint, "Name").casecmp("winrm").zero?
|
228
227
|
@winrmport = xml_content(endpoint, "PublicPort")
|
229
228
|
else
|
230
|
-
hash =
|
229
|
+
hash = {}
|
231
230
|
hash["Name"] = xml_content(endpoint, "Name")
|
232
231
|
hash["Vip"] = xml_content(endpoint, "Vip")
|
233
232
|
hash["PublicPort"] = xml_content(endpoint, "PublicPort")
|
@@ -251,7 +250,7 @@ module Azure
|
|
251
250
|
|
252
251
|
# Expects endpoint_param_string to be in the form {localport}:{publicport}:{lb_set_name}:{lb_probe_path}
|
253
252
|
# Only localport is mandatory.
|
254
|
-
def parse_endpoint_from_params(protocol,
|
253
|
+
def parse_endpoint_from_params(protocol, _azure_vm_name, endpoint_param_string)
|
255
254
|
fields = endpoint_param_string.split(":").map(&:strip)
|
256
255
|
hash = {}
|
257
256
|
hash["LocalPort"] = fields[0]
|
@@ -274,22 +273,21 @@ module Azure
|
|
274
273
|
end
|
275
274
|
|
276
275
|
def find_deploy(params)
|
277
|
-
@connection.hosts.find(params[:azure_dns_name]).deploys[0] # TODO this relies on the 'production only' bug.
|
276
|
+
@connection.hosts.find(params[:azure_dns_name]).deploys[0] # TODO: this relies on the 'production only' bug.
|
278
277
|
end
|
279
278
|
|
280
279
|
def add_endpoints_to_xml(xml, endpoints, params)
|
281
280
|
existing_endpoints = find_deploy(params).input_endpoints
|
282
281
|
|
283
282
|
endpoints.each do |ep|
|
284
|
-
|
285
283
|
if existing_endpoints
|
286
284
|
existing_endpoints.each do |eep|
|
287
|
-
ep = eep if eep["LoadBalancedEndpointSetName"] && ep["LoadBalancedEndpointSetName"] && (
|
285
|
+
ep = eep if eep["LoadBalancedEndpointSetName"] && ep["LoadBalancedEndpointSetName"] && (eep["LoadBalancedEndpointSetName"] == ep["LoadBalancedEndpointSetName"])
|
288
286
|
end
|
289
287
|
end
|
290
288
|
|
291
289
|
if ep["Port"] == params[:port] && ep["Protocol"].casecmp("tcp").zero?
|
292
|
-
puts("Skipping tcp-endpoints: #{ep[
|
290
|
+
puts("Skipping tcp-endpoints: #{ep["LocalPort"]} because this port is already in use by ssh/winrm endpoint in current VM.")
|
293
291
|
next
|
294
292
|
end
|
295
293
|
|
@@ -336,20 +334,20 @@ module Azure
|
|
336
334
|
xml.ConfigurationSet("i:type" => "LinuxProvisioningConfigurationSet") do
|
337
335
|
xml.ConfigurationSetType "LinuxProvisioningConfiguration"
|
338
336
|
xml.HostName params[:azure_vm_name]
|
339
|
-
xml.UserName params[:
|
340
|
-
|
337
|
+
xml.UserName params[:connection_user]
|
338
|
+
if params[:ssh_identity_file].nil?
|
339
|
+
xml.UserPassword params[:connection_password]
|
340
|
+
xml.DisableSshPasswordAuthentication "false"
|
341
|
+
else
|
341
342
|
xml.DisableSshPasswordAuthentication "true"
|
342
343
|
xml.SSH do
|
343
344
|
xml.PublicKeys do
|
344
345
|
xml.PublicKey do
|
345
346
|
xml.Fingerprint params[:fingerprint].to_s.upcase
|
346
|
-
xml.Path "/home/" + params[:
|
347
|
+
xml.Path "/home/" + params[:connection_user] + "/.ssh/authorized_keys"
|
347
348
|
end
|
348
349
|
end
|
349
350
|
end
|
350
|
-
else
|
351
|
-
xml.UserPassword params[:ssh_password]
|
352
|
-
xml.DisableSshPasswordAuthentication "false"
|
353
351
|
end
|
354
352
|
end
|
355
353
|
elsif params[:os_type] == "Windows"
|
@@ -370,7 +368,7 @@ module Azure
|
|
370
368
|
xml.MachineObjectOU params[:azure_domain_ou_dn] if params[:azure_domain_ou_dn]
|
371
369
|
end
|
372
370
|
end
|
373
|
-
if params[:
|
371
|
+
if params[:connection_protocol].casecmp("winrm").zero?
|
374
372
|
if params[:ssl_cert_fingerprint]
|
375
373
|
xml.StoredCertificateSettings do
|
376
374
|
xml.CertificateSetting do
|
@@ -382,7 +380,7 @@ module Azure
|
|
382
380
|
end
|
383
381
|
xml.WinRM do
|
384
382
|
xml.Listeners do
|
385
|
-
if params[:
|
383
|
+
if params[:winrm_ssl] || params[:ssl_cert_fingerprint]
|
386
384
|
xml.Listener do
|
387
385
|
xml.CertificateThumbprint params[:ssl_cert_fingerprint] if params[:ssl_cert_fingerprint]
|
388
386
|
xml.Protocol "Https"
|
@@ -395,8 +393,8 @@ module Azure
|
|
395
393
|
end
|
396
394
|
end
|
397
395
|
end
|
398
|
-
xml.AdminUsername params[:
|
399
|
-
if params[:
|
396
|
+
xml.AdminUsername params[:connection_user]
|
397
|
+
if params[:connection_protocol].casecmp("winrm").zero? && (params[:winrm_max_timeout] || params[:winrm_max_memory_per_shell])
|
400
398
|
xml.AdditionalUnattendContent do
|
401
399
|
xml.Passes do
|
402
400
|
xml.UnattendPass do
|
@@ -410,7 +408,7 @@ module Azure
|
|
410
408
|
xml.Content Base64.encode64(
|
411
409
|
Nokogiri::XML::Builder.new do |auto_logon_xml|
|
412
410
|
auto_logon_xml.AutoLogon do
|
413
|
-
auto_logon_xml.Username params[:
|
411
|
+
auto_logon_xml.Username params[:connection_user]
|
414
412
|
auto_logon_xml.Password do
|
415
413
|
auto_logon_xml.Value params[:admin_password]
|
416
414
|
auto_logon_xml.PlainText true
|
@@ -434,11 +432,11 @@ module Azure
|
|
434
432
|
end
|
435
433
|
end
|
436
434
|
|
437
|
-
if params[:
|
435
|
+
if params[:winrm_max_memory_per_shell]
|
438
436
|
first_logon_xml.SynchronousCommand("wcm:action" => "add") do
|
439
437
|
first_logon_xml.Order 2
|
440
|
-
first_logon_xml.CommandLine "cmd.exe /c winrm set winrm/config/winrs @{MaxMemoryPerShellMB=\"#{params[:
|
441
|
-
first_logon_xml.Description "Bump WinRM max memory per shell to #{params[:
|
438
|
+
first_logon_xml.CommandLine "cmd.exe /c winrm set winrm/config/winrs @{MaxMemoryPerShellMB=\"#{params[:winrm_max_memory_per_shell]}\"}"
|
439
|
+
first_logon_xml.Description "Bump WinRM max memory per shell to #{params[:winrm_max_memory_per_shell]} MB"
|
442
440
|
end
|
443
441
|
end
|
444
442
|
end
|
@@ -458,13 +456,12 @@ module Azure
|
|
458
456
|
xml.ConfigurationSet("i:type" => "NetworkConfigurationSet") do
|
459
457
|
xml.ConfigurationSetType "NetworkConfiguration"
|
460
458
|
xml.InputEndpoints do
|
461
|
-
|
462
|
-
#
|
463
|
-
#
|
464
|
-
|
465
|
-
if (params[:os_type] == "Windows") && (params[:bootstrap_proto].casecmp("winrm").zero?)
|
459
|
+
# 1. connection_protocol = 'winrm' for windows => Set winrm port
|
460
|
+
# 2. connection_protocol = 'ssh' for windows and linux => Set ssh port
|
461
|
+
# 3. connection_protocol = 'cloud-api' for windows and linux => Set no port
|
462
|
+
if (params[:os_type] == "Windows") && params[:connection_protocol].casecmp("winrm").zero?
|
466
463
|
xml.InputEndpoint do
|
467
|
-
if params[:
|
464
|
+
if params[:winrm_ssl]
|
468
465
|
xml.LocalPort "5986"
|
469
466
|
else
|
470
467
|
xml.LocalPort "5985"
|
@@ -473,7 +470,7 @@ module Azure
|
|
473
470
|
xml.Port params[:port]
|
474
471
|
xml.Protocol "TCP"
|
475
472
|
end
|
476
|
-
elsif params[:
|
473
|
+
elsif params[:connection_protocol].casecmp("ssh").zero?
|
477
474
|
xml.InputEndpoint do
|
478
475
|
xml.LocalPort "22"
|
479
476
|
xml.Name "SSH"
|
@@ -481,7 +478,7 @@ module Azure
|
|
481
478
|
xml.Protocol "TCP"
|
482
479
|
end
|
483
480
|
end
|
484
|
-
all_endpoints =
|
481
|
+
all_endpoints = []
|
485
482
|
|
486
483
|
if params[:tcp_endpoints]
|
487
484
|
params[:tcp_endpoints].split(",").map(&:strip).each do |endpoint|
|
@@ -504,7 +501,7 @@ module Azure
|
|
504
501
|
end
|
505
502
|
|
506
503
|
# Azure resource extension support
|
507
|
-
if params[:
|
504
|
+
if params[:connection_protocol] == "cloud-api"
|
508
505
|
xml.ResourceExtensionReferences do
|
509
506
|
xml.ResourceExtensionReference do
|
510
507
|
xml.ReferenceName params[:chef_extension]
|
@@ -540,7 +537,7 @@ module Azure
|
|
540
537
|
|
541
538
|
xml.Label Base64.encode64(params[:azure_vm_name]).strip
|
542
539
|
|
543
|
-
#OSVirtualHardDisk not required in case azure_source_image is a VMImage
|
540
|
+
# OSVirtualHardDisk not required in case azure_source_image is a VMImage
|
544
541
|
unless params[:is_vm_image]
|
545
542
|
xml.OSVirtualHardDisk do
|
546
543
|
disk_name = params[:azure_os_disk_name] || "disk_" + SecureRandom.uuid
|
@@ -552,15 +549,15 @@ module Azure
|
|
552
549
|
end
|
553
550
|
|
554
551
|
xml.RoleSize params[:azure_vm_size]
|
555
|
-
xml.ProvisionGuestAgent true if params[:
|
552
|
+
xml.ProvisionGuestAgent true if params[:connection_protocol] == "cloud-api"
|
556
553
|
end
|
557
554
|
end
|
558
555
|
builder.doc
|
559
556
|
end
|
560
557
|
|
561
558
|
def create(params, roleXML)
|
562
|
-
servicecall = "hostedservices/#{params[:azure_dns_name]}/deployments"
|
563
|
-
|
559
|
+
servicecall = "hostedservices/#{params[:azure_dns_name]}/deployments" \
|
560
|
+
"/#{params["deploy_name"]}/roles"
|
564
561
|
@connection.query_azure(servicecall, "post", roleXML.to_xml)
|
565
562
|
end
|
566
563
|
|
@@ -580,13 +577,13 @@ module Azure
|
|
580
577
|
"xmlns" => "http://schemas.microsoft.com/windowsazure",
|
581
578
|
"xmlns:i" => "http://www.w3.org/2001/XMLSchema-instance"
|
582
579
|
) do
|
583
|
-
xml.ConfigurationSets role_xml.at_css("ConfigurationSets").children
|
584
|
-
xml.ResourceExtensionReferences role_xml.at_css("ResourceExtensionReferences").children
|
585
|
-
xml.AvailabilitySetName role_xml.at_css("AvailabilitySetName").children
|
586
|
-
xml.DataVirtualHardDisks role_xml.at_css("DataVirtualHardDisks").children
|
587
|
-
xml.OSVirtualHardDisk role_xml.at_css("OSVirtualHardDisk").children
|
588
|
-
xml.RoleSize role_xml.at_css("RoleSize").children
|
589
|
-
xml.ProvisionGuestAgent role_xml.at_css("ProvisionGuestAgent").children
|
580
|
+
xml.ConfigurationSets role_xml.at_css("ConfigurationSets").children unless role_xml.at_css("ConfigurationSets").nil?
|
581
|
+
xml.ResourceExtensionReferences role_xml.at_css("ResourceExtensionReferences").children unless role_xml.at_css("ResourceExtensionReferences").nil?
|
582
|
+
xml.AvailabilitySetName role_xml.at_css("AvailabilitySetName").children unless role_xml.at_css("AvailabilitySetName").nil?
|
583
|
+
xml.DataVirtualHardDisks role_xml.at_css("DataVirtualHardDisks").children unless role_xml.at_css("DataVirtualHardDisks").nil?
|
584
|
+
xml.OSVirtualHardDisk role_xml.at_css("OSVirtualHardDisk").children unless role_xml.at_css("OSVirtualHardDisk").nil?
|
585
|
+
xml.RoleSize role_xml.at_css("RoleSize").children unless role_xml.at_css("RoleSize").nil?
|
586
|
+
xml.ProvisionGuestAgent role_xml.at_css("ProvisionGuestAgent").children unless role_xml.at_css("ProvisionGuestAgent").nil?
|
590
587
|
end
|
591
588
|
end
|
592
589
|
|
@@ -608,8 +605,8 @@ module Azure
|
|
608
605
|
## if no than install it, else raise error saying that the extension is
|
609
606
|
## already installed
|
610
607
|
ext = nil
|
611
|
-
|
612
|
-
|
608
|
+
unless add_resource_extension_references
|
609
|
+
unless resource_extension_references.at_css("ReferenceName").nil?
|
613
610
|
resource_extension_references.css("ReferenceName").each { |node| ext = node if node.content == params[:chef_extension] }
|
614
611
|
end
|
615
612
|
end
|
@@ -707,11 +704,11 @@ module Azure
|
|
707
704
|
|
708
705
|
def update(name, params, roleXML)
|
709
706
|
puts "Updating server role..."
|
710
|
-
servicecall = "hostedservices/#{params[:azure_dns_name]}"
|
711
|
-
|
707
|
+
servicecall = "hostedservices/#{params[:azure_dns_name]}" \
|
708
|
+
"/deployments/#{params[:deploy_name]}/roles/#{name}"
|
712
709
|
ret_val = @connection.query_azure(servicecall, "put", roleXML, "", true, true, "application/xml")
|
713
710
|
error_code, error_message = error_from_response_xml(ret_val)
|
714
|
-
|
711
|
+
unless error_code.empty?
|
715
712
|
Chef::Log.debug(ret_val.to_s)
|
716
713
|
raise "Unable to update role:" + error_code + " : " + error_message
|
717
714
|
end
|