From 034278b527de91c5db250d02a4df76f3d059c40f Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Fri, 14 Jun 2013 11:24:02 +0530 Subject: [PATCH 01/12] optimize image listing to load only once. --- lib/azure/image.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/azure/image.rb b/lib/azure/image.rb index 7866220..a3dd8ca 100755 --- a/lib/azure/image.rb +++ b/lib/azure/image.rb @@ -22,14 +22,16 @@ class Azure @connection=connection end def all - images = Array.new - response = @connection.query_azure('images') - osimages = response.css('OSImage') - osimages.each do |image| - item = Image.new(image) - images << item + @images ||= begin + images = Array.new + response = @connection.query_azure('images') + osimages = response.css('OSImage') + osimages.each do |image| + item = Image.new(image) + images << item + end + images end - images end def exists(name) imageExists = false From 8ee2c9d430ab7246b59ea252424a929a45832df4 Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Sat, 22 Jun 2013 11:17:50 +0530 Subject: [PATCH 02/12] optimize azure image list classes. --- lib/azure/image.rb | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/azure/image.rb b/lib/azure/image.rb index a3dd8ca..12903cd 100755 --- a/lib/azure/image.rb +++ b/lib/azure/image.rb @@ -21,25 +21,29 @@ class Azure def initialize(connection) @connection=connection end - def all + def load @images ||= begin - images = Array.new + images = Hash.new response = @connection.query_azure('images') osimages = response.css('OSImage') osimages.each do |image| item = Image.new(image) - images << item + images[item.name] = item end images end end - def exists(name) - imageExists = false - self.all.each do |host| - next unless host.name == name - imageExists = true - end - imageExists + + def all + self.load.values + end + + def exists?(name) + self.all.key?(name) + end + + def find(name) + self.load[name] end end end From 58d0d3becaf52ab2702fda3c340a2f5f4379765e Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Sat, 22 Jun 2013 13:44:19 +0530 Subject: [PATCH 03/12] optimize azure storage account lookups. --- lib/azure/deploy.rb | 2 +- lib/azure/storageaccount.rb | 51 ++++++++++++++++++++++---------- spec/spec_helper.rb | 1 + spec/unit/assets/error_404.xml | 5 ++++ spec/unit/query_azure_mock.rb | 16 ++++++++++ spec/unit/storageaccount_spec.rb | 9 ++++++ 6 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 spec/unit/assets/error_404.xml diff --git a/lib/azure/deploy.rb b/lib/azure/deploy.rb index b9ed342..3b4d931 100755 --- a/lib/azure/deploy.rb +++ b/lib/azure/deploy.rb @@ -54,7 +54,7 @@ class Azure exit 1 end end - unless @connection.storageaccounts.exists(params[:azure_storage_account]) + unless @connection.storageaccounts.exists?(params[:azure_storage_account]) @connection.storageaccounts.create(params) end if params[:identity_file] diff --git a/lib/azure/storageaccount.rb b/lib/azure/storageaccount.rb index 719cb96..6e8f91a 100644 --- a/lib/azure/storageaccount.rb +++ b/lib/azure/storageaccount.rb @@ -21,24 +21,45 @@ class Azure def initialize(connection) @connection=connection end + # force_load should be true when there is something in local cache and we want to reload + # first call is always load. + def load(force_load = false) + if not @azure_storage_accounts || force_load + @azure_storage_accounts = begin + azure_storage_accounts = Hash.new + responseXML = @connection.query_azure('storageservices') + servicesXML = responseXML.css('StorageServices StorageService') + servicesXML.each do |serviceXML| + storage = StorageAccount.new(@connection).parse(serviceXML) + azure_storage_accounts[storage.name] = storage + end + azure_storage_accounts + end + end + @azure_storage_accounts + end + def all - azure_storage_accounts = Array.new - responseXML = @connection.query_azure('storageservices') - servicesXML = responseXML.css('StorageServices StorageService') - servicesXML.each do |serviceXML| - azure_storage_account = StorageAccount.new(@connection) - azure_storage_accounts << azure_storage_account.parse(serviceXML) - end - azure_storage_accounts + self.load.values end - def exists(name) - storageExists = false - self.all.each do |storage| - next unless storage.name == name - storageExists = true - end - storageExists + + # first look up local cache if we have already loaded list. + def exists?(name) + return @azure_storage_accounts.key?(name) if @azure_storage_accounts + self.exists_on_cloud?(name) end + + # Look up on cloud and not local cache + def exists_on_cloud?(name) + ret_val = @connection.query_azure("storageservices/#{name}") + if ret_val.nil? || ret_val.css('Error Code').length > 0 + Chef::Log.warn 'Unable to find storage account:' + ret_val.at_css('Error Code').content + ' : ' + ret_val.at_css('Error Message').content if ret_val + false + else + true + end + end + def create(params) storage = StorageAccount.new(@connection) storage.create(params) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6e756a0..54eee26 100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,6 +8,7 @@ require 'azure/image' require 'azure/deploy' require 'azure/role' require 'azure/disk' +require 'azure/utility' require 'chef/knife/azure_server_list' require 'chef/knife/azure_server_delete' diff --git a/spec/unit/assets/error_404.xml b/spec/unit/assets/error_404.xml new file mode 100644 index 0000000..4904a44 --- /dev/null +++ b/spec/unit/assets/error_404.xml @@ -0,0 +1,5 @@ + + + 404 + The specified resource does not exist. + \ No newline at end of file diff --git a/spec/unit/query_azure_mock.rb b/spec/unit/query_azure_mock.rb index 5de63b8..eee366c 100755 --- a/spec/unit/query_azure_mock.rb +++ b/spec/unit/query_azure_mock.rb @@ -1,4 +1,7 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + module QueryAzureMock + include AzureUtility def setup_query_azure_mock create_connection stub_query_azure (@connection) @@ -51,6 +54,19 @@ module QueryAzureMock retval = Nokogiri::XML readFile('list_deployments_for_service004.xml') elsif name == 'storageservices' retval = Nokogiri::XML readFile('list_storageaccounts.xml') + elsif name =~ /storageservices\/.*/ + service_name = /storageservices\/(.*)/.match(name)[1] + responseXML = Nokogiri::XML readFile('list_storageaccounts.xml') + servicesXML = responseXML.css('StorageServices StorageService') + not_found = true + servicesXML.each do |serviceXML| + if xml_content(serviceXML, 'ServiceName') == service_name + not_found = false + retval = serviceXML + break + end + end + retval = Nokogiri::XML readFile('error_404.xml') if not_found else Chef::Log.warn 'unknown get value:' + name end diff --git a/spec/unit/storageaccount_spec.rb b/spec/unit/storageaccount_spec.rb index d974ff9..1e72784 100644 --- a/spec/unit/storageaccount_spec.rb +++ b/spec/unit/storageaccount_spec.rb @@ -19,6 +19,15 @@ describe "storageaccounts" do end end + context 'check storage account existence' do + it 'storage account should exist' do + expect(@connection.storageaccounts.exists?("storage-service-name")).to be_true + end + it 'storage account should not exist' do + expect(@connection.storageaccounts.exists?("invalid-storage-service-name")).to be_false + end + end + context 'create a new storage account' do it 'using explicity parameters it should pass in expected body' do params = { From 750aea3dd993fd47de240e0a532d33db04f8c79e Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Sat, 22 Jun 2013 15:09:42 +0530 Subject: [PATCH 04/12] optimize hosted services lookup. --- lib/azure/host.rb | 54 ++++++++++++++++++++++++----------- spec/unit/hosts_spec.rb | 4 +-- spec/unit/query_azure_mock.rb | 35 ++++++++++++++--------- 3 files changed, 62 insertions(+), 31 deletions(-) diff --git a/lib/azure/host.rb b/lib/azure/host.rb index bbfd95f..3bf1db3 100755 --- a/lib/azure/host.rb +++ b/lib/azure/host.rb @@ -21,30 +21,52 @@ class Azure def initialize(connection) @connection=connection end + + # force_load should be true when there is something in local cache and we want to reload + # first call is always load. + def load(force_load = false) + if not @hosted_services || force_load + @hosted_services = begin + hosted_services = Hash.new + responseXML = @connection.query_azure('hostedservices') + servicesXML = responseXML.css('HostedServices HostedService') + servicesXML.each do |serviceXML| + host = Host.new(@connection).parse(serviceXML) + hosted_services[host.name] = host + end + hosted_services + end + end + @hosted_services + end + def all - hosted_services = Array.new - responseXML = @connection.query_azure('hostedservices') - servicesXML = responseXML.css('HostedServices HostedService') - servicesXML.each do |serviceXML| - host = Host.new(@connection) - hosted_services << host.parse(serviceXML) - end - hosted_services + self.load.values end - def exists(name) - hostExists = false - self.all.each do |host| - next unless host.name == name - hostExists = true - end - hostExists + + # first look up local cache if we have already loaded list. + def exists?(name) + return @hosted_services.key?(name) if @hosted_services + self.exists_on_cloud?(name) end + + # Look up on cloud and not local cache + def exists_on_cloud?(name) + ret_val = @connection.query_azure("hostedservices/#{name}") + if ret_val.nil? || ret_val.css('Error Code').length > 0 + Chef::Log.warn 'Unable to find hosted(cloud) service:' + ret_val.at_css('Error Code').content + ' : ' + ret_val.at_css('Error Message').content if ret_val + false + else + true + end + end + def create(params) host = Host.new(@connection) host.create(params) end def delete(name) - if self.exists name + if self.exists?(name) servicecall = "hostedservices/" + name @connection.query_azure(servicecall, "delete") end diff --git a/spec/unit/hosts_spec.rb b/spec/unit/hosts_spec.rb index fa9c1dc..b8bfc73 100755 --- a/spec/unit/hosts_spec.rb +++ b/spec/unit/hosts_spec.rb @@ -23,8 +23,8 @@ describe "hosts" do host.status.should_not be_nil end end - specify {@connection.hosts.exists("notExpectedName").should == false} - specify {@connection.hosts.exists("service001").should == true} + specify {@connection.hosts.exists?("notExpectedName").should == false} + specify {@connection.hosts.exists?("service001").should == true} end context 'create a new host' do diff --git a/spec/unit/query_azure_mock.rb b/spec/unit/query_azure_mock.rb index eee366c..b593aee 100755 --- a/spec/unit/query_azure_mock.rb +++ b/spec/unit/query_azure_mock.rb @@ -11,6 +11,22 @@ module QueryAzureMock @connection = Azure::Connection.new(TEST_PARAMS) end + def lookup_resource_in_test_xml(lookup_name, lookup_pty, tag, in_file) + dataXML = Nokogiri::XML readFile(in_file) + itemsXML = dataXML.css(tag) + not_found = true + retval = '' + itemsXML.each do |itemXML| + if xml_content(itemXML, lookup_pty) == lookup_name + not_found = false + retval = itemXML + break + end + end + retval = Nokogiri::XML readFile('error_404.xml') if not_found + retval + end + def stub_query_azure (connection) @getname = '' @getverb = '' @@ -38,6 +54,9 @@ module QueryAzureMock retval = Nokogiri::XML readFile('list_disks_for_role002.xml') elsif name == 'hostedservices' retval = Nokogiri::XML readFile('list_hosts.xml') + elsif name =~ /hostedservices\/([-\w]*)$/ + service_name = /hostedservices\/([-\w]*)/.match(name)[1] + retval = lookup_resource_in_test_xml(service_name, 'ServiceName', 'HostedServices HostedService', 'list_hosts.xml') elsif name == 'hostedservices/service001/deploymentslots/Production' retval = Nokogiri::XML readFile('list_deployments_for_service001.xml') elsif name == 'hostedservices/service001/deployments/deployment001/roles/role001' @@ -54,19 +73,9 @@ module QueryAzureMock retval = Nokogiri::XML readFile('list_deployments_for_service004.xml') elsif name == 'storageservices' retval = Nokogiri::XML readFile('list_storageaccounts.xml') - elsif name =~ /storageservices\/.*/ - service_name = /storageservices\/(.*)/.match(name)[1] - responseXML = Nokogiri::XML readFile('list_storageaccounts.xml') - servicesXML = responseXML.css('StorageServices StorageService') - not_found = true - servicesXML.each do |serviceXML| - if xml_content(serviceXML, 'ServiceName') == service_name - not_found = false - retval = serviceXML - break - end - end - retval = Nokogiri::XML readFile('error_404.xml') if not_found + elsif name =~ /storageservices\/[-\w]*$/ + service_name = /storageservices\/([-\w]*)/.match(name)[1] + retval = lookup_resource_in_test_xml(service_name, 'ServiceName', 'StorageServices StorageService', 'list_storageaccounts.xml') else Chef::Log.warn 'unknown get value:' + name end From 49ea97e9dab54db92f8a5a5b513f027d3d4bff4e Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Mon, 24 Jun 2013 11:12:30 +0530 Subject: [PATCH 05/12] optimize deployments load. --- lib/azure/deploy.rb | 31 ++++++++++++++++++++++--------- lib/azure/host.rb | 8 ++++++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/lib/azure/deploy.rb b/lib/azure/deploy.rb index 3b4d931..c99d00b 100755 --- a/lib/azure/deploy.rb +++ b/lib/azure/deploy.rb @@ -21,18 +21,31 @@ class Azure def initialize(connection) @connection=connection end - def all - deploys = Array.new - hosts = @connection.hosts.all - hosts.each do |host| - deploy = Deploy.new(@connection) - deploy.retrieve(host.name) - unless deploy.name == nil - deploys << deploy + # force_load should be true when there is something in local cache and we want to reload + # first call is always load. + def load(force_load = false) + if not @deploys || force_load + @deploys = begin + deploys = Array.new + hosts = @connection.hosts.all + hosts.each do |host| + deploy = Deploy.new(@connection) + deploy.retrieve(host.name) + if deploy.name + host.add_deploy(deploy) + deploys << deploy + end + end + deploys end end - deploys + @deploys end + + def all + self.load + end + def find(hostedservicename) deployName = nil self.all.each do |deploy| diff --git a/lib/azure/host.rb b/lib/azure/host.rb index 3bf1db3..fbc214c 100755 --- a/lib/azure/host.rb +++ b/lib/azure/host.rb @@ -80,8 +80,11 @@ class Azure attr_accessor :connection, :name, :url, :label attr_accessor :dateCreated, :description, :location attr_accessor :dateModified, :status + attr_accessor :deploys + def initialize(connection) @connection = connection + @deploys = [] end def parse(serviceXML) @name = xml_content(serviceXML, 'ServiceName') @@ -108,5 +111,10 @@ class Azure def details response = @connection.query_azure('hostedservices/' + @name + '?embed-detail=true') end + + # Deploys within this hostedservice + def add_deploy(deploy) + @deploys << deploy + end end end From 0ede31526c6d86bff97030cbfe1cd9673be23aee Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Mon, 24 Jun 2013 12:38:51 +0530 Subject: [PATCH 06/12] optimize and rename deploy name lookup method --- lib/azure/deploy.rb | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/azure/deploy.rb b/lib/azure/deploy.rb index c99d00b..66e506a 100755 --- a/lib/azure/deploy.rb +++ b/lib/azure/deploy.rb @@ -46,17 +46,20 @@ class Azure self.load end - def find(hostedservicename) - deployName = nil - self.all.each do |deploy| - next unless deploy.hostedservicename == hostedservicename - deployName = deploy.name + # TODO - Current knife-azure plug-in seems to have assumption that single hostedservice + # will always have one deployment (production). see Deploy#retrieve below + def get_deploy_name_for_hostedservice(hostedservicename) + host = @connection.hosts.find(hostedservicename) + if host && host.deploys.length > 0 + host.deploys[0].name + else + nil end - deployName end + def create(params) if params[:azure_connect_to_existing_dns] - unless @connection.hosts.exists(params[:azure_dns_name]) + unless @connection.hosts.exists?(params[:azure_dns_name]) Chef::Log.fatal 'The specified Azure DNS Name does not exist.' exit 1 end @@ -73,7 +76,7 @@ class Azure if params[:identity_file] params[:fingerprint] = @connection.certificates.create(params) end - params['deploy_name'] = find(params[:azure_dns_name]) + params['deploy_name'] = get_deploy_name_for_hostedservice(params[:azure_dns_name]) if params['deploy_name'] != nil role = Role.new(@connection) From b28211fc425133de10df95aee1cbbd7b322e3415 Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Mon, 24 Jun 2013 12:39:14 +0530 Subject: [PATCH 07/12] optimize deploys load within a hosted service. --- lib/azure/host.rb | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/lib/azure/host.rb b/lib/azure/host.rb index fbc214c..0e349d2 100755 --- a/lib/azure/host.rb +++ b/lib/azure/host.rb @@ -61,6 +61,23 @@ class Azure end end + # first look up local cache if we have already loaded list. + def find(name) + return @hosted_services[name] if @hosted_services && @hosted_services.key?(name) + self.fetch_from_cloud(name) + end + + # Look up hosted service on cloud and not local cache + def fetch_from_cloud(name) + ret_val = @connection.query_azure("hostedservices/#{name}") + if ret_val.nil? || ret_val.css('Error Code').length > 0 + Chef::Log.warn 'Unable to find hosted(cloud) service:' + ret_val.at_css('Error Code').content + ' : ' + ret_val.at_css('Error Message').content if ret_val + nil + else + Host.new(@connection).parse(ret_val) + end + end + def create(params) host = Host.new(@connection) host.create(params) @@ -80,11 +97,11 @@ class Azure attr_accessor :connection, :name, :url, :label attr_accessor :dateCreated, :description, :location attr_accessor :dateModified, :status - attr_accessor :deploys def initialize(connection) @connection = connection - @deploys = [] + @deploys_loaded = false + @deploys = Hash.new end def parse(serviceXML) @name = xml_content(serviceXML, 'ServiceName') @@ -112,9 +129,23 @@ class Azure response = @connection.query_azure('hostedservices/' + @name + '?embed-detail=true') end - # Deploys within this hostedservice + # Deployments within this hostedservice def add_deploy(deploy) - @deploys << deploy + @deploys[deploy.name] = deploy + end + + def load_deploys + end + + def deploys + # check if we have deploys loaded, else load. + if (@deploys.length == 0) && !@deploys_loaded + deploy = Deploy.new(@connection) + deploy.retrieve(@name) + @deploys[deploy.name] = deploy + @deploys_loaded = true + end + @deploys.values end end end From bbee423e6fe0a23883a66848e5d6547ee344a6d6 Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Mon, 24 Jun 2013 13:37:34 +0530 Subject: [PATCH 08/12] optimize role lookup within hostedservice --- lib/azure/host.rb | 8 ++++++++ lib/azure/role.rb | 48 ++++++++++++++++++++++------------------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/lib/azure/host.rb b/lib/azure/host.rb index 0e349d2..1d41343 100755 --- a/lib/azure/host.rb +++ b/lib/azure/host.rb @@ -147,5 +147,13 @@ class Azure end @deploys.values end + + def roles + roles = [] + deploys.each do |deploy| + roles.concat(deploy.roles) if deploy.roles + end + roles + end end end diff --git a/lib/azure/role.rb b/lib/azure/role.rb index 131a618..72ed0a4 100755 --- a/lib/azure/role.rb +++ b/lib/azure/role.rb @@ -34,29 +34,35 @@ class Azure @roles end - def find_in_hosted_service(name, hostedservicename) - find_roles_with_hostedservice(hostedservicename).each do | role | - if (role.name == name) - return role - end - end - return nil + def find_roles_within_hostedservice(hostedservicename) + host = @connection.hosts.find(hostedservicename) + (host) ? host.roles : nil # nil says invalid hosted service end - def find(name, params= nil) + def find_in_hosted_service(role_name, hostedservicename) + roles = find_roles_within_hostedservice(hostedservicename) + return nil if roles.nil? + roles.each do | role | + return role if (role.name == role_name) + end + end + + def find(role_name, params= nil) if params && params[:azure_dns_name] - return find_in_hosted_service(name, params[:azure_dns_name]) - end - if @roles == nil - all + return find_in_hosted_service(role_name, params[:azure_dns_name]) end + + all if @roles == nil + + # TODO - optimize this lookup @roles.each do |role| - if(role.name == name) + if(role.name == role_name) return role end end nil end + def alone_on_host(found_role) @roles.each do |role| if (role.name != found_role.name && @@ -94,7 +100,7 @@ class Azure unless params[:preserve_azure_dns_name] unless params[:azure_dns_name].nil? - roles_using_same_service = find_roles_with_hostedservice(params[:azure_dns_name]) + roles_using_same_service = find_roles_within_hostedservice(params[:azure_dns_name]) if roles_using_same_service.size <= 1 servicecall = "hostedservices/" + params[:azure_dns_name] @connection.query_azure(servicecall, "delete") @@ -135,19 +141,9 @@ class Azure end end - def find_roles_with_hostedservice(hostedservicename) - if @roles == nil - all - end - return_roles = Array.new - @roles.each do |role| - if(role.hostedservicename == hostedservicename) - return_roles << role - end - end - return_roles - end + end + class Role include AzureUtility attr_accessor :connection, :name, :status, :size, :ipaddress, :publicipaddress From 7db9ea1a5d37ef99202ff36b5195346581fef985 Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Mon, 24 Jun 2013 15:02:02 +0530 Subject: [PATCH 09/12] update Roles#alone_on_host to use new find methods. --- lib/azure/deploy.rb | 4 ++++ lib/azure/host.rb | 3 ++- lib/azure/role.rb | 19 +++++++++---------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/azure/deploy.rb b/lib/azure/deploy.rb index 66e506a..c967439 100755 --- a/lib/azure/deploy.rb +++ b/lib/azure/deploy.rb @@ -142,5 +142,9 @@ class Azure servicecall = "hostedservices/#{params[:azure_dns_name]}/deployments" @connection.query_azure(servicecall, "post", deployXML.to_xml) end + # just delete from local cache + def delete_role_if_present(role) + @roles.delete_if { |r| r.name == role.name } if @roles + end end end diff --git a/lib/azure/host.rb b/lib/azure/host.rb index 1d41343..5cea80b 100755 --- a/lib/azure/host.rb +++ b/lib/azure/host.rb @@ -134,7 +134,8 @@ class Azure @deploys[deploy.name] = deploy end - def load_deploys + def delete_role(role) + deploys.each { |d| d.delete_role_if_present(role) } end def deploys diff --git a/lib/azure/role.rb b/lib/azure/role.rb index 72ed0a4..c125e9a 100755 --- a/lib/azure/role.rb +++ b/lib/azure/role.rb @@ -63,16 +63,14 @@ class Azure nil end - def alone_on_host(found_role) - @roles.each do |role| - if (role.name != found_role.name && - role.deployname == found_role.deployname && - role.hostedservicename == found_role.hostedservicename) - return false; - end + def alone_on_hostedservice(found_role) + roles = find_roles_within_hostedservice(found_role.hostedservicename) + if roles && roles.length > 1 + return false end - true + return true end + def exists(name) find(name) != nil end @@ -80,7 +78,7 @@ class Azure def delete(name, params) role = find(name) if role != nil - if alone_on_host(role) + if alone_on_hostedservice(role) servicecall = "hostedservices/#{role.hostedservicename}/deployments" + "/#{role.deployname}" else @@ -96,7 +94,8 @@ class Azure @connection.query_azure(servicecall, "delete") # delete role from local cache as well. - @roles.delete(role) + @connection.hosts.find(role.hostedservicename).delete_role(role) + @roles.delete(role) if @roles unless params[:preserve_azure_dns_name] unless params[:azure_dns_name].nil? From 0082192cc37c68e15fa7939cd8ca5c29285a5c20 Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Mon, 24 Jun 2013 15:35:22 +0530 Subject: [PATCH 10/12] hash the roles within deploy --- lib/azure/deploy.rb | 19 +++++++++++++++---- lib/azure/host.rb | 9 +++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/azure/deploy.rb b/lib/azure/deploy.rb index c967439..81d7eb7 100755 --- a/lib/azure/deploy.rb +++ b/lib/azure/deploy.rb @@ -100,7 +100,8 @@ class Azure class Deploy include AzureUtility - attr_accessor :connection, :name, :status, :url, :roles, :hostedservicename + attr_accessor :connection, :name, :status, :url, :hostedservicename + def initialize(connection) @connection = connection end @@ -111,12 +112,12 @@ class Azure @name = xml_content(deployXML, 'Deployment Name') @status = xml_content(deployXML,'Deployment Status') @url = xml_content(deployXML, 'Deployment Url') - @roles = Array.new + @roles = Hash.new rolesXML = deployXML.css('Deployment RoleInstanceList RoleInstance') rolesXML.each do |roleXML| role = Role.new(@connection) role.parse(roleXML, hostedservicename, @name) - @roles << role + @roles[role.name] = role end end end @@ -142,9 +143,19 @@ class Azure servicecall = "hostedservices/#{params[:azure_dns_name]}/deployments" @connection.query_azure(servicecall, "post", deployXML.to_xml) end + + def roles + @roles.values if @roles + end + # just delete from local cache def delete_role_if_present(role) - @roles.delete_if { |r| r.name == role.name } if @roles + @roles.delete(role.name) if @roles end + + def find_role(name) + @roles[name] if @roles + end + end end diff --git a/lib/azure/host.rb b/lib/azure/host.rb index 5cea80b..38e7a90 100755 --- a/lib/azure/host.rb +++ b/lib/azure/host.rb @@ -156,5 +156,14 @@ class Azure end roles end + + def find_role(role_name, deploy_name = nil) + return @deploys[deploy_name].find_role(role_name) if deploy_name && deploys + # else lookup all deploys within hostedservice + deploys.each do |deploy| + role = deploy.find_role(role_name) + return role if role + end + end end end From c3f38198365f78fd454bef453b2938b830b80341 Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Mon, 24 Jun 2013 15:50:45 +0530 Subject: [PATCH 11/12] use hostedservice find_role rather thatn iterating all roles. --- lib/azure/role.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/azure/role.rb b/lib/azure/role.rb index c125e9a..bdc0c2c 100755 --- a/lib/azure/role.rb +++ b/lib/azure/role.rb @@ -24,6 +24,7 @@ class Azure @connection = connection @roles = nil end + # do not use this unless you want a list of all roles(vms) in your subscription def all @roles = Array.new @connection.deploys.all.each do |deploy| @@ -40,11 +41,9 @@ class Azure end def find_in_hosted_service(role_name, hostedservicename) - roles = find_roles_within_hostedservice(hostedservicename) - return nil if roles.nil? - roles.each do | role | - return role if (role.name == role_name) - end + host = @connection.hosts.find(hostedservicename) + return nil if host.nil? + host.find_role(role_name) end def find(role_name, params= nil) From 62a9dd4bc0a7903ffae784f9c9a1a961a92d63de Mon Sep 17 00:00:00 2001 From: kaustubh-d Date: Mon, 24 Jun 2013 16:00:09 +0530 Subject: [PATCH 12/12] Roles #exists return boolean --- lib/azure/role.rb | 2 +- spec/unit/roles_list_spec.rb | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/azure/role.rb b/lib/azure/role.rb index bdc0c2c..d689e71 100755 --- a/lib/azure/role.rb +++ b/lib/azure/role.rb @@ -70,7 +70,7 @@ class Azure return true end - def exists(name) + def exists?(name) find(name) != nil end diff --git a/spec/unit/roles_list_spec.rb b/spec/unit/roles_list_spec.rb index 8dbfa4e..82e702b 100755 --- a/spec/unit/roles_list_spec.rb +++ b/spec/unit/roles_list_spec.rb @@ -14,11 +14,11 @@ describe "roles" do end roles.length.should == 7 end - specify {@connection.roles.exists('vm01').should == true} - specify {@connection.roles.exists('vm002').should == true} - specify {@connection.roles.exists('role001').should == true} - specify {@connection.roles.exists('role002').should == true} - specify {@connection.roles.exists('role002qqqqq').should == false} + specify {@connection.roles.exists?('vm01').should == true} + specify {@connection.roles.exists?('vm002').should == true} + specify {@connection.roles.exists?('role001').should == true} + specify {@connection.roles.exists?('role002').should == true} + specify {@connection.roles.exists?('role002qqqqq').should == false} it 'each role should have values' do role = @connection.roles.find('vm01')