Use system scope credentials in providers

This change enforces usage of system scope credentials to manage
flavors and aggregates, following the new policy rules for SRBAC
support in nova.

Depends-on: https://review.opendev.org/815311
Change-Id: Ic87422ae98943054ee58343157301d8fc780211f
This commit is contained in:
Takashi Kajinami 2021-10-28 22:50:37 +09:00
parent ee0e3834b0
commit 5e62f69b5e
10 changed files with 221 additions and 272 deletions

View File

@ -1,9 +1,3 @@
# Run test ie with: rspec spec/unit/provider/nova_spec.rb
# Add openstacklib code to $LOAD_PATH so that we can load this during
# standalone compiles without error.
File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
require 'puppet/util/inifile'
require 'puppet/provider/openstack'
require 'puppet/provider/openstack/auth'
@ -13,27 +7,44 @@ 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
CLOUDS_FILENAME = '/etc/nova/clouds.yaml'
def self.project_request(service, action, properties=nil, options={})
self.request(service, action, properties, options, 'project')
end
def self.nova_request(service, action, error, properties=nil)
def self.system_request(service, action, properties=nil, options={})
self.request(service, action, properties, options, 'system')
end
def self.request(service, action, properties=nil, options={}, scope='project')
super
rescue Puppet::Error::OpenstackAuthInputError => error
nova_request(service, action, error, properties, options, scope)
end
def self.nova_request(service, action, error, properties=nil, options={}, scope='project')
properties ||= []
@credentials.username = nova_credentials['username']
@credentials.password = nova_credentials['password']
@credentials.project_name = nova_credentials['project_name']
@credentials.auth_url = auth_endpoint
@credentials.user_domain_name = nova_credentials['user_domain_name']
@credentials.project_domain_name = nova_credentials['project_domain_name']
if nova_credentials['region_name']
@credentials.region_name = nova_credentials['region_name']
unless @system_credential
@system_credential = Puppet::Provider::Openstack::CredentialsV3.new
@system_credential.cloud = 'system'
@system_credential.client_config_file = clouds_filename
end
raise error unless @credentials.set?
Puppet::Provider::Openstack.request(service, action, properties, @credentials)
unless @project_credential
@project_credential = Puppet::Provider::Openstack::CredentialsV3.new
@project_credential.cloud = 'project'
@project_credential.client_config_file = clouds_filename
end
if scope == 'system'
cred = @system_credential
else
cred = @project_credential
end
Puppet::Provider::Openstack.request(service, action, properties, cred, options)
end
def self.nova_manage_request(*args)
@ -70,58 +81,13 @@ class Puppet::Provider::Nova < Puppet::Provider::Openstack
@nova_conf
end
def self.nova_credentials
@nova_credentials ||= get_nova_credentials
end
def nova_credentials
self.class.nova_credentials
end
def self.get_nova_credentials
#needed keys for authentication
auth_keys = ['auth_url', 'project_name', 'username', 'password']
conf = nova_conf
if conf and conf['keystone_authtoken'] and
auth_keys.all?{|k| !conf['keystone_authtoken'][k].nil?}
creds = Hash[ auth_keys.map \
{ |k| [k, conf['keystone_authtoken'][k].strip] } ]
if !conf['keystone_authtoken']['region_name'].nil?
creds['region_name'] = conf['keystone_authtoken']['region_name'].strip
end
if !conf['keystone_authtoken']['project_domain_name'].nil?
creds['project_domain_name'] = conf['keystone_authtoken']['project_domain_name'].strip
else
creds['project_domain_name'] = 'Default'
end
if !conf['keystone_authtoken']['user_domain_name'].nil?
creds['user_domain_name'] = conf['keystone_authtoken']['user_domain_name'].strip
else
creds['user_domain_name'] = 'Default'
end
return creds
else
raise(Puppet::Error, "File: #{conf_filename} does not contain all " +
"required sections. Nova types will not work if nova is not " +
"correctly configured.")
end
end
def self.get_auth_endpoint
q = nova_credentials
"#{q['auth_url']}"
end
def self.auth_endpoint
@auth_endpoint ||= get_auth_endpoint
def self.clouds_filename
CLOUDS_FILENAME
end
def self.reset
@nova_conf = nil
@nova_credentials = nil
@project_credential = nil
@system_credential = nil
end
def self.str2hash(s)

View File

@ -13,8 +13,8 @@ Puppet::Type.type(:nova_aggregate).provide(
mk_resource_methods
def self.instances
request('aggregate', 'list').collect do |el|
attrs = request('aggregate', 'show', el[:name])
system_request('aggregate', 'list').collect do |el|
attrs = system_request('aggregate', 'show', el[:name])
properties = parsestring(attrs[:properties]) rescue nil
new(
:ensure => :present,
@ -43,7 +43,7 @@ Puppet::Type.type(:nova_aggregate).provide(
def self.get_known_hosts
# get list of hosts known to be active from openstack
return request('compute service', 'list', ['--service', 'nova-compute']).map{|el| el[:host]}
return system_request('compute service', 'list', ['--service', 'nova-compute']).map{|el| el[:host]}
end
def exists?
@ -53,9 +53,9 @@ Puppet::Type.type(:nova_aggregate).provide(
def destroy
@property_hash[:hosts].each do |h|
properties = [@property_hash[:name], h]
self.class.request('aggregate', 'remove host', properties)
self.class.system_request('aggregate', 'remove host', properties)
end
self.class.request('aggregate', 'delete', @property_hash[:name])
self.class.system_request('aggregate', 'delete', @property_hash[:name])
end
def create
@ -68,7 +68,7 @@ Puppet::Type.type(:nova_aggregate).provide(
properties << "--property" << "#{key}=#{value}"
end
end
@property_hash = self.class.request('aggregate', 'create', properties)
@property_hash = self.class.system_request('aggregate', 'create', properties)
if not @resource[:hosts].nil? and not @resource[:hosts].empty?
# filter host list by known hosts if filter_hosts is set
if @resource[:filter_hosts] == :true
@ -76,13 +76,14 @@ Puppet::Type.type(:nova_aggregate).provide(
end
@resource[:hosts].each do |host|
properties = [@property_hash[:name], host]
self.class.request('aggregate', 'add host', properties)
self.class.system_request('aggregate', 'add host', properties)
end
end
@property_hash[:ensure] = :present
end
def availability_zone=(value)
self.class.request('aggregate', 'set', [ @resource[:name], '--zone', @resource[:availability_zone] ])
self.class.system_request('aggregate', 'set', [ @resource[:name], '--zone', @resource[:availability_zone] ])
end
def metadata=(value)
@ -92,13 +93,13 @@ Puppet::Type.type(:nova_aggregate).provide(
(@property_hash[:metadata].keys - @resource[:metadata].keys).each do |key|
properties << "--property" << "#{key}"
end
self.class.request('aggregate', 'unset', properties)
self.class.system_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)
self.class.system_request('aggregate', 'set', properties)
end
def hosts=(value)
@ -109,11 +110,11 @@ Puppet::Type.type(:nova_aggregate).provide(
if not @property_hash[:hosts].nil?
# remove hosts that are not present in update
(@property_hash[:hosts] - value).each do |host|
self.class.request('aggregate', 'remove host', [@property_hash[:id], host])
self.class.system_request('aggregate', 'remove host', [@property_hash[:id], host])
end
# add hosts that are not already present
(value - @property_hash[:hosts]).each do |host|
self.class.request('aggregate', 'add host', [@property_hash[:id], host])
self.class.system_request('aggregate', 'add host', [@property_hash[:id], host])
end
end
end

View File

@ -26,16 +26,16 @@ Puppet::Type.type(:nova_flavor).provide(
(opts << '--vcpus' << @resource[:vcpus]) if @resource[:vcpus]
(opts << '--swap' << @resource[:swap]) if @resource[:swap]
(opts << '--rxtx-factor' << @resource[:rxtx_factor]) if @resource[:rxtx_factor]
@property_hash = self.class.request('flavor', 'create', opts)
@property_hash = self.class.system_request('flavor', 'create', opts)
if @resource[:properties]
prop_opts = [@resource[:name]]
prop_opts << props_to_s(@resource[:properties])
self.class.request('flavor', 'set', prop_opts)
self.class.system_request('flavor', 'set', prop_opts)
end
if @resource[:project]
if @resource[:project] and @resource[:project] != ''
proj_opts = [@resource[:name]]
proj_opts << '--project' << @resource[:project]
self.class.request('flavor', 'set', proj_opts)
self.class.system_request('flavor', 'set', proj_opts)
end
@property_hash[:ensure] = :present
end
@ -45,7 +45,7 @@ Puppet::Type.type(:nova_flavor).provide(
end
def destroy
self.class.request('flavor', 'delete', @property_hash[:id])
self.class.system_request('flavor', 'delete', @property_hash[:id])
end
mk_resource_methods
@ -87,8 +87,8 @@ Puppet::Type.type(:nova_flavor).provide(
end
def self.instances
request('flavor', 'list', ['--long', '--all']).collect do |attrs|
project = request('flavor', 'show', [attrs[:id], '-c', 'access_project_ids'])
system_request('flavor', 'list', ['--long', '--all']).collect do |attrs|
project = system_request('flavor', 'show', [attrs[:id], '-c', 'access_project_ids'])
access_project_ids = project[:access_project_ids]
# Client can return None and this should be considered as ''
@ -133,17 +133,17 @@ Puppet::Type.type(:nova_flavor).provide(
opts = [@resource[:name]]
opts << props_to_s(@property_flush[:properties])
self.class.request('flavor', 'set', opts)
self.class.system_request('flavor', 'set', opts)
@property_flush.clear
end
unless @project_flush.empty?
opts = [@resource[:name]]
unless @project_flush[:project]
unless @project_flush[:project] == ''
opts << '--project' << @project_flush[:project]
self.class.request('flavor', 'set', opts)
self.class.system_request('flavor', 'set', opts)
else
opts << '--project' << @property_hash[:project]
self.class.request('flavor', 'unset', opts)
self.class.system_request('flavor', 'unset', opts)
end
@project_flush.clear
end
@ -154,4 +154,3 @@ Puppet::Type.type(:nova_flavor).provide(
props.flat_map{ |k, v| ['--property', "#{k}=#{v}"] }
end
end

View File

@ -14,7 +14,7 @@ Puppet::Type.type(:nova_service).provide(
def self.instances
hosts = {}
request('compute service', 'list').collect do |host_svc|
system_request('compute service', 'list').collect do |host_svc|
hname = host_svc[:host]
if hosts[hname].nil?
hosts[hname] = Hash.new {|h,k| h[k]=[]}
@ -53,7 +53,7 @@ Puppet::Type.type(:nova_service).provide(
svcname_id_map.each do |service_name, id|
if (@resource[:service_name].empty? ||
(@resource[:service_name].include? service_name))
self.class.request('compute service', 'delete', id)
self.class.system_request('compute service', 'delete', id)
end
end
@property_hash[:ensure] = :absent

View File

@ -284,4 +284,33 @@ class nova::keystone::authtoken(
service_type => $service_type,
interface => $interface;
}
$system_scope_real = is_service_default($system_scope) ? {
true => pick($::nova::keystone::auth::system_scope, 'all'),
default => $system_scope,
}
$region_name_real = is_service_default($region_name) ? {
true => undef,
default => $region_name,
}
$interface_real = is_service_default($interface) ? {
true => undef,
default => $interface,
}
openstacklib::clouds { '/etc/nova/clouds.yaml':
username => $username,
password => $password,
auth_url => $auth_url,
project_name => $project_name,
system_scope => $system_scope_real,
region_name => $region_name_real,
interface => $interface_real,
}
Anchor['nova::config::begin']
-> Openstacklib::Clouds['/etc/nova/clouds.yaml']
-> Anchor['nova::config::end']
}

View File

@ -50,7 +50,8 @@ describe 'nova::keystone::auth' do
:system_roles => ['admin', 'member', 'reader'],
:public_url => 'https://10.10.10.10:80',
:internal_url => 'http://10.10.10.11:81',
:admin_url => 'http://10.10.10.12:81' }
:admin_url => 'http://10.10.10.12:81',
}
end
it { is_expected.to contain_keystone__resource__service_identity('nova').with(

View File

@ -2,14 +2,12 @@ require 'puppet'
require 'spec_helper'
require 'puppet/provider/nova_aggregate/openstack'
provider_class = Puppet::Type.type(:nova_aggregate).provider(:openstack)
describe Puppet::Type.type(:nova_aggregate).provider(:openstack) do
describe provider_class do
shared_examples 'authenticated with environment variables' do
let(:set_env) do
ENV['OS_USERNAME'] = 'test'
ENV['OS_PASSWORD'] = 'abc123'
ENV['OS_PROJECT_NAME'] = 'test'
ENV['OS_SYSTEM_SCOPE'] = 'all'
ENV['OS_AUTH_URL'] = 'http://127.0.0.1:5000/v3'
end
@ -30,96 +28,93 @@ describe provider_class do
end
let(:provider) do
provider_class.new(resource)
described_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"
before(:each) do
set_env
end
describe '#instances' do
it 'finds existing aggregates' do
described_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"
described_class.expects(:openstack)
.with('aggregate', 'show', '--format', 'shell', 'simple')
.returns('"id="just"
name="simple"
availability_zone=just"
properties="key1=\'tomato\', key2=\'mushroom\'"
hosts="[]"
')
instances = provider_class.instances
expect(instances.count).to eq(1)
expect(instances[0].name).to eq('simple')
expect(instances[0].metadata).to eq({"key1"=>"tomato", "key2"=>"mushroom"})
end
instances = described_class.instances
expect(instances.count).to eq(1)
expect(instances[0].name).to eq('simple')
expect(instances[0].metadata).to eq({"key1"=>"tomato", "key2"=>"mushroom"})
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"
describe '#create' do
it 'creates aggregate' do
described_class.expects(: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"
described_class.expects(: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
provider.create
expect(provider.exists?).to be_truthy
end
end
describe '#destroy' do
it 'removes aggregate with hosts' do
described_class.expects(:openstack)
.with('aggregate', 'remove host', ['just', 'example'])
described_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
describe '#pythondict2hash' do
it 'should return a hash with key-value when provided with a unicode python dict' do
s = "{u'key': 'value', u'key2': 'value2'}"
expect(described_class.pythondict2hash(s)).to eq({"key"=>"value", "key2"=>"value2"})
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
it 'should return a hash with key-value when provided with a python dict' do
s = "{'key': 'value', 'key2': 'value2'}"
expect(described_class.pythondict2hash(s)).to eq({"key"=>"value", "key2"=>"value2"})
end
end
describe '#parsestring' do
it 'should call string2hash when provided with a string' do
s = "key='value', key2='value2'"
expect(described_class.parsestring(s)).to eq({"key"=>"value", "key2"=>"value2"})
end
describe '#pythondict2hash' do
it 'should return a hash with key-value when provided with a unicode python dict' do
s = "{u'key': 'value', u'key2': 'value2'}"
expect(provider_class.pythondict2hash(s)).to eq({"key"=>"value", "key2"=>"value2"})
end
it 'should return a hash with key-value when provided with a python dict' do
s = "{'key': 'value', 'key2': 'value2'}"
expect(provider_class.pythondict2hash(s)).to eq({"key"=>"value", "key2"=>"value2"})
end
it 'should call pythondict2hash when provided with a hash' do
s = "{u'key': 'value', u'key2': 'value2'}"
expect(described_class.parsestring(s)).to eq({"key"=>"value", "key2"=>"value2"})
end
describe '#parsestring' do
it 'should call string2hash when provided with a string' do
s = "key='value', key2='value2'"
expect(provider_class.parsestring(s)).to eq({"key"=>"value", "key2"=>"value2"})
end
it 'should call pythondict2hash when provided with a hash' do
s = "{u'key': 'value', u'key2': 'value2'}"
expect(provider_class.parsestring(s)).to eq({"key"=>"value", "key2"=>"value2"})
end
end
end
end
@ -143,83 +138,83 @@ hosts="[u\'example\']"
end
let(:provider) do
provider_class.new(resource)
described_class.new(resource)
end
it_behaves_like 'authenticated with environment variables' do
before(:each) do
set_env
end
# create an aggregate and actually aggregate hosts to it
describe 'create aggregate and add/remove hosts with filter_hosts toggled' do
# create an aggregate and actually aggregate hosts to it
describe 'create aggregate and add/remove hosts with filter_hosts toggled' do
it 'creates aggregate with filter_hosts toggled' do
it 'creates aggregate with filter_hosts toggled' do
provider.class.stubs(:get_known_hosts)
.returns(['known', 'known_too'])
provider.class.stubs(:get_known_hosts)
.returns(['known', 'known_too'])
# these expectations are the actual tests that check the provider's behaviour
# and make sure only known hosts ('known' is the only known host) will be
# aggregated.
# these expectations are the actual tests that check the provider's behaviour
# and make sure only known hosts ('known' is the only known host) will be
# aggregated.
provider_class.expects(:openstack)
.with('aggregate', 'create', '--format', 'shell', ['just', '--zone', 'simple', "--property", "nice=cookie"])
.once
.returns('name="just"
described_class.expects(:openstack)
.with('aggregate', 'create', '--format', 'shell', ['just', '--zone', 'simple', "--property", "nice=cookie"])
.once
.returns('name="just"
id="just"
availability_zone="simple"
properties="{u\'nice\': u\'cookie\'}"
hosts="[]"
')
provider_class.expects(:openstack)
.with('aggregate', 'add host', ['just', 'known'])
.once
.returns('name="just"
described_class.expects(:openstack)
.with('aggregate', 'add host', ['just', 'known'])
.once
.returns('name="just"
id="just"
availability_zone="simple"
properties="{u\'nice\': u\'cookie\'}"
hosts="[u\'known\']"
')
provider_class.expects(:openstack)
.with('aggregate', 'add host', ['just', 'known_too'])
.once
.returns('name="just"
described_class.expects(:openstack)
.with('aggregate', 'add host', ['just', 'known_too'])
.once
.returns('name="just"
id="just"
availability_zone="simple"
properties="{u\'nice\': u\'cookie\'}"
hosts="[u\'known\', u\'known_too\']"
')
provider_class.expects(:openstack)
.with('aggregate', 'remove host', ['just', 'known'])
.once
.returns('name="just"
described_class.expects(:openstack)
.with('aggregate', 'remove host', ['just', 'known'])
.once
.returns('name="just"
id="just"
availability_zone="simple"
properties="{u\'nice\': u\'cookie\'}"
hosts="[u\'known_too\']"
')
# this creates a provider with the attributes defined above as 'aggregate_attrs'
# and tries to add some hosts and then to remove some hosts.
# the hosts will be filtered against known active hosts and the expectations
# described above are the actual tests that check the provider's behaviour
# this creates a provider with the attributes defined above as 'aggregate_attrs'
# and tries to add some hosts and then to remove some hosts.
# the hosts will be filtered against known active hosts and the expectations
# described above are the actual tests that check the provider's behaviour
provider.create
property_hash = provider.instance_variable_get(:@property_hash)
property_hash[:hosts] = ['known']
provider.instance_variable_set(:@property_hash, property_hash)
provider.create
property_hash = provider.instance_variable_get(:@property_hash)
property_hash[:hosts] = ['known']
provider.instance_variable_set(:@property_hash, property_hash)
provider.hosts = ['known', 'known_too', 'unknown']
property_hash = provider.instance_variable_get(:@property_hash)
property_hash[:hosts] = ['known', 'known_too']
provider.instance_variable_set(:@property_hash, property_hash)
provider.hosts = ['known', 'known_too', 'unknown']
property_hash = provider.instance_variable_get(:@property_hash)
property_hash[:hosts] = ['known', 'known_too']
provider.instance_variable_set(:@property_hash, property_hash)
provider.hosts = ['known_too']
provider.hosts = ['known_too']
end
end
end
end

View File

@ -2,9 +2,14 @@ require 'puppet'
require 'spec_helper'
require 'puppet/provider/nova_flavor/openstack'
provider_class = Puppet::Type.type(:nova_flavor).provider(:openstack)
describe Puppet::Type.type(:nova_flavor).provider(:openstack) do
describe provider_class do
let(:set_env) do
ENV['OS_USERNAME'] = 'test'
ENV['OS_PASSWORD'] = 'abc123'
ENV['OS_SYSTEM_SCOPE'] = 'all'
ENV['OS_AUTH_URL'] = 'http://127.0.0.1:5000/v3'
end
describe 'managing flavors' do
let(:flavor_attrs) do
@ -23,17 +28,20 @@ describe provider_class do
end
let(:provider) do
provider_class.new(resource)
described_class.new(resource)
end
before(:each) do
set_env
end
describe '#create' do
it 'creates flavor' do
provider.class.stubs(:openstack)
.with('flavor', 'list', ['--long', '--all'])
.returns('"ID", "Name", "RAM", "Disk", "Ephemeral", "VCPUs", "Is Public", "Swap", "RXTX Factor", "Properties"')
provider.class.stubs(:openstack)
.with('flavor', 'create', 'shell', ['example', '--public', '--id', '1', '--ram', '512', '--disk', '1', '--vcpus', '1'])
.returns('os-flv-disabled:disabled="False"
described_class.expects(:openstack)
.with('flavor', 'create', '--format', 'shell',
['example', '--public', '--id', '1', '--ram', '512',
'--disk', '1', '--vcpus', '1'])
.returns('os-flv-disabled:disabled="False"
os-flv-ext-data:ephemeral="0"
disk="1"
id="1"
@ -43,12 +51,14 @@ ram="512"
rxtx_factor="1.0"
swap=""
vcpus="1"')
provider.create
expect(provider.exists?).to be_truthy
end
end
describe '#destroy' do
it 'removes flavor' do
provider_class.expects(:openstack)
described_class.expects(:openstack)
.with('flavor', 'delete', '1')
provider.instance_variable_set(:@property_hash, flavor_attrs)
provider.destroy

View File

@ -9,7 +9,7 @@ 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_SYSTEM_SCOPE'] = 'all'
ENV['OS_AUTH_URL'] = 'http://127.0.0.1:5000/v3'
end

View File

@ -9,62 +9,10 @@ describe Puppet::Provider::Nova do
described_class
end
let :credential_hash do
{
'auth_url' => 'https://192.168.56.210:5000/v3/',
'project_name' => 'admin_tenant',
'username' => 'admin',
'password' => 'password',
'region_name' => 'Region1',
}
end
let :auth_endpoint do
'https://192.168.56.210:5000/v3/'
end
let :credential_error do
/Nova types will not work/
end
after :each do
klass.reset
end
describe 'when determining credentials' do
it 'should fail if config is empty' do
conf = {}
klass.expects(:nova_conf).returns(conf)
expect do
klass.nova_credentials
end.to raise_error(Puppet::Error, credential_error)
end
it 'should fail if config does not have keystone_authtoken section.' do
conf = {'foo' => 'bar'}
klass.expects(:nova_conf).returns(conf)
expect do
klass.nova_credentials
end.to raise_error(Puppet::Error, credential_error)
end
it 'should fail if config does not contain all auth params' do
conf = {'keystone_authtoken' => {'invalid_value' => 'foo'}}
klass.expects(:nova_conf).returns(conf)
expect do
klass.nova_credentials
end.to raise_error(Puppet::Error, credential_error)
end
it 'should use specified uri in the auth endpoint' do
conf = {'keystone_authtoken' => credential_hash}
klass.expects(:nova_conf).returns(conf)
expect(klass.get_auth_endpoint).to eq(auth_endpoint)
end
end
describe 'when parse a string line' do
it 'should return the same string' do
res = klass.str2hash("zone1")