knife-azure 3.0.6 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/azure/custom_errors.rb +1 -1
  3. data/lib/azure/resource_management/ARM_deployment_template.rb +5 -5
  4. data/lib/azure/resource_management/ARM_interface.rb +4 -6
  5. data/lib/azure/resource_management/windows_credentials.rb +2 -2
  6. data/lib/chef/knife/azurerm_server_create.rb +1 -1
  7. data/lib/chef/knife/bootstrap/bootstrapper.rb +5 -10
  8. data/lib/chef/knife/helpers/azurerm_base.rb +4 -4
  9. data/lib/knife-azure/version.rb +1 -1
  10. metadata +30 -43
  11. data/lib/azure/service_management/ASM_interface.rb +0 -310
  12. data/lib/azure/service_management/ag.rb +0 -99
  13. data/lib/azure/service_management/certificate.rb +0 -235
  14. data/lib/azure/service_management/connection.rb +0 -102
  15. data/lib/azure/service_management/deploy.rb +0 -221
  16. data/lib/azure/service_management/disk.rb +0 -68
  17. data/lib/azure/service_management/host.rb +0 -184
  18. data/lib/azure/service_management/image.rb +0 -94
  19. data/lib/azure/service_management/loadbalancer.rb +0 -78
  20. data/lib/azure/service_management/rest.rb +0 -126
  21. data/lib/azure/service_management/role.rb +0 -717
  22. data/lib/azure/service_management/storageaccount.rb +0 -127
  23. data/lib/azure/service_management/utility.rb +0 -40
  24. data/lib/azure/service_management/vnet.rb +0 -134
  25. data/lib/chef/knife/azure_ag_create.rb +0 -73
  26. data/lib/chef/knife/azure_ag_list.rb +0 -35
  27. data/lib/chef/knife/azure_image_list.rb +0 -56
  28. data/lib/chef/knife/azure_internal-lb_create.rb +0 -74
  29. data/lib/chef/knife/azure_internal-lb_list.rb +0 -35
  30. data/lib/chef/knife/azure_server_create.rb +0 -531
  31. data/lib/chef/knife/azure_server_delete.rb +0 -136
  32. data/lib/chef/knife/azure_server_list.rb +0 -38
  33. data/lib/chef/knife/azure_server_show.rb +0 -41
  34. data/lib/chef/knife/azure_vnet_create.rb +0 -74
  35. data/lib/chef/knife/azure_vnet_list.rb +0 -35
  36. data/lib/chef/knife/bootstrap_azure.rb +0 -191
  37. data/lib/chef/knife/helpers/azure_base.rb +0 -392
@@ -1,99 +0,0 @@
1
- #
2
- # Author:: Jeff Mendoza (jeffmendoza@live.com)
3
- # Copyright:: Copyright (c) Chef Software 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
- module Azure
20
- class AGs
21
- def initialize(connection)
22
- @connection = connection
23
- end
24
-
25
- def load
26
- @ags ||= begin
27
- @ags = {}
28
- response = @connection.query_azure("affinitygroups",
29
- "get",
30
- "",
31
- "",
32
- true,
33
- false)
34
- response.css("AffinityGroup").each do |ag|
35
- item = AG.new(@connection).parse(ag)
36
- @ags[item.name] = item
37
- end
38
- @ags
39
- end
40
- end
41
-
42
- def all
43
- load.values
44
- end
45
-
46
- def exists?(name)
47
- load.key?(name)
48
- end
49
-
50
- def find(name)
51
- load[name]
52
- end
53
-
54
- def create(params)
55
- ag = AG.new(@connection)
56
- ag.create(params)
57
- end
58
- end
59
- end
60
-
61
- module Azure
62
- class AG
63
- attr_accessor :name, :label, :description, :location
64
-
65
- def initialize(connection)
66
- @connection = connection
67
- end
68
-
69
- def parse(image)
70
- @name = image.at_css("Name").content
71
- @label = image.at_css("Label").content
72
- @description = image.at_css("Description").content if
73
- image.at_css("Description")
74
- @location = image.at_css("Location").content if image.at_css("Location")
75
- self
76
- end
77
-
78
- def create(params)
79
- builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
80
- xml.CreateAffinityGroup(
81
- xmlns: "http://schemas.microsoft.com/windowsazure"
82
- ) do
83
- xml.Name params[:azure_ag_name]
84
- xml.Label Base64.strict_encode64(params[:azure_ag_name])
85
- unless params[:azure_ag_desc].nil?
86
- xml.Description params[:azure_ag_desc]
87
- end
88
- xml.Location params[:azure_location]
89
- end
90
- end
91
- @connection.query_azure("affinitygroups",
92
- "post",
93
- builder.to_xml,
94
- "",
95
- true,
96
- false)
97
- end
98
- end
99
- end
@@ -1,235 +0,0 @@
1
- #
2
- # Author:: Mukta Aphale (mukta.aphale@clogeny.com)
3
- # Copyright:: Copyright (c) Chef Software 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
- module Azure
20
- class Certificates
21
- def initialize(connection)
22
- @connection = connection
23
- end
24
-
25
- def create(params)
26
- certificate = Certificate.new(@connection)
27
- certificate.create(params)
28
- end
29
-
30
- def add(certificate_data, certificate_password, certificate_format, dns_name)
31
- certificate = Certificate.new(@connection)
32
- certificate.add_certificate certificate_data, certificate_password, certificate_format, dns_name
33
- end
34
-
35
- def create_ssl_certificate(azure_dns_name)
36
- cert_params = { output_file: "winrm", key_length: 2048, cert_validity: 24,
37
- azure_dns_name: azure_dns_name }
38
- certificate = Certificate.new(@connection)
39
- thumbprint = certificate.create_ssl_certificate(cert_params)
40
- end
41
-
42
- def get_certificate(dns_name, fingerprint)
43
- certificate = Certificate.new(@connection)
44
- certificate.get_certificate(dns_name, fingerprint)
45
- end
46
- end
47
- end
48
-
49
- module Azure
50
- class Certificate
51
- attr_accessor :connection
52
- attr_accessor :cert_data, :fingerprint, :certificate_version
53
- def initialize(connection)
54
- @connection = connection
55
- @certificate_version = 2 # cf. RFC 5280 - to make it a "v3" certificate
56
- end
57
-
58
- def create(params)
59
- # If RSA private key has been specified, then generate an x 509 certificate from the
60
- # public part of the key
61
- @cert_data = generate_public_key_certificate_data({ ssh_key: params[:ssh_identity_file],
62
- ssh_key_passphrase: params[:identity_file_passphrase] })
63
- add_certificate @cert_data, "knifeazure", "pfx", params[:azure_dns_name]
64
-
65
- # Return the fingerprint to be used while adding role
66
- @fingerprint
67
- end
68
-
69
- def generate_public_key_certificate_data(params)
70
- # Generate OpenSSL RSA key from the mentioned ssh key path (and passphrase)
71
- key = OpenSSL::PKey::RSA.new(File.read(params[:ssh_key]), params[:ssh_key_passphrase])
72
- # Generate X 509 certificate
73
- ca = OpenSSL::X509::Certificate.new
74
- ca.version = @certificate_version
75
- ca.serial = Random.rand(65534) + 1 # 2 digit byte range random number for better security aspect
76
- ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=knife-plugin/CN=Opscode CA"
77
- ca.issuer = ca.subject # root CA's are "self-signed"
78
- ca.public_key = key.public_key # Assign the ssh-key's public part to the certificate
79
- ca.not_before = Time.now
80
- ca.not_after = ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
81
- ef = OpenSSL::X509::ExtensionFactory.new
82
- ef.subject_certificate = ca
83
- ef.issuer_certificate = ca
84
- ca.add_extension(ef.create_extension("basicConstraints", "CA:TRUE", true))
85
- ca.add_extension(ef.create_extension("keyUsage", "keyCertSign, cRLSign", true))
86
- ca.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false))
87
- ca.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false))
88
- ca.sign(key, OpenSSL::Digest.new("SHA256"))
89
- # Generate the SHA1 fingerprint of the der format of the X 509 certificate
90
- @fingerprint = OpenSSL::Digest::SHA1.new(ca.to_der)
91
- # Create the pfx format of the certificate
92
- pfx = OpenSSL::PKCS12.create("knifeazure", "knife-azure-pfx", key, ca)
93
- # Encode the pfx format - upload this certificate
94
- Base64.strict_encode64(pfx.to_der)
95
- end
96
-
97
- def add_certificate(certificate_data, certificate_password, certificate_format, dns_name)
98
- # Generate XML to call the API
99
- # Add certificate to the hosted service
100
- builder = Nokogiri::XML::Builder.new do |xml|
101
- xml.CertificateFile("xmlns" => "http://schemas.microsoft.com/windowsazure") do
102
- xml.Data certificate_data
103
- xml.CertificateFormat certificate_format
104
- xml.Password certificate_password
105
- end
106
- end
107
- # Windows Azure API call
108
- @connection.query_azure("hostedservices/#{dns_name}/certificates", "post", builder.to_xml)
109
-
110
- # Check if certificate is available else raise error
111
- for attempt in 0..4
112
- Chef::Log.info "Waiting to get certificate ..."
113
- res = get_certificate(dns_name, @fingerprint)
114
- break unless res.empty?
115
- if attempt == 4
116
- raise "The certificate with thumbprint #{fingerprint} was not found."
117
- else
118
- sleep 5
119
- end
120
- end
121
- end
122
-
123
- def get_certificate(dns_name, fingerprint)
124
- @connection.query_azure("hostedservices/#{dns_name}/certificates/sha1-#{fingerprint}", "get").search("Certificate")
125
- end
126
-
127
- ######## SSL certificate generation for knife-azure ssl bootstrap ######
128
- def create_ssl_certificate(cert_params)
129
- file_path = cert_params[:output_file].sub(/\.(\w+)$/, "")
130
- path = prompt_for_file_path
131
- file_path = File.join(path, file_path) unless path.empty?
132
- cert_params[:domain] = prompt_for_domain
133
-
134
- rsa_key = generate_keypair cert_params[:key_length]
135
- cert = generate_certificate(rsa_key, cert_params)
136
- write_certificate_to_file cert, file_path, rsa_key, cert_params
137
- puts "*" * 70
138
- puts "Generated Certificates:"
139
- puts "- #{file_path}.pfx - PKCS12 format keypair. Contains both the public and private keys, usually used on the server."
140
- puts "- #{file_path}.b64 - Base64 encoded PKCS12 keypair. Contains both the public and private keys, for upload to the Azure REST API."
141
- puts "- #{file_path}.pem - Base64 encoded public certificate only. Required by the client to connect to the server."
142
- puts "Certificate Thumbprint: #{@thumbprint.to_s.upcase}"
143
- puts "*" * 70
144
-
145
- config[:ca_trust_file] = file_path + ".pem" if config[:ca_trust_file].nil?
146
- cert_data = File.read (file_path + ".b64")
147
- add_certificate cert_data, @winrm_cert_passphrase, "pfx", cert_params[:azure_dns_name]
148
- @thumbprint
149
- end
150
-
151
- def generate_keypair(key_length)
152
- OpenSSL::PKey::RSA.new(key_length.to_i)
153
- end
154
-
155
- def prompt_for_passphrase
156
- passphrase = ""
157
- begin
158
- print "Passphrases do not match. Try again.\n" unless passphrase.empty?
159
- print "Enter certificate passphrase (empty for no passphrase):"
160
- passphrase = STDIN.gets
161
- return passphrase.strip if passphrase == "\n"
162
-
163
- print "Enter same passphrase again:"
164
- confirm_passphrase = STDIN.gets
165
- end until passphrase == confirm_passphrase
166
- passphrase.strip
167
- end
168
-
169
- def prompt_for_file_path
170
- file_path = ""
171
- counter = 0
172
- begin
173
- print "Invalid location! \n" unless file_path.empty?
174
- print 'Enter the file path for certificates e.g. C:\Windows (empty for current location):'
175
- file_path = STDIN.gets
176
- stripped_file_path = file_path.strip
177
- return stripped_file_path if file_path == "\n"
178
-
179
- counter += 1
180
- exit(1) if counter == 3
181
- end until File.directory?(stripped_file_path)
182
- stripped_file_path
183
- end
184
-
185
- def prompt_for_domain
186
- counter = 0
187
- begin
188
- print "Enter the domain (mandatory):"
189
- domain = STDIN.gets
190
- domain = domain.strip
191
- counter += 1
192
- exit(1) if counter == 3
193
- end until !domain.empty?
194
- domain
195
- end
196
-
197
- def generate_certificate(rsa_key, cert_params)
198
- @hostname = "*"
199
- if cert_params[:domain]
200
- @hostname = "*." + cert_params[:domain]
201
- end
202
-
203
- # Create a self-signed X509 certificate from the rsa_key (unencrypted)
204
- cert = OpenSSL::X509::Certificate.new
205
- cert.version = 2
206
- cert.serial = Random.rand(65534) + 1 # 2 digit byte range random number for better security aspect
207
-
208
- cert.subject = OpenSSL::X509::Name.parse "/CN=#{@hostname}"
209
- cert.issuer = cert.subject
210
- cert.public_key = rsa_key.public_key
211
- cert.not_before = Time.now
212
- cert.not_after = cert.not_before + 2 * 365 * cert_params[:cert_validity].to_i * 60 * 60 # 2 years validity
213
- ef = OpenSSL::X509::ExtensionFactory.new
214
- ef.subject_certificate = cert
215
- ef.issuer_certificate = cert
216
- cert.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false))
217
- cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false))
218
- cert.add_extension(ef.create_extension("extendedKeyUsage", "1.3.6.1.5.5.7.3.1", false))
219
- cert.sign(rsa_key, OpenSSL::Digest.new("SHA1"))
220
- @thumbprint = OpenSSL::Digest::SHA1.new(cert.to_der)
221
- cert
222
- end
223
-
224
- def write_certificate_to_file(cert, file_path, rsa_key, cert_params)
225
- File.open(file_path + ".pem", "wb") { |f| f.print cert.to_pem }
226
- @winrm_cert_passphrase = prompt_for_passphrase unless @winrm_cert_passphrase
227
- pfx = OpenSSL::PKCS12.create("#{cert_params[:winrm_cert_passphrase]}", "winrmcert", rsa_key, cert)
228
- File.open(file_path + ".pfx", "wb") { |f| f.print pfx.to_der }
229
- File.open(file_path + ".b64", "wb") { |f| f.print Base64.strict_encode64(pfx.to_der) }
230
- end
231
-
232
- ########## SSL certificate generation ends ###########
233
-
234
- end
235
- end
@@ -1,102 +0,0 @@
1
- #
2
- # Author:: Barry Davis (barryd@jetstreamsoftware.com)
3
- # Copyright:: Copyright (c) Chef Software 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_relative "image"
20
- require_relative "role"
21
- require_relative "deploy"
22
- require_relative "host"
23
- require_relative "loadbalancer"
24
- require_relative "vnet"
25
- require_relative "utility"
26
- require_relative "ag"
27
- require_relative "storageaccount"
28
- require_relative "certificate"
29
- require_relative "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
@@ -1,221 +0,0 @@
1
- #
2
- # Author:: Barry Davis (barryd@jetstreamsoftware.com)
3
- # Copyright:: Copyright (c) Chef Software 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
- module Azure
20
- class Deploys
21
- include AzureUtility
22
- def initialize(connection)
23
- @connection = connection
24
- end
25
-
26
- # force_load should be true when there is something in local cache and we want to reload
27
- # first call is always load.
28
- def load(force_load = false)
29
- unless @deploys || force_load
30
- @deploys = begin
31
- deploys = []
32
- hosts = @connection.hosts.all
33
- hosts.each do |host|
34
- deploy = Deploy.new(@connection)
35
- deploy.retrieve(host.name)
36
- if deploy.name
37
- host.add_deploy(deploy)
38
- deploys << deploy
39
- end
40
- end
41
- deploys
42
- end
43
- end
44
- @deploys
45
- end
46
-
47
- def all
48
- load
49
- end
50
-
51
- # TODO - Current knife-azure plug-in seems to have assumption that single hostedservice
52
- # will always have one deployment (production). see Deploy#retrieve below
53
- def get_deploy_name_for_hostedservice(hostedservicename)
54
- host = @connection.hosts.find(hostedservicename)
55
- if host && host.deploys.length > 0
56
- host.deploys[0].name
57
- else
58
- nil
59
- end
60
- end
61
-
62
- def create(params)
63
- if params[:azure_connect_to_existing_dns]
64
- unless @connection.hosts.exists?(params[:azure_dns_name])
65
- Chef::Log.fatal "The specified Azure DNS Name does not exist."
66
- exit 1
67
- end
68
- else
69
- ret_val = @connection.hosts.create(params)
70
- error_code, error_message = error_from_response_xml(ret_val)
71
- if error_code.length > 0
72
- Chef::Log.fatal "Unable to create DNS:" + error_code + " : " + error_message
73
- exit 1
74
- end
75
- end
76
- unless @connection.storageaccounts.exists?(params[:azure_storage_account])
77
- @connection.storageaccounts.create(params)
78
- end
79
- if params[:ssh_identity_file]
80
- params[:fingerprint] = @connection.certificates.create(params)
81
- end
82
- if params[:cert_path]
83
- cert_data = File.read (params[:cert_path])
84
- @connection.certificates.add cert_data, params[:cert_password], "pfx", params[:azure_dns_name]
85
- elsif params[:winrm_ssl]
86
- # TODO: generate certificates for ssl listener
87
- end
88
-
89
- params["deploy_name"] = get_deploy_name_for_hostedservice(params[:azure_dns_name])
90
-
91
- if !params["deploy_name"].nil?
92
- role = Role.new(@connection)
93
- roleXML = role.setup(params)
94
- ret_val = role.create(params, roleXML)
95
- else
96
- params["deploy_name"] = params[:azure_dns_name]
97
- deploy = Deploy.new(@connection)
98
- deployXML = deploy.setup(params)
99
- ret_val = deploy.create(params, deployXML)
100
- end
101
- error_code, error_message = error_from_response_xml(ret_val)
102
- if error_code.length > 0
103
- Chef::Log.debug(ret_val.to_s)
104
- raise Chef::Log.fatal "Unable to create role:" + error_code + " : " + error_message
105
- end
106
- @connection.roles.find_in_hosted_service(params[:azure_vm_name], params[:azure_dns_name])
107
- end
108
-
109
- def delete(rolename); end
110
-
111
- def queryDeploy(hostedservicename)
112
- deploy = Deploy.new(@connection)
113
- deploy.retrieve(hostedservicename)
114
- deploy
115
- end
116
- end
117
-
118
- class Deploy
119
- include AzureUtility
120
- attr_accessor :connection, :name, :status, :url, :hostedservicename, :input_endpoints, :loadbalancers
121
-
122
- def initialize(connection)
123
- @connection = connection
124
- end
125
-
126
- def retrieve(hostedservicename)
127
- @hostedservicename = hostedservicename
128
- deployXML = @connection.query_azure("hostedservices/#{hostedservicename}/deploymentslots/Production")
129
- if deployXML.at_css("Deployment Name") != nil
130
- @name = xml_content(deployXML, "Deployment Name")
131
- @status = xml_content(deployXML, "Deployment Status")
132
- @url = xml_content(deployXML, "Deployment Url")
133
- @roles = {}
134
- rolesXML = deployXML.css("Deployment RoleInstanceList RoleInstance")
135
- rolesListXML = deployXML.css("Deployment RoleList Role")
136
- rolesXML.zip(rolesListXML).each do |roleXML, roleListXML|
137
- role = Role.new(@connection)
138
- role.parse(roleXML, hostedservicename, @name)
139
- if role.publicipaddress.to_s.empty?
140
- role.publicipaddress = xml_content(deployXML, "VirtualIPs VirtualIP Address")
141
- end
142
- role.parse_role_list_xml(roleListXML)
143
- @roles[role.name] = role
144
- end
145
- @input_endpoints = []
146
- endpointsXML = deployXML.css("InputEndpoint")
147
- endpointsXML.each do |endpointXML|
148
- @input_endpoints << parse_endpoint(endpointXML)
149
- end
150
- @loadbalancers = {}
151
- lbsXML = deployXML.css("Deployment LoadBalancers LoadBalancer")
152
- lbsXML.each do |lbXML|
153
- loadbalancer = Loadbalancer.new(@connection)
154
- loadbalancer.parse(lbXML, hostedservicename)
155
- @loadbalancers[loadbalancer.name] = loadbalancer
156
- end
157
- end
158
- end
159
-
160
- def setup(params)
161
- role = Role.new(@connection)
162
- roleXML = role.setup(params)
163
- builder = Nokogiri::XML::Builder.new do |xml|
164
- xml.Deployment(
165
- "xmlns" => "http://schemas.microsoft.com/windowsazure",
166
- "xmlns:i" => "http://www.w3.org/2001/XMLSchema-instance"
167
- ) do
168
- xml.Name params["deploy_name"]
169
- xml.DeploymentSlot "Production"
170
- xml.Label Base64.encode64(params["deploy_name"]).strip
171
- xml.RoleList { xml.Role("i:type" => "PersistentVMRole") }
172
- if params[:azure_network_name]
173
- xml.VirtualNetworkName params[:azure_network_name]
174
- end
175
- end
176
- end
177
- builder.doc.at_css("Role") << roleXML.at_css("PersistentVMRole").children.to_s
178
- builder.doc
179
- end
180
-
181
- def create(params, deployXML)
182
- servicecall = "hostedservices/#{params[:azure_dns_name]}/deployments"
183
- @connection.query_azure(servicecall, "post", deployXML.to_xml)
184
- end
185
-
186
- # This parses endpoints from a RoleList-Role-InputEndpoint, NOT a RoleInstanceList-RoleInstance-InstanceEndpoint
187
- # Refactor: make this an object rather than a hash..?
188
- def parse_endpoint(inputendpoint_xml)
189
- hash = {}
190
- %w{LoadBalancedEndpointSetName LocalPort Name Port Protocol EnableDirectServerReturn LoadBalancerName IdleTimeoutInMinutes}.each do |key|
191
- hash[key] = xml_content(inputendpoint_xml, key, nil)
192
- end
193
- # Protocol could be in there twice... If we have two, pick the second one as the first is for the probe.
194
- if inputendpoint_xml.css("Protocol").count > 1
195
- hash["Protocol"] = inputendpoint_xml.css("Protocol")[1].content
196
- end
197
- probe = inputendpoint_xml.css("LoadBalancerProbe")
198
- if probe
199
- hash["LoadBalancerProbe"] = {}
200
- %w{Path Port Protocol IntervalInSeconds TimeoutInSeconds}.each do |key|
201
- hash["LoadBalancerProbe"][key] = xml_content(probe, key, nil)
202
- end
203
- end
204
- hash
205
- end
206
-
207
- def roles
208
- @roles.values if @roles
209
- end
210
-
211
- # just delete from local cache
212
- def delete_role_if_present(role)
213
- @roles.delete(role.name) if @roles
214
- end
215
-
216
- def find_role(name)
217
- @roles[name] if @roles
218
- end
219
-
220
- end
221
- end