Merge branch 'master' of github.com:opscode/knife-azure into OC-7832

Conflicts:
	lib/chef/knife/azure_server_list.rb
This commit is contained in:
Chirag Jog 2013-05-24 12:22:57 +05:30
Родитель cc1352b912 d144be6d2b
Коммит bd9f0ce2f3
16 изменённых файлов: 357 добавлений и 66 удалений

Просмотреть файл

@ -24,7 +24,6 @@ require 'rspec/core'
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec) do |spec|
spec.pattern = FileList['spec/unit/**/*_spec.rb']
touch "AzureLinuxCert.pem"
end
RSpec::Core::RakeTask.new(:functional) do |spec|

87
lib/azure/certificate.rb Executable file
Просмотреть файл

@ -0,0 +1,87 @@
#
# Author:: Mukta Aphale (mukta.aphale@clogeny.com)
# Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
# License:: Apache License, Version 2.0
#
# 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.
#
class Azure
class Certificates
def initialize(connection)
@connection=connection
end
def create(params)
certificate = Certificate.new(@connection)
certificate.create(params)
end
end
end
class Azure
class Certificate
attr_accessor :connection
attr_accessor :cert_data, :fingerprint, :certificate_version
def initialize(connection)
@connection = connection
@certificate_version = 2 # cf. RFC 5280 - to make it a "v3" certificate
end
def create(params)
# If RSA private key has been specified, then generate an x 509 certificate from the
# public part of the key
@cert_data = generate_public_key_certificate_data({:ssh_key => params[:identity_file],
:ssh_key_passphrase => params[:identity_file_passphrase]})
# Generate XML to call the API
# Add certificate to the hosted service
builder = Nokogiri::XML::Builder.new do |xml|
xml.CertificateFile('xmlns'=>'http://schemas.microsoft.com/windowsazure') {
xml.Data @cert_data
xml.CertificateFormat 'pfx'
xml.Password 'knifeazure'
}
end
# Windows Azure API call
@connection.query_azure("hostedservices/#{params[:hosted_service_name]}/certificates", "post", builder.to_xml)
# Return the fingerprint to be used while adding role
@fingerprint
end
def generate_public_key_certificate_data (params)
# Generate OpenSSL RSA key from the mentioned ssh key path (and passphrase)
key = OpenSSL::PKey::RSA.new(File.read(params[:ssh_key]), params[:ssh_key_passphrase])
# Generate X 509 certificate
ca = OpenSSL::X509::Certificate.new
ca.version = @certificate_version
ca.serial = Random.rand(65534) + 1 # 2 digit byte range random number for better security aspect
ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=knife-plugin/CN=Opscode CA"
ca.issuer = ca.subject # root CA's are "self-signed"
ca.public_key = key.public_key # Assign the ssh-key's public part to the certificate
ca.not_before = Time.now
ca.not_after = ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = ca
ef.issuer_certificate = ca
ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
ca.sign(key, OpenSSL::Digest::SHA256.new)
# Generate the SHA1 fingerprint of the der format of the X 509 certificate
@fingerprint = OpenSSL::Digest::SHA1.new(ca.to_der)
# Create the pfx format of the certificate
pfx = OpenSSL::PKCS12.create('knifeazure', 'knife-azure-pfx', key, ca)
# Encode the pfx format - upload this certificate
Base64.strict_encode64(pfx.to_der)
end
end
end

Просмотреть файл

@ -23,11 +23,12 @@ require File.expand_path('../deploy', __FILE__)
require File.expand_path('../role', __FILE__)
require File.expand_path('../disk', __FILE__)
require File.expand_path('../image', __FILE__)
require File.expand_path('../certificate', __FILE__)
class Azure
class Connection
include AzureAPI
attr_accessor :hosts, :rest, :images, :deploys, :roles, :disks, :storageaccounts
attr_accessor :hosts, :rest, :images, :deploys, :roles, :disks, :storageaccounts, :certificates
def initialize(params={})
@rest = Rest.new(params)
@hosts = Hosts.new(self)
@ -36,6 +37,7 @@ class Azure
@deploys = Deploys.new(self)
@roles = Roles.new(self)
@disks = Disks.new(self)
@certificates = Certificates.new(self)
end
def query_azure(service_name, verb = 'get', body = '')
Chef::Log.info 'calling ' + verb + ' ' + service_name

