knife-azure 1.6.0.rc.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +304 -8
- data/lib/azure/azure_interface.rb +81 -0
- data/lib/azure/custom_errors.rb +35 -0
- data/lib/azure/helpers.rb +44 -0
- data/lib/azure/resource_management/ARM_base.rb +29 -0
- data/lib/azure/resource_management/ARM_deployment_template.rb +561 -0
- data/lib/azure/resource_management/ARM_interface.rb +795 -0
- data/lib/azure/resource_management/windows_credentials.rb +136 -0
- data/lib/azure/service_management/ASM_interface.rb +301 -0
- data/lib/azure/{ag.rb → service_management/ag.rb} +2 -2
- data/lib/azure/{certificate.rb → service_management/certificate.rb} +2 -2
- data/lib/azure/service_management/connection.rb +102 -0
- data/lib/azure/{deploy.rb → service_management/deploy.rb} +8 -2
- data/lib/azure/{disk.rb → service_management/disk.rb} +2 -2
- data/lib/azure/{host.rb → service_management/host.rb} +2 -2
- data/lib/azure/{image.rb → service_management/image.rb} +2 -2
- data/lib/azure/{loadbalancer.rb → service_management/loadbalancer.rb} +4 -18
- data/lib/azure/{rest.rb → service_management/rest.rb} +15 -10
- data/lib/azure/{role.rb → service_management/role.rb} +174 -6
- data/lib/azure/{storageaccount.rb → service_management/storageaccount.rb} +2 -2
- data/lib/azure/{utility.rb → service_management/utility.rb} +0 -0
- data/lib/azure/{vnet.rb → service_management/vnet.rb} +2 -2
- data/lib/chef/knife/azure_ag_create.rb +3 -6
- data/lib/chef/knife/azure_ag_list.rb +2 -16
- data/lib/chef/knife/azure_base.rb +89 -22
- data/lib/chef/knife/azure_image_list.rb +3 -7
- data/lib/chef/knife/azure_internal-lb_create.rb +2 -5
- data/lib/chef/knife/azure_internal-lb_list.rb +2 -16
- data/lib/chef/knife/azure_server_create.rb +122 -501
- data/lib/chef/knife/azure_server_delete.rb +15 -38
- data/lib/chef/knife/azure_server_list.rb +2 -27
- data/lib/chef/knife/azure_server_show.rb +4 -60
- data/lib/chef/knife/azure_vnet_create.rb +2 -7
- data/lib/chef/knife/azure_vnet_list.rb +2 -17
- data/lib/chef/knife/azurerm_base.rb +228 -0
- data/lib/chef/knife/azurerm_server_create.rb +393 -0
- data/lib/chef/knife/azurerm_server_delete.rb +121 -0
- data/lib/chef/knife/azurerm_server_list.rb +18 -0
- data/lib/chef/knife/azurerm_server_show.rb +37 -0
- data/lib/chef/knife/bootstrap/bootstrap_options.rb +105 -0
- data/lib/chef/knife/bootstrap/bootstrapper.rb +343 -0
- data/lib/chef/knife/bootstrap/common_bootstrap_options.rb +116 -0
- data/lib/chef/knife/bootstrap_azure.rb +110 -0
- data/lib/chef/knife/bootstrap_azurerm.rb +116 -0
- data/lib/knife-azure/version.rb +1 -2
- metadata +132 -16
- data/lib/azure/connection.rb +0 -99
@@ -16,7 +16,7 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
|
19
|
+
module Azure
|
20
20
|
class Certificates
|
21
21
|
def initialize(connection)
|
22
22
|
@connection=connection
|
@@ -39,7 +39,7 @@ class Azure
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
module Azure
|
43
43
|
class Certificate
|
44
44
|
attr_accessor :connection
|
45
45
|
attr_accessor :cert_data, :fingerprint, :certificate_version
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
+
# Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'azure/service_management/image'
|
20
|
+
require 'azure/service_management/role'
|
21
|
+
require 'azure/service_management/deploy'
|
22
|
+
require 'azure/service_management/host'
|
23
|
+
require 'azure/service_management/loadbalancer'
|
24
|
+
require 'azure/service_management/vnet'
|
25
|
+
require 'azure/service_management/utility'
|
26
|
+
require 'azure/service_management/ag'
|
27
|
+
require 'azure/service_management/storageaccount'
|
28
|
+
require 'azure/service_management/certificate'
|
29
|
+
require 'azure/service_management/disk'
|
30
|
+
|
31
|
+
module Azure
|
32
|
+
class ServiceManagement
|
33
|
+
class Connection
|
34
|
+
include AzureUtility
|
35
|
+
attr_accessor :hosts, :rest, :images, :deploys, :roles,
|
36
|
+
:disks, :storageaccounts, :certificates, :ags, :vnets, :lbs
|
37
|
+
def initialize(rest)
|
38
|
+
@images = Images.new(self)
|
39
|
+
@roles = Roles.new(self)
|
40
|
+
@deploys = Deploys.new(self)
|
41
|
+
@hosts = Hosts.new(self)
|
42
|
+
@rest = rest
|
43
|
+
@lbs = Loadbalancer.new(self)
|
44
|
+
@vnets = Vnets.new(self)
|
45
|
+
@ags = AGs.new(self)
|
46
|
+
@storageaccounts = StorageAccounts.new(self)
|
47
|
+
@certificates = Certificates.new(self)
|
48
|
+
@disks = Disks.new(self)
|
49
|
+
end
|
50
|
+
|
51
|
+
def query_azure(service_name,
|
52
|
+
verb = 'get',
|
53
|
+
body = '',
|
54
|
+
params = '',
|
55
|
+
wait = true,
|
56
|
+
services = true,
|
57
|
+
content_type = nil)
|
58
|
+
Chef::Log.info 'calling ' + verb + ' ' + service_name + (wait ? " synchronously" : " asynchronously")
|
59
|
+
Chef::Log.debug body unless body == ''
|
60
|
+
response = @rest.query_azure(service_name, verb, body, params, services, content_type)
|
61
|
+
if response.code.to_i == 200
|
62
|
+
ret_val = Nokogiri::XML response.body
|
63
|
+
elsif !wait && response.code.to_i == 202
|
64
|
+
Chef::Log.debug 'Request accepted in asynchronous mode'
|
65
|
+
ret_val = Nokogiri::XML response.body
|
66
|
+
elsif response.code.to_i >= 201 && response.code.to_i <= 299
|
67
|
+
ret_val = wait_for_completion()
|
68
|
+
else
|
69
|
+
if response.body
|
70
|
+
ret_val = Nokogiri::XML response.body
|
71
|
+
Chef::Log.debug ret_val.to_xml
|
72
|
+
error_code, error_message = error_from_response_xml(ret_val)
|
73
|
+
Chef::Log.debug error_code + ' : ' + error_message if error_code.length > 0
|
74
|
+
else
|
75
|
+
Chef::Log.warn 'http error: ' + response.code
|
76
|
+
end
|
77
|
+
end
|
78
|
+
ret_val
|
79
|
+
end
|
80
|
+
|
81
|
+
def wait_for_completion()
|
82
|
+
status = 'InProgress'
|
83
|
+
Chef::Log.info 'Waiting while status returns InProgress'
|
84
|
+
while status == 'InProgress'
|
85
|
+
response = @rest.query_for_completion()
|
86
|
+
ret_val = Nokogiri::XML response.body
|
87
|
+
status = xml_content(ret_val,'Status')
|
88
|
+
if status == 'InProgress'
|
89
|
+
print '.'
|
90
|
+
sleep(0.5)
|
91
|
+
elsif status == 'Succeeded'
|
92
|
+
Chef::Log.debug 'not InProgress : ' + ret_val.to_xml
|
93
|
+
else
|
94
|
+
error_code, error_message = error_from_response_xml(ret_val)
|
95
|
+
Chef::Log.debug status + error_code + ' : ' + error_message if error_code.length > 0
|
96
|
+
end
|
97
|
+
end
|
98
|
+
ret_val
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -16,7 +16,7 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
|
19
|
+
module Azure
|
20
20
|
class Deploys
|
21
21
|
include AzureUtility
|
22
22
|
def initialize(connection)
|
@@ -104,6 +104,7 @@ class Azure
|
|
104
104
|
end
|
105
105
|
@connection.roles.find_in_hosted_service(params[:azure_vm_name], params[:azure_dns_name])
|
106
106
|
end
|
107
|
+
|
107
108
|
def delete(rolename)
|
108
109
|
end
|
109
110
|
|
@@ -130,9 +131,14 @@ class Azure
|
|
130
131
|
@url = xml_content(deployXML, 'Deployment Url')
|
131
132
|
@roles = Hash.new
|
132
133
|
rolesXML = deployXML.css('Deployment RoleInstanceList RoleInstance')
|
133
|
-
|
134
|
+
rolesListXML = deployXML.css('Deployment RoleList Role')
|
135
|
+
rolesXML.zip(rolesListXML).each do |roleXML,roleListXML|
|
134
136
|
role = Role.new(@connection)
|
135
137
|
role.parse(roleXML, hostedservicename, @name)
|
138
|
+
if role.publicipaddress.to_s.empty?
|
139
|
+
role.publicipaddress = xml_content(deployXML, 'VirtualIPs VirtualIP Address')
|
140
|
+
end
|
141
|
+
role.parse_role_list_xml(roleListXML)
|
136
142
|
@roles[role.name] = role
|
137
143
|
end
|
138
144
|
@input_endpoints = Array.new
|
@@ -16,7 +16,7 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
|
19
|
+
module Azure
|
20
20
|
class Disks
|
21
21
|
def initialize(connection)
|
22
22
|
@connection=connection
|
@@ -51,7 +51,7 @@ class Azure
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
|
54
|
+
module Azure
|
55
55
|
class Disk
|
56
56
|
attr_accessor :name, :attached
|
57
57
|
def initialize(disk)
|
@@ -16,7 +16,7 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
|
19
|
+
module Azure
|
20
20
|
class Hosts
|
21
21
|
include AzureUtility
|
22
22
|
def initialize(connection)
|
@@ -94,7 +94,7 @@ class Azure
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
|
97
|
+
module Azure
|
98
98
|
class Host
|
99
99
|
include AzureUtility
|
100
100
|
attr_accessor :connection, :name, :url, :label
|
@@ -16,7 +16,7 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
|
19
|
+
module Azure
|
20
20
|
class Images
|
21
21
|
def initialize(connection)
|
22
22
|
@connection=connection
|
@@ -76,7 +76,7 @@ class Azure
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
-
|
79
|
+
module Azure
|
80
80
|
class Image
|
81
81
|
attr_accessor :category, :label
|
82
82
|
attr_accessor :name, :os, :eula, :description, :location
|
@@ -16,8 +16,10 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
|
20
|
-
class
|
19
|
+
module Azure
|
20
|
+
class Loadbalancer
|
21
|
+
include AzureUtility
|
22
|
+
attr_accessor :name, :service, :subnet, :vip
|
21
23
|
|
22
24
|
def initialize(connection)
|
23
25
|
@connection = connection
|
@@ -45,22 +47,6 @@ class Azure
|
|
45
47
|
load[name]
|
46
48
|
end
|
47
49
|
|
48
|
-
def create(params)
|
49
|
-
lb = Loadbalancer.new(@connection)
|
50
|
-
lb.create(params)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
class Azure
|
56
|
-
class Loadbalancer
|
57
|
-
include AzureUtility
|
58
|
-
attr_accessor :name, :service, :subnet, :vip
|
59
|
-
|
60
|
-
def initialize(connection)
|
61
|
-
@connection = connection
|
62
|
-
end
|
63
|
-
|
64
50
|
def parse(lbXML, hostedservicename)
|
65
51
|
@name = xml_content(lbXML, 'Name')
|
66
52
|
ip_configXML = lbXML.css('FrontendIpConfiguration')
|
@@ -33,32 +33,36 @@ module AzureAPI
|
|
33
33
|
verb = 'get',
|
34
34
|
body = '',
|
35
35
|
params = '',
|
36
|
-
services = true
|
36
|
+
services = true,
|
37
|
+
content_type = nil)
|
37
38
|
svc_str = services ? '/services' : ''
|
38
|
-
|
39
|
-
|
39
|
+
uri = URI.parse("#{@host_name}/#{@subscription_id}#{svc_str}/#{service_name}")
|
40
|
+
scheme = !uri.scheme ? "https://" : ""
|
41
|
+
request_url = "#{scheme}#{@host_name}/#{@subscription_id}#{svc_str}/#{service_name}"
|
40
42
|
print '.'
|
41
|
-
response = http_query(request_url, verb, body, params)
|
43
|
+
response = http_query(request_url, verb, body, params, content_type)
|
42
44
|
if response.code.to_i == 307
|
43
45
|
Chef::Log.debug "Redirect to #{response['Location']}"
|
44
|
-
response = http_query(response['Location'], verb, body, params)
|
46
|
+
response = http_query(response['Location'], verb, body, params, content_type)
|
45
47
|
end
|
46
48
|
@last_request_id = response['x-ms-request-id']
|
47
49
|
response
|
48
50
|
end
|
49
51
|
|
50
|
-
def http_query(request_url, verb, body, params)
|
52
|
+
def http_query(request_url, verb, body, params, content_type = nil)
|
51
53
|
uri = URI.parse(request_url)
|
52
54
|
uri.query = params
|
53
55
|
http = http_setup(uri)
|
54
|
-
request = request_setup(uri, verb, body)
|
56
|
+
request = request_setup(uri, verb, body, content_type)
|
55
57
|
response = http.request(request)
|
56
58
|
@last_request_id = response['x-ms-request-id']
|
57
59
|
response
|
58
60
|
end
|
59
61
|
|
60
62
|
def query_for_completion()
|
61
|
-
|
63
|
+
uri = URI.parse("#{@host_name}/#{@subscription_id}/operations/#{@last_request_id}")
|
64
|
+
scheme = !uri.scheme ? "https://" : ""
|
65
|
+
request_url = "#{scheme}#{@host_name}/#{@subscription_id}/operations/#{@last_request_id}"
|
62
66
|
response = http_query(request_url, 'get', '', '')
|
63
67
|
if response.code.to_i == 307
|
64
68
|
Chef::Log.debug "Redirect to #{response['Location']}"
|
@@ -86,7 +90,7 @@ module AzureAPI
|
|
86
90
|
http.key = OpenSSL::PKey::RSA.new(@pem_file)
|
87
91
|
http
|
88
92
|
end
|
89
|
-
def request_setup(uri, verb, body)
|
93
|
+
def request_setup(uri, verb, body, content_type)
|
90
94
|
if verb == 'get'
|
91
95
|
request = Net::HTTP::Get.new(uri.request_uri)
|
92
96
|
elsif verb == 'post'
|
@@ -96,7 +100,7 @@ module AzureAPI
|
|
96
100
|
elsif verb == 'put'
|
97
101
|
request = Net::HTTP::Put.new(uri.request_uri)
|
98
102
|
end
|
99
|
-
text = verb == 'put'
|
103
|
+
text = verb == 'put' && content_type.nil?
|
100
104
|
request["x-ms-version"] = "2014-05-01"
|
101
105
|
request["content-type"] = text ? "text/plain" : "application/xml"
|
102
106
|
request["accept"] = "application/xml"
|
@@ -104,6 +108,7 @@ module AzureAPI
|
|
104
108
|
request.body = body
|
105
109
|
request
|
106
110
|
end
|
111
|
+
|
107
112
|
def showResponse(response)
|
108
113
|
puts "=== response body ==="
|
109
114
|
puts response.body
|
@@ -16,8 +16,9 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
require 'securerandom'
|
19
|
+
require 'azure/service_management/utility'
|
19
20
|
|
20
|
-
|
21
|
+
module Azure
|
21
22
|
class Roles
|
22
23
|
include AzureUtility
|
23
24
|
attr_accessor :connection, :roles
|
@@ -75,8 +76,8 @@ class Azure
|
|
75
76
|
find(name) != nil
|
76
77
|
end
|
77
78
|
|
78
|
-
def delete(
|
79
|
-
role = find(name)
|
79
|
+
def delete(params)
|
80
|
+
role = find(params[:name])
|
80
81
|
if role != nil
|
81
82
|
roleXML = nil
|
82
83
|
roleXML = @connection.query_azure("hostedservices/#{role.hostedservicename}", "get", "", "embed-detail=true")
|
@@ -165,6 +166,12 @@ class Azure
|
|
165
166
|
end
|
166
167
|
end
|
167
168
|
|
169
|
+
def update(name, params)
|
170
|
+
role = Role.new(@connection)
|
171
|
+
roleExtensionXml = role.setup_extension(params)
|
172
|
+
role.update(name, params, roleExtensionXml)
|
173
|
+
end
|
174
|
+
|
168
175
|
private :check_and_delete_role_and_resources, :check_and_delete_disks, :check_and_delete_service, :check_and_delete_storage
|
169
176
|
|
170
177
|
end
|
@@ -175,6 +182,7 @@ class Azure
|
|
175
182
|
attr_accessor :sshport, :hostedservicename, :deployname, :thumbprint
|
176
183
|
attr_accessor :winrmport
|
177
184
|
attr_accessor :hostname, :tcpports, :udpports
|
185
|
+
attr_accessor :role_xml, :os_type, :os_version
|
178
186
|
|
179
187
|
TCP_ENDPOINTS_MAPPING = { '3389' => 'Remote Desktop',
|
180
188
|
'5986' => 'PowerShell',
|
@@ -233,6 +241,13 @@ class Azure
|
|
233
241
|
end
|
234
242
|
end
|
235
243
|
|
244
|
+
def parse_role_list_xml(roleListXML)
|
245
|
+
@role_xml = roleListXML
|
246
|
+
os_disk_xml = roleListXML.css('OSVirtualHardDisk')
|
247
|
+
@os_type = xml_content(os_disk_xml, 'OS')
|
248
|
+
@os_version = xml_content(os_disk_xml, 'SourceImageName')
|
249
|
+
end
|
250
|
+
|
236
251
|
# Expects endpoint_param_string to be in the form {localport}:{publicport}:{lb_set_name}:{lb_probe_path}
|
237
252
|
# Only localport is mandatory.
|
238
253
|
def parse_endpoint_from_params(protocol, azure_vm_name, endpoint_param_string)
|
@@ -499,14 +514,14 @@ class Azure
|
|
499
514
|
if params[:chef_extension_public_param]
|
500
515
|
xml.ResourceExtensionParameterValue {
|
501
516
|
xml.Key "PublicParams"
|
502
|
-
xml.Value params[:chef_extension_public_param]
|
517
|
+
xml.Value Base64.encode64(params[:chef_extension_public_param].to_json)
|
503
518
|
xml.Type "Public"
|
504
519
|
}
|
505
520
|
end
|
506
521
|
if params[:chef_extension_private_param]
|
507
522
|
xml.ResourceExtensionParameterValue {
|
508
523
|
xml.Key "PrivateParams"
|
509
|
-
xml.Value params[:chef_extension_private_param]
|
524
|
+
xml.Value Base64.encode64(params[:chef_extension_private_param].to_json)
|
510
525
|
xml.Type "Private"
|
511
526
|
}
|
512
527
|
end
|
@@ -529,7 +544,7 @@ class Azure
|
|
529
544
|
xml.OSVirtualHardDisk {
|
530
545
|
disk_name = params[:azure_os_disk_name] || "disk_" + SecureRandom.uuid
|
531
546
|
xml.DiskName disk_name
|
532
|
-
domain_suffix = params[:azure_api_host_name].scan(/core.*/)[0]
|
547
|
+
domain_suffix = params[:azure_api_host_name] ? params[:azure_api_host_name].scan(/core.*/)[0] : ''
|
533
548
|
xml.MediaLink 'http://' + params[:azure_storage_account] + '.blob.' + domain_suffix + '/vhds/' + disk_name + '.vhd'
|
534
549
|
xml.SourceImageName params[:azure_source_image]
|
535
550
|
}
|
@@ -547,5 +562,158 @@ class Azure
|
|
547
562
|
"/#{params['deploy_name']}/roles"
|
548
563
|
@connection.query_azure(servicecall, "post", roleXML.to_xml)
|
549
564
|
end
|
565
|
+
|
566
|
+
def setup_extension(params)
|
567
|
+
## add Chef Extension config in role_xml retrieved from the server
|
568
|
+
puts "Adding Chef Extension config in server role..."
|
569
|
+
role_xml = update_role_xml_for_extension(params[:role_xml], params)
|
570
|
+
|
571
|
+
## role_xml can't be used for update as it has additional tags like
|
572
|
+
## role_name, osversion etc. which update API does not support, also the
|
573
|
+
## xml is the child of parent node 'Deployment' in XML, so instead of
|
574
|
+
## modifying the role_xml to fit for our requirements, we create
|
575
|
+
## new XML (with Chef Extension config and other pre-existing VM config)
|
576
|
+
## using the required values of the updated role_xml
|
577
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
578
|
+
xml.PersistentVMRole(
|
579
|
+
'xmlns' => 'http://schemas.microsoft.com/windowsazure',
|
580
|
+
'xmlns:i' => 'http://www.w3.org/2001/XMLSchema-instance'
|
581
|
+
) {
|
582
|
+
xml.ConfigurationSets role_xml.at_css('ConfigurationSets').children if !role_xml.at_css('ConfigurationSets').nil?
|
583
|
+
xml.ResourceExtensionReferences role_xml.at_css('ResourceExtensionReferences').children if !role_xml.at_css('ResourceExtensionReferences').nil?
|
584
|
+
xml.AvailabilitySetName role_xml.at_css('AvailabilitySetName').children if !role_xml.at_css('AvailabilitySetName').nil?
|
585
|
+
xml.DataVirtualHardDisks role_xml.at_css('DataVirtualHardDisks').children if !role_xml.at_css('DataVirtualHardDisks').nil?
|
586
|
+
xml.OSVirtualHardDisk role_xml.at_css('OSVirtualHardDisk').children if !role_xml.at_css('OSVirtualHardDisk').nil?
|
587
|
+
xml.RoleSize role_xml.at_css('RoleSize').children if !role_xml.at_css('RoleSize').nil?
|
588
|
+
xml.ProvisionGuestAgent role_xml.at_css('ProvisionGuestAgent').children if !role_xml.at_css('ProvisionGuestAgent').nil?
|
589
|
+
}
|
590
|
+
end
|
591
|
+
|
592
|
+
builder.doc.to_xml.gsub("<\;","<").gsub(">\;",">")
|
593
|
+
end
|
594
|
+
|
595
|
+
def update_role_xml_for_extension(roleXML, params)
|
596
|
+
## check if 'ResourceExtensionReferences' node already exist in the XML,
|
597
|
+
## if no add it, else retrieve the object of the existing node
|
598
|
+
add_resource_extension_references = roleXML.at_css('ResourceExtensionReferences').nil?
|
599
|
+
|
600
|
+
if add_resource_extension_references
|
601
|
+
resource_extension_references = Nokogiri::XML::Node.new('ResourceExtensionReferences', roleXML)
|
602
|
+
else
|
603
|
+
resource_extension_references = roleXML.css('ResourceExtensionReferences')
|
604
|
+
end
|
605
|
+
|
606
|
+
## check if Azure Chef Extension is already installed on the given server,
|
607
|
+
## if no than install it, else raise error saying that the extension is
|
608
|
+
## already installed
|
609
|
+
ext = nil
|
610
|
+
if !add_resource_extension_references
|
611
|
+
if !resource_extension_references.at_css('ReferenceName').nil?
|
612
|
+
resource_extension_references.css('ReferenceName').each { |node| ext = node if node.content == params[:chef_extension] }
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
616
|
+
add_resource_extension_reference = ext.nil?
|
617
|
+
|
618
|
+
## create Azure Chef Extension config and add it in the role_xml
|
619
|
+
if add_resource_extension_reference
|
620
|
+
resource_extension_reference = Nokogiri::XML::Node.new('ResourceExtensionReference', roleXML)
|
621
|
+
|
622
|
+
reference_name = Nokogiri::XML::Node.new('ReferenceName', roleXML)
|
623
|
+
reference_name.content = params[:chef_extension]
|
624
|
+
resource_extension_reference.add_child(reference_name)
|
625
|
+
|
626
|
+
publisher = Nokogiri::XML::Node.new('Publisher', roleXML)
|
627
|
+
publisher.content = params[:chef_extension_publisher]
|
628
|
+
resource_extension_reference.add_child(publisher)
|
629
|
+
|
630
|
+
name = Nokogiri::XML::Node.new('Name', roleXML)
|
631
|
+
name.content = params[:chef_extension]
|
632
|
+
resource_extension_reference.add_child(name)
|
633
|
+
|
634
|
+
version = Nokogiri::XML::Node.new('Version', roleXML)
|
635
|
+
version.content = params[:chef_extension_version]
|
636
|
+
resource_extension_reference.add_child(version)
|
637
|
+
|
638
|
+
resource_extension_parameter_values = Nokogiri::XML::Node.new('ResourceExtensionParameterValues', roleXML)
|
639
|
+
if params[:chef_extension_public_param]
|
640
|
+
resource_extension_parameter_value = Nokogiri::XML::Node.new('ResourceExtensionParameterValue', roleXML)
|
641
|
+
|
642
|
+
key = Nokogiri::XML::Node.new('Key', roleXML)
|
643
|
+
key.content = 'PublicParams'
|
644
|
+
resource_extension_parameter_value.add_child(key)
|
645
|
+
|
646
|
+
value = Nokogiri::XML::Node.new('Value', roleXML)
|
647
|
+
value.content = Base64.encode64(params[:chef_extension_public_param].to_json)
|
648
|
+
resource_extension_parameter_value.add_child(value)
|
649
|
+
|
650
|
+
type = Nokogiri::XML::Node.new('Type', roleXML)
|
651
|
+
type.content = 'Public'
|
652
|
+
resource_extension_parameter_value.add_child(type)
|
653
|
+
|
654
|
+
resource_extension_parameter_values.add_child(resource_extension_parameter_value)
|
655
|
+
end
|
656
|
+
|
657
|
+
if params[:chef_extension_private_param]
|
658
|
+
resource_extension_parameter_value = Nokogiri::XML::Node.new('ResourceExtensionParameterValue', roleXML)
|
659
|
+
|
660
|
+
key = Nokogiri::XML::Node.new('Key', roleXML)
|
661
|
+
key.content = 'PrivateParams'
|
662
|
+
resource_extension_parameter_value.add_child(key)
|
663
|
+
|
664
|
+
value = Nokogiri::XML::Node.new('Value', roleXML)
|
665
|
+
value.content = Base64.encode64(params[:chef_extension_private_param].to_json)
|
666
|
+
resource_extension_parameter_value.add_child(value)
|
667
|
+
|
668
|
+
type = Nokogiri::XML::Node.new('Type', roleXML)
|
669
|
+
type.content = 'Private'
|
670
|
+
resource_extension_parameter_value.add_child(type)
|
671
|
+
|
672
|
+
resource_extension_parameter_values.add_child(resource_extension_parameter_value)
|
673
|
+
end
|
674
|
+
|
675
|
+
resource_extension_reference.add_child(resource_extension_parameter_values)
|
676
|
+
|
677
|
+
state = Nokogiri::XML::Node.new('State', roleXML)
|
678
|
+
state.content = 'enable'
|
679
|
+
resource_extension_reference.add_child(state)
|
680
|
+
|
681
|
+
if add_resource_extension_references
|
682
|
+
resource_extension_references.add_child(resource_extension_reference)
|
683
|
+
else
|
684
|
+
resource_extension_references.last.add_child(resource_extension_reference)
|
685
|
+
end
|
686
|
+
|
687
|
+
roleXML.add_child(resource_extension_references) if add_resource_extension_references
|
688
|
+
|
689
|
+
add_provision_guest_agent = roleXML.at_css('ProvisionGuestAgent').nil?
|
690
|
+
|
691
|
+
if add_provision_guest_agent
|
692
|
+
provision_guest_agent = Nokogiri::XML::Node.new('ProvisionGuestAgent', roleXML)
|
693
|
+
provision_guest_agent.content = true
|
694
|
+
else
|
695
|
+
provision_guest_agent = roleXML.css('ProvisionGuestAgent')
|
696
|
+
provision_guest_agent.first.content = true
|
697
|
+
end
|
698
|
+
|
699
|
+
roleXML.add_child(provision_guest_agent) if add_provision_guest_agent
|
700
|
+
else ## raise error as Chef Extension is already installed on the server
|
701
|
+
raise "Chef Extension is already installed on the server #{params[:azure_vm_name]}."
|
702
|
+
end
|
703
|
+
|
704
|
+
roleXML
|
705
|
+
end
|
706
|
+
|
707
|
+
def update(name, params, roleXML)
|
708
|
+
puts "Updating server role..."
|
709
|
+
servicecall = "hostedservices/#{params[:azure_dns_name]}" +
|
710
|
+
"/deployments/#{params[:deploy_name]}/roles/#{name}"
|
711
|
+
ret_val = @connection.query_azure(servicecall, 'put', roleXML, '', true, true, 'application/xml')
|
712
|
+
error_code, error_message = error_from_response_xml(ret_val)
|
713
|
+
if error_code.length > 0
|
714
|
+
Chef::Log.debug(ret_val.to_s)
|
715
|
+
raise 'Unable to update role:' + error_code + ' : ' + error_message
|
716
|
+
end
|
717
|
+
end
|
550
718
|
end
|
551
719
|
end
|