knife-azure 1.6.0.rc.0 → 1.6.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 +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
|