Просмотреть файл

@ -48,6 +48,9 @@ class Azure
unless @connection.storageaccounts.exists(params[:storage_account])
@connection.storageaccounts.create(params)
end
if params[:identity_file]
params[:fingerprint] = @connection.certificates.create(params)
end
params['deploy_name'] = find(params[:hosted_service_name])
if params['deploy_name'] != nil
role = Role.new(@connection)

Просмотреть файл

@ -33,7 +33,20 @@ class Azure
end
@roles
end
def find(name)
def find_in_hosted_service(name, hostedservicename)
find_roles_with_hostedservice(hostedservicename).each do | role |
if (role.name == name)
return role
end
end
return nil
end
def find(name, params= nil)
if params && params[:azure_hosted_service_name]
return find_in_hosted_service(name, params[:azure_hosted_service_name])
end
if @roles == nil
all
end
@ -44,8 +57,7 @@ class Azure
end
nil
end
def alone_on_host(name)
found_role = find(name)
def alone_on_host(found_role)
@roles.each do |role|
if (role.name != found_role.name &&
role.deployname == found_role.deployname &&
@ -61,7 +73,7 @@ class Azure
def delete(name, params)
role = find(name)
if role != nil
if alone_on_host(name)
if alone_on_host(role)
servicecall = "hostedservices/#{role.hostedservicename}/deployments" +
"/#{role.deployname}"
else
@ -69,12 +81,24 @@ class Azure
"/#{role.deployname}/roles/#{role.name}"
end
roleXML = nil
if params[:purge_os_disk]
unless params[:preserve_os_disk]
roleXML = @connection.query_azure(servicecall, "get")
end
@connection.query_azure(servicecall, "delete")
# delete role from local cache as well.
@roles.delete(role)
if params[:purge_os_disk]
unless params[:preserve_hosted_service]
unless params[:hostedservicename].nil?
roles_using_same_service = find_roles_with_hostedservice(params[:hostedservicename])
if roles_using_same_service.size <= 1
servicecall = "hostedservices/" + params[:hostedservicename]
@connection.query_azure(servicecall, "delete")
end
end
end
unless params[:preserve_os_disk]
osdisk = roleXML.css(roleXML, 'OSVirtualHardDisk')
disk_name = xml_content(osdisk, 'DiskName')
servicecall = "disks/#{disk_name}"
@ -82,12 +106,24 @@ class Azure
end
end
end
def find_roles_with_hostedservice(hostedservicename)
if @roles == nil
all
end
return_roles = Array.new
@roles.each do |role|
if(role.hostedservicename == hostedservicename)
return_roles << role
end
end
return_roles
end
end
class Role
include AzureUtility
attr_accessor :connection, :name, :status, :size, :ipaddress
attr_accessor :sshport, :sshipaddress, :hostedservicename, :deployname
attr_accessor :winrmport, :winrmipaddress
attr_accessor :connection, :name, :status, :size, :ipaddress, :publicipaddress
attr_accessor :sshport, :hostedservicename, :deployname
attr_accessor :winrmport
attr_accessor :hostname, :tcpports, :udpports
def initialize(connection)
@ -105,13 +141,12 @@ class Azure
@udpports = Array.new
endpoints = roleXML.css('InstanceEndpoint')
@publicipaddress = xml_content(endpoints[0], 'Vip') if !endpoints.empty?
endpoints.each do |endpoint|
if xml_content(endpoint, 'Name').downcase == 'ssh'
@sshport = xml_content(endpoint, 'PublicPort')
@sshipaddress = xml_content(endpoint, 'Vip')
elsif xml_content(endpoint, 'Name').downcase == 'winrm'
@winrmport = xml_content(endpoint, 'PublicPort')
@winrmipaddress = xml_content(endpoint, 'Vip')
else
hash = Hash.new
hash['Name'] = xml_content(endpoint, 'Name')
@ -142,8 +177,20 @@ class Azure
xml.ConfigurationSetType 'LinuxProvisioningConfiguration'
xml.HostName params[:host_name]
xml.UserName params[:ssh_user]
unless params[:identity_file].nil?
xml.DisableSshPasswordAuthentication 'true'
xml.SSH {
xml.PublicKeys {
xml.PublicKey {
xml.Fingerprint params[:fingerprint]
xml.Path '/home/' + params[:ssh_user] + '/.ssh/authorized_keys'
}
}
}
else
xml.UserPassword params[:ssh_password]
xml.DisableSshPasswordAuthentication 'false'
end
}
elsif params[:os_type] == 'Windows'
xml.ConfigurationSet('i:type' => 'WindowsProvisioningConfigurationSet') {

Просмотреть файл

@ -49,7 +49,7 @@ class Chef
option :azure_host_name,
:short => "-H HOSTNAME",
:long => "--azure_host_name HOSTNAME",
:long => "--azure-host-name HOSTNAME",
:description => "Your Azure host name",
:proc => Proc.new { |key| Chef::Config[:knife][:azure_host_name] = key }

Просмотреть файл

@ -31,13 +31,18 @@ class Chef
require 'readline'
require 'chef/json_compat'
require 'chef/knife/bootstrap'
require 'chef/knife/bootstrap_windows_winrm'
require 'chef/knife/bootstrap_windows_ssh'
require 'chef/knife/core/windows_bootstrap_context'
require 'chef/knife/winrm'
Chef::Knife::Bootstrap.load_deps
end
def load_winrm_deps
require 'winrm'
require 'em-winrm'
require 'chef/knife/winrm'
require 'chef/knife/bootstrap_windows_winrm'
end
banner "knife azure server create (options)"
attr_accessor :initial_sleep_delay
@ -62,11 +67,6 @@ class Chef
:long => "--ssh-password PASSWORD",
:description => "The ssh password"
option :identity_file,
:short => "-i IDENTITY_FILE",
:long => "--identity-file IDENTITY_FILE",
:description => "The SSH identity file used for authentication"
option :prerelease,
:long => "--prerelease",
:description => "Install the pre-release chef gems"
@ -157,6 +157,13 @@ class Chef
:long => "--udp-endpoints PORT_LIST",
:description => "Comma separated list of UDP local and public ports to open i.e. '80:80,433:5000'"
option :identity_file,
:long => "--identity-file FILENAME",
:description => "SSH key path, optional. It is the RSA private key. Specify either ssh-password or identity-file"
option :identity_file_passphrase,
:long => "--identity-file-passphrase PASSWORD",
:description => "SSH key passphrase. Optional, specify if passphrase for identity-file exists"
def strip_non_ascii(string)
string.gsub(/[^0-9a-z ]/i, '')
@ -241,9 +248,6 @@ class Chef
end
puts ui.list(details, :columns_across, 4)
end
def is_platform_windows?
return RUBY_PLATFORM.scan('w32').size > 0
end
def run
$stdout.sync = true
@ -268,22 +272,13 @@ class Chef
config[:storage_account] = storage.name.to_s
end
end
if is_image_windows?
if is_platform_windows?
#require 'em-winrs'
else
require 'gssapi'
require 'winrm'
require 'em-winrm'
end
end
server = connection.deploys.create(create_server_def)
fqdn = server.publicipaddress
puts("\n")
if is_image_windows?
if locate_config_value(:bootstrap_protocol) == 'ssh'
fqdn = server.sshipaddress
port = server.sshport
print "\n#{ui.color("Waiting for sshd on #{fqdn}:#{port}", :magenta)}"
@ -293,7 +288,6 @@ class Chef
}
elsif locate_config_value(:bootstrap_protocol) == 'winrm'
fqdn = server.winrmipaddress
port = server.winrmport
print "\n#{ui.color("Waiting for winrm on #{fqdn}:#{port}", :magenta)}"
@ -307,12 +301,11 @@ class Chef
sleep 15
bootstrap_for_windows_node(server,fqdn).run
else
unless server && server.sshipaddress && server.sshport
unless server && server.publicipaddress && server.sshport
Chef::Log.fatal("server not created")
exit 1
end
fqdn = server.sshipaddress
port = server.sshport
print "\n#{ui.color("Waiting for sshd on #{fqdn}:#{port}", :magenta)}"
@ -340,13 +333,12 @@ class Chef
def bootstrap_for_windows_node(server, fqdn)
if locate_config_value(:bootstrap_protocol) == 'winrm'
if is_platform_windows?
#require 'em-winrs'
else
load_winrm_deps
if not Chef::Platform.windows?
require 'gssapi'
require 'winrm'
require 'em-winrm'
end
bootstrap = Chef::Knife::BootstrapWindowsWinrm.new
bootstrap.config[:winrm_user] = locate_config_value(:winrm_user) || 'Administrator'
@ -386,6 +378,7 @@ class Chef
bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
bootstrap.config[:distro] = locate_config_value(:distro)
bootstrap.config[:use_sudo] = true unless locate_config_value(:ssh_user) == 'root'
bootstrap.config[:use_sudo_password] = true if bootstrap.config[:use_sudo]
bootstrap.config[:template_file] = config[:template_file]
bootstrap.config[:environment] = locate_config_value(:environment)
# may be needed for vpc_mode
@ -430,12 +423,19 @@ class Chef
else
server_def[:os_type] = 'Linux'
server_def[:bootstrap_proto] = 'ssh'
if not locate_config_value(:ssh_user) or not locate_config_value(:ssh_password)
ui.error("SSH User and SSH Password are compulsory parameters")
if not locate_config_value(:ssh_user)
ui.error("SSH User is compulsory parameter")
exit 1
end
unless locate_config_value(:ssh_password) or locate_config_value(:identity_file)
ui.error("Specify either SSH Key or SSH Password")
exit 1
end
server_def[:ssh_user] = locate_config_value(:ssh_user)
server_def[:ssh_password] = locate_config_value(:ssh_password)
server_def[:identity_file] = locate_config_value(:identity_file)
server_def[:identity_file_passphrase] = locate_config_value(:identity_file_passphrase)
end
server_def
end

Просмотреть файл

@ -32,11 +32,11 @@ class Chef
banner "knife azure server delete SERVER [SERVER] (options)"
option :purge_os_disk,
:long => "--purge-os-disk",
option :preserve_os_disk,
:long => "--preserve-os-disk",
:boolean => true,
:default => true,
:description => "Destroy corresponding OS Disk"
:default => false,
:description => "Preserve corresponding OS Disk"
option :purge,
:short => "-P",
@ -50,6 +50,16 @@ class Chef
:long => "--node-name NAME",
:description => "The name of the node and client to delete, if it differs from the server name. Only has meaning when used with the '--purge' option."
option :preserve_hosted_service,
:long => "--preserve-hosted-service",
:boolean => true,
:default => false,
:description => "Dont destroy corresponding hosted service. If the option is not set, it deletes the service not used by any VMs."
option :azure_hosted_service_name,
:long => "--azure-dns-name NAME",
:description => "specifies the DNS name (also known as hosted service name)"
# Extracted from Chef::Knife.delete_object, because it has a
# confirmation step built in... By specifying the '--purge'
# flag (and also explicitly confirming the server destruction!)
@ -72,7 +82,7 @@ class Chef
@name_args.each do |name|
begin
server = connection.roles.find(name)
server = connection.roles.find(name, params = { :azure_hosted_service_name => locate_config_value(:azure_hosted_service_name) })
if not server
ui.warn("Server #{name} does not exist")
return
@ -82,13 +92,13 @@ class Chef
msg_pair('Deployment', server.deployname)
msg_pair('Role', server.name)
msg_pair('Size', server.size)
msg_pair('SSH Ip Address', server.sshipaddress)
msg_pair('SSH Port', server.sshport)
msg_pair('Public Ip Address', server.publicipaddress)
puts "\n"
confirm("Do you really want to delete this server")
connection.roles.delete(name, params = { :purge_os_disk => locate_config_value(:purge_os_disk) })
connection.roles.delete(name, params = { :preserve_os_disk => locate_config_value(:preserve_os_disk),
:preserve_hosted_service => locate_config_value(:preserve_hosted_service),
:hostedservicename => server.hostedservicename })
puts "\n"
ui.warn("Deleted server #{server.name}")

Просмотреть файл

@ -51,7 +51,7 @@ class Chef
ui.color('ready', :green)
end
end
server_list << server.sshipaddress.to_s
server_list << server.publicipaddress.to_s
server_list << server.sshport.to_s
server_list << server.winrmport.to_s
end

Просмотреть файл

@ -15,6 +15,10 @@ require 'chef/knife/azure_server_create'
require 'chef/knife/azure_server_describe'
require 'chef/knife/azure_image_list'
require 'fileutils'
#Create an empty mock certificate file
FileUtils.touch('AzureLinuxCert.pem')
def tmpFile filename
tmpdir = 'tmp'
Dir::mkdir tmpdir unless FileTest::directory?(tmpdir)

Просмотреть файл

@ -168,6 +168,52 @@ describe "for bootstrap protocol ssh:" do
@bootstrap.should_receive(:run)
@server_instance.run
end
context "ssh key" do
before do
Chef::Config[:knife][:ssh_password] = ''
Chef::Config[:knife][:identity_file] = 'ssh_key'
end
it "check if ssh-key set correctly" do
@server_instance.should_receive(:is_image_windows?).and_return(false)
@server_params = @server_instance.create_server_def
@server_params[:os_type].should == 'Linux'
@server_params[:identity_file].should == 'ssh_key'
@server_params[:ssh_user].should == 'ssh_user'
@server_params[:bootstrap_proto].should == 'ssh'
@server_params[:hosted_service_name].should == 'service001'
end
it "successful bootstrap with ssh key" do
@server_instance.should_receive(:is_image_windows?).exactly(3).times.and_return(false)
@bootstrap = Chef::Knife::Bootstrap.new
Chef::Knife::Bootstrap.stub(:new).and_return(@bootstrap)
@bootstrap.should_receive(:run)
@server_instance.connection.certificates.stub(:generate_public_key_certificate_data).and_return("cert_data")
@server_instance.connection.certificates.should_receive(:create)
@server_instance.run
end
end
context "bootstrap"
before do
@server_params = @server_instance.create_server_def
@bootstrap = Chef::Knife::Bootstrap.new
Chef::Knife::Bootstrap.stub(:new).and_return(@bootstrap)
end
it "enables sudo password when ssh_user is not root" do
@bootstrap.should_receive(:run)
@server_instance.run
@bootstrap.config[:use_sudo_password].should == true
end
it "does not enable sudo password when ssh_user is root" do
@bootstrap.should_receive(:run)
Chef::Config[:knife][:ssh_user] = 'root'
@server_instance.run
@bootstrap.config[:use_sudo_password].should_not == true
end
end
end

Просмотреть файл

@ -0,0 +1,90 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
require File.expand_path(File.dirname(__FILE__) + '/../unit/query_azure_mock')
describe Chef::Knife::AzureServerDelete do
include AzureSpecHelper
include QueryAzureMock
before do
@server_instance = Chef::Knife::AzureServerDelete.new
{
:azure_subscription_id => 'azure_subscription_id',
:azure_mgmt_cert => 'AzureLinuxCert.pem',
:azure_host_name => 'preview.core.windows-int.net',
:role_name => 'vm01',
:service_location => 'service_location',
:source_image => 'source_image',
:role_size => 'role_size',
:hosted_service_name => 'service001',
:storage_account => 'ka001testeurope'
}.each do |key, value|
Chef::Config[:knife][key] = value
end
stub_query_azure (@server_instance.connection)
@server_instance.stub(:confirm).and_return(:true)
@server_instance.stub(:puts)
@server_instance.stub(:print)
@server_instance.ui.stub(:warn)
@server_instance.ui.should_not_receive(:error).and_call_original
end
it "server delete test" do
@server_instance.name_args = ['vm01']
@server_instance.ui.should_receive(:warn).twice
@server_instance.connection.roles.should_receive(:delete).and_call_original
@server_instance.run
end
it "test hosted service cleanup with shared service" do
@server_instance.name_args = ['role001']
@server_instance.ui.should_receive(:warn).twice
@server_instance.connection.roles.should_receive(:delete).and_call_original
@server_instance.connection.hosts.should_not_receive(:delete)
@server_instance.run
end
it "dont cleanup hosted service when --preserve-hosted-service param set" do
@server_instance.name_args = ['vm01']
Chef::Config[:knife][:preserve_hosted_service] = true
@server_instance.ui.should_receive(:warn).twice
@server_instance.connection.roles.should_receive(:delete).and_call_original
@server_instance.connection.hosts.should_not_receive(:delete)
@server_instance.run
end
it "delete vm within a hosted service when --azure-dns-name param set" do
test_hostname = 'vm002'
@server_instance.name_args = [test_hostname]
Chef::Config[:knife][:azure_hosted_service_name] = 'service001'
Chef::Config[:knife][:preserve_os_disk] = true
@server_instance.connection.roles.should_receive(:delete).and_call_original
# test correct params are passed to azure API.
@server_instance.connection.should_receive(:query_azure).with("hostedservices/#{Chef::Config[:knife][:azure_hosted_service_name]}/deployments/deployment001/roles/#{test_hostname}", "delete")
@server_instance.run
end
it "delete multiple vm's within a hosted service when --azure-dns-name param set" do
test_hostnames = ['vm002', 'role002', 'role001']
@server_instance.name_args = test_hostnames
Chef::Config[:knife][:azure_hosted_service_name] = 'service001'
Chef::Config[:knife][:preserve_os_disk] = true
@server_instance.connection.roles.should_receive(:delete).exactly(3).times.and_call_original
# test correct calls are made to azure API.
@server_instance.connection.should_receive(:query_azure).with("hostedservices/#{Chef::Config[:knife][:azure_hosted_service_name]}/deployments/deployment001/roles/#{test_hostnames[0]}", "delete")
@server_instance.connection.should_receive(:query_azure).with("hostedservices/#{Chef::Config[:knife][:azure_hosted_service_name]}/deployments/deployment001/roles/#{test_hostnames[1]}", "delete")
@server_instance.connection.should_receive(:query_azure).with("hostedservices/#{Chef::Config[:knife][:azure_hosted_service_name]}/deployments/deployment001", "delete")
@server_instance.run
end
end

Просмотреть файл

@ -27,7 +27,7 @@ include AzureSpecHelper
role.size.should_not be_nil
role.ipaddress.should_not be_nil
role.sshport.should_not be_nil
role.sshipaddress.should_not be_nil
role.publicipaddress.should_not be_nil
end
end
end
@ -41,7 +41,7 @@ include AzureSpecHelper
puts 'size: ' + role.size
puts 'ip address: ' + role.ipaddress
puts 'ssh port: ' + role.sshport
puts 'ssh ip address: ' + role.sshipaddress
puts 'ssh ip address: ' + role.publicipaddress
role.tcpports.each do |port|
puts ' tcp: ' + port['Name'] + ' ' + port['Vip'] + ' ' +
port['PublicPort'] + ' ' + port['LocalPort']

Просмотреть файл

@ -1,4 +1,3 @@
module QueryAzureMock
def setup_query_azure_mock
create_connection
@ -36,8 +35,12 @@ module QueryAzureMock
retval = Nokogiri::XML readFile('list_hosts.xml')
elsif name == 'hostedservices/service001/deploymentslots/Production'
retval = Nokogiri::XML readFile('list_deployments_for_service001.xml')
elsif name == 'hostedservices/service001/deployments/deployment001/roles/role001'
retval = Nokogiri::XML readFile('list_deployments_for_service001.xml')
elsif name == 'hostedservices/service002/deploymentslots/Production'
retval = Nokogiri::XML readFile('list_deployments_for_service002.xml')
elsif name == 'hostedservices/service002/deployments/testrequest'
retval = Nokogiri::XML readFile('list_deployments_for_service002.xml')
elsif name == 'hostedservices/service003/deploymentslots/Production'
retval = Nokogiri::XML readFile('list_deployments_for_service003.xml')
elsif name == 'storageservices'

Просмотреть файл

@ -10,7 +10,7 @@ describe "roles" do
context 'delete a role' do
context 'when the role is not the only one in a deployment' do
it 'should pass in correct name, verb, and body' do
@connection.roles.delete('vm002', {:purge_os_disk => false});
@connection.roles.delete('vm002', {:preserve_os_disk => true});
@deletename.should == 'hostedservices/service001/deployments/deployment001/roles/vm002'
@deleteverb.should == 'delete'
@deletebody.should == nil
@ -20,7 +20,7 @@ describe "roles" do
context 'delete a role' do
context 'when the role is the only one in a deployment' do
it 'should pass in correct name, verb, and body' do
@connection.roles.delete('vm01', {:purge_os_disk => false});
@connection.roles.delete('vm01', {:preserve_os_disk => true});
@deletename.should == 'hostedservices/service002/deployments/testrequest'
@deleteverb.should == 'delete'
@deletebody.should == nil

Просмотреть файл

@ -27,6 +27,6 @@ describe "roles" do
role.size.should_not be_nil
role.ipaddress.should_not be_nil
role.sshport.should_not be_nil
role.sshipaddress.should_not be_nil
role.publicipaddress.should_not be_nil
end
end