1. RDFE Endpoint for SQL Servers
2. Storage Management: 2.1 Added get_storage_account API 2.2 Added update_storage_account API 3. Virtual Machine Management: Implemented Add Role API 4. Extended existing Cloud Services APIs to read all the parameters 5. Added/Modified related test cases
This commit is contained in:
Родитель
2a35598806
Коммит
04a1e4ad2b
|
@ -108,6 +108,10 @@ There are two ways you can set up the connections:
|
|||
config.management_certificate = "<path to your *.pem or *.pfx>"
|
||||
config.subscription_id = "<your Subscriptionid>"
|
||||
config.management_endpoint = "https://management.core.windows.net"
|
||||
# This property enables/disables SQL API RDFE endpoint. By default RDFE is enabled. RDFE will also be enabled if you do not set this property
|
||||
config.disable_sql_rdfe = true
|
||||
# Configure the non-RDFE SQL API endpoint here
|
||||
config.sql_management_endpoint = "http://management.database.windows.net:8443"
|
||||
end
|
||||
```
|
||||
* Against local Emulator (Windows Only)
|
||||
|
@ -146,7 +150,8 @@ There are two ways you can set up the connections:
|
|||
AZURE_MANAGEMENT_CERTIFICATE = <path to *.pem or *.pfx>
|
||||
AZURE_SUBSCRIPTION_ID = <your subscription ID>
|
||||
AZURE_MANAGEMENT_ENDPOINT = <The endpoint URL of Windows Azure management service>
|
||||
|
||||
AZURE_SQL_MANAGEMENT_ENDPOINT = <Non-RDFE SQL Management Endpoint>
|
||||
AZURE_DISABLE_SQL_RDFE = <true_or_false>
|
||||
```
|
||||
* Against local Emulator (Windows Only)
|
||||
* Storage
|
||||
|
|
14
Rakefile
14
Rakefile
|
@ -89,16 +89,17 @@ namespace :test do
|
|||
task component => "test:require_environment"
|
||||
end
|
||||
|
||||
component_task :blob
|
||||
component_task :queue
|
||||
component_task :table
|
||||
component_task :service_bus
|
||||
component_task :database
|
||||
component_task :affinity_group
|
||||
component_task :blob
|
||||
component_task :database
|
||||
component_task :location
|
||||
component_task :vnet
|
||||
component_task :queue
|
||||
component_task :service_bus
|
||||
component_task :storage_management
|
||||
component_task :table
|
||||
component_task :vm
|
||||
component_task :vm_image
|
||||
component_task :vnet
|
||||
end
|
||||
|
||||
task :cleanup => :require_environment do
|
||||
|
@ -117,6 +118,7 @@ namespace :test do
|
|||
# config.sb_issuer = ENV.fetch("AZURE_SERVICEBUS_ISSUER")
|
||||
config.management_certificate = ENV.fetch('AZURE_MANAGEMENT_CERTIFICATE')
|
||||
config.management_endpoint = ENV.fetch("AZURE_MANAGEMENT_ENDPOINT")
|
||||
config.sql_management_endpoint = ENV.fetch("AZURE_SQL_MANAGEMENT_ENDPOINT")
|
||||
config.subscription_id = ENV.fetch("AZURE_SUBSCRIPTION_ID")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,6 +28,7 @@ require 'azure/table/batch'
|
|||
require 'azure/table/query'
|
||||
require 'azure/core/utility'
|
||||
require 'azure/base_management/management_http_request'
|
||||
require 'azure/base_management/sql_management_http_request'
|
||||
require 'azure/base_management/base_management_service'
|
||||
require 'azure/virtual_machine_image_management/virtual_machine_image_management_service'
|
||||
require 'azure/virtual_machine_management/virtual_machine_management_service'
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#-------------------------------------------------------------------------
|
||||
# Copyright 2013 Microsoft Open Technologies, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#--------------------------------------------------------------------------
|
||||
# Represents an HTTP request that can perform synchronous queries to
|
||||
# an HTTP server, returning a HttpResponse
|
||||
module Azure
|
||||
module BaseManagement
|
||||
# This class is used for communicating with the non-RDFE SQL API endpoint
|
||||
class SqlManagementHttpRequest < ManagementHttpRequest
|
||||
attr_accessor :uri
|
||||
# Public: Creates the ManagementHttpRequest
|
||||
#
|
||||
# method - Symbol. The HTTP method to use (:get, :post, :put, :del, etc...)
|
||||
# path - URI. The URI of the HTTP endpoint to query
|
||||
# body - IO or String. The request body (optional)
|
||||
# key - String. The request key
|
||||
# cert - String. The request certificate
|
||||
def initialize(method, path, body=nil)
|
||||
super(method, path, body)
|
||||
@uri = URI.parse(Azure.config.sql_management_endpoint + Azure.config.subscription_id + path)
|
||||
@key = Azure.config.http_private_key
|
||||
@cert = Azure.config.http_certificate_key
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -21,11 +21,18 @@ module Azure
|
|||
yield self if block_given?
|
||||
end
|
||||
|
||||
attr_accessor :url
|
||||
attr_accessor :name
|
||||
attr_accessor :label
|
||||
attr_accessor :description
|
||||
attr_accessor :location
|
||||
attr_accessor :affinity_group
|
||||
attr_accessor :status
|
||||
attr_accessor :date_created
|
||||
attr_accessor :date_modified
|
||||
attr_accessor :extended_properties
|
||||
attr_accessor :default_winrm_certificate_thumbprint
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,13 +32,22 @@ module Azure
|
|||
# ==== Options
|
||||
#
|
||||
# Accepted key/value pairs in options parameter are:
|
||||
# * +:location+ - String. The regional data center location where the cloud service will be created.(optional)
|
||||
# * +:label+ -String. The label for this cloud service.
|
||||
# * +:description+ - String. A description for the hosted service. (optional)
|
||||
# * +:location+ - String. The regional data center location where the
|
||||
# cloud service will be created. Required if affinity group not
|
||||
# specified (optional)
|
||||
# * +:affinity_group_name - String. Name of the affinity group with
|
||||
# which to assocate the cloud service. Required if location not
|
||||
# specified (optional)
|
||||
# * +:extended_properties+ - Hash. Key/Value pairs of extended
|
||||
# properties to add to the cloud service. The key is used as the
|
||||
# property name and the value as its value. (optional)
|
||||
#
|
||||
# See http://msdn.microsoft.com/en-us/library/windowsazure/gg441304.aspx
|
||||
#
|
||||
# Returns None
|
||||
def create_cloud_service(name, options={})
|
||||
def create_cloud_service(name, options = {})
|
||||
Loggerx.error_with_exit "Cloud service name is not valid " unless name
|
||||
if get_cloud_service(name)
|
||||
Loggerx.warn "Cloud service #{name} already exists. Skipped..."
|
||||
|
|
|
@ -18,30 +18,68 @@ require 'azure/cloud_service_management/cloud_service'
|
|||
module Azure
|
||||
module CloudServiceManagement
|
||||
module Serialization
|
||||
def self.cloud_services_to_xml(name, options = {})
|
||||
options[:label] = options[:label] || name
|
||||
|
||||
def self.cloud_services_to_xml(name, options={})
|
||||
builder = Nokogiri::XML::Builder.new do |xml|
|
||||
xml.CreateHostedService('xmlns'=>'http://schemas.microsoft.com/windowsazure') {
|
||||
xml.ServiceName name
|
||||
xml.Label Base64.encode64(name)
|
||||
xml.Description options[:description] || 'Explicitly created cloud service'
|
||||
if !options[:affinity_group_name].nil?
|
||||
xml.AffinityGroup options[:affinity_group_name]
|
||||
xml.CreateHostedService(
|
||||
'xmlns' => 'http://schemas.microsoft.com/windowsazure'
|
||||
) do
|
||||
xml.ServiceName(name)
|
||||
xml.Label(Base64.encode64(options[:label]))
|
||||
xml.Description(options[:description]) unless\
|
||||
options[:description].nil? || options[:description].empty?
|
||||
|
||||
unless options[:affinity_group_name].nil?
|
||||
xml.AffinityGroup(options[:affinity_group_name])
|
||||
else
|
||||
xml.Location options[:location]
|
||||
xml.Location(options[:location])
|
||||
end
|
||||
}
|
||||
|
||||
xml.ExtendedProperties do
|
||||
options[:extended_properties].each do |prop_name, prop_value|
|
||||
xml.ExtendedProperty do
|
||||
xml.Name(prop_name)
|
||||
xml.Value(prop_value)
|
||||
end unless (prop_name.nil? || prop_name.empty?)\
|
||||
|| (prop_value.nil? || prop_value.empty?)
|
||||
end
|
||||
end unless options[:extended_properties].nil?\
|
||||
|| options[:extended_properties].empty?
|
||||
end
|
||||
end
|
||||
builder.doc.to_xml
|
||||
end
|
||||
|
||||
def self.cloud_services_from_xml(cloudXML)
|
||||
|
||||
def self.cloud_services_from_xml(cloud_xml)
|
||||
clouds = []
|
||||
cloud_services_xml = cloudXML.css('HostedServices HostedService')
|
||||
cloud_services_xml = cloud_xml.css('HostedServices HostedService')
|
||||
cloud_services_xml.each do |cloud_service_xml|
|
||||
cloud = CloudService.new
|
||||
cloud.url = xml_content(cloud_service_xml, 'Url')
|
||||
cloud.name = xml_content(cloud_service_xml, 'ServiceName')
|
||||
cloud.affinity_group = xml_content(cloud_service_xml, 'HostedServiceProperties AffinityGroup')
|
||||
|
||||
props_xml = cloud_service_xml.css('HostedServiceProperties')
|
||||
|
||||
cloud.label = Base64.decode64(xml_content(props_xml, 'Label'))
|
||||
cloud.description = xml_content(props_xml, 'Description')
|
||||
cloud.location = xml_content(props_xml, 'Location')
|
||||
cloud.affinity_group = xml_content(props_xml, 'AffinityGroup')
|
||||
cloud.status = xml_content(props_xml, 'Status')
|
||||
cloud.date_created = xml_content(props_xml, 'DateCreated')
|
||||
cloud.date_modified = xml_content(props_xml, 'DateLastModified')
|
||||
|
||||
cloud.extended_properties = {}
|
||||
props_xml.css('ExtendedProperties ExtendedProperty').map do |prop|
|
||||
p_name = xml_content(prop, 'Name')
|
||||
p_value = xml_content(prop, 'Value')
|
||||
cloud.extended_properties[p_name] = p_value
|
||||
end
|
||||
|
||||
cloud.default_winrm_certificate_thumbprint = xml_content(
|
||||
cloud_service_xml, 'DefaultWinRMCertificateThumbprint'
|
||||
)
|
||||
|
||||
clouds << cloud
|
||||
end
|
||||
clouds.compact
|
||||
|
|
|
@ -18,7 +18,8 @@ module Azure::Core; end
|
|||
require "azure/core/error"
|
||||
require "azure/core/configuration"
|
||||
|
||||
# load default configuration from environment variables (user can always override this later)
|
||||
# load default configuration from environment variables
|
||||
# (user can always override this later)
|
||||
Azure.configure do |config|
|
||||
config.storage_access_key = ENV["AZURE_STORAGE_ACCESS_KEY"]
|
||||
config.storage_account_name = ENV["AZURE_STORAGE_ACCOUNT"]
|
||||
|
@ -33,4 +34,7 @@ Azure.configure do |config|
|
|||
config.management_certificate = ENV["AZURE_MANAGEMENT_CERTIFICATE"]
|
||||
config.subscription_id = ENV["AZURE_SUBSCRIPTION_ID"]
|
||||
config.management_endpoint = ENV["AZURE_MANAGEMENT_ENDPOINT"]
|
||||
end
|
||||
config.sql_management_endpoint = ENV["AZURE_SQL_MANAGEMENT_ENDPOINT"]
|
||||
|
||||
config.disable_sql_rdfe = ENV['AZURE_DISABLE_SQL_RDFE'] || 'false'
|
||||
end
|
||||
|
|
|
@ -167,6 +167,9 @@ module Azure
|
|||
#Public: Set the certificate key for SSL/HTTPS request with PEM certificate
|
||||
attr_accessor :http_certificate_key
|
||||
|
||||
# Public: Set the host for SQL Management API (non-RDFE SQL Endpoint)
|
||||
attr_accessor :sql_management_endpoint
|
||||
|
||||
def management_endpoint
|
||||
if @management_endpoint.nil? or @management_endpoint.empty?
|
||||
"https://management.core.windows.net/"
|
||||
|
@ -179,6 +182,25 @@ module Azure
|
|||
end
|
||||
end
|
||||
|
||||
def sql_management_endpoint
|
||||
if @sql_management_endpoint.nil? or @sql_management_endpoint.empty?
|
||||
"https://management.database.windows.net:8443/"
|
||||
elsif !@sql_management_endpoint.end_with?('/')
|
||||
@sql_management_endpoint += '/'
|
||||
elsif URI(@sql_management_endpoint).scheme.nil?
|
||||
"https://#{@sql_management_endpoint}"
|
||||
else
|
||||
@management_endpoint
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Set this true to use non-RDFE SQL API Endpoint
|
||||
attr_accessor :disable_sql_rdfe
|
||||
|
||||
def disable_sql_rdfe
|
||||
return false if @disable_sql_rdfe.nil? or @disable_sql_rdfe.empty?
|
||||
@disable_sql_rdfe.downcase == 'true'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -61,6 +61,9 @@ module Azure
|
|||
end
|
||||
|
||||
def self.firewall_rule_to_xml(options)
|
||||
# Need to revisit and implement RDFE request XML.
|
||||
# Currently Azure is throwing Internal Server Error when executing the
|
||||
# API
|
||||
builder = Nokogiri::XML::Builder.new do |xml|
|
||||
xml.FirewallRule('xmlns'=>'http://schemas.microsoft.com/sqlazure/2010/12/',
|
||||
'xmlns:xsi'=>'http://www.w3.org/2001/XMLSchema-instance',
|
||||
|
@ -74,13 +77,31 @@ module Azure
|
|||
|
||||
def self.database_firewall_from_xml(response_xml)
|
||||
firewalls = []
|
||||
database_firewallXML = response_xml.css('FirewallRules FirewallRule')
|
||||
database_firewallXML.each do |firewall_xml|
|
||||
firewall = { :rule => xml_content(firewall_xml, 'Name'),
|
||||
:start_ip_address => xml_content(firewall_xml, 'StartIpAddress'),
|
||||
:end_ip_address => xml_content(firewall_xml, 'EndIpAddress')
|
||||
}
|
||||
firewalls << firewall
|
||||
if Azure.config.disable_sql_rdfe
|
||||
database_firewallXML = response_xml.css('FirewallRules FirewallRule')
|
||||
database_firewallXML.each do |firewall_xml|
|
||||
firewall = {
|
||||
:rule => xml_content(firewall_xml, 'Name'),
|
||||
:start_ip_address => xml_content(firewall_xml, 'StartIpAddress'),
|
||||
:end_ip_address => xml_content(firewall_xml, 'EndIpAddress')
|
||||
}
|
||||
firewalls << firewall
|
||||
end
|
||||
else
|
||||
service_resources = response_xml.css(
|
||||
'ServiceResources ServiceResource'
|
||||
)
|
||||
service_resources.each do |resource|
|
||||
type = xml_content(resource, 'Type')
|
||||
if type == 'Microsoft.SqlAzure.FirewallRule'
|
||||
firewall = {
|
||||
rule: xml_content(resource, 'Name'),
|
||||
start_ip_address: xml_content(resource, 'StartIPAddress'),
|
||||
end_ip_address: xml_content(resource, 'EndIPAddress')
|
||||
}
|
||||
firewalls << firewall
|
||||
end
|
||||
end
|
||||
end
|
||||
firewalls.compact
|
||||
end
|
||||
|
|
|
@ -31,8 +31,15 @@ module Azure
|
|||
# Returns an array of Azure::SqlDatabaseManagement::SqlDatabase objects
|
||||
def list_servers
|
||||
request_path = "/servers"
|
||||
request = ManagementHttpRequest.new(:get, request_path, nil)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
|
||||
if Azure.config.disable_sql_rdfe
|
||||
request = SqlManagementHttpRequest.new(:get, request_path, nil)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
else
|
||||
request_path = "/services/sqlservers#{request_path}"
|
||||
request = ManagementHttpRequest.new(:get, request_path, nil)
|
||||
end
|
||||
|
||||
response = request.call
|
||||
Serialization.databases_from_xml(response)
|
||||
end
|
||||
|
@ -51,8 +58,15 @@ module Azure
|
|||
def create_server(login, password, location)
|
||||
body = Serialization.database_to_xml(login, password, location)
|
||||
request_path = "/servers"
|
||||
request = ManagementHttpRequest.new(:post, request_path, body)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
|
||||
if Azure.config.disable_sql_rdfe
|
||||
request = SqlManagementHttpRequest.new(:post, request_path, body)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
else
|
||||
request_path = "/services/sqlservers#{request_path}"
|
||||
request = ManagementHttpRequest.new(:post, request_path, body)
|
||||
end
|
||||
|
||||
response = request.call
|
||||
sql_server = Serialization.server_name_from_xml(response, login, location)
|
||||
Loggerx.info "SQL database server #{sql_server.name} is created." if sql_server
|
||||
|
@ -72,8 +86,15 @@ module Azure
|
|||
def delete_server(name)
|
||||
if get_sql_server(name)
|
||||
request_path = "/servers/#{name}"
|
||||
request = ManagementHttpRequest.new(:delete, request_path)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
|
||||
if Azure.config.disable_sql_rdfe
|
||||
request = SqlManagementHttpRequest.new(:delete, request_path)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
else
|
||||
request_path = "/services/sqlservers#{request_path}"
|
||||
request = ManagementHttpRequest.new(:delete, request_path)
|
||||
end
|
||||
|
||||
request.call
|
||||
Loggerx.info "Deleted database server #{name}."
|
||||
end
|
||||
|
@ -94,8 +115,15 @@ module Azure
|
|||
if get_sql_server(name)
|
||||
request_path = "/servers/#{name}?op=ResetPassword"
|
||||
body = Serialization.reset_password_to_xml(password)
|
||||
request = ManagementHttpRequest.new(:post, request_path, body)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
|
||||
if Azure.config.disable_sql_rdfe
|
||||
request = SqlManagementHttpRequest.new(:post, request_path, body)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
else
|
||||
request_path = "/services/sqlservers#{request_path}"
|
||||
request = ManagementHttpRequest.new(:post, request_path, body)
|
||||
end
|
||||
|
||||
request.call
|
||||
Loggerx.info "Password for server #{name} changed successfully."
|
||||
end
|
||||
|
@ -132,8 +160,12 @@ module Azure
|
|||
request_path = "/servers/#{server_name}/firewallrules/#{rule_name}?op=AutoDetectClientIP"
|
||||
method = :post
|
||||
end
|
||||
request = ManagementHttpRequest.new(method, request_path, body)
|
||||
request = SqlManagementHttpRequest.new(method, request_path, body)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
|
||||
# RDFE Endpoint throws errors for this operation. Need to re-visit
|
||||
# this once the Azure API is working.
|
||||
|
||||
request.call
|
||||
Loggerx.info "Added server-level firewall rule #{rule_name}."
|
||||
end
|
||||
|
@ -152,8 +184,15 @@ module Azure
|
|||
def list_sql_server_firewall_rules(server_name)
|
||||
if get_sql_server(server_name)
|
||||
request_path = "/servers/#{server_name}/firewallrules"
|
||||
request = ManagementHttpRequest.new(:get, request_path)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
|
||||
if Azure.config.disable_sql_rdfe
|
||||
request = SqlManagementHttpRequest.new(:get, request_path)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
else
|
||||
request_path = "/services/sqlservers#{request_path}"
|
||||
request = ManagementHttpRequest.new(:get, request_path)
|
||||
end
|
||||
|
||||
response = request.call
|
||||
Serialization.database_firewall_from_xml(response)
|
||||
end
|
||||
|
@ -175,8 +214,15 @@ module Azure
|
|||
raise error
|
||||
elsif get_sql_server(server_name)
|
||||
request_path = "/servers/#{server_name}/firewallrules/#{rule_name}"
|
||||
request = ManagementHttpRequest.new(:delete, request_path)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
|
||||
if Azure.config.disable_sql_rdfe
|
||||
request = SqlManagementHttpRequest.new(:delete, request_path)
|
||||
request.headers["x-ms-version"] = @x_ms_version
|
||||
else
|
||||
request_path = "/services/sqlservers#{request_path}"
|
||||
request = ManagementHttpRequest.new(:delete, request_path)
|
||||
end
|
||||
|
||||
request.call
|
||||
Loggerx.info "Deleted server-level firewall rule #{rule_name}."
|
||||
end
|
||||
|
|
|
@ -17,34 +17,174 @@ require 'azure/storage_management/storage_account'
|
|||
|
||||
module Azure
|
||||
module StorageManagement
|
||||
# Storage management serialization module is responsible for converting
|
||||
# the objects to XML and vice versa.
|
||||
module Serialization
|
||||
def self.storage_services_to_xml(name, options={})
|
||||
def self.storage_services_to_xml(name, options = {})
|
||||
builder = Nokogiri::XML::Builder.new do |xml|
|
||||
xml.CreateStorageServiceInput('xmlns'=>'http://schemas.microsoft.com/windowsazure') {
|
||||
xml.ServiceName name
|
||||
xml.Label Base64.encode64(name)
|
||||
xml.Description options[:description] || 'Explicitly created storage service'
|
||||
if !options[:affinity_group_name].nil?
|
||||
xml.CreateStorageServiceInput(
|
||||
'xmlns' => 'http://schemas.microsoft.com/windowsazure'
|
||||
) do
|
||||
xml.ServiceName(name)
|
||||
label = options[:label] || name
|
||||
xml.Label(Base64.encode64(label))
|
||||
xml.Description options[:description]\
|
||||
|| 'Explicitly created storage service'
|
||||
unless options[:affinity_group_name].nil?
|
||||
xml.AffinityGroup options[:affinity_group_name]
|
||||
else
|
||||
xml.Location options[:location]
|
||||
end
|
||||
}
|
||||
add_options_to_xml(xml, options)
|
||||
end
|
||||
end
|
||||
builder.doc.to_xml
|
||||
end
|
||||
|
||||
def self.storage_services_from_xml(storageXML)
|
||||
|
||||
def self.storage_services_from_xml(storage_xml)
|
||||
storage_accounts = []
|
||||
storage_servicesXML = storageXML.css('StorageServices StorageService')
|
||||
storage_servicesXML.each do |storage_service_xml|
|
||||
storage_services_xml = storage_xml.css('StorageService')
|
||||
storage_services_xml.each do |storage_service_xml|
|
||||
storage_account = StorageAccount.new
|
||||
storage_account.name = xml_content(storage_service_xml, 'ServiceName')
|
||||
|
||||
storage_account.url = xml_content(storage_service_xml, 'Url')
|
||||
storage_account.name = xml_content(
|
||||
storage_service_xml, 'ServiceName'
|
||||
)
|
||||
|
||||
storage_service_properties = storage_service_xml.css(
|
||||
'StorageServiceProperties'
|
||||
)
|
||||
|
||||
storage_account.description = xml_content(
|
||||
storage_service_properties, 'Description'
|
||||
)
|
||||
storage_account.affinity_group = xml_content(
|
||||
storage_service_properties, 'AffinityGroup'
|
||||
)
|
||||
storage_account.location = xml_content(
|
||||
storage_service_properties, 'Location'
|
||||
)
|
||||
storage_account.label = Base64.decode64(
|
||||
xml_content(storage_service_properties, 'Label')
|
||||
)
|
||||
storage_account.status = xml_content(
|
||||
storage_service_properties, 'Status'
|
||||
)
|
||||
storage_account.endpoints = storage_service_properties.css(
|
||||
'Endpoints Endpoint'
|
||||
).map { |endpoint| endpoint.content }
|
||||
storage_account.geo_replication_enabled = xml_content(
|
||||
storage_service_properties, 'GeoReplicationEnabled'
|
||||
)
|
||||
storage_account.geo_primary_region = xml_content(
|
||||
storage_service_properties, 'GeoPrimaryRegion'
|
||||
)
|
||||
storage_account.status_of_primary = xml_content(
|
||||
storage_service_properties, 'StatusOfPrimary'
|
||||
)
|
||||
storage_account.last_geo_failover_time = xml_content(
|
||||
storage_service_properties, 'LastGeoFailoverTime'
|
||||
)
|
||||
storage_account.geo_secondary_region = xml_content(
|
||||
storage_service_properties, 'GeoSecondaryRegion'
|
||||
)
|
||||
storage_account.status_of_secondary = xml_content(
|
||||
storage_service_properties, 'StatusOfSecondary'
|
||||
)
|
||||
storage_account.creation_time = xml_content(
|
||||
storage_service_properties, 'CreationTime'
|
||||
)
|
||||
storage_account.extended_properties = storage_service_xml.css(
|
||||
'ExtendedProperties ExtendedProperty'
|
||||
).map do |prop|
|
||||
{
|
||||
name: xml_content(prop, 'Name'),
|
||||
value: xml_content(prop, 'Value')
|
||||
}
|
||||
end
|
||||
|
||||
storage_accounts << storage_account
|
||||
end
|
||||
|
||||
# returns the first storage account if only one found
|
||||
# This will be the case when calling the get_storage_account_properties
|
||||
# API or if only one storage account exists for the subscription
|
||||
return storage_accounts.first if storage_accounts.size == 1
|
||||
|
||||
# returns all the storage accounts, if more than 1 found
|
||||
storage_accounts.compact
|
||||
end
|
||||
|
||||
def self.storage_update_to_xml(options)
|
||||
# Cannot update if options is nil or empty
|
||||
fail 'No options specified' if options.nil? || options.empty?
|
||||
|
||||
# Either one of Label, or Description is required.
|
||||
if (options[:label].nil? || options[:label].empty?) &&
|
||||
(options[:description].nil? || options[:description].empty?)
|
||||
fail 'Either one of Label or Description'\
|
||||
' has to be provided. Both cannot be empty'
|
||||
end
|
||||
|
||||
# The input param may not be nil or empty, but the values inside may
|
||||
# be. Check if atleast one value exists before proceeding.
|
||||
is_empty = true
|
||||
options.each do |option, value|
|
||||
case option
|
||||
when :description, :label
|
||||
is_empty = value.nil? || value.empty?
|
||||
when :geo_replication_enabled
|
||||
is_empty = !(value.kind_of?(TrueClass)\
|
||||
|| value.kind_of?(FalseClass))
|
||||
when :extended_properties
|
||||
value.each do |p, v|
|
||||
is_empty = ((p.nil? || p.empty?) || (v.nil? || v.empty?))
|
||||
break unless is_empty
|
||||
end
|
||||
end
|
||||
|
||||
break unless is_empty
|
||||
end
|
||||
|
||||
# Raise a RuntimeError if no options were provided
|
||||
fail 'No Options Specified' if is_empty
|
||||
|
||||
builder = Nokogiri::XML::Builder.new do |xml|
|
||||
xml.UpdateStorageServiceInput(
|
||||
'xmlns' => 'http://schemas.microsoft.com/windowsazure'
|
||||
) do
|
||||
# Check if label is nil. Use description only if label is nil
|
||||
if options[:label].nil? || options[:label].empty?
|
||||
desc = options[:description]
|
||||
xml.Description(desc) unless desc.nil? || desc.empty?
|
||||
else
|
||||
label = Base64.encode64(options[:label])
|
||||
xml.Label(label) unless label.nil? || label.empty?
|
||||
end
|
||||
add_options_to_xml(xml, options)
|
||||
end
|
||||
end
|
||||
builder.to_xml
|
||||
end
|
||||
|
||||
def self.add_options_to_xml(xml, options = {})
|
||||
gre = options[:geo_replication_enabled]
|
||||
xml.GeoReplicationEnabled(
|
||||
gre
|
||||
) unless gre.nil?\
|
||||
|| !(gre.kind_of?(TrueClass) || gre.kind_of?(FalseClass))
|
||||
xml.ExtendedProperties do
|
||||
options[:extended_properties].each do |name, value|
|
||||
xml.ExtendedProperty do
|
||||
xml.Name name
|
||||
xml.Value value
|
||||
end unless (name.nil? || name.empty?)\
|
||||
|| (value.nil? || value.empty?)
|
||||
end
|
||||
end unless options[:extended_properties].nil?\
|
||||
|| options[:extended_properties].empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,16 +14,27 @@
|
|||
#--------------------------------------------------------------------------
|
||||
module Azure
|
||||
module StorageManagement
|
||||
# Represents a Windows Azure storage account
|
||||
class StorageAccount
|
||||
|
||||
def initialize
|
||||
yield self if block_given?
|
||||
end
|
||||
|
||||
attr_accessor :url
|
||||
attr_accessor :name
|
||||
attr_accessor :description
|
||||
attr_accessor :location
|
||||
|
||||
attr_accessor :affinity_group
|
||||
attr_accessor :label
|
||||
attr_accessor :status
|
||||
attr_accessor :endpoints
|
||||
attr_accessor :geo_replication_enabled
|
||||
attr_accessor :geo_primary_region
|
||||
attr_accessor :status_of_primary
|
||||
attr_accessor :last_geo_failover_time
|
||||
attr_accessor :geo_secondary_region
|
||||
attr_accessor :status_of_secondary
|
||||
attr_accessor :creation_time
|
||||
attr_accessor :extended_properties
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,17 +16,17 @@ require 'azure/storage_management/serialization'
|
|||
|
||||
module Azure
|
||||
module StorageManagement
|
||||
# Provides Storage Management API
|
||||
class StorageManagementService < BaseManagementService
|
||||
|
||||
def initialize
|
||||
super()
|
||||
end
|
||||
|
||||
# Public: Gets a list of storage accounts available under the current subscription.
|
||||
# Public: Gets a list of storage accounts available under the
|
||||
# current subscription.
|
||||
#
|
||||
# Returns an array of Azure::StorageManagement::StorageAccount objects
|
||||
def list_storage_accounts
|
||||
request_path = "/services/storageservices"
|
||||
request_path = '/services/storageservices'
|
||||
request = ManagementHttpRequest.new(:get, request_path, nil)
|
||||
response = request.call
|
||||
Serialization.storage_services_from_xml(response)
|
||||
|
@ -39,11 +39,12 @@ module Azure
|
|||
# * +name+ - String. Storage account name.
|
||||
#
|
||||
# Returns: A boolean value indicating whether the storage account exists.
|
||||
# If true, the storage account exists. If false, the storage account does not exist.
|
||||
# If true, the storage account exists. If false, the storage account
|
||||
# does not exist.
|
||||
def get_storage_account(name)
|
||||
return false if name.nil?
|
||||
flag = false
|
||||
storage_accounts = Azure::StorageManagementService.new.list_storage_accounts
|
||||
storage_accounts = list_storage_accounts
|
||||
storage_accounts.each do |storage|
|
||||
if storage.name == name
|
||||
flag = true
|
||||
|
@ -53,6 +54,22 @@ module Azure
|
|||
flag
|
||||
end
|
||||
|
||||
# Public: Gets the properties of the storage account specified.
|
||||
#
|
||||
# ==== Attributes
|
||||
#
|
||||
# * +name+ - String. The name of the storage account. Required.
|
||||
#
|
||||
# See http://msdn.microsoft.com/en-us/library/windowsazure/ee460802.aspx
|
||||
#
|
||||
# Returns the storage account
|
||||
def get_storage_account_properties(name)
|
||||
request_path = "/services/storageservices/#{name}"
|
||||
request = ManagementHttpRequest.new(:get, request_path, nil)
|
||||
response = request.call
|
||||
Serialization.storage_services_from_xml(response)
|
||||
end
|
||||
|
||||
# Public: Create a new storage account in Windows Azure.
|
||||
#
|
||||
# ==== Attributes
|
||||
|
@ -63,23 +80,73 @@ module Azure
|
|||
# ==== Options
|
||||
#
|
||||
# Accepted key/value pairs in options parameter are:
|
||||
# * +:location+ - String. The location where the storage service will be created.(optional)
|
||||
# * +:description+ - String. A description for the storage service. (optional)
|
||||
# * +:label+ - String. The label for this storage account. The name will
|
||||
# be used as label if none specified. (optional)
|
||||
# * +:location+ - String. The location where the storage
|
||||
# service will be created. Reqruied if no affinity_group_name specified.
|
||||
# * +:description+ - String. A description for the storage
|
||||
# service. (optional)
|
||||
# * +:affinity_group_name+ - String. The name of an existing affinity group
|
||||
# in the specified subscription. Required if no location specified.
|
||||
# * +:geo_replication_enabled+ - String. A flag indicating wheter to
|
||||
# turn Geo replication on or off. Values other than 'true'/'false'
|
||||
# will result in an error from the REST API. (optional)
|
||||
# * +:extended_properties+ - Hash. Key/Value pairs of extended
|
||||
# properties to add to the storage account. The key is used as the
|
||||
# property name and the value as its value. (optional)
|
||||
#
|
||||
# Returns None
|
||||
def create_storage_account(name, options={})
|
||||
def create_storage_account(name, options = {})
|
||||
raise 'Name not specified' if !name || name.class != String || name.empty?
|
||||
if get_storage_account(name)
|
||||
Loggerx.warn "Storage Account #{name} already exists. Skipped..."
|
||||
else
|
||||
Loggerx.info "Creating Storage Account #{name}."
|
||||
body = Serialization.storage_services_to_xml(name, options)
|
||||
request_path = "/services/storageservices"
|
||||
request_path = '/services/storageservices'
|
||||
request = ManagementHttpRequest.new(:post, request_path, body)
|
||||
request.call
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Deletes the specified storage account of given subscription id from Windows Azure.
|
||||
# Public: Updates an existing storage account in Windows Azure
|
||||
#
|
||||
# ==== Attributes
|
||||
#
|
||||
# * +name+ - String. The name of the storage service.
|
||||
# * +options+ - Hash. Optional parameters.
|
||||
#
|
||||
# ==== Options
|
||||
#
|
||||
# Accepted key/value pairs in options parameter are:
|
||||
# * +:label+ - String. A label for the storage service. Required if no
|
||||
# description is provided. If both label and description are
|
||||
# provided, only the label will get updated.
|
||||
# * +:description+ - String. A description for the storage service.
|
||||
# Required if no label is provided. If both label and description are
|
||||
# provided, only the label will get updated.
|
||||
# * +:geo_replication_enabled+ - Boolean (TrueClass/FalseClass). Boolean
|
||||
# flag indicating wheter to turn Geo replication on or off. (optional)
|
||||
# * +:extended_properties+ - Hash. Key/Value pairs of extended
|
||||
# properties to add to the storage account. The key is used as the
|
||||
# property name and the value as its value. (optional)
|
||||
#
|
||||
# Returns None
|
||||
# Fails with RuntimeError if invalid options specified
|
||||
def update_storage_account(name, options = {})
|
||||
if get_storage_account name
|
||||
Loggerx.info "Account '#{name}' exists, updating..."
|
||||
body = Serialization.storage_update_to_xml options
|
||||
request_path = "/services/storageservices/#{name}"
|
||||
request = ManagementHttpRequest.new(:put, request_path, body)
|
||||
request.call
|
||||
else
|
||||
Loggerx.warn "Storage Account '#{name}' does not exist. Skipped..."
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Deletes the specified storage account of given subscription id
|
||||
# from Windows Azure.
|
||||
#
|
||||
# ==== Attributes
|
||||
#
|
||||
|
|
|
@ -71,7 +71,8 @@ module Azure
|
|||
# ==== Attributes
|
||||
#
|
||||
# * +params+ - Hash. parameters.
|
||||
# * +Options+ - Hash. Optional parameters.
|
||||
# * +options+ - Hash. Optional parameters.
|
||||
# * +add_role+ - true/false. Optional Parameter. Default is false
|
||||
#
|
||||
# ==== Params
|
||||
#
|
||||
|
@ -81,6 +82,8 @@ module Azure
|
|||
# * +:password+ - String. A description for the hosted service.
|
||||
# * +:image+ - String. Name of the disk image to use to create the virtual machine.
|
||||
# * +:location+ - String. The location where the virtual machine will be created.
|
||||
# * +:affinity_group_name - String. The affinity group name to be used
|
||||
# for the cloud service and the storage account if these do not exist.
|
||||
#
|
||||
# ==== Options
|
||||
#
|
||||
|
@ -96,36 +99,60 @@ module Azure
|
|||
# * +:vm_size+ - String. Specifies the size of the virtual machine instance.
|
||||
# * +:winrm_transport+ - Array. Specifies WINRM transport protocol.
|
||||
#
|
||||
# ==== add_role
|
||||
#
|
||||
# Accepted values are:
|
||||
# * +false+ - Will add a new deployment in a cloud service.
|
||||
# * +true+ - Will add a new role to a cloud service. Atleast one
|
||||
# deployment should exist before you can add a role.
|
||||
#
|
||||
# Returns Azure::VirtualMachineManagement::VirtualMachine objects of newly created instance.
|
||||
def create_virtual_machine(params, options={})
|
||||
#
|
||||
# See:
|
||||
# http://msdn.microsoft.com/en-us/library/windowsazure/jj157194.aspx
|
||||
# http://msdn.microsoft.com/en-us/library/windowsazure/jj157186.aspx
|
||||
def create_virtual_machine(params, options = {}, add_role = false)
|
||||
options[:os_type] = get_os_type(params[:image])
|
||||
validate_deployment_params(params, options)
|
||||
options[:cloud_service_name] = generate_cloud_service_name(params[:vm_name]) unless options[:cloud_service_name]
|
||||
options[:storage_account_name] = generate_storage_account_name(params[:vm_name]) unless options[:storage_account_name]
|
||||
optionals = {}
|
||||
if options[:virtual_network_name]
|
||||
virtual_network_service = Azure::VirtualNetworkManagementService.new
|
||||
virtual_networks = virtual_network_service.list_virtual_networks.select{|x| x.name == options[:virtual_network_name]}
|
||||
if virtual_networks.empty?
|
||||
Loggerx.error_with_exit "Virtual network #{options[:virtual_network_name]} doesn't exists"
|
||||
else
|
||||
optionals[:affinity_group_name] = virtual_networks.first.affinity_group
|
||||
end
|
||||
elsif options[:affinity_group_name]
|
||||
optionals[:affinity_group_name] = options[:affinity_group_name]
|
||||
else
|
||||
optionals[:location] = params[:location]
|
||||
end
|
||||
cloud_service = Azure::CloudServiceManagementService.new
|
||||
cloud_service.create_cloud_service(options[:cloud_service_name], optionals)
|
||||
cloud_service.upload_certificate(options[:cloud_service_name],params[:certificate]) unless params[:certificate].empty?
|
||||
Azure::StorageManagementService.new.create_storage_account(options[:storage_account_name], optionals)
|
||||
options[:deployment_name] ||= options[:cloud_service_name]
|
||||
|
||||
unless add_role
|
||||
Loggerx.info "Creating deploymnent..."
|
||||
options[:cloud_service_name] = generate_cloud_service_name(params[:vm_name]) unless options[:cloud_service_name]
|
||||
options[:storage_account_name] = generate_storage_account_name(params[:vm_name]) unless options[:storage_account_name]
|
||||
|
||||
optionals = {}
|
||||
|
||||
if options[:virtual_network_name]
|
||||
virtual_network_service = Azure::VirtualNetworkManagementService.new
|
||||
virtual_networks = virtual_network_service.list_virtual_networks.select{|x| x.name == options[:virtual_network_name]}
|
||||
if virtual_networks.empty?
|
||||
Loggerx.error_with_exit "Virtual network #{options[:virtual_network_name]} doesn't exists"
|
||||
else
|
||||
optionals[:affinity_group_name] = virtual_networks.first.affinity_group
|
||||
end
|
||||
elsif options[:affinity_group_name]
|
||||
optionals[:affinity_group_name] = options[:affinity_group_name]
|
||||
else
|
||||
optionals[:location] = params[:location]
|
||||
end
|
||||
|
||||
cloud_service = Azure::CloudServiceManagementService.new
|
||||
cloud_service.create_cloud_service(options[:cloud_service_name], optionals)
|
||||
cloud_service.upload_certificate(options[:cloud_service_name],params[:certificate]) unless params[:certificate].empty?
|
||||
Azure::StorageManagementService.new.create_storage_account(options[:storage_account_name], optionals)
|
||||
body = Serialization.deployment_to_xml(params,options)
|
||||
path = "/services/hostedservices/#{options[:cloud_service_name]}/deployments"
|
||||
else
|
||||
Loggerx.info "Deployment exists, adding role..."
|
||||
body = Serialization.role_to_xml(params, options).to_xml
|
||||
path = "/services/hostedservices/#{options[:cloud_service_name]}/deployments/#{options[:deployment_name]}/roles"
|
||||
end
|
||||
|
||||
body = Serialization.deployment_to_xml(params,options)
|
||||
path = "/services/hostedservices/#{options[:cloud_service_name]}/deployments"
|
||||
Loggerx.info "Deployment in progress..."
|
||||
request = ManagementHttpRequest.new(:post, path, body)
|
||||
request.call
|
||||
|
||||
get_virtual_machine(params[:vm_name],options[:cloud_service_name])
|
||||
rescue Exception => e
|
||||
e.message
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>BadRequest</Code>
|
||||
<Message>The description is too long</Message>
|
||||
</Error>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>BadRequest</Code>
|
||||
<Message>verbose...............................................
|
||||
........................................................................................
|
||||
.........................This is a lengthy value...............................................................
|
||||
........................................................................................ value is too long. Only 255 characters are permitted</Message>
|
||||
</Error>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>BadRequest</Code>
|
||||
<Message>Extended property name blobnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
|
||||
nnnnnnnnns is too long. Only 64 characters are permitted.</Message>
|
||||
</Error>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>BadRequest</Code>
|
||||
<Message>The subscription policy limit for resource type 'storage account count' was exceeded. The limit for resourc
|
||||
e type 'storage account count' is 26 per subscription, the current count is 26, and the requested increment is 1.</Message>
|
||||
</Error>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>BadRequest</Code>
|
||||
<Message>The label is not a valid storage account label.</Message>
|
||||
</Error>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>BadRequest</Code>
|
||||
<Message>The location constraint is not valid</Message>
|
||||
</Error>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>BadRequest</Code>
|
||||
<Message>The name is not a valid storage account name. Storage account names must be between 3 and 24 characters in
|
||||
length and use numbers and lower-case letters only.</Message>
|
||||
</Error>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>BadRequest</Code>
|
||||
<Message>Storage account storagewithcontainer has container(s) which have an active image and/or disk artifacts. Ensure those artifacts are removed from the image repository before deleting this storage account.</Message>
|
||||
</Error>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>ResourceNotFound</Code>
|
||||
<Message>The storage account invalidstorageacc was not found.</Message>
|
||||
</Error>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>Error</Code>
|
||||
<Message>Resource not found</Message>
|
||||
</Error>
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
<?xml version="1.0"?>
|
||||
<StorageService xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Url>https://management.core.windows.net/dummysubscriptionid/services/storageservices/storageacc</Url
|
||||
>
|
||||
<ServiceName>storageacc</ServiceName>
|
||||
<StorageServiceProperties>
|
||||
<Description i:nil="true"/>
|
||||
<AffinityGroup>agbabu1</AffinityGroup>
|
||||
<Label>VmFsaWRMYWJlbA==</Label>
|
||||
<Status>Created</Status>
|
||||
<Endpoints>
|
||||
<Endpoint>http://storageacc.blob.core.windows.net/</Endpoint>
|
||||
<Endpoint>http://storageacc.queue.core.windows.net/</Endpoint>
|
||||
<Endpoint>http://storageacc.table.core.windows.net/</Endpoint>
|
||||
</Endpoints>
|
||||
<GeoReplicationEnabled>false</GeoReplicationEnabled>
|
||||
<GeoPrimaryRegion>East US</GeoPrimaryRegion>
|
||||
<GeoSecondaryRegion/>
|
||||
<CreationTime>2013-12-03T19:39:33Z</CreationTime>
|
||||
<CustomDomains/>
|
||||
</StorageServiceProperties>
|
||||
<ExtendedProperties>
|
||||
<ExtendedProperty>
|
||||
<Name>blob</Name>
|
||||
<Value>verbose</Value>
|
||||
</ExtendedProperty>
|
||||
</ExtendedProperties>
|
||||
<Capabilities>
|
||||
<Capability>PersistentVMRole</Capability>
|
||||
</Capabilities>
|
||||
</StorageService>
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
<?xml version="1.0"?>
|
||||
<StorageService xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Url>https://management.core.windows.net/82f43e56-n564-4e01-hfie-4ce5362a101a/services/storageservices/storageacc</Url
|
||||
>
|
||||
<ServiceName>storageacc</ServiceName>
|
||||
<StorageServiceProperties>
|
||||
<Description i:nil="true"/>
|
||||
<AffinityGroup>agbabu1</AffinityGroup>
|
||||
<Label>VmFsaWRMYWJlbA==</Label>
|
||||
<Status>Created</Status>
|
||||
<Endpoints>
|
||||
<Endpoint>http://storageacc.blob.core.windows.net/</Endpoint>
|
||||
<Endpoint>http://storageacc.queue.core.windows.net/</Endpoint>
|
||||
<Endpoint>http://storageacc.table.core.windows.net/</Endpoint>
|
||||
</Endpoints>
|
||||
<GeoReplicationEnabled>false</GeoReplicationEnabled>
|
||||
<GeoPrimaryRegion>East US</GeoPrimaryRegion>
|
||||
<GeoSecondaryRegion/>
|
||||
<CreationTime>2013-12-03T19:39:33Z</CreationTime>
|
||||
<CustomDomains/>
|
||||
</StorageServiceProperties>
|
||||
<ExtendedProperties>
|
||||
<ExtendedProperty>
|
||||
<Name>blob</Name>
|
||||
<Value>verbose</Value>
|
||||
</ExtendedProperty>
|
||||
</ExtendedProperties>
|
||||
<Capabilities>
|
||||
<Capability>PersistentVMRole</Capability>
|
||||
</Capabilities>
|
||||
</StorageService>
|
|
@ -10,8 +10,18 @@
|
|||
<Status>Created</Status>
|
||||
<DateCreated>2013-04-22T07:37:56Z</DateCreated>
|
||||
<DateLastModified>2013-04-22T07:38:09Z</DateLastModified>
|
||||
<ExtendedProperties/>
|
||||
<ExtendedProperties>
|
||||
<ExtendedProperty>
|
||||
<Name>prop_1_name</Name>
|
||||
<Value>prop_1_value</Value>
|
||||
</ExtendedProperty>
|
||||
<ExtendedProperty>
|
||||
<Name>prop_2_name</Name>
|
||||
<Value>prop_2_value</Value>
|
||||
</ExtendedProperty>
|
||||
</ExtendedProperties>
|
||||
</HostedServiceProperties>
|
||||
<DefaultWinRMCertificateThumbprint>dummy-cert-value</DefaultWinRMCertificateThumbprint>
|
||||
</HostedService>
|
||||
<HostedService>
|
||||
<Url>https://management.core.windows.net/268abcd2-fabc-4cd3-a4ea-80324bddff87/services/hostedservices/cloud-service-2</Url>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0"?>
|
||||
<ServiceResources xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ServiceResource>
|
||||
<Name>AllowAllWindowsAzureIps</Name>
|
||||
<Type>Microsoft.SqlAzure.FirewallRule</Type>
|
||||
<StartIpAddress>0.0.0.0</StartIpAddress>
|
||||
<EndIpAddress>0.0.0.0</EndIpAddress>
|
||||
</ServiceResource>
|
||||
<ServiceResource>
|
||||
<Name>ClientIPAddress_2013-09-03_13:54:21</Name>
|
||||
<Type>Microsoft.SqlAzure.FirewallRule</Type>
|
||||
<StartIpAddress>167.220.224.226</StartIpAddress>
|
||||
<EndIpAddress>167.220.224.226</EndIpAddress>
|
||||
</ServiceResource>
|
||||
<ServiceResource>
|
||||
<Name>Rule1</Name>
|
||||
<Type>Microsoft.SqlAzure.FirewallRule</Type>
|
||||
<StartIpAddress>10.0.0.1</StartIpAddress>
|
||||
<EndIpAddress>10.0.0.255</EndIpAddress>
|
||||
</ServiceResource>
|
||||
<ServiceResource>
|
||||
<Name>Rule2</Name>
|
||||
<Type>Microsoft.SqlAzure.FirewallRule</Type>
|
||||
<StartIpAddress>192.168.1.1</StartIpAddress>
|
||||
<EndIpAddress>192.168.1.255</EndIpAddress>
|
||||
</ServiceResource>
|
||||
</ServiceResources>
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0"?>
|
||||
<UpdateStorageServiceInput xmlns="http://schemas.microsoft.com/windowsazure">
|
||||
<Label>VGVzdCBMYWJlbA==
|
||||
</Label>
|
||||
<GeoReplicationEnabled>false</GeoReplicationEnabled>
|
||||
<ExtendedProperties>
|
||||
<ExtendedProperty>
|
||||
<Name>prop_1_name</Name>
|
||||
<Value>prop_1_value</Value>
|
||||
</ExtendedProperty>
|
||||
<ExtendedProperty>
|
||||
<Name>prop_2_name</Name>
|
||||
<Value>prop_2_value</Value>
|
||||
</ExtendedProperty>
|
||||
</ExtendedProperties>
|
||||
</UpdateStorageServiceInput>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Code>InvalidXmlRequest</Code>
|
||||
<Message>The request body's XML was invalid or not correctly specified.</Message>
|
||||
</Error>
|
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0"?>
|
||||
<StorageServices xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<StorageService>
|
||||
<Url>https://management.core.windows.net/268a3762-abcd-4cd3-a4ea-80e84bddff87/services/storageservices/storage1</Url>
|
||||
<ServiceName>storage1</ServiceName>
|
||||
<StorageServiceProperties>
|
||||
<Description i:nil="true"/>
|
||||
<Location>West US</Location>
|
||||
<Label>c3VzZQ==</Label>
|
||||
<Status>Created</Status>
|
||||
<Endpoints>
|
||||
<Endpoint>http://storage1.blob.core.windows.net/</Endpoint>
|
||||
<Endpoint>http://storage1.queue.core.windows.net/</Endpoint>
|
||||
<Endpoint>http://storage1.table.core.windows.net/</Endpoint>
|
||||
</Endpoints>
|
||||
<GeoReplicationEnabled>true</GeoReplicationEnabled>
|
||||
<GeoPrimaryRegion>West US</GeoPrimaryRegion>
|
||||
<StatusOfPrimary/>
|
||||
<GeoSecondaryRegion>East US</GeoSecondaryRegion>
|
||||
<StatusOfSecondary/>
|
||||
</StorageServiceProperties>
|
||||
<ExtendedProperties/>
|
||||
</StorageService>
|
||||
<StorageService>
|
||||
<Url>https://management.core.windows.net/268a3762-abcd-4cd3-a4ea-80e84bddff87/services/storageservices/storage2</Url>
|
||||
<ServiceName>storage2</ServiceName>
|
||||
<StorageServiceProperties>
|
||||
<Location>West US</Location>
|
||||
<Label>VGVzdCBMYWJlbA==</Label>
|
||||
<Status>Created</Status>
|
||||
<Endpoints>
|
||||
<Endpoint>http://storage2.blob.core.windows.net/</Endpoint>
|
||||
<Endpoint>http://storage2.queue.core.windows.net/</Endpoint>
|
||||
<Endpoint>http://storage2.table.core.windows.net/</Endpoint>
|
||||
</Endpoints>
|
||||
<GeoReplicationEnabled>false</GeoReplicationEnabled>
|
||||
<GeoPrimaryRegion>West US</GeoPrimaryRegion>
|
||||
<StatusOfPrimary/>
|
||||
<GeoSecondaryRegion>East US</GeoSecondaryRegion>
|
||||
<StatusOfSecondary/>
|
||||
</StorageServiceProperties>
|
||||
<ExtendedProperties>
|
||||
<ExtendedProperty>
|
||||
<Name>prop_1_name</Name>
|
||||
<Value>prop_1_value</Value>
|
||||
</ExtendedProperty>
|
||||
<ExtendedProperty>
|
||||
<Name>prop_2_name</Name>
|
||||
<Value>prop_2_value</Value>
|
||||
</ExtendedProperty>
|
||||
</ExtendedProperties>
|
||||
</StorageService>
|
||||
</StorageServices>
|
|
@ -19,15 +19,15 @@ describe Azure::SqlDatabaseManagementService do
|
|||
subject { Azure::SqlDatabaseManagementService.new }
|
||||
let(:login_name) {'ms_open_tech'}
|
||||
let(:sql_server) { subject.create_server(login_name, 'User1@123', WindowsImageLocation) }
|
||||
|
||||
describe "#set_sql_server_firewall_rule" do
|
||||
|
||||
before {
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
Azure.config.management_endpoint = SqlServerEndpoint
|
||||
}
|
||||
|
||||
after {
|
||||
Azure.config.management_endpoint = ManagementServiceEndpoint
|
||||
subject.delete_server(sql_server.name)
|
||||
}
|
||||
|
||||
it "should adds a new server-level firewall rule for a SQL Database server with requester's IP address." do
|
||||
|
|
|
@ -22,11 +22,6 @@ describe Azure::SqlDatabaseManagementService do
|
|||
|
||||
before {
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
Azure.config.management_endpoint = SqlServerEndpoint
|
||||
}
|
||||
|
||||
after {
|
||||
Azure.config.management_endpoint = ManagementServiceEndpoint
|
||||
}
|
||||
|
||||
it "should be able to create a new sql database server." do
|
||||
|
@ -34,6 +29,8 @@ describe Azure::SqlDatabaseManagementService do
|
|||
sql_server.name.wont_be_nil
|
||||
sql_server.location.must_equal WindowsImageLocation
|
||||
sql_server.administrator_login.must_equal login_name
|
||||
|
||||
subject.delete_server sql_server.name
|
||||
end
|
||||
|
||||
it "errors if the sql server location does not exist" do
|
||||
|
|
|
@ -22,14 +22,13 @@ describe Azure::SqlDatabaseManagementService do
|
|||
|
||||
before {
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
Azure.config.management_endpoint = SqlServerEndpoint
|
||||
subject.set_sql_server_firewall_rule(sql_server.name, "rule1")
|
||||
ip_range = {:start_ip_address => "10.20.30.0", :end_ip_address => "10.20.30.255"}
|
||||
subject.set_sql_server_firewall_rule(sql_server.name, "rule2", ip_range)
|
||||
}
|
||||
|
||||
after {
|
||||
Azure.config.management_endpoint = ManagementServiceEndpoint
|
||||
subject.delete_server(sql_server.name)
|
||||
}
|
||||
|
||||
describe "#delete_sql_server_firewall_rule" do
|
||||
|
@ -58,7 +57,6 @@ describe Azure::SqlDatabaseManagementService do
|
|||
end
|
||||
|
||||
it "errors if the sql server firewall rule does not exist" do
|
||||
server_name = "unknown-server"
|
||||
rule_name = 'rule10'
|
||||
exception = assert_raises(RuntimeError) do
|
||||
subject.delete_sql_server_firewall_rule(sql_server.name, rule_name)
|
||||
|
|
|
@ -18,11 +18,6 @@ describe Azure::SqlDatabaseManagementService do
|
|||
|
||||
before {
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
Azure.config.management_endpoint = SqlServerEndpoint
|
||||
}
|
||||
|
||||
after {
|
||||
Azure.config.management_endpoint = ManagementServiceEndpoint
|
||||
}
|
||||
|
||||
subject { Azure::SqlDatabaseManagementService.new }
|
||||
|
|
|
@ -23,14 +23,13 @@ describe Azure::SqlDatabaseManagementService do
|
|||
|
||||
before {
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
Azure.config.management_endpoint = SqlServerEndpoint
|
||||
ip_range = {:start_ip_address => "10.20.30.0", :end_ip_address => "10.20.30.255"}
|
||||
subject.set_sql_server_firewall_rule(sql_server.name, "rule1", ip_range)
|
||||
subject.set_sql_server_firewall_rule(sql_server.name, "rule2")
|
||||
}
|
||||
|
||||
after {
|
||||
Azure.config.management_endpoint = ManagementServiceEndpoint
|
||||
subject.delete_server(sql_server.name)
|
||||
}
|
||||
|
||||
it "returns a list of SQL databse server firewall" do
|
||||
|
|
|
@ -22,22 +22,21 @@ describe Azure::SqlDatabaseManagementService do
|
|||
|
||||
before {
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
Azure.config.management_endpoint = SqlServerEndpoint
|
||||
subject.create_server(login_name, 'User1@123', WindowsImageLocation)
|
||||
subject.create_server(login_name, 'User2@123', 'East US')
|
||||
}
|
||||
|
||||
after {
|
||||
Azure.config.management_endpoint = ManagementServiceEndpoint
|
||||
}
|
||||
|
||||
it "returns a list of SQL databse servers" do
|
||||
server1 = subject.create_server(login_name, 'User1@123', WindowsImageLocation)
|
||||
server2 = subject.create_server(login_name, 'User2@123', 'East US')
|
||||
|
||||
sql_servers = subject.list_servers
|
||||
sql_servers.wont_be_nil
|
||||
sql_servers.must_be_kind_of Array
|
||||
sql_server = sql_servers.first
|
||||
sql_server.must_be_kind_of Azure::SqlDatabaseManagement::SqlDatabase
|
||||
assert_operator sql_servers.size, :>=, 2
|
||||
|
||||
subject.delete_server(server1.name)
|
||||
subject.delete_server(server2.name)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -24,11 +24,10 @@ describe Azure::SqlDatabaseManagementService do
|
|||
|
||||
before {
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
Azure.config.management_endpoint = SqlServerEndpoint
|
||||
}
|
||||
|
||||
after {
|
||||
Azure.config.management_endpoint = ManagementServiceEndpoint
|
||||
subject.delete_server(sql_server.name)
|
||||
}
|
||||
|
||||
it "should be able to reset password of sql database server." do
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
#-------------------------------------------------------------------------
|
||||
# Copyright 2013 Microsoft Open Technologies, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#--------------------------------------------------------------------------
|
||||
require "test_helper"
|
||||
require 'azure/storage_management/storage_account'
|
||||
|
||||
describe Azure::StorageManagementService do
|
||||
|
||||
subject { Azure::StorageManagementService.new }
|
||||
let(:request_path) {'/services/storageservices'}
|
||||
let(:method) { :post }
|
||||
let(:mock_request){ mock() }
|
||||
let(:get_storage_account_properties) { Fixtures["get_storage_account_properties_new"] }
|
||||
let(:responseStorageProps) {
|
||||
responseStorageProps = mock()
|
||||
responseStorageProps.stubs(:body).returns(get_storage_account_properties)
|
||||
responseStorageProps
|
||||
}
|
||||
let(:responseStorageProps_body) {Nokogiri::XML responseStorageProps.body}
|
||||
let(:create_storage_name_error) { Fixtures["create_storage_name_error"] }
|
||||
let(:response) {
|
||||
response = mock()
|
||||
response.stubs(:body).returns(create_storage_name_error)
|
||||
response
|
||||
}
|
||||
let(:response_body) {Nokogiri::XML response.body}
|
||||
|
||||
let(:create_storage_location_error) { Fixtures["create_storage_location_error"] }
|
||||
let(:responseLoc) {
|
||||
responseLoc = mock()
|
||||
responseLoc.stubs(:body).returns(create_storage_location_error)
|
||||
responseLoc
|
||||
}
|
||||
let(:responseLoc_body) {Nokogiri::XML responseLoc.body}
|
||||
let(:create_storage_desc_error) { Fixtures["create_storage_desc_error"] }
|
||||
let(:responseDescErr) {
|
||||
responseDescErr = mock()
|
||||
responseDescErr.stubs(:body).returns(create_storage_desc_error)
|
||||
responseDescErr
|
||||
}
|
||||
let(:responseDescErr_body) {Nokogiri::XML responseDescErr.body}
|
||||
|
||||
let(:create_storage_extendedprop_error) { Fixtures["create_storage_extendedprop_error"] }
|
||||
let(:responseExtndErr) {
|
||||
responseExtndErr = mock()
|
||||
responseExtndErr.stubs(:body).returns(create_storage_extendedprop_error)
|
||||
responseExtndErr
|
||||
}
|
||||
let(:responseExtndErr_body) {Nokogiri::XML responseExtndErr.body}
|
||||
let(:create_storage_extendedpropname_error) { Fixtures["create_storage_extendedpropname_error"] }
|
||||
let(:responseExtndNameErr) {
|
||||
responseExtndNameErr = mock()
|
||||
responseExtndNameErr.stubs(:body).returns(create_storage_extendedpropname_error)
|
||||
responseExtndNameErr
|
||||
}
|
||||
|
||||
let(:responseExtndNameErr_body) {Nokogiri::XML responseExtndNameErr.body}
|
||||
|
||||
let(:create_storage_label_error) { Fixtures["create_storage_label_error"] }
|
||||
let(:responseLabelErr) {
|
||||
responseLabelErr = mock()
|
||||
responseLabelErr.stubs(:body).returns(create_storage_label_error)
|
||||
responseLabelErr
|
||||
}
|
||||
|
||||
let(:responseLabelErr_body) {Nokogiri::XML responseLabelErr.body}
|
||||
let(:paramsLocInvalid){
|
||||
{
|
||||
:location => "West US",
|
||||
}
|
||||
}
|
||||
let(:paramsLoc){
|
||||
{
|
||||
:location => "West US",
|
||||
}
|
||||
}
|
||||
let(:paramsDesc){
|
||||
{
|
||||
:description => "Description",
|
||||
:location => "West US",
|
||||
}
|
||||
}
|
||||
let(:paramsDescInvalid){
|
||||
{
|
||||
:location => "West US",
|
||||
:description => "..............................................................................................................................................................................................................................................................................................................",
|
||||
}
|
||||
}
|
||||
let(:paramsAffinityGrp){
|
||||
{
|
||||
:affinity_group_name => "agbabu1"
|
||||
}
|
||||
}
|
||||
let(:paramslocGeoTrue){
|
||||
{
|
||||
:location => "West US",
|
||||
:geo_replication_enabled => 'true',
|
||||
}
|
||||
}
|
||||
let(:paramslocGeoFalse){
|
||||
{
|
||||
:location => "West US",
|
||||
:geo_replication_enabled => 'false',
|
||||
}
|
||||
}
|
||||
let(:paramsExtendedPropsValue){
|
||||
{
|
||||
:location => "West US",
|
||||
:extended_properties =>{:blobs =>'verbose...............................................
|
||||
........................................................................................
|
||||
.........................This is a lengthy value...............................................................
|
||||
........................................................................................
|
||||
',:test =>'test'},
|
||||
}
|
||||
}
|
||||
let(:paramsExtendedProps){
|
||||
{
|
||||
:location => "West US",
|
||||
:extended_properties =>{:blobs =>'verbose',:test =>'test'},
|
||||
}
|
||||
}
|
||||
let(:paramsExtendedPropsName){
|
||||
{
|
||||
:location => "West US",
|
||||
:extended_properties =>{:blobnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnns =>'verbose',:test =>'test'},
|
||||
}
|
||||
}
|
||||
let(:paramsLabel){
|
||||
{
|
||||
:location => "West US",
|
||||
:label => "ValidLabel"
|
||||
}
|
||||
}
|
||||
|
||||
let(:paramsLabelInvalid){
|
||||
{
|
||||
:location => "West US",
|
||||
:label => "ValidLabel.................................................................................................................
|
||||
............................................
|
||||
...................................
|
||||
...............................",
|
||||
}
|
||||
}
|
||||
before{
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
}
|
||||
|
||||
describe "#create_storage_account" do
|
||||
|
||||
it "Create storage account with long name" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('longstoragename..............................................').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns response_body
|
||||
subject.create_storage_account 'longstoragename..............................................'
|
||||
msg = response_body.at('Error')
|
||||
assert_match(/^The name is not a valid storage account name. Storage account names must be between 3 and 24 characters in\nlength and use numbers and lower-case letters only.*/, msg.at('Message').text)
|
||||
end
|
||||
|
||||
it "Create storage account name with spl characters" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('%^%$$^$^').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns response_body
|
||||
subject.create_storage_account '%^%$$^$^'
|
||||
msg = response_body.at('Error')
|
||||
assert_match(/^The name is not a valid storage account name. Storage account names must be between 3 and 24 characters in
|
||||
length and use numbers and lower-case letters only.*/, msg.at('Message').text)
|
||||
end
|
||||
|
||||
it "Create storage account with valid name and invalid location" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('invalidlocation').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns responseLoc
|
||||
subject.create_storage_account('invalidlocation',paramsLocInvalid)
|
||||
msg = responseLoc_body.at('Error')
|
||||
assert_match(/^The location constraint is not valid*/, msg.at('Message').text)
|
||||
end
|
||||
|
||||
|
||||
it "Create valid storage account with only name and valid location" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('storageacc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns 'succeeded'
|
||||
subject.create_storage_account('storageacc',paramsLoc)
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account_properties).with('storageacc').returns(responseStorageProps)
|
||||
subject.get_storage_account_properties('storageacc')
|
||||
msg = responseStorageProps_body.at('StorageServiceProperties')
|
||||
assert_match(/^Created*/, msg.at('Status').text)
|
||||
end
|
||||
|
||||
it "Create valid storage account with only name and valid description" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('validdesc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns responseLoc
|
||||
subject.create_storage_account('validdesc',paramsDesc)
|
||||
msg = responseLoc_body.at('Error')
|
||||
assert_match(/^The location constraint is not valid*/, msg.at('Message').text)
|
||||
end
|
||||
|
||||
it "Create valid storage account with only name, location and long description" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('longdesc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns responseDescErr_body
|
||||
subject.create_storage_account('longdesc',paramsDescInvalid)
|
||||
msg = responseDescErr_body.at('Error')
|
||||
assert_match(/^The description is too long*/, msg.at('Message').text)
|
||||
end
|
||||
|
||||
it "Create storage account with name and affinity group" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('storageacc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns ""
|
||||
subject.create_storage_account('storageacc',paramsAffinityGrp)
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account_properties).with('storageacc').returns(responseStorageProps)
|
||||
subject.get_storage_account_properties('storageacc')
|
||||
msg = responseStorageProps_body.at('StorageServiceProperties')
|
||||
assert_match(/^Created*/, msg.at('Status').text)
|
||||
assert_match(/^agbabu1*/, msg.at('AffinityGroup').text)
|
||||
end
|
||||
|
||||
it "Create storage account with name, location and geo_replication_enabled true" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('storageacc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns ""
|
||||
subject.create_storage_account('storageacc',paramslocGeoTrue)
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account_properties).with('storageacc').returns(responseStorageProps)
|
||||
subject.get_storage_account_properties('storageacc')
|
||||
msg = responseStorageProps_body.at('StorageServiceProperties')
|
||||
assert_match(/^Created*/, msg.at('Status').text)
|
||||
end
|
||||
|
||||
it "Create storage account with name, location and geo_replication_enabled false" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('storageacc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns ""
|
||||
subject.create_storage_account('storageacc',paramslocGeoFalse)
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account_properties).with('storageacc').returns(responseStorageProps)
|
||||
subject.get_storage_account_properties('storageacc')
|
||||
msg = responseStorageProps_body.at('StorageServiceProperties')
|
||||
assert_match(/^Created*/, msg.at('Status').text)
|
||||
assert_match(/^false*/, msg.at('GeoReplicationEnabled').text)
|
||||
end
|
||||
|
||||
it "Create storage account with name, location and extended properties" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('storageacc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns "succeeded"
|
||||
msg = subject.create_storage_account('storageacc',paramsExtendedProps)
|
||||
assert_match(/^succeeded*/, msg)
|
||||
end
|
||||
|
||||
it "Create storage account with name, location and lengthy extended property value" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('storageacc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns responseExtndErr
|
||||
subject.create_storage_account('storageacc',paramsExtendedPropsValue)
|
||||
msg = responseExtndErr_body.at('Error')
|
||||
assert_match(/^verbose...............................................
|
||||
........................................................................................
|
||||
.........................This is a lengthy value...............................................................
|
||||
........................................................................................ value is too long. Only 255 characters are permitted*/, msg.at('Message').text)
|
||||
end
|
||||
|
||||
it "Create storage account with name, location and lengthy extended property name" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('storageacc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns responseExtndNameErr
|
||||
subject.create_storage_account('storageacc',paramsExtendedPropsName)
|
||||
msg = responseExtndNameErr_body.at('Error')
|
||||
assert_match(/^Extended property name blobnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
|
||||
nnnnnnnnns is too long. Only 64 characters are permitted.*/, msg.at('Message').text)
|
||||
end
|
||||
|
||||
it "Create storage account with name, location and label" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('storageacc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns ""
|
||||
subject.create_storage_account('storageacc',paramsLabel)
|
||||
msg = responseExtndNameErr_body.at('Error')
|
||||
assert_match(/^*/, "")
|
||||
end
|
||||
|
||||
it "Create storage account with name, location and lengthy label" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('storageacc').returns(false)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns responseLabelErr
|
||||
subject.create_storage_account('storageacc',paramsLabelInvalid)
|
||||
msg = responseLabelErr_body.at('Error')
|
||||
assert_match(/^The label is not a valid storage account label.*/, msg.at('Message').text)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,59 @@
|
|||
#-------------------------------------------------------------------------
|
||||
# Copyright 2013 Microsoft Open Technologies, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#--------------------------------------------------------------------------
|
||||
require "test_helper"
|
||||
require 'azure/storage_management/storage_account'
|
||||
|
||||
describe Azure::StorageManagementService do
|
||||
|
||||
subject { Azure::StorageManagementService.new }
|
||||
let(:request_path) {'/services/storageservices'}
|
||||
let(:method) { :post }
|
||||
let(:mock_request){ mock() }
|
||||
let(:delete_storage_error) { Fixtures["delete_storage_error"] }
|
||||
let(:responseResourceNotFound) {
|
||||
responseResourceNotFound = mock()
|
||||
responseResourceNotFound.stubs(:body).returns(delete_storage_error)
|
||||
responseResourceNotFound
|
||||
}
|
||||
let(:responseResourceNotFound_body) {Nokogiri::XML responseResourceNotFound.body}
|
||||
let(:delete_storage_container_error) { Fixtures["delete_storage_container_error"] }
|
||||
let(:responseBadRequest) {
|
||||
responseBadRequest = mock()
|
||||
responseBadRequest.stubs(:body).returns(delete_storage_container_error)
|
||||
responseBadRequest
|
||||
}
|
||||
let(:responseBadRequest_body) {Nokogiri::XML responseBadRequest.body}
|
||||
|
||||
before{
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
}
|
||||
|
||||
describe "#delete_storage_account" do
|
||||
|
||||
it "Delete non existing storage account" do
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns responseResourceNotFound_body
|
||||
subject.delete_storage_account 'invalidstorageacc'
|
||||
msg = responseResourceNotFound_body.at('Error')
|
||||
assert_match(/^ResourceNotFound*/, msg.at('Code').text)
|
||||
end
|
||||
|
||||
it "Delete storage account with containers having disks" do
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns responseBadRequest_body
|
||||
subject.delete_storage_account 'storagewithcontainer'
|
||||
msg = responseBadRequest_body.at('Error')
|
||||
assert_match(/^BadRequest*/, msg.at('Code').text)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,55 @@
|
|||
#-------------------------------------------------------------------------
|
||||
# Copyright 2013 Microsoft Open Technologies, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#--------------------------------------------------------------------------
|
||||
require "test_helper"
|
||||
require 'azure/storage_management/storage_account'
|
||||
|
||||
describe Azure::StorageManagementService do
|
||||
|
||||
subject { Azure::StorageManagementService.new }
|
||||
let(:request_path) {'/services/storageservices'}
|
||||
let(:method) { :get }
|
||||
let(:mock_request){ mock() }
|
||||
let(:get_storage_account_properties) { Fixtures["get_storage_account_properties_new"] }
|
||||
let(:responseStorageProps) {
|
||||
responseStorageProps = mock()
|
||||
responseStorageProps.stubs(:body).returns(get_storage_account_properties)
|
||||
responseStorageProps
|
||||
}
|
||||
let(:responseStorageProps_body) {Nokogiri::XML responseStorageProps.body}
|
||||
|
||||
before{
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
}
|
||||
|
||||
describe "#create_storage_account" do
|
||||
|
||||
it "Get storage account properties" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account_properties).with('storageacc').returns(responseStorageProps)
|
||||
subject.get_storage_account_properties('storageacc')
|
||||
msg = responseStorageProps_body.at('StorageServiceProperties')
|
||||
|
||||
#Description assertion fails as there is a bug in RDFE for the description value not getting updated accordingly
|
||||
assert_match(/^Description*/, msg.at('Description').text)
|
||||
assert_match(/^agbabu1*/, msg.at('AffinityGroup').text)
|
||||
assert_match(/^VmFsaWRMYWJlbA==*/, msg.at('Label').text)
|
||||
assert_match(/^Created*/, msg.at('Created').text)
|
||||
assert_match(/^false*/, msg.at('GeoReplicationEnabled').text)
|
||||
assert_match(/^false*/, msg.at('GeoPrimaryRegion').text)
|
||||
msg = responseStorageProps_body.at('ExtendedProperty')
|
||||
assert_match(/^verbose*/, msg.at('blob').text)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,67 @@
|
|||
#-------------------------------------------------------------------------
|
||||
# Copyright 2013 Microsoft Open Technologies, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#--------------------------------------------------------------------------
|
||||
require "test_helper"
|
||||
|
||||
describe Azure::StorageManagementService do
|
||||
|
||||
subject { Azure::StorageManagementService.new }
|
||||
let(:request_path) {'/services/storageservices'}
|
||||
let(:get_storage_accounts_xml) { Fixtures["get_storage_properties"] }
|
||||
let(:method) { :get }
|
||||
let(:mock_request){ mock() }
|
||||
let(:response) {
|
||||
response = mock()
|
||||
response.stubs(:body).returns(get_storage_accounts_xml)
|
||||
response
|
||||
}
|
||||
let(:get_storage_account_error_xml) { Fixtures["get_storage_account_error"] }
|
||||
let(:response1) {
|
||||
response1 = mock()
|
||||
response1.stubs(:body).returns(get_storage_account_error_xml)
|
||||
response1
|
||||
}
|
||||
let(:response_body) {Nokogiri::XML response.body}
|
||||
before{
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
}
|
||||
|
||||
describe "#get_storage_account" do
|
||||
it "Get storage account by specifying null" do
|
||||
result = subject.get_storage_account nil
|
||||
result.must_equal false
|
||||
end
|
||||
|
||||
it "Get storage account with valid name" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('validname').returns(true)
|
||||
result = subject.get_storage_account 'validname'
|
||||
result.must_equal true
|
||||
end
|
||||
|
||||
it "Get storage account with invalid name - spl characters" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('invalidname@@@@@@@@@@@@@@@@@@').returns(false)
|
||||
result = subject.get_storage_account 'invalidname@@@@@@@@@@@@@@@@@@'
|
||||
result.must_equal false
|
||||
end
|
||||
|
||||
it "Get storage account with invalid name - long name" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('invalidname....................................').returns(false)
|
||||
result = subject.get_storage_account 'invalidname....................................'
|
||||
result.must_equal false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
#-------------------------------------------------------------------------
|
||||
# Copyright 2013 Microsoft Open Technologies, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#--------------------------------------------------------------------------
|
||||
require "test_helper"
|
||||
require 'azure/storage_management/storage_account'
|
||||
|
||||
describe Azure::StorageManagementService do
|
||||
|
||||
subject { Azure::StorageManagementService.new }
|
||||
let(:request_path) {'/services/storageservices'}
|
||||
let(:method) { :post }
|
||||
let(:mock_request){ mock() }
|
||||
let(:update_storage_error) { Fixtures["update_storage_error"] }
|
||||
let(:response) {
|
||||
response = mock()
|
||||
response.stubs(:body).returns(update_storage_error)
|
||||
response
|
||||
}
|
||||
let(:response_body) {Nokogiri::XML response.body}
|
||||
let(:params){
|
||||
{
|
||||
:label => "SampleLabel",
|
||||
:description => "SampleDescription",
|
||||
|
||||
}
|
||||
}
|
||||
let(:params1){
|
||||
{
|
||||
:label => "SampleLabel",
|
||||
:geo_replication_enabled => 'invalid',
|
||||
}
|
||||
}
|
||||
let(:params2){
|
||||
{
|
||||
:label => "SampleLabel",
|
||||
:description => "..............................................
|
||||
...............................................................
|
||||
................................................................
|
||||
................................................................
|
||||
..................................................................",
|
||||
:geo_replication_enabled => 'invalid',
|
||||
}
|
||||
}
|
||||
let(:params3){
|
||||
{
|
||||
:label => "..............................................
|
||||
...............................................................
|
||||
................................................................
|
||||
................................................................
|
||||
..................................................................",
|
||||
:description => "sampledescription",
|
||||
:geo_replication_enabled => 'invalid',
|
||||
}
|
||||
}
|
||||
let(:params4){
|
||||
{
|
||||
:label => "@#@#@#@#@",
|
||||
:description => nil,
|
||||
:geo_replication_enabled => nil,
|
||||
}
|
||||
}
|
||||
|
||||
before{
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
}
|
||||
|
||||
describe "update_storage_account" do
|
||||
|
||||
it "Update non existing storage account" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('nonexistantstorageacc').returns(false)
|
||||
msg = subject.update_storage_account('nonexistantstorageacc',params)
|
||||
assert_match(/^Storage Account 'nonexistantstorageacc' does not exist. Skipped...*/, msg)
|
||||
end
|
||||
|
||||
|
||||
it "Update invalid geo_replication_enabled value" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('validstoragename').returns(true)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns response_body
|
||||
subject.update_storage_account('validstoragename',params1)
|
||||
msg = response_body.at('Error')
|
||||
assert_match(/^InvalidXmlRequest*/, msg.at('Code').text)
|
||||
end
|
||||
|
||||
|
||||
it "Update long description" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('validstoragename').returns(true)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns response_body
|
||||
subject.update_storage_account('validstoragename',params2)
|
||||
msg = response_body.at('Error')
|
||||
assert_match(/^InvalidXmlRequest*/, msg.at('Code').text)
|
||||
end
|
||||
|
||||
it "Update long label" do
|
||||
storagename='nonexistantstorageacc'
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('validstoragename').returns(true)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns response_body
|
||||
subject.update_storage_account('validstoragename',params3)
|
||||
msg = response_body.at('Error')
|
||||
assert_match(/^InvalidXmlRequest*/, msg.at('Code').text)
|
||||
end
|
||||
|
||||
it "Update long description" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('validstoragename').returns(true)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns response_body
|
||||
subject.update_storage_account('validstoragename',params2)
|
||||
msg = response_body.at('Error')
|
||||
assert_match(/^InvalidXmlRequest*/, msg.at('Code').text)
|
||||
end
|
||||
|
||||
it "Update label with spl characters" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('validstoragename').returns(true)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns response_body
|
||||
subject.update_storage_account('validstoragename',params3)
|
||||
msg = response_body.at('Error')
|
||||
assert_match(/^InvalidXmlRequest*/, msg.at('Code').text)
|
||||
end
|
||||
|
||||
it "Update valid geo_location_enabled" do
|
||||
Azure::StorageManagementService.any_instance.stubs(:get_storage_account).with('validstoragename').returns(true)
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns ""
|
||||
subject.update_storage_account('validstoragename',params3)
|
||||
assert_match(/^*/, "")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -31,8 +31,6 @@ Azure::Core.configure do |config|
|
|||
end
|
||||
|
||||
StorageAccountName = random_string('storagetest',10)
|
||||
SqlServerEndpoint = "https://management.database.windows.net:8443/"
|
||||
ManagementServiceEndpoint = Azure.config.management_endpoint
|
||||
Images = Azure::VirtualMachineImageManagementService.new.list_virtual_machine_images
|
||||
LinuxImage = Images.select{|image| image.os_type == 'Linux'}.first
|
||||
WindowsImage = Images.select{|image| image.os_type == 'Windows'}.first
|
||||
|
|
|
@ -25,6 +25,7 @@ describe Azure::VirtualMachineManagementService do
|
|||
let(:password) { 'Admin123' }
|
||||
let(:certificate) { Fixtures["certificate.pem"] }
|
||||
let(:private_key) { Fixtures["privatekey.key"] }
|
||||
|
||||
let(:params){
|
||||
{
|
||||
:vm_name => virtual_machine_name,
|
||||
|
@ -50,8 +51,9 @@ describe Azure::VirtualMachineManagementService do
|
|||
let(:options){
|
||||
{
|
||||
:storage_account_name => storage_account_name,
|
||||
:virtual_network_name => in_vnet_name,
|
||||
:subnet_name => 'Subnet-1'
|
||||
:cloud_service_name => cloud_service_name,
|
||||
|
||||
:vm_size =>'A7'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +84,7 @@ describe Azure::VirtualMachineManagementService do
|
|||
describe "#deployment" do
|
||||
|
||||
it "should set options hash with valid cloud_service_name, deployment_name, storage_account_name and virtual network" do
|
||||
subject.create_virtual_machine(params, options)
|
||||
subject.create_virtual_machine(params, options,add_role=false)
|
||||
cloud_name = options[:cloud_service_name]
|
||||
virtual_machine = subject.get_virtual_machine(virtual_machine_name, cloud_name)
|
||||
virtual_machine.must_be_kind_of Azure::VirtualMachineManagement::VirtualMachine
|
||||
|
@ -93,13 +95,11 @@ describe Azure::VirtualMachineManagementService do
|
|||
virtual_machine.os_type.must_equal 'Linux'
|
||||
options[:storage_account_name].wont_be_nil
|
||||
assert_match(/^#{params[:vm_name]+'-service'}*/, cloud_name)
|
||||
virtual_machine.virtual_network_name.must_equal in_vnet_name
|
||||
virtual_machine.virtual_network.must_be_kind_of Azure::VirtualNetworkManagement::VirtualNetwork
|
||||
end
|
||||
|
||||
it "should creates http and https enabled winrm virtual machine without certificate." do
|
||||
default_options.merge!(:winrm_transport => ['https','http'])
|
||||
subject.create_virtual_machine(windows_params, default_options)
|
||||
subject.create_virtual_machine(windows_params, default_options,add_role=false)
|
||||
result = subject.get_virtual_machine(virtual_machine_name, cloud_service_name)
|
||||
result.must_be_kind_of Azure::VirtualMachineManagement::VirtualMachine
|
||||
assert_equal(result.os_type, 'Windows',"Error in the OS type of VI created")
|
||||
|
@ -114,7 +114,7 @@ describe Azure::VirtualMachineManagementService do
|
|||
|
||||
it "should creates https enabled winrm virtual machine using certificate." do
|
||||
default_options.merge!(:winrm_transport => ['https'], :private_key_file => private_key, :certificate_file => certificate)
|
||||
subject.create_virtual_machine(windows_params, default_options)
|
||||
subject.create_virtual_machine(windows_params, default_options,add_role=false)
|
||||
result = subject.get_virtual_machine(virtual_machine_name, cloud_service_name)
|
||||
result.must_be_kind_of Azure::VirtualMachineManagement::VirtualMachine
|
||||
assert_equal(result.os_type, 'Windows',"Error in the OS type of VI created")
|
||||
|
@ -127,7 +127,7 @@ describe Azure::VirtualMachineManagementService do
|
|||
|
||||
it "should creates windows virtual machine without winrm." do
|
||||
default_options.merge!(:winrm_transport => ['none'])
|
||||
subject.create_virtual_machine(windows_params, default_options)
|
||||
subject.create_virtual_machine(windows_params, default_options,add_role=false)
|
||||
result = subject.get_virtual_machine(virtual_machine_name, cloud_service_name)
|
||||
result.must_be_kind_of Azure::VirtualMachineManagement::VirtualMachine
|
||||
assert_equal(result.os_type, 'Windows',"Error in the OS type of VI created")
|
||||
|
@ -141,46 +141,27 @@ describe Azure::VirtualMachineManagementService do
|
|||
|
||||
it "created linux virtual machine should be accessible using password and certificate" do
|
||||
default_options.merge!(:private_key_file => private_key, :certificate_file => certificate)
|
||||
subject.create_virtual_machine(params, default_options)
|
||||
subject.create_virtual_machine(params, default_options,add_role=false)
|
||||
result = subject.get_virtual_machine(virtual_machine_name, cloud_service_name)
|
||||
result.must_be_kind_of Azure::VirtualMachineManagement::VirtualMachine
|
||||
assert_equal(result.os_type, 'Linux',"Error in the OS type of VI created")
|
||||
end
|
||||
|
||||
it "ssh should be accessible using certificate on different port and virtual machine size should be Medium" do
|
||||
params.delete(:password)
|
||||
default_options.merge!(:ssh_port => '2222', :vm_size => 'Medium', :private_key_file => private_key, :certificate_file => certificate)
|
||||
subject.create_virtual_machine(params, default_options)
|
||||
result = subject.get_virtual_machine(virtual_machine_name, cloud_service_name)
|
||||
result.must_be_kind_of Azure::VirtualMachineManagement::VirtualMachine
|
||||
endpoints = {}
|
||||
result.tcp_endpoints.each do |tcp_endpoint|
|
||||
endpoints[tcp_endpoint["Name"]] =
|
||||
{
|
||||
"PublicPort" => tcp_endpoint["PublicPort"],
|
||||
"LocalPort" => tcp_endpoint["LocalPort"]
|
||||
}
|
||||
end
|
||||
endpoints.keys.must_include "SSH"
|
||||
assert_equal(endpoints["SSH"]["PublicPort"], "2222")
|
||||
assert_equal(endpoints["SSH"]["LocalPort"], "22")
|
||||
assert_equal(result.role_size, 'Medium')
|
||||
end
|
||||
|
||||
it "throws Runtime error as port value is beyond or less than actual range" do
|
||||
default_options.merge!(:tcp_endpoints => '80,166535:166535')
|
||||
msg = subject.create_virtual_machine(params, default_options)
|
||||
msg = subject.create_virtual_machine(params, default_options,add_role=false)
|
||||
assert_match(/invalid. Allowed values are 'a number between 1 to 65535'./i, msg)
|
||||
|
||||
default_options.merge!(:tcp_endpoints => '80,0:0')
|
||||
msg = subject.create_virtual_machine(params, default_options)
|
||||
msg = subject.create_virtual_machine(params, default_options,add_role=false)
|
||||
assert_match(/invalid. Allowed values are 'a number between 1 to 65535'./i, msg)
|
||||
|
||||
cloud_service.delete_cloud_service(cloud_service_name)
|
||||
end
|
||||
|
||||
it "throws error when multiple VMs created under same DNS" do
|
||||
subject.create_virtual_machine(params, default_options)
|
||||
subject.create_virtual_machine(params, default_options,add_role=false)
|
||||
msg = subject.create_virtual_machine(windows_params, default_options)
|
||||
assert_match(/The specified deployment slot Production is occupied./i,msg)
|
||||
end
|
||||
|
@ -199,34 +180,34 @@ describe Azure::VirtualMachineManagementService do
|
|||
|
||||
it "error thrown when invalid storage account name is given" do
|
||||
default_options.merge!(:storage_account_name=>'storageuse_91')
|
||||
msg = subject.create_virtual_machine(params, default_options)
|
||||
msg = subject.create_virtual_machine(params, default_options,add_role=false)
|
||||
assert_match(/The name is not a valid storage account name./i, msg)
|
||||
cloud_service.delete_cloud_service(cloud_service_name)
|
||||
end
|
||||
|
||||
it "error thrown when invalid cloud name is given" do
|
||||
default_options.merge!(:cloud_service_name => 'cloud-server-test_91')
|
||||
msg = subject.create_virtual_machine(params, default_options)
|
||||
msg = subject.create_virtual_machine(params, default_options,add_role=false)
|
||||
assert_match(/The hosted service name is invalid/i, msg)
|
||||
end
|
||||
|
||||
it "error thrown when invalid deployment name provided" do
|
||||
default_options.merge!(:deployment_name => 'instance_B')
|
||||
msg = subject.create_virtual_machine(params, default_options)
|
||||
msg = subject.create_virtual_machine(params, default_options,add_role=false)
|
||||
assert_match(/The deployment name is invalid/i, msg)
|
||||
cloud_service.delete_cloud_service(cloud_service_name)
|
||||
end
|
||||
|
||||
it "error thrown when invalid Virtual Machine name for Windows OS provided" do
|
||||
windows_params.merge!(:vm_name => "MSServerInstnce01")
|
||||
msg = subject.create_virtual_machine(windows_params, default_options)
|
||||
msg = subject.create_virtual_machine(windows_params, default_options,add_role=false)
|
||||
assert_match(/The computer name cannot be more than 15 characters long, be entirely numeric, or contain the following characters/i, msg)
|
||||
cloud_service.delete_cloud_service(cloud_service_name)
|
||||
end
|
||||
|
||||
it "error thrown when blank password for Windows OS provided" do
|
||||
windows_params.delete(:password)
|
||||
msg = subject.create_virtual_machine(windows_params, default_options)
|
||||
msg = subject.create_virtual_machine(windows_params, default_options,add_role=false)
|
||||
assert_match(/You did not provide a valid 'password' value./i, msg)
|
||||
end
|
||||
|
||||
|
|
|
@ -72,17 +72,6 @@ class VirtualMachineNameGenerator
|
|||
end
|
||||
end
|
||||
|
||||
# Delete SQL servers
|
||||
Azure.config.management_endpoint = SqlServerEndpoint
|
||||
sql_database_service = Azure::SqlDatabaseManagementService.new
|
||||
sql_database_servers = sql_database_service.list_servers
|
||||
sql_database_servers.each do |sql_server|
|
||||
if sql_server.administrator_login == 'ms_open_tech'
|
||||
sql_database_service.delete_server(sql_server.name) rescue nil
|
||||
end
|
||||
end
|
||||
Azure.config.management_endpoint = ManagementServiceEndpoint
|
||||
|
||||
# Delete disks
|
||||
disk_management_service = Azure::VirtualMachineImageManagement::VirtualMachineDiskManagementService.new
|
||||
disks = disk_management_service.list_virtual_machine_disks
|
||||
|
|
|
@ -20,19 +20,42 @@ describe Azure::CloudServiceManagement::Serialization do
|
|||
let(:cloud_services_from_xml) { Fixtures['list_cloud_services'] }
|
||||
|
||||
describe '#cloud_services_from_xml' do
|
||||
|
||||
let (:cloud_services_xml) { Nokogiri::XML(cloud_services_from_xml) }
|
||||
it 'accepts an XML string' do
|
||||
subject.cloud_services_from_xml Nokogiri::XML(cloud_services_from_xml)
|
||||
end
|
||||
|
||||
it 'returns an Array of CloudService instances' do
|
||||
results = subject.cloud_services_from_xml(
|
||||
Nokogiri::XML(cloud_services_from_xml)
|
||||
)
|
||||
results = subject.cloud_services_from_xml(cloud_services_xml)
|
||||
results.must_be_kind_of Array
|
||||
results[0].must_be_kind_of(Azure::CloudServiceManagement::CloudService)
|
||||
results.count.must_equal 2
|
||||
end
|
||||
|
||||
it 'populates all properties for a cloud service' do
|
||||
results = subject.cloud_services_from_xml(cloud_services_xml)
|
||||
cloud = results.first
|
||||
cloud_xml = cloud_services_xml.css('HostedServices HostedService').first
|
||||
cloud.url.must_equal(cloud_xml.css('Url').text)
|
||||
cloud.name.must_equal(cloud_xml.css('ServiceName').text)
|
||||
cloud.description.must_equal(cloud_xml.css('Description').text)
|
||||
cloud.location.must_equal(cloud_xml.css('Location').text)
|
||||
cloud.label.must_equal(Base64.decode64(cloud_xml.css('Label').text))
|
||||
cloud.status.must_equal(cloud_xml.css('Status').text)
|
||||
cloud.date_created.must_equal(cloud_xml.css('DateCreated').text)
|
||||
cloud.date_modified.must_equal(cloud_xml.css('DateLastModified').text)
|
||||
cloud.extended_properties.size.must_equal(
|
||||
cloud_xml.css('ExtendedProperties ExtendedProperty').size
|
||||
)
|
||||
cloud_xml.css('ExtendedProperties ExtendedProperty').each do |p|
|
||||
cloud.extended_properties[p.css('Name').text].must_equal(
|
||||
p.css('Value').text
|
||||
)
|
||||
end
|
||||
cloud.default_winrm_certificate_thumbprint.must_equal(
|
||||
cloud_xml.css('DefaultWinRMCertificateThumbprint').text
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#cloud_services_to_xml' do
|
||||
|
@ -42,6 +65,31 @@ describe Azure::CloudServiceManagement::Serialization do
|
|||
subject.cloud_services_to_xml cloud_service_name
|
||||
end
|
||||
|
||||
it 'uses name for label if label not provided' do
|
||||
results = subject.cloud_services_to_xml(
|
||||
cloud_service_name,
|
||||
{
|
||||
location: 'East Asia'
|
||||
}
|
||||
)
|
||||
|
||||
doc = Nokogiri::XML(results)
|
||||
Base64.decode64(doc.css('Label').text).must_equal(cloud_service_name)
|
||||
end
|
||||
|
||||
it 'uses label when label is provided' do
|
||||
results = subject.cloud_services_to_xml(
|
||||
cloud_service_name,
|
||||
{
|
||||
location: 'East Asia',
|
||||
label: 'My Label'
|
||||
}
|
||||
)
|
||||
|
||||
doc = Nokogiri::XML(results)
|
||||
Base64.decode64(doc.css('Label').text).must_equal('My Label')
|
||||
end
|
||||
|
||||
it 'serializes the argument to xml' do
|
||||
results = subject.cloud_services_to_xml(
|
||||
cloud_service_name, { location: 'West US' }
|
||||
|
@ -52,15 +100,60 @@ describe Azure::CloudServiceManagement::Serialization do
|
|||
doc.css('Location').text.must_equal 'West US'
|
||||
end
|
||||
|
||||
it 'uses affinity_group if provided' do
|
||||
it 'uses affinity_group if provided and ignores location' do
|
||||
results = subject.cloud_services_to_xml(
|
||||
cloud_service_name,
|
||||
{ affinity_group_name: 'my-affinity-group', location: 'West US' }
|
||||
{
|
||||
affinity_group_name: 'my-affinity-group',
|
||||
location: 'West US'
|
||||
}
|
||||
)
|
||||
results.must_be_kind_of String
|
||||
doc = Nokogiri::XML results
|
||||
doc.css('ServiceName').text.must_equal cloud_service_name
|
||||
doc.css('AffinityGroup').text.must_equal 'my-affinity-group'
|
||||
doc.css('ServiceName').text.must_equal(cloud_service_name)
|
||||
doc.css('AffinityGroup').wont_be_empty
|
||||
doc.css('AffinityGroup').text.must_equal('my-affinity-group')
|
||||
doc.css('Location').must_be_empty
|
||||
end
|
||||
|
||||
it 'uses location when affinity group not provided' do
|
||||
results = subject.cloud_services_to_xml(
|
||||
cloud_service_name,
|
||||
{
|
||||
location: 'East Asia'
|
||||
}
|
||||
)
|
||||
|
||||
doc = Nokogiri::XML(results)
|
||||
doc.css('AffinityGroup').must_be_empty
|
||||
doc.css('Location').wont_be_empty
|
||||
doc.css('Location').text.must_equal('East Asia')
|
||||
end
|
||||
|
||||
it 'serializes extended properties when provided' do
|
||||
xtended_props = {
|
||||
prop_1_name: 'prop_1_value',
|
||||
prop_2_name: 'prop_2_value'
|
||||
}
|
||||
results = subject.cloud_services_to_xml(
|
||||
cloud_service_name,
|
||||
{
|
||||
extended_properties: xtended_props
|
||||
}
|
||||
)
|
||||
|
||||
doc = Nokogiri::XML(results)
|
||||
props_xml = doc.css('ExtendedProperties ExtendedProperty')
|
||||
props_xml.wont_be_empty
|
||||
props_xml.size.must_equal(2)
|
||||
props_xml.css('Name').first.text.must_equal('prop_1_name')
|
||||
props_xml.css('Value').first.text.must_equal(
|
||||
xtended_props[:"#{props_xml.css('Name').first.text}"]
|
||||
)
|
||||
props_xml.css('Name').last.text.must_equal('prop_2_name')
|
||||
props_xml.css('Value').last.text.must_equal(
|
||||
xtended_props[:"#{props_xml.css('Name').last.text}"]
|
||||
)
|
||||
end
|
||||
|
||||
it 'serializes the options hash to xml' do
|
||||
|
@ -73,4 +166,4 @@ describe Azure::CloudServiceManagement::Serialization do
|
|||
results.must_be_kind_of String
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,6 +19,15 @@ describe Azure::SqlDatabaseManagement::Serialization do
|
|||
|
||||
let(:sql_servers_xml) { Fixtures['list_sql_database'] }
|
||||
|
||||
before {
|
||||
@rdfe = Azure.config.disable_sql_rdfe
|
||||
Azure.config.disable_sql_rdfe = 'true'
|
||||
}
|
||||
|
||||
after {
|
||||
Azure.config.disable_sql_rdfe = "#{@rdfe}"
|
||||
}
|
||||
|
||||
describe '#databases_from_xml' do
|
||||
|
||||
it 'accepts an XML string' do
|
||||
|
|
|
@ -14,17 +14,24 @@
|
|||
#--------------------------------------------------------------------------
|
||||
require 'test_helper'
|
||||
|
||||
describe Azure::SqlDatabaseManagementService do
|
||||
describe 'Azure::SqlDatabaseManagementService - non-RDFE Endpoint' do
|
||||
subject { Azure::SqlDatabaseManagementService.new }
|
||||
|
||||
let(:response_headers) { {} }
|
||||
let(:mock_request) { mock }
|
||||
let(:response) { mock }
|
||||
let(:response_xml) { nil }
|
||||
|
||||
before do
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
mock_request.stubs(:headers).returns(response_headers)
|
||||
mock_request.expects(:call).returns(Nokogiri::XML response_xml).at_least(0)
|
||||
@rdfe_off = Azure.config.disable_sql_rdfe
|
||||
Azure.config.disable_sql_rdfe = 'true'
|
||||
end
|
||||
|
||||
after do
|
||||
Azure.config.disable_sql_rdfe = "#{@rdfe_off}"
|
||||
end
|
||||
|
||||
describe '#list_servers' do
|
||||
|
@ -33,7 +40,7 @@ describe Azure::SqlDatabaseManagementService do
|
|||
let(:request_path) { '/servers' }
|
||||
|
||||
before do
|
||||
ManagementHttpRequest.stubs(:new).with(
|
||||
SqlManagementHttpRequest.stubs(:new).with(
|
||||
method,
|
||||
request_path,
|
||||
nil
|
||||
|
@ -91,7 +98,7 @@ describe Azure::SqlDatabaseManagementService do
|
|||
:list_servers
|
||||
).returns([sql_server])
|
||||
|
||||
ManagementHttpRequest.stubs(:new).with(
|
||||
SqlManagementHttpRequest.stubs(:new).with(
|
||||
method,
|
||||
request_path,
|
||||
nil
|
||||
|
@ -119,7 +126,7 @@ describe Azure::SqlDatabaseManagementService do
|
|||
let(:location) { 'West US' }
|
||||
|
||||
before do
|
||||
ManagementHttpRequest.stubs(:new).with(
|
||||
SqlManagementHttpRequest.stubs(:new).with(
|
||||
method,
|
||||
request_path,
|
||||
anything
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
#-------------------------------------------------------------------------
|
||||
# Copyright 2013 Microsoft Open Technologies, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#--------------------------------------------------------------------------
|
||||
require 'test_helper'
|
||||
|
||||
describe 'Azure::SqlDatabaseManagementService - RDFE Endpoint' do
|
||||
subject { Azure::SqlDatabaseManagementService.new }
|
||||
|
||||
let(:response_headers) { {} }
|
||||
let(:mock_request) { mock }
|
||||
let(:response) { mock }
|
||||
let(:response_xml) { nil }
|
||||
|
||||
before do
|
||||
Loggerx.expects(:puts).returns(nil).at_least(0)
|
||||
mock_request.stubs(:headers).returns(response_headers)
|
||||
mock_request.expects(:call).returns(Nokogiri::XML response_xml).at_least(0)
|
||||
@rdfe_off = Azure.config.disable_sql_rdfe
|
||||
Azure.config.disable_sql_rdfe = nil
|
||||
end
|
||||
|
||||
after do
|
||||
Azure.config.disable_sql_rdfe = "#{@rdfe_off}"
|
||||
end
|
||||
|
||||
describe '#list_servers' do
|
||||
let(:response_xml) { Fixtures['list_sql_database'] }
|
||||
let(:method) { :get }
|
||||
let(:request_path) { '/services/sqlservers/servers' }
|
||||
|
||||
before do
|
||||
ManagementHttpRequest.stubs(:new).with(
|
||||
method,
|
||||
request_path,
|
||||
nil
|
||||
).returns(mock_request)
|
||||
end
|
||||
|
||||
it 'assembles a URI for the request' do
|
||||
subject.list_servers
|
||||
end
|
||||
|
||||
it 'returns a list of sql servers for the account' do
|
||||
results = subject.list_servers
|
||||
results.must_be_kind_of Array
|
||||
results.length.must_equal 3
|
||||
sql_server = results.first
|
||||
sql_server.must_be_kind_of Azure::SqlDatabaseManagement::SqlDatabase
|
||||
sql_server.name.must_equal 'nn1koc2ney'
|
||||
sql_server.administrator_login.must_equal 'SqlServer2'
|
||||
sql_server.location.must_equal 'West US'
|
||||
sql_server.feature_name.must_equal 'Premium Mode'
|
||||
sql_server.feature_value.must_equal 'false'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#delete_server' do
|
||||
before do
|
||||
Azure::SqlDatabaseManagementService.any_instance.stubs(
|
||||
:list_servers
|
||||
).returns([])
|
||||
end
|
||||
|
||||
it 'error if sql server does not exists' do
|
||||
s_name = 'unknown-server'
|
||||
exception = assert_raises(Azure::Error::Error) do
|
||||
subject.delete_server s_name
|
||||
end
|
||||
s_id = Azure.config.subscription_id
|
||||
assert_match(/Subscription #{s_id} does not have server #{s_name}./i,
|
||||
exception.message)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe '#list_sql_server_firewall_rules' do
|
||||
let(:response_xml) { Fixtures['list_sql_server_firewall_rdfe'] }
|
||||
let(:method) { :get }
|
||||
let(:sql_server_name) { 'server1' }
|
||||
let(:request_path) { "/services/sqlservers/servers/#{sql_server_name}/firewallrules" }
|
||||
|
||||
before do
|
||||
sql_server = Azure::SqlDatabaseManagement::SqlDatabase.new do |server|
|
||||
server.name = sql_server_name
|
||||
end
|
||||
Azure::SqlDatabaseManagementService.any_instance.stubs(
|
||||
:list_servers
|
||||
).returns([sql_server])
|
||||
|
||||
ManagementHttpRequest.stubs(:new).with(
|
||||
method,
|
||||
request_path,
|
||||
nil
|
||||
).returns(mock_request)
|
||||
end
|
||||
|
||||
it 'assembles a URI for the sql server firewall request' do
|
||||
subject.list_sql_server_firewall_rules sql_server_name
|
||||
end
|
||||
|
||||
it 'returns a list of firewall of given sql servers' do
|
||||
results = subject.list_sql_server_firewall_rules sql_server_name
|
||||
results.must_be_kind_of Array
|
||||
results.length.must_equal 4
|
||||
results.first.must_be_kind_of Hash
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create_server' do
|
||||
let(:response_xml) { Fixtures['create_sql_database_server'] }
|
||||
let(:method) { :post }
|
||||
let(:request_path) { '/services/sqlservers/servers' }
|
||||
let(:password) { 'User@123' }
|
||||
let(:login) { 'ms_open_tech' }
|
||||
let(:location) { 'West US' }
|
||||
|
||||
before do
|
||||
ManagementHttpRequest.stubs(:new).with(
|
||||
method,
|
||||
request_path,
|
||||
anything
|
||||
).returns(mock_request)
|
||||
|
||||
mock_request.stubs(:headers).returns(response_headers)
|
||||
mock_request.expects(:call).returns(
|
||||
Nokogiri::XML response_xml
|
||||
).at_least(0)
|
||||
end
|
||||
|
||||
it 'create sql server' do
|
||||
sql_server = subject.create_server(login, password, location)
|
||||
sql_server.name.must_equal 'gxyfzrhx2c'
|
||||
sql_server.administrator_login.must_equal login
|
||||
sql_server.location.must_equal location
|
||||
end
|
||||
end
|
||||
|
||||
describe '#set_sql_server_firewall_rule' do
|
||||
it 'create sql server' do
|
||||
ip_range = { start_ip_address: '0.0.0.1', end_ip_address: '0.0.0.5' }
|
||||
exception = assert_raises(RuntimeError) do
|
||||
subject.set_sql_server_firewall_rule('zv2nfoah2t1', ip_range)
|
||||
end
|
||||
assert_match(/Missing parameter server_name or rule_name/i,
|
||||
exception.message)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -35,6 +35,14 @@ describe Azure::StorageManagement::Serialization do
|
|||
|
||||
describe "#storage_services_to_xml" do
|
||||
let(:storage_service_name) {'storage-service'}
|
||||
let(:storage_options) { {
|
||||
:extended_properties=> {
|
||||
:prop_1_name=>"prop_1_value"
|
||||
},
|
||||
:label=>"Test Label",
|
||||
:geo_replication_enabled=>true
|
||||
}
|
||||
}
|
||||
|
||||
it "accepts an name and options hash" do
|
||||
subject.storage_services_to_xml storage_service_name
|
||||
|
@ -61,5 +69,164 @@ describe Azure::StorageManagement::Serialization do
|
|||
doc.css('AffinityGroup').text.must_equal 'my-affinity-group'
|
||||
results.must_be_kind_of String
|
||||
end
|
||||
|
||||
it 'serializes geo_replication_enabled and extended_properties to xml' do
|
||||
results = subject.storage_services_to_xml(
|
||||
storage_service_name, storage_options
|
||||
)
|
||||
|
||||
doc = Nokogiri::XML(results)
|
||||
doc.css('GeoReplicationEnabled').text.must_equal(
|
||||
"#{storage_options[:geo_replication_enabled]}"
|
||||
)
|
||||
doc.css('ExtendedProperties ExtendedProperty').size.must_equal(1)
|
||||
doc.css('ExtendedProperties ExtendedProperty').first.css(
|
||||
'Name'
|
||||
).text.must_equal('prop_1_name')
|
||||
doc.css('ExtendedProperties ExtendedProperty').first.css(
|
||||
'Value'
|
||||
).text.must_equal(storage_options[:extended_properties][:prop_1_name])
|
||||
end
|
||||
|
||||
it 'uses provided label instead of name for Label' do
|
||||
options = {
|
||||
label: 'My Label'
|
||||
}
|
||||
results = subject.storage_services_to_xml(storage_service_name, options)
|
||||
doc = Nokogiri::XML(results)
|
||||
Base64.decode64(doc.css('Label').text).must_equal(options[:label])
|
||||
end
|
||||
|
||||
it 'uses name for Label when label is not provided' do
|
||||
results = subject.storage_services_to_xml(storage_service_name)
|
||||
doc = Nokogiri::XML(results)
|
||||
Base64.decode64(doc.css('Label').text).must_equal(storage_service_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#storage_update_to_xml" do
|
||||
nil_options = {
|
||||
description: nil,
|
||||
label: nil,
|
||||
geo_replication_enabled: 'nil',
|
||||
extended_properties: nil
|
||||
}
|
||||
|
||||
let(:empty_options) { {
|
||||
description: '',
|
||||
label: '',
|
||||
geo_replication_enabled: '',
|
||||
extended_properties: ''
|
||||
}
|
||||
}
|
||||
|
||||
let(:partial_options_gre_bool) { {
|
||||
label: 'label',
|
||||
geo_replication_enabled: false
|
||||
}
|
||||
}
|
||||
|
||||
let(:partial_options_gre_string) { {
|
||||
description: 'label',
|
||||
geo_replication_enabled: 'false'
|
||||
}
|
||||
}
|
||||
|
||||
let(:options) { {
|
||||
extended_properties: {
|
||||
prop_1_name: 'prop_1_value'
|
||||
},
|
||||
description: 'Test Description',
|
||||
label: 'Test Label',
|
||||
geo_replication_enabled: true
|
||||
}
|
||||
}
|
||||
|
||||
let(:no_options_message) {'No options specified'}
|
||||
let(:label_or_desc_required) { 'Either one of Label or Description has to be provided. Both cannot be empty' }
|
||||
|
||||
it "checks if the parameter is nil" do
|
||||
exception = assert_raises RuntimeError do
|
||||
subject.storage_update_to_xml nil
|
||||
end
|
||||
assert_match no_options_message, exception.message
|
||||
end
|
||||
|
||||
it "checks if the parameter is empty" do
|
||||
exception = assert_raises RuntimeError do
|
||||
subject.storage_update_to_xml Hash.new
|
||||
end
|
||||
assert_match no_options_message, exception.message
|
||||
end
|
||||
|
||||
it "checks if all options are nil" do
|
||||
exception = assert_raises RuntimeError do
|
||||
subject.storage_update_to_xml nil_options
|
||||
end
|
||||
assert_match label_or_desc_required, exception.message
|
||||
end
|
||||
|
||||
it "checks if all options are empty" do
|
||||
exception = assert_raises RuntimeError do
|
||||
subject.storage_update_to_xml empty_options
|
||||
end
|
||||
assert_match label_or_desc_required, exception.message
|
||||
end
|
||||
|
||||
it "returns xml for the partial options provided" do
|
||||
storage_update_xml_string = subject.storage_update_to_xml partial_options_gre_bool
|
||||
storage_update_xml_string.must_be_kind_of String
|
||||
|
||||
storage_update_xml = Nokogiri::XML storage_update_xml_string
|
||||
storage_update_xml.css('Label').text.must_equal(Base64::encode64(partial_options_gre_bool[:label]))
|
||||
storage_update_xml.css('GeoReplicationEnabled').text.must_equal "#{partial_options_gre_bool[:geo_replication_enabled]}"
|
||||
|
||||
storage_update_xml.css('Description').size.must_equal 0
|
||||
storage_update_xml.css('ExtendedProperties').size.must_equal 0
|
||||
end
|
||||
|
||||
it "returns xml for the partial options provided without gre" do
|
||||
storage_update_xml_string = subject.storage_update_to_xml partial_options_gre_string
|
||||
storage_update_xml_string.must_be_kind_of String
|
||||
|
||||
storage_update_xml = Nokogiri::XML storage_update_xml_string
|
||||
storage_update_xml.css('Description').size.must_equal 1
|
||||
storage_update_xml.css('Description').text.must_equal partial_options_gre_string[:description]
|
||||
|
||||
storage_update_xml.css('GeoReplicationEnabled').size.must_equal 0
|
||||
|
||||
storage_update_xml.css('ExtendedProperties').size.must_equal 0
|
||||
end
|
||||
|
||||
it "returns xml for the options provided" do
|
||||
update_xml_string = subject.storage_update_to_xml options
|
||||
update_xml_string.must_be_kind_of String
|
||||
|
||||
update_xml = Nokogiri::XML update_xml_string
|
||||
|
||||
update_xml.css('Label').text.must_equal(Base64::encode64(options[:label]))
|
||||
update_xml.css('GeoReplicationEnabled').size.must_equal 1
|
||||
update_xml.css('GeoReplicationEnabled').text.must_equal "#{options[:geo_replication_enabled]}"
|
||||
|
||||
update_xml.css('ExtendedProperties ExtendedProperty').size.must_equal 1
|
||||
update_xml.css('ExtendedProperties ExtendedProperty Name').text.must_equal "#{:prop_1_name}"
|
||||
update_xml.css('ExtendedProperties ExtendedProperty Value').text.must_equal options[:extended_properties][:prop_1_name]
|
||||
end
|
||||
|
||||
it "returns xml for options but with description in absence of label" do
|
||||
options.delete(:label)
|
||||
update_xml_string = subject.storage_update_to_xml(options)
|
||||
update_xml_string.must_be_kind_of(String)
|
||||
|
||||
update_xml = Nokogiri::XML(update_xml_string)
|
||||
|
||||
update_xml.css('Description').text.must_equal(options[:description])
|
||||
update_xml.css('GeoReplicationEnabled').size.must_equal(1)
|
||||
update_xml.css('ExtendedProperties ExtendedProperty').size.must_equal(1)
|
||||
update_xml.css('ExtendedProperties ExtendedProperty Name').text
|
||||
.must_equal("#{:prop_1_name}")
|
||||
update_xml.css('ExtendedProperties ExtendedProperty Value')
|
||||
.text.must_equal(options[:extended_properties][:prop_1_name])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -55,7 +55,6 @@ describe Azure::StorageManagementService do
|
|||
end
|
||||
|
||||
describe "#get_storage_account" do
|
||||
|
||||
before {
|
||||
ManagementHttpRequest.stubs(:new).with(method, request_path, nil).returns(mock_request)
|
||||
mock_request.expects(:call).returns(response_body)
|
||||
|
@ -77,6 +76,33 @@ describe Azure::StorageManagementService do
|
|||
end
|
||||
|
||||
describe "#create_storage_account" do
|
||||
let(:options) {
|
||||
{
|
||||
location: 'East Asia',
|
||||
description: 'Test Storage Description'
|
||||
}
|
||||
}
|
||||
|
||||
it 'Checks if name is provided' do
|
||||
exception = assert_raises(RuntimeError) do
|
||||
subject.create_storage_account(options)
|
||||
end
|
||||
assert_match('Name not specified', exception.message)
|
||||
end
|
||||
|
||||
it 'Checks if name is not nil' do
|
||||
exception = assert_raises(RuntimeError) do
|
||||
subject.create_storage_account('', options)
|
||||
end
|
||||
assert_match('Name not specified', exception.message)
|
||||
end
|
||||
|
||||
it 'Checks if name is not empty' do
|
||||
exception = assert_raises(RuntimeError) do
|
||||
subject.create_storage_account('', options)
|
||||
end
|
||||
assert_match('Name not specified', exception.message)
|
||||
end
|
||||
|
||||
it "Create storage account return message if storage account exists of given name." do
|
||||
ManagementHttpRequest.any_instance.expects(:call).returns response_body
|
||||
|
@ -91,4 +117,117 @@ describe Azure::StorageManagementService do
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
describe "#update_storage_account" do
|
||||
let(:updated_accounts_xml) { Fixtures["updated_storage_accounts"] }
|
||||
let(:no_options_specified) { 'No options specified' }
|
||||
let(:update_storage_account_req) { Fixtures["update_storage_account"] }
|
||||
|
||||
let(:updated_storage_account_mock_request){ mock() }
|
||||
let(:updated_storage_account_response) {
|
||||
updated_storage_account_response = mock()
|
||||
updated_storage_account_response.stubs(:body).returns(updated_accounts_xml)
|
||||
updated_storage_account_response
|
||||
}
|
||||
let(:updated_storage_account_response_body) {Nokogiri::XML updated_storage_account_response.body}
|
||||
|
||||
let(:update_request) {
|
||||
update_request = mock()
|
||||
update_request.stubs(:body).returns('')
|
||||
update_request
|
||||
}
|
||||
|
||||
before {
|
||||
ManagementHttpRequest.stubs(:new).with(method, request_path, nil).returns(mock_request)
|
||||
mock_request.expects(:call).returns(response_body)
|
||||
|
||||
Azure::StorageManagement::Serialization.stubs(:update_storage_account).returns(update_storage_account_req)
|
||||
}
|
||||
|
||||
let(:options) { {
|
||||
description: 'Test Description',
|
||||
label: 'Test Label',
|
||||
geo_replication_enabled: false,
|
||||
extended_properties: {
|
||||
prop_1_name: 'prop_1_value',
|
||||
prop_2_name: 'prop_2_value'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it "checks if nil options is provided" do
|
||||
exception = assert_raises RuntimeError do
|
||||
subject.update_storage_account 'storage2', nil
|
||||
end
|
||||
assert_match no_options_specified, exception.message
|
||||
end
|
||||
|
||||
it "checks if empty options is provided" do
|
||||
exception = assert_raises RuntimeError do
|
||||
subject.update_storage_account 'storage2', Hash.new
|
||||
end
|
||||
assert_match no_options_specified, exception.message
|
||||
end
|
||||
|
||||
it "checks if account exists before updating" do
|
||||
ret_val = subject.update_storage_account 'storage3', Hash.new
|
||||
ret_val.must_equal "Storage Account 'storage3' does not exist. Skipped..."
|
||||
end
|
||||
|
||||
it "updates the specified account" do
|
||||
ManagementHttpRequest.stubs(:new).with(:put, "#{request_path}/storage2", update_storage_account_req).returns(update_request)
|
||||
update_request.expects(:call).returns('')
|
||||
|
||||
subject.update_storage_account 'storage2', options
|
||||
|
||||
ManagementHttpRequest.stubs(:new).with(method, request_path, nil).returns(updated_storage_account_mock_request)
|
||||
updated_storage_account_mock_request.expects(:call).returns(updated_storage_account_response_body)
|
||||
|
||||
accounts = subject.list_storage_accounts
|
||||
|
||||
accounts.each { |account|
|
||||
next unless account.name == 'storage2'
|
||||
|
||||
account.name.must_equal 'storage2'
|
||||
account.label.must_equal options[:label]
|
||||
account.geo_replication_enabled.must_equal "#{options[:geo_replication_enabled]}"
|
||||
|
||||
account.extended_properties.each { |prop|
|
||||
prop[:value].must_equal "#{options[:extended_properties][:"#{prop[:name]}"]}"
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_storage_account_properties' do
|
||||
let(:account_name) { 'storage2' }
|
||||
let(:label) { 'ValidLabel' }
|
||||
let(:request_path) { "/services/storageservices/#{account_name}" }
|
||||
let(:account_xml) { Fixtures['get_storage_account_properties'] }
|
||||
|
||||
let(:get_account_mock_request) { mock() }
|
||||
let(:get_account_response) {
|
||||
get_account_response = mock()
|
||||
get_account_response.stubs(:body).returns(account_xml)
|
||||
get_account_response
|
||||
}
|
||||
let(:get_account_response_body) {
|
||||
Nokogiri::XML(get_account_response.body)
|
||||
}
|
||||
|
||||
before {
|
||||
ManagementHttpRequest.stubs(:new).with(
|
||||
:get, request_path, nil
|
||||
).returns(get_account_mock_request)
|
||||
get_account_mock_request.expects(:call).returns(
|
||||
get_account_response_body
|
||||
)
|
||||
}
|
||||
|
||||
it 'returns the label as a Base64 decoded string' do
|
||||
account = subject.get_storage_account_properties(account_name)
|
||||
account.label.must_be_kind_of(String)
|
||||
account.label.must_equal(label)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче