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:
parent
ee0e3834b0
commit
5e62f69b5e
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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']
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue