Rebased with master
This commit is contained in:
Коммит
07088d0fd2
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче