Support for services different only by type.
First, Keystone_service provider was not able to create service
different by type. So service type computev3 and compute with name nova
could not be created.
Second, on a system with such resource it would not be able to
differentiate between the two. Then if
keystone_service {'nova': type => 'compute'}
was in the catalog, then the service nova/computev3 would be changed to
nova/compute.
Now you can specify:
keystone_service {'service::type'}
or
keystone_service {'service': type => 'type'}
It keeps a full backward compatibility.
Change-Id: I24bbcf8cbf3760fd061e2439f37864ae97ce86f6
Closes-Bug: #1508886
This commit is contained in:
@@ -272,4 +272,16 @@ describe 'basic keystone server with resources' do
|
||||
end
|
||||
end
|
||||
end
|
||||
describe 'composite namevar for keystone_service' do
|
||||
let(:pp) do
|
||||
<<-EOM
|
||||
keystone_service { 'service_1::type_1': ensure => present }
|
||||
keystone_service { 'service_1': type => 'type_2', ensure => present }
|
||||
EOM
|
||||
end
|
||||
it 'should be possible to create two services different only by their type' do
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -239,6 +239,45 @@ describe 'keystone server running with Apache/WSGI with resources' do
|
||||
include_examples 'keystone user/tenant/service/role/endpoint resources using v3 API',
|
||||
'--os-username beaker-civ3 --os-password secret --os-project-name servicesv3 --os-user-domain-name service_domain --os-project-domain-name service_domain'
|
||||
end
|
||||
|
||||
end
|
||||
describe 'composite namevar quick test' do
|
||||
context 'similar resources different naming' do
|
||||
let(:pp) do
|
||||
<<-EOM
|
||||
keystone_tenant { 'openstackv3':
|
||||
ensure => present,
|
||||
enabled => true,
|
||||
description => 'admin tenant',
|
||||
domain => 'admin_domain'
|
||||
}
|
||||
keystone_user { 'adminv3::useless_when_the_domain_is_set':
|
||||
ensure => present,
|
||||
enabled => true,
|
||||
email => 'test@example.tld',
|
||||
password => 'a_big_secret',
|
||||
domain => 'admin_domain'
|
||||
}
|
||||
keystone_user_role { 'adminv3::admin_domain@openstackv3::admin_domain':
|
||||
ensure => present,
|
||||
roles => ['admin'],
|
||||
}
|
||||
EOM
|
||||
end
|
||||
it 'should not do any modification' do
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
end
|
||||
end
|
||||
end
|
||||
describe 'composite namevar for keystone_service' do
|
||||
let(:pp) do
|
||||
<<-EOM
|
||||
keystone_service { 'service_1::type_1': ensure => present }
|
||||
keystone_service { 'service_1': type => 'type_2', ensure => present }
|
||||
EOM
|
||||
end
|
||||
it 'should be possible to create two services different only by their type' do
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,10 +8,7 @@ shared_examples_for 'parse title correctly' do |result|
|
||||
let(:title) do |example|
|
||||
example.metadata[:example_group][:description]
|
||||
end
|
||||
let(:current_class) do |example|
|
||||
example.metadata[:described_class]
|
||||
end
|
||||
let(:resource) { current_class.new(:title => title) }
|
||||
let(:resource) { described_class.new(:title => title) }
|
||||
it 'should parse this title correctly' do
|
||||
times = result.delete(:calling_default) || 0
|
||||
Puppet::Provider::Keystone.expects(:default_domain).times(times).returns('Default')
|
||||
@@ -23,12 +20,41 @@ shared_examples_for 'croak on the title' do
|
||||
let(:title) do |example|
|
||||
example.metadata[:example_group][:description]
|
||||
end
|
||||
let(:current_class) do |example|
|
||||
example.metadata[:described_class]
|
||||
end
|
||||
let(:user) { current_class.new(:title => title) }
|
||||
let(:resource) { described_class.new(:title => title) }
|
||||
it 'croak on the title' do
|
||||
expect { user }.to raise_error(Puppet::Error, /No set of title patterns matched the title/)
|
||||
expect { resource }.to raise_error(Puppet::Error, /No set of title patterns matched the title/)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'croak on the required parameter' do |attr|
|
||||
let(:title) do |example|
|
||||
example.metadata[:example_group][:description]
|
||||
end
|
||||
prefix = attr.is_a?(String) ? attr : ''
|
||||
|
||||
let(:resource) { described_class.new(:title => title) }
|
||||
it 'croak on the missing required parameter' do
|
||||
expect { resource }
|
||||
.to raise_error(Puppet::ResourceError, "#{prefix} Required parameter.")
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'croak on read-only parameter' do |resource|
|
||||
prefix = resource.delete(:_prefix)
|
||||
it 'should raise an error' do
|
||||
expect { described_class.new(resource) }
|
||||
.to raise_error(Puppet::ResourceError, "#{prefix} Read-only property.")
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'succeed with the required parameters' do |extra_params|
|
||||
let(:title) do |example|
|
||||
example.metadata[:example_group][:description]
|
||||
end
|
||||
extra_params_to_merge = extra_params || {}
|
||||
let(:resource) { described_class.new({ :title => title }.merge(extra_params_to_merge)) }
|
||||
it 'has all required parameters' do
|
||||
expect { resource }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
@@ -51,9 +77,6 @@ end
|
||||
|
||||
# Let resources to [<existing>, <non_existing>]
|
||||
shared_examples_for 'prefetch the resources' do
|
||||
let(:current_class) do |example|
|
||||
example.metadata[:described_class]
|
||||
end
|
||||
it 'should correctly prefetch the existing resource' do
|
||||
existing = resources[0]
|
||||
non_existing = resources[1]
|
||||
@@ -68,8 +91,8 @@ shared_examples_for 'prefetch the resources' do
|
||||
resource.expects(:values).returns(m_value)
|
||||
m_value.expects(:first).returns(m_first)
|
||||
m_first.expects(:catalog).returns(catalog)
|
||||
m_first.expects(:class).returns(current_class.resource_type)
|
||||
current_class.prefetch(resource)
|
||||
m_first.expects(:class).returns(described_class.resource_type)
|
||||
described_class.prefetch(resource)
|
||||
|
||||
# found and not found
|
||||
expect(existing.provider.ensure).to eq(:present)
|
||||
@@ -81,7 +104,8 @@ end
|
||||
# - the first hash are the expected result
|
||||
# - second are parameters to test default domain, required but can be empty
|
||||
# - the rest are the combination of attributes you want to test
|
||||
# see examples in user/user_role/tenant
|
||||
# The provider must be build from ressource_attrs
|
||||
# see examples in keystone_{user/user_role/tenant/service}
|
||||
shared_examples_for 'create the correct resource' do |attributes|
|
||||
expected_results = attributes.shift['expected_results']
|
||||
default_domain = attributes.shift
|
||||
|
||||
@@ -17,19 +17,19 @@ describe provider_class do
|
||||
set_env
|
||||
end
|
||||
|
||||
describe 'when managing a service' do
|
||||
describe 'when managing service' do
|
||||
|
||||
let(:service_attrs) do
|
||||
let(:resource_attrs) do
|
||||
{
|
||||
:name => 'foo',
|
||||
:description => 'foo',
|
||||
:name => 'service_one',
|
||||
:description => 'Service One',
|
||||
:ensure => 'present',
|
||||
:type => 'foo',
|
||||
:type => 'type_one'
|
||||
}
|
||||
end
|
||||
|
||||
let(:resource) do
|
||||
Puppet::Type::Keystone_service.new(service_attrs)
|
||||
Puppet::Type::Keystone_service.new(resource_attrs)
|
||||
end
|
||||
|
||||
let(:provider) do
|
||||
@@ -37,63 +37,100 @@ describe provider_class do
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
it 'creates a service' do
|
||||
provider.class.stubs(:openstack)
|
||||
.with('service', 'list', '--quiet', '--format', 'csv', '--long')
|
||||
.returns('"ID","Name","Type","Description"
|
||||
"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo"
|
||||
'
|
||||
)
|
||||
provider.class.stubs(:openstack)
|
||||
.with('service', 'create', '--format', 'shell', ['foo', '--name', 'foo', '--description', 'foo'])
|
||||
.returns('description="foo"
|
||||
before(:each) do
|
||||
provider_class.expects(:openstack)
|
||||
.with('service', 'create', '--format', 'shell',
|
||||
['type_one', '--name', 'service_one', '--description', 'Service One'])
|
||||
.returns('description="Service One"
|
||||
enabled="True"
|
||||
id="8f0dd4c0abc44240998fbb3f5089ecbf"
|
||||
name="foo"
|
||||
type="foo"
|
||||
'
|
||||
)
|
||||
provider.create
|
||||
expect(provider.exists?).to be_truthy
|
||||
name="service_one"
|
||||
type="type_one"
|
||||
')
|
||||
end
|
||||
include_examples 'create the correct resource', [
|
||||
{
|
||||
'expected_results' => {
|
||||
:type => 'type_one',
|
||||
:id => '8f0dd4c0abc44240998fbb3f5089ecbf',
|
||||
:name => 'service_one',
|
||||
:description => 'Service One'
|
||||
}
|
||||
},
|
||||
{},
|
||||
{
|
||||
'type in title' => {
|
||||
:title => 'service_one::type_one',
|
||||
:description => 'Service One'
|
||||
}
|
||||
},
|
||||
{
|
||||
'type in parameter' => {
|
||||
:title => 'service_one',
|
||||
:type => 'type_one',
|
||||
:description => 'Service One'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
end
|
||||
describe '#destroy' do
|
||||
it 'destroys a service' do
|
||||
provider_class.expects(:openstack)
|
||||
.with('service', 'delete', [])
|
||||
provider.destroy
|
||||
expect(provider.exists?).to be_falsey
|
||||
end
|
||||
|
||||
describe '#destroy' do
|
||||
it 'destroys a service' do
|
||||
provider.class.stubs(:openstack)
|
||||
.with('service', 'list', '--quiet', '--format', 'csv', '--long')
|
||||
.returns('"ID","Name","Type","Description"
|
||||
"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo"
|
||||
'
|
||||
)
|
||||
provider.class.stubs(:openstack)
|
||||
.with('service', 'delete', [])
|
||||
provider.destroy
|
||||
expect(provider.exists?).to be_falsey
|
||||
end
|
||||
|
||||
context 'when service does not exist' do
|
||||
subject(:response) do
|
||||
provider.class.stubs(:openstack)
|
||||
.with('service', 'list', '--quiet', '--format', 'csv', '--long')
|
||||
.returns('"ID","Name","Type","Description"')
|
||||
response = provider.exists?
|
||||
end
|
||||
it { is_expected.to be_falsey }
|
||||
context 'when service does not exist' do
|
||||
subject(:response) do
|
||||
provider.exists?
|
||||
end
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#instances' do
|
||||
it 'finds every service' do
|
||||
provider.class.stubs(:openstack)
|
||||
.with('service', 'list', '--quiet', '--format', 'csv', '--long')
|
||||
.returns('"ID","Name","Type","Description"
|
||||
"8f0dd4c0abc44240998fbb3f5089ecbf","foo","foo","foo"
|
||||
'
|
||||
)
|
||||
instances = Puppet::Type::Keystone_service::ProviderOpenstack.instances
|
||||
expect(instances.count).to eq(1)
|
||||
end
|
||||
describe '#instances' do
|
||||
it 'finds every service' do
|
||||
provider_class.expects(:openstack)
|
||||
.with('service', 'list', '--quiet', '--format', 'csv', '--long')
|
||||
.returns('"ID","Name","Type","Description"
|
||||
"8f0dd4c0abc44240998fbb3f5089ecbf","service_one","type_one","Service One"
|
||||
')
|
||||
instances = provider_class.instances
|
||||
expect(instances.count).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context '#prefetch' do
|
||||
before(:each) do
|
||||
# This call done by self.instance in prefetch in what make the
|
||||
# resource exists.
|
||||
provider_class.expects(:openstack)
|
||||
.with('service', 'list', '--quiet', '--format', 'csv', '--long')
|
||||
.returns('"ID","Name","Type","Description"
|
||||
"8f0dd4c0abc44240998fbb3f5089ecbf","service_1","type_1",""
|
||||
')
|
||||
end
|
||||
let(:service_1) do
|
||||
Puppet::Type::Keystone_service.new(:title => 'service_1::type_1')
|
||||
end
|
||||
let(:service_2) do
|
||||
Puppet::Type::Keystone_service.new(:title => 'service_1', :type => 'type_2')
|
||||
end
|
||||
let(:resources) { [service_1, service_2] }
|
||||
include_examples 'prefetch the resources'
|
||||
end
|
||||
|
||||
context 'duplicate detection' do
|
||||
let(:service_1) do
|
||||
Puppet::Type::Keystone_service.new(:title => 'service_1::type_1')
|
||||
end
|
||||
let(:service_2) do
|
||||
Puppet::Type::Keystone_service.new(:title => 'service_1', :type => 'type_1')
|
||||
end
|
||||
let(:resources) { [service_1, service_2] }
|
||||
include_examples 'detect duplicate resource'
|
||||
end
|
||||
end
|
||||
|
||||
32
spec/unit/type/keystone_service_spec.rb
Normal file
32
spec/unit/type/keystone_service_spec.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
require 'spec_helper'
|
||||
require 'puppet'
|
||||
require 'puppet/type/keystone_service'
|
||||
|
||||
describe Puppet::Type.type(:keystone_service) do
|
||||
|
||||
let(:project) do
|
||||
Puppet::Type.type(:keystone_service).new(
|
||||
:id => 'blah',
|
||||
:name => 'foo',
|
||||
:type => 'foo-type'
|
||||
)
|
||||
end
|
||||
|
||||
include_examples 'croak on read-only parameter',
|
||||
:title => 'service::type', :id => '12345',
|
||||
:_prefix => 'Parameter id failed on Keystone_service[service::type]:'
|
||||
|
||||
describe 'service::type' do
|
||||
include_examples 'parse title correctly', :name => 'service', :type => 'type'
|
||||
end
|
||||
|
||||
describe 'new_service_without_type' do
|
||||
include_examples 'croak on the required parameter',
|
||||
'Parameter type failed on Keystone_service[new_service_without_type]:'
|
||||
end
|
||||
|
||||
describe 'new_service_with_type_as_parameter' do
|
||||
include_examples 'succeed with the required parameters', :type => 'type'
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user