This commit is contained in:
Mukta Aphale 2013-05-23 12:52:32 +05:30
Родитель c105f06bc2 011bc1e222
Коммит 07088d0fd2
12 изменённых файлов: 287 добавлений и 114 удалений

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

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

@ -50,7 +50,11 @@ class Azure
unless @connection.storageaccounts.exists(params[:azure_storage_account])
@connection.storageaccounts.create(params)
end
if params[:identity_file]
params[:fingerprint] = @connection.certificates.create(params)
end
params['deploy_name'] = find(params[:azure_dns_name])
if params['deploy_name'] != nil
role = Role.new(@connection)
roleXML = role.setup(params)

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

@ -33,22 +33,34 @@ 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
@roles.each do |role|
if(role.name == name)
return role
return role
end
end
nil
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 &&
if (role.name != found_role.name &&
role.deployname == found_role.deployname &&
role.hostedservicename == found_role.hostedservicename)
return false;
end
@ -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
@ -72,20 +84,21 @@ class Azure
unless params[:preserve_os_disk]
roleXML = @connection.query_azure(servicecall, "get")
end
@connection.query_azure(servicecall, "delete")
@connection.query_azure(servicecall, "delete")
# delete role from local cache as well.
@roles.delete(role)
unless params[:preserve_hosted_service]
unless params[:hostedservicename].nil?
roles_using_same_service = connection.roles.find_roles_with_hostedservice(params[:hostedservicename])
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')
osdisk = roleXML.css(roleXML, 'OSVirtualHardDisk')
disk_name = xml_content(osdisk, 'DiskName')
servicecall = "disks/#{disk_name}"
@connection.query_azure(servicecall, "delete")
@ -99,7 +112,7 @@ class Azure
return_roles = Array.new
@roles.each do |role|
if(role.hostedservicename == hostedservicename)
return_roles << role
return_roles << role
end
end
return_roles
@ -107,9 +120,9 @@ class Azure
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)
@ -125,15 +138,14 @@ class Azure
@deployname = deployname
@tcpports = Array.new
@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')
@ -159,13 +171,25 @@ class Azure
xml.RoleType 'PersistentVMRole'
xml.ConfigurationSets {
if params[:os_type] == 'Linux'
xml.ConfigurationSet('i:type' => 'LinuxProvisioningConfigurationSet') {
xml.ConfigurationSetType 'LinuxProvisioningConfiguration'
xml.HostName params[:azure_vm_name]
xml.UserName params[:ssh_user]
xml.UserPassword params[:ssh_password]
xml.DisableSshPasswordAuthentication 'false'
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') {
@ -183,7 +207,7 @@ class Azure
xml.InputEndpoints {
if params[:bootstrap_proto].downcase == 'ssh'
xml.InputEndpoint {
xml.LocalPort '22'
xml.LocalPort '22'
xml.Name 'SSH'
xml.Port params[:port]
xml.Protocol 'TCP'
@ -196,7 +220,7 @@ class Azure
xml.Protocol 'TCP'
}
end
if params[:tcp_endpoints]
params[:tcp_endpoints].split(',').each do |endpoint|
ports = endpoint.split(':')
@ -207,7 +231,7 @@ class Azure
xml.Port ports[1]
else
xml.Port ports[0]
end
end
xml.Protocol 'TCP'
}
end
@ -222,7 +246,7 @@ class Azure
xml.Port ports[1]
else
xml.Port ports[0]
end
end
xml.Protocol 'UDP'
}
end
@ -237,13 +261,13 @@ class Azure
}
xml.RoleSize params[:azure_vm_size]
}
end
end
builder.doc
end
def create(params, roleXML)
servicecall = "hostedservices/#{params[:azure_dns_name]}/deployments" +
"/#{params['deploy_name']}/roles"
@connection.query_azure(servicecall, "post", roleXML.to_xml)
@connection.query_azure(servicecall, "post", roleXML.to_xml)
end
end
end

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

@ -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
@ -67,11 +72,6 @@ class Chef
:description => "The ssh port. Default is 22.",
:default => '22'
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"
@ -170,6 +170,13 @@ class Chef
:default => false,
:description => "Set this flag to add the new VM to an existing deployment/service. Must give the name of the existing
DNS correctly in the --dns-name option"
option :identity_file,
:long => "--identity-file FILENAME",
:description => "SSH identity file for authentication, optional. It is the RSA private key path. 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, '')
@ -228,10 +235,6 @@ class Chef
tcp_socket && tcp_socket.close
end
def is_platform_windows?
return RUBY_PLATFORM.scan('w32').size > 0
end
def run
$stdout.sync = true
storage = nil
@ -256,18 +259,12 @@ class Chef
end
end
if is_image_windows?
require 'gssapi'
require 'winrm'
require 'em-winrm'
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)}"
@ -277,7 +274,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)}"
@ -291,12 +287,11 @@ class Chef
sleep 15
bootstrap_for_windows_node(server,fqdn, port).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)}"
@ -324,13 +319,12 @@ class Chef
def bootstrap_for_windows_node(server, fqdn, port)
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'
@ -437,16 +431,23 @@ 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
end
end
end

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

@ -55,6 +55,11 @@ class Chef
: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!)
@ -77,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
@ -87,8 +92,7 @@ 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")

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

@ -33,18 +33,13 @@ class Chef
validate!
server_list = [
ui.color('Status', :bold),
ui.color('Service', :bold),
ui.color('Deployment', :bold),
ui.color('Role', :bold),
ui.color('Host', :bold),
ui.color('IP Address', :bold),
ui.color('SSH Port', :bold),
ui.color('WinRM Port', :bold)
]
server_labels = ['DNS Name', 'VM Name', 'Status', 'IP Address', 'SSH Port', 'WinRM Port' ]
server_list = server_labels.map {|label| ui.color(label, :bold)}
items = connection.roles.all
items.each do |server|
server_list << server.hostedservicename.to_s+".cloudapp.net" # Info about the DNS name at http://msdn.microsoft.com/en-us/library/ee460806.aspx
server_list << server.name.to_s
server_list << begin
state = server.status.to_s.downcase
case state
@ -55,17 +50,13 @@ class Chef
else
ui.color('ready', :green)
end
end
server_list << server.hostedservicename.to_s
server_list << server.deployname.to_s
server_list << server.name.to_s
server_list << server.hostname.to_s
server_list << server.sshipaddress.to_s
end
server_list << server.publicipaddress.to_s
server_list << server.sshport.to_s
server_list << server.winrmport.to_s
end
puts ''
puts ui.list(server_list, :columns_across, 8)
puts ui.list(server_list, :uneven_columns_across, 6)
end
end
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)

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

@ -13,7 +13,7 @@ describe Chef::Knife::AzureServerCreate do
include AzureSpecHelper
include QueryAzureMock
before do
before do
@server_instance = Chef::Knife::AzureServerCreate.new
{
@ -44,13 +44,13 @@ describe "parameter test:" do
context "compulsory parameters" do
it "azure_subscription_id" do
Chef::Config[:knife].delete(:azure_subscription_id)
@server_instance.ui.should_receive(:error)
it "azure_subscription_id" do
Chef::Config[:knife].delete(:azure_subscription_id)
@server_instance.ui.should_receive(:error)
expect {@server_instance.run}.to raise_error
end
it "azure_mgmt_cert" do
Chef::Config[:knife].delete(:azure_mgmt_cert)
it "azure_mgmt_cert" do
Chef::Config[:knife].delete(:azure_mgmt_cert)
@server_instance.ui.should_receive(:error)
expect {@server_instance.run}.to raise_error
end
@ -154,7 +154,7 @@ describe "for bootstrap protocol winrm:" do
end
it "successful bootstrap of windows instance" do
@server_instance.should_receive(:is_image_windows?).exactly(4).times.and_return(true)
@server_instance.should_receive(:is_image_windows?).exactly(3).times.and_return(true)
@server_instance.run
end
end
@ -167,10 +167,10 @@ describe "for bootstrap protocol ssh:" do
context "windows instance:" do
it "successful bootstrap" do
@server_instance.should_receive(:is_image_windows?).exactly(4).times.and_return(true)
@server_instance.should_receive(:is_image_windows?).exactly(3).times.and_return(true)
@bootstrap = Chef::Knife::BootstrapWindowsSsh.new
Chef::Knife::BootstrapWindowsSsh.stub(:new).and_return(@bootstrap)
@bootstrap.should_receive(:run)
@bootstrap.should_receive(:run)
@server_instance.run
end
end
@ -193,13 +193,38 @@ describe "for bootstrap protocol ssh:" do
end
it "successful bootstrap" do
@server_instance.should_receive(:is_image_windows?).exactly(4).times.and_return(false)
@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.run
end
context "ssh key" do
before do
Chef::Config[:knife][:ssh_password] = ''
Chef::Config[:knife][:identity_file] = 'path_to_rsa_private_key'
end
it "check if ssh-key set correctly" do
@server_instance.should_receive(:is_image_windows?).twice.and_return(false)
@server_params = @server_instance.create_server_def
@server_params[:os_type].should == 'Linux'
@server_params[:identity_file].should == 'path_to_rsa_private_key'
@server_params[:ssh_user].should == 'ssh_user'
@server_params[:bootstrap_proto].should == 'ssh'
@server_params[:azure_dns_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
@ -224,4 +249,4 @@ describe "for bootstrap protocol ssh:" do
end
end
end

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

@ -32,28 +32,59 @@ before do
@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 "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 "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 "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
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']

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

@ -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