Merge "Use OpenstackClient for nova providers auth"
This commit is contained in:
commit
2c9bb31867
@ -1,13 +1,37 @@
|
||||
# Run test ie with: rspec spec/unit/provider/nova_spec.rb
|
||||
|
||||
require 'puppet/util/inifile'
|
||||
require 'puppet/provider/openstack'
|
||||
require 'puppet/provider/openstack/auth'
|
||||
require 'puppet/provider/openstack/credentials'
|
||||
|
||||
class Puppet::Provider::Nova < Puppet::Provider
|
||||
class Puppet::Provider::Nova < Puppet::Provider::Openstack
|
||||
|
||||
extend Puppet::Provider::Openstack::Auth
|
||||
|
||||
def self.request(service, action, properties=nil)
|
||||
begin
|
||||
super
|
||||
rescue Puppet::Error::OpenstackAuthInputError => error
|
||||
nova_request(service, action, error, properties)
|
||||
end
|
||||
end
|
||||
|
||||
def self.nova_request(service, action, error, properties=nil)
|
||||
properties ||= []
|
||||
@credentials.username = nova_credentials['admin_user']
|
||||
@credentials.password = nova_credentials['admin_password']
|
||||
@credentials.project_name = nova_credentials['admin_tenant_name']
|
||||
@credentials.auth_url = auth_endpoint
|
||||
raise error unless @credentials.set?
|
||||
Puppet::Provider::Openstack.request(service, action, properties, @credentials)
|
||||
end
|
||||
|
||||
def self.conf_filename
|
||||
'/etc/nova/nova.conf'
|
||||
end
|
||||
|
||||
# deprecated: method for old nova cli auth
|
||||
def self.withenv(hash, &block)
|
||||
saved = ENV.to_hash
|
||||
hash.each do |name, val|
|
||||
@ -66,6 +90,7 @@ class Puppet::Provider::Nova < Puppet::Provider
|
||||
@auth_endpoint ||= get_auth_endpoint
|
||||
end
|
||||
|
||||
# deprecated: method for old nova cli auth
|
||||
def self.auth_nova(*args)
|
||||
q = nova_credentials
|
||||
authenv = {
|
||||
@ -94,6 +119,7 @@ class Puppet::Provider::Nova < Puppet::Provider
|
||||
end
|
||||
end
|
||||
|
||||
# deprecated: method for old nova cli auth
|
||||
def auth_nova(*args)
|
||||
self.class.auth_nova(args)
|
||||
end
|
||||
@ -113,6 +139,7 @@ class Puppet::Provider::Nova < Puppet::Provider
|
||||
end
|
||||
end
|
||||
|
||||
# deprecated: string to list for nova cli
|
||||
def self.str2list(s)
|
||||
#parse string
|
||||
if s.include? ","
|
||||
@ -146,6 +173,7 @@ class Puppet::Provider::Nova < Puppet::Provider
|
||||
end
|
||||
end
|
||||
|
||||
# deprecated: nova cli to list
|
||||
def self.cliout2list(output)
|
||||
#don't proceed with empty output
|
||||
if output.empty?
|
||||
@ -176,69 +204,4 @@ class Puppet::Provider::Nova < Puppet::Provider
|
||||
return hash_list
|
||||
end
|
||||
|
||||
def self.nova_hosts
|
||||
return @nova_hosts if @nova_hosts
|
||||
cmd_output = auth_nova("host-list")
|
||||
@nova_hosts = cliout2list(cmd_output)
|
||||
@nova_hosts
|
||||
end
|
||||
|
||||
def self.nova_get_host_by_name_and_type(host_name, service_type)
|
||||
#find the host by name and service type
|
||||
nova_hosts.each do |entry|
|
||||
# (mdorman) Support api!cell_name@host_name -style output of nova host-list under nova cells
|
||||
if entry["host_name"] =~ /^([a-zA-Z0-9\-_]+![a-zA-Z0-9\-_]+@)?#{Regexp.quote(host_name)}$/
|
||||
if entry["service"] == service_type
|
||||
return host_name
|
||||
end
|
||||
end
|
||||
end
|
||||
#name/service combo not found
|
||||
return nil
|
||||
end
|
||||
|
||||
def self.nova_aggregate_resources_ids(force_refresh=false)
|
||||
# return the cached list unless requested
|
||||
if not force_refresh
|
||||
return @nova_aggregate_resources_ids if @nova_aggregate_resources_ids
|
||||
end
|
||||
#produce a list of hashes with Id=>Name pairs
|
||||
lines = []
|
||||
#run command
|
||||
cmd_output = auth_nova("aggregate-list")
|
||||
#parse output
|
||||
@nova_aggregate_resources_ids = cliout2list(cmd_output)
|
||||
#only interessted in Id and Name
|
||||
@nova_aggregate_resources_ids.map{ |e| e.delete("Availability Zone")}
|
||||
@nova_aggregate_resources_ids.map{ |e|
|
||||
if e['Id'] =~ /^[0-9]+$/
|
||||
e['Id'] = e['Id'].to_i
|
||||
end }
|
||||
@nova_aggregate_resources_ids
|
||||
end
|
||||
|
||||
def self.nova_aggregate_resources_get_name_by_id(name, force_refresh=false)
|
||||
#find the id by the given name
|
||||
nova_aggregate_resources_ids(force_refresh).each do |entry|
|
||||
if entry["Name"] == name
|
||||
return entry["Id"]
|
||||
end
|
||||
end
|
||||
#name not found
|
||||
return nil
|
||||
end
|
||||
|
||||
def self.nova_aggregate_resources_attr(id)
|
||||
#run command to get details for given Id
|
||||
cmd_output = auth_nova("aggregate-details", id)
|
||||
list = cliout2list(cmd_output)[0]
|
||||
if ! list["Hosts"].is_a?(Array)
|
||||
if list["Hosts"] == ""
|
||||
list["Hosts"] = []
|
||||
else
|
||||
list["Hosts"] = [ list["Hosts"] ]
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
end
|
||||
|
@ -1,169 +0,0 @@
|
||||
require File.join(File.dirname(__FILE__), '..','..','..',
|
||||
'puppet/provider/nova')
|
||||
|
||||
Puppet::Type.type(:nova_aggregate).provide(
|
||||
:nova,
|
||||
:parent => Puppet::Provider::Nova
|
||||
) do
|
||||
|
||||
desc "Manage nova aggregations"
|
||||
|
||||
commands :nova => 'nova'
|
||||
|
||||
mk_resource_methods
|
||||
|
||||
def self.instances
|
||||
nova_aggregate_resources_ids().collect do |el|
|
||||
attrs = nova_aggregate_resources_attr(el['Name'])
|
||||
new(
|
||||
:ensure => :present,
|
||||
:name => attrs['Name'],
|
||||
:id => attrs['Id'],
|
||||
:availability_zone => attrs['Availability Zone'],
|
||||
:metadata => attrs['Metadata'],
|
||||
:hosts => attrs['Hosts'].sort
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def self.prefetch(resources)
|
||||
instances_ = instances
|
||||
resources.keys.each do |name|
|
||||
if provider = instances_.find{ |instance| instance.name == name }
|
||||
resources[name].provider = provider
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def exists?
|
||||
@property_hash[:ensure] == :present
|
||||
end
|
||||
|
||||
def destroy
|
||||
#delete hosts first
|
||||
if not @property_hash[:hosts].nil?
|
||||
@property_hash[:hosts].each do |h|
|
||||
auth_nova("aggregate-remove-host", name, h)
|
||||
end
|
||||
end
|
||||
#now delete aggregate
|
||||
auth_nova("aggregate-delete", name)
|
||||
@property_hash[:ensure] = :absent
|
||||
end
|
||||
|
||||
def create
|
||||
extras = Array.new
|
||||
#check for availability zone
|
||||
if not @resource[:availability_zone].nil? and not @resource[:availability_zone].empty?
|
||||
extras << "#{@resource[:availability_zone]}"
|
||||
end
|
||||
#run the command
|
||||
result = auth_nova("aggregate-create", resource[:name], extras)
|
||||
|
||||
#get Id by Name
|
||||
#force a refresh of the aggregate list on creation
|
||||
id = self.class.nova_aggregate_resources_get_name_by_id(resource[:name], true)
|
||||
|
||||
@property_hash = {
|
||||
:ensure => :present,
|
||||
:name => resource[:name],
|
||||
:id => id,
|
||||
:availability_zone => resource[:availability_zone]
|
||||
}
|
||||
|
||||
#add metadata
|
||||
if not @resource[:metadata].nil? and not @resource[:metadata].empty?
|
||||
@resource[:metadata].each do |key, value|
|
||||
set_metadata_helper(resource[:name], key, value)
|
||||
end
|
||||
@property_hash[:metadata] = resource[:metadata]
|
||||
end
|
||||
|
||||
#add hosts - This throws an error if the host is already attached to another aggregate!
|
||||
if not @resource[:hosts].nil? and not @resource[:hosts].empty?
|
||||
@resource[:hosts].each do |host|
|
||||
# make sure the host exists in nova, or nova will fail the call
|
||||
# this solves weird ordering issues with a compute node that's
|
||||
# not 100% up being added to the host aggregate
|
||||
if is_host_in_nova?(host)
|
||||
auth_nova("aggregate-add-host", resource[:name], "#{host}")
|
||||
else
|
||||
warning("Cannot add #{host} to host aggregate, it's not available yet in nova host-list")
|
||||
end
|
||||
end
|
||||
@property_hash[:hosts] = resource[:hosts]
|
||||
end
|
||||
end
|
||||
|
||||
def is_host_in_nova?(host)
|
||||
return host==self.class.nova_get_host_by_name_and_type(host, "compute")
|
||||
end
|
||||
|
||||
def hosts=(val)
|
||||
#get current hosts
|
||||
attrs = self.class.nova_aggregate_resources_attr(name)
|
||||
#remove all hosts which are not in new value list
|
||||
attrs['Hosts'].each do |h|
|
||||
if not val.include? h
|
||||
auth_nova("aggregate-remove-host", name, "#{h}")
|
||||
end
|
||||
end
|
||||
|
||||
#add hosts from the value list
|
||||
val.each do |h|
|
||||
if not attrs['Hosts'].include? h
|
||||
if is_host_in_nova?(h)
|
||||
auth_nova("aggregate-add-host", name, "#{h}")
|
||||
else
|
||||
warning("Cannot add #{h} to host aggregate, it's not available yet in nova host-list")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def set_metadata_helper(agg_id, key, value)
|
||||
auth_nova("aggregate-set-metadata", agg_id, "#{key}=#{value}")
|
||||
end
|
||||
|
||||
def metadata
|
||||
#get current metadata
|
||||
attrs = self.class.nova_aggregate_resources_attr(name)
|
||||
#just ignore the availability_zone. that's handled directly by nova
|
||||
attrs['Metadata'].delete('availability_zone')
|
||||
return attrs['Metadata']
|
||||
end
|
||||
|
||||
def metadata=(val)
|
||||
#get current metadata
|
||||
attrs = self.class.nova_aggregate_resources_attr(name)
|
||||
#get keys which are in current metadata but not in val. Make sure it has data first!
|
||||
if attrs['Metadata'].length > 0
|
||||
obsolete_keys = attrs['Metadata'].keys - val.keys
|
||||
end
|
||||
# clear obsolete keys. If there are any!
|
||||
if obsolete_keys
|
||||
obsolete_keys.each do |key|
|
||||
if not key.include? 'availability_zone'
|
||||
auth_nova("aggregate-set-metadata", name, "#{key}")
|
||||
end
|
||||
end
|
||||
#handle keys (with obsolete keys)
|
||||
new_keys = val.keys - obsolete_keys
|
||||
else
|
||||
#handle keys (without obsolete keys)
|
||||
new_keys = val.keys
|
||||
end
|
||||
#set new metadata if value changed
|
||||
new_keys.each do |key|
|
||||
if val[key] != attrs['Metadata'][key.to_s]
|
||||
value = val[key]
|
||||
set_metadata_helper(name, key, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def availability_zone=(val)
|
||||
auth_nova("aggregate-set-metadata", name, "availability_zone=#{val}")
|
||||
end
|
||||
|
||||
end
|
107
lib/puppet/provider/nova_aggregate/openstack.rb
Normal file
107
lib/puppet/provider/nova_aggregate/openstack.rb
Normal file
@ -0,0 +1,107 @@
|
||||
require 'puppet/provider/nova'
|
||||
|
||||
Puppet::Type.type(:nova_aggregate).provide(
|
||||
:openstack,
|
||||
:parent => Puppet::Provider::Nova
|
||||
) do
|
||||
desc <<-EOT
|
||||
Provider to manage nova aggregations
|
||||
EOT
|
||||
|
||||
@credentials = Puppet::Provider::Openstack::CredentialsV2_0.new
|
||||
|
||||
mk_resource_methods
|
||||
|
||||
def self.instances
|
||||
request('aggregate', 'list').collect do |el|
|
||||
attrs = request('aggregate', 'show', el[:name])
|
||||
new(
|
||||
:ensure => :present,
|
||||
:name => attrs[:name],
|
||||
:id => attrs[:id],
|
||||
:availability_zone => attrs[:availability_zone],
|
||||
:metadata => str2hash(attrs[:properties]),
|
||||
:hosts => string2list(attrs[:hosts]).sort
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def self.string2list(input)
|
||||
return input[1..-2].split(",").map { |x| x.match(/'(.*?)'/)[1] }
|
||||
end
|
||||
|
||||
def self.prefetch(resources)
|
||||
instances_ = instances
|
||||
resources.keys.each do |name|
|
||||
if provider = instances_.find{ |instance| instance.name == name }
|
||||
resources[name].provider = provider
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def exists?
|
||||
@property_hash[:ensure] == :present
|
||||
end
|
||||
|
||||
def destroy
|
||||
@property_hash[:hosts].each do |h|
|
||||
properties = [@property_hash[:name], h]
|
||||
self.class.request('aggregate', 'remove host', properties)
|
||||
end
|
||||
self.class.request('aggregate', 'delete', @property_hash[:name])
|
||||
end
|
||||
|
||||
def create
|
||||
properties = [@resource[:name]]
|
||||
if not @resource[:availability_zone].nil? and not @resource[:availability_zone].empty?
|
||||
properties << "--zone" << @resource[:availability_zone]
|
||||
end
|
||||
if not @resource[:metadata].nil? and not @resource[:metadata].empty?
|
||||
@resource[:metadata].each do |key, value|
|
||||
properties << "--property" << "#{key}=#{value}"
|
||||
end
|
||||
end
|
||||
@property_hash = self.class.request('aggregate', 'create', properties)
|
||||
|
||||
if not @resource[:hosts].nil? and not @resource[:hosts].empty?
|
||||
@resource[:hosts].each do |host|
|
||||
properties = [@property_hash[:name], host]
|
||||
self.class.request('aggregate', 'add host', properties)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def availability_zone=(value)
|
||||
self.class.request('aggregate', 'set', [ @resource[:name], '--zone', @resource[:availability_zone] ])
|
||||
end
|
||||
|
||||
def metadata=(value)
|
||||
# clear obsolete keys
|
||||
# wip untill #1559866
|
||||
# if @property_hash[:metadata].keys.length > 0
|
||||
# properties = [@resource[:name] ]
|
||||
# (@property_hash[:metadata].keys - @resource[:metadata].keys).each do |key|
|
||||
# properties << "--property" << "#{key}"
|
||||
# end
|
||||
# self.class.request('aggregate', 'unset', properties)
|
||||
# end
|
||||
properties = [@resource[:name] ]
|
||||
@resource[:metadata].each do |key, value|
|
||||
properties << "--property" << "#{key}=#{value}"
|
||||
end
|
||||
self.class.request('aggregate', 'set', properties)
|
||||
end
|
||||
|
||||
def hosts=(value)
|
||||
# remove hosts, which are not present in update
|
||||
(@property_hash[:hosts] - @resource[:hosts]).each do |host|
|
||||
properties = [@property_hash[:id], host]
|
||||
self.class.request('aggregate', 'remove host', properties)
|
||||
end
|
||||
# add new hosts
|
||||
(@resource[:hosts] - @property_hash[:hosts]).each do |host|
|
||||
properties = [@property_hash[:id], host]
|
||||
self.class.request('aggregate', 'add host', properties)
|
||||
end
|
||||
end
|
||||
end
|
@ -45,7 +45,7 @@ Puppet::Type.newtype(:nova_aggregate) do
|
||||
ensurable
|
||||
|
||||
autorequire(:nova_config) do
|
||||
['auth_host', 'auth_port', 'auth_protocol', 'admin_tenant_name', 'admin_user', 'admin_password']
|
||||
['auth_uri', 'admin_tenant_name', 'admin_user', 'admin_password']
|
||||
end
|
||||
|
||||
newparam(:name, :namevar => true) do
|
||||
@ -105,7 +105,11 @@ Puppet::Type.newtype(:nova_aggregate) do
|
||||
desc 'Single host or comma seperated list of hosts'
|
||||
#convert DSL/string form to internal form
|
||||
munge do |value|
|
||||
return value.split(",").map{|el| el.strip()}.sort
|
||||
if value.is_a?(Array)
|
||||
return value
|
||||
else
|
||||
return value.split(",").map{|el| el.strip()}.sort
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Using OpenStack client for Nova providers
|
@ -66,6 +66,14 @@ describe 'basic nova' do
|
||||
}
|
||||
class { '::nova::scheduler': }
|
||||
class { '::nova::vncproxy': }
|
||||
|
||||
nova_aggregate { 'test_aggregate':
|
||||
ensure => present,
|
||||
availability_zone => 'zone1',
|
||||
metadata => 'test=property',
|
||||
require => Class['nova::api'],
|
||||
}
|
||||
|
||||
# TODO: networking with neutron
|
||||
EOS
|
||||
|
||||
@ -91,5 +99,13 @@ describe 'basic nova' do
|
||||
it { is_expected.to have_entry('1 0 * * * nova-manage db archive_deleted_rows --max_rows 100 >>/var/log/nova/nova-rowsflush.log 2>&1').with_user('nova') }
|
||||
end
|
||||
|
||||
describe 'nova aggregate' do
|
||||
it 'should create new aggregate' do
|
||||
shell('openstack --os-username nova --os-password a_big_secret --os-tenant-name services --os-auth-url http://127.0.0.1:5000/v2.0 aggregate list') do |r|
|
||||
expect(r.stdout).to match(/test_aggregate/)
|
||||
expect(r.stderr).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,3 +1,5 @@
|
||||
# Load libraries from openstacklib here to simulate how they live together in a real puppet run (for provider unit tests)
|
||||
$LOAD_PATH.push(File.join(File.dirname(__FILE__), 'fixtures', 'modules', 'openstacklib', 'lib'))
|
||||
require 'puppetlabs_spec_helper/module_spec_helper'
|
||||
require 'shared_examples'
|
||||
|
||||
|
100
spec/unit/provider/nova_aggregate/openstack_spec.rb
Normal file
100
spec/unit/provider/nova_aggregate/openstack_spec.rb
Normal file
@ -0,0 +1,100 @@
|
||||
require 'puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppet/provider/nova_aggregate/openstack'
|
||||
|
||||
provider_class = Puppet::Type.type(:nova_aggregate).provider(:openstack)
|
||||
|
||||
describe provider_class do
|
||||
|
||||
shared_examples 'authenticated with environment variables' do
|
||||
ENV['OS_USERNAME'] = 'test'
|
||||
ENV['OS_PASSWORD'] = 'abc123'
|
||||
ENV['OS_PROJECT_NAME'] = 'test'
|
||||
ENV['OS_AUTH_URL'] = 'http://127.0.0.1:35357/v3'
|
||||
end
|
||||
|
||||
describe 'managing aggregates' do
|
||||
|
||||
let(:aggregate_attrs) do
|
||||
{
|
||||
:name => 'just',
|
||||
:availability_zone => 'simple',
|
||||
:hosts => ['example'],
|
||||
:ensure => 'present',
|
||||
:metadata => 'nice=cookie',
|
||||
}
|
||||
end
|
||||
|
||||
let(:resource) do
|
||||
Puppet::Type::Nova_aggregate.new(aggregate_attrs)
|
||||
end
|
||||
|
||||
let(:provider) do
|
||||
provider_class.new(resource)
|
||||
end
|
||||
|
||||
it_behaves_like 'authenticated with environment variables' do
|
||||
describe '#instances' do
|
||||
it 'finds existing aggregates' do
|
||||
provider_class.expects(:openstack)
|
||||
.with('aggregate', 'list', '--quiet', '--format', 'csv', [])
|
||||
.returns('"ID","Name","Availability Zone"
|
||||
just,"simple","just"
|
||||
')
|
||||
provider_class.expects(:openstack)
|
||||
.with('aggregate', 'show', '--format', 'shell', 'simple')
|
||||
.returns('"id="just"
|
||||
name="simple"
|
||||
availability_zone=just"
|
||||
properties="key=\'2value\'"
|
||||
hosts="[]"
|
||||
')
|
||||
instances = provider_class.instances
|
||||
expect(instances.count).to eq(1)
|
||||
expect(instances[0].name).to eq('simple')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
it 'creates aggregate' do
|
||||
provider.class.stubs(:openstack)
|
||||
.with('aggregate', 'list', '--quiet', '--format', 'csv', '--long')
|
||||
.returns('"ID","Name","Availability Zone","Properties"
|
||||
')
|
||||
provider.class.stubs(:openstack)
|
||||
.with('aggregate', 'create', '--format', 'shell', ['just', '--zone', 'simple', '--property', 'nice=cookie' ])
|
||||
.returns('name="just"
|
||||
id="just"
|
||||
availability_zone="simple"
|
||||
properties="{u\'nice\': u\'cookie\'}"
|
||||
hosts="[]"
|
||||
')
|
||||
provider.class.stubs(:openstack)
|
||||
.with('aggregate', 'add host', ['just', 'example'])
|
||||
.returns('name="just"
|
||||
id="just"
|
||||
availability_zone="simple"
|
||||
properties="{u\'nice\': u\'cookie\'}"
|
||||
hosts="[u\'example\']"
|
||||
')
|
||||
provider.exists?
|
||||
provider.create
|
||||
expect(provider.exists?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe '#destroy' do
|
||||
it 'removes aggregate with hosts' do
|
||||
provider_class.expects(:openstack)
|
||||
.with('aggregate', 'remove host', ['just', 'example'])
|
||||
provider_class.expects(:openstack)
|
||||
.with('aggregate', 'delete', 'just')
|
||||
provider.instance_variable_set(:@property_hash, aggregate_attrs)
|
||||
provider.destroy
|
||||
expect(provider.exists?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
@ -283,149 +283,4 @@ EOT
|
||||
{"Id"=>"api!cell@8", "Name"=>"api!cell@my2", "Availability Zone"=>""}])
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when handling cli output' do
|
||||
it 'should return the availble Id' do
|
||||
output = <<-EOT
|
||||
+----+-------+-------------------+
|
||||
| Id | Name | Availability Zone |
|
||||
+----+-------+-------------------+
|
||||
| 1 | haha | haha2 |
|
||||
| 2 | haha2 | - |
|
||||
+----+-------+-------------------+
|
||||
EOT
|
||||
klass.expects(:auth_nova).returns(output)
|
||||
res = klass.nova_aggregate_resources_get_name_by_id("haha2")
|
||||
expect(res).to eql(2)
|
||||
end
|
||||
|
||||
it 'should return nil because given name is not available' do
|
||||
output = <<-EOT
|
||||
+----+-------+-------------------+
|
||||
| Id | Name | Availability Zone |
|
||||
+----+-------+-------------------+
|
||||
| 1 | haha | haha2 |
|
||||
| 2 | haha2 | - |
|
||||
+----+-------+-------------------+
|
||||
EOT
|
||||
# used the cache copy, don't call nova again
|
||||
klass.expects(:auth_nova).never()
|
||||
res = klass.nova_aggregate_resources_get_name_by_id("notavailable")
|
||||
expect(res).to eql(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when handling cli output with cells enabled' do
|
||||
it 'should return the availble Id' do
|
||||
output = <<-EOT
|
||||
+-------------+----------------+-------------------+
|
||||
| Id | Name | Availability Zone |
|
||||
+-------------+----------------+-------------------+
|
||||
| api!cell@1 | api!cell@haha | haha2 |
|
||||
| api!cell@2 | api!cell@haha2 | - |
|
||||
+-------------+----------------+-------------------+
|
||||
EOT
|
||||
klass.expects(:auth_nova).returns(output)
|
||||
res = klass.nova_aggregate_resources_get_name_by_id("api!cell@haha2", true)
|
||||
expect(res).to eq("api!cell@2")
|
||||
end
|
||||
|
||||
it 'should return nil because given name is not available' do
|
||||
output = <<-EOT
|
||||
+----+-------+-------------------+
|
||||
| Id | Name | Availability Zone |
|
||||
+----+-------+-------------------+
|
||||
| api!cell@1 | api!cell@haha | haha2 |
|
||||
| api!cell@2 | api!cell@haha2 | - |
|
||||
+----+-------+-------------------+
|
||||
EOT
|
||||
# used the cache copy, don't call nova again
|
||||
klass.expects(:auth_nova).never()
|
||||
res = klass.nova_aggregate_resources_get_name_by_id("notavailable")
|
||||
expect(res).to eql(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when getting details for given Id' do
|
||||
it 'should return a Hash with the details' do
|
||||
output = <<-EOT
|
||||
+----+-------+-------------------+-------+--------------------------------------------------+
|
||||
| Id | Name | Availability Zone | Hosts | Metadata |
|
||||
+----+-------+-------------------+-------+--------------------------------------------------+
|
||||
| 16 | agg94 | my_-zone1 | | 'a=b', 'availability_zone= my_-zone1', 'x_q-r=y' |
|
||||
+----+-------+-------------------+-------+--------------------------------------------------+
|
||||
EOT
|
||||
klass.expects(:auth_nova).returns(output)
|
||||
res = klass.nova_aggregate_resources_attr(16)
|
||||
expect(res).to eq({
|
||||
"Id"=>"16",
|
||||
"Name"=>"agg94",
|
||||
"Availability Zone"=>"my_-zone1",
|
||||
"Hosts"=>[],
|
||||
"Metadata"=>{
|
||||
"a"=>"b",
|
||||
"availability_zone"=>" my_-zone1",
|
||||
"x_q-r"=>"y"
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when getting details for given Id with cells enabled' do
|
||||
it 'should return a Hash with the details' do
|
||||
output = <<-EOT
|
||||
+-------------+----------------+-------------------+-------+--------------------------------------------------+
|
||||
| Id | Name | Availability Zone | Hosts | Metadata |
|
||||
+-------------+----------------+-------------------+-------+--------------------------------------------------+
|
||||
| api!cell@16 | api!cell@agg94 | my_-zone1 | | 'a=b', 'availability_zone= my_-zone1', 'x_q-r=y' |
|
||||
+-------------+----------------+-------------------+-------+--------------------------------------------------+
|
||||
EOT
|
||||
klass.expects(:auth_nova).returns(output)
|
||||
res = klass.nova_aggregate_resources_attr(16)
|
||||
expect(res).to eq({
|
||||
"Id"=>"api!cell@16",
|
||||
"Name"=>"api!cell@agg94",
|
||||
"Availability Zone"=>"my_-zone1",
|
||||
"Hosts"=>[],
|
||||
"Metadata"=>{
|
||||
"a"=>"b",
|
||||
"availability_zone"=>" my_-zone1",
|
||||
"x_q-r"=>"y"
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when searching for a host/type combo' do
|
||||
it 'should find the hostname if there is a match' do
|
||||
output = <<-EOT
|
||||
+-------------------+-------------+----------+
|
||||
| host_name | service | zone |
|
||||
+-------------------+-------------+----------+
|
||||
| node-control-001 | consoleauth | internal |
|
||||
| node-control-001 | cert | internal |
|
||||
| node-compute-002 | compute | nova |
|
||||
+-------------------+-------------+----------+
|
||||
EOT
|
||||
klass.expects(:auth_nova).returns(output)
|
||||
res = klass.nova_get_host_by_name_and_type("node-compute-002","compute")
|
||||
expect(res).to eq("node-compute-002")
|
||||
end
|
||||
|
||||
it 'should return nil because there is no host/type combo match' do
|
||||
output = <<-EOT
|
||||
+-------------------+-------------+----------+
|
||||
| host_name | service | zone |
|
||||
+-------------------+-------------+----------+
|
||||
| node-control-001 | consoleauth | internal |
|
||||
| node-control-001 | cert | internal |
|
||||
| node-compute-002 | compute | nova |
|
||||
+-------------------+-------------+----------+
|
||||
EOT
|
||||
# used the cache copy, don't call nova again
|
||||
klass.expects(:auth_nova).never()
|
||||
res = klass.nova_get_host_by_name_and_type("node-compute-002","internal")
|
||||
expect(res).to eql(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
33
spec/unit/type/nova_aggregate_spec.rb
Normal file
33
spec/unit/type/nova_aggregate_spec.rb
Normal file
@ -0,0 +1,33 @@
|
||||
require 'puppet'
|
||||
require 'puppet/type/nova_aggregate'
|
||||
|
||||
describe Puppet::Type.type(:nova_aggregate) do
|
||||
|
||||
before :each do
|
||||
Puppet::Type.rmtype(:nova_aggregate)
|
||||
end
|
||||
|
||||
it 'should raise error for setting id property' do
|
||||
incorrect_input = {
|
||||
:name => 'test_type',
|
||||
:id => 'some_id'
|
||||
}
|
||||
expect { Puppet::Type.type(:nova_aggregate).new(incorrect_input) }.to raise_error(Puppet::ResourceError, /This is a read only property/)
|
||||
end
|
||||
|
||||
it 'should raise error if wrong format of metadata' do
|
||||
incorrect_input = {
|
||||
:name => 'new_aggr',
|
||||
:metadata => 'some_id,sd'
|
||||
}
|
||||
expect { Puppet::Type.type(:nova_aggregate).new(incorrect_input) }.to raise_error(Puppet::ResourceError, /Key\/value pairs must be separated by an =/)
|
||||
end
|
||||
|
||||
it 'should raise error if wrong type for availability zone' do
|
||||
incorrect_input = {
|
||||
:name => 'new_aggr',
|
||||
:availability_zone => {'zone'=>'23'},
|
||||
}
|
||||
expect { Puppet::Type.type(:nova_aggregate).new(incorrect_input) }.to raise_error(Puppet::ResourceError, /availability zone must be a String/)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user