Add resource to manage implied roles
Keystone supports implied roles, and some of the default roles imply different roles. (eg. admin implies manager) This introduces a resource type to manage implied roles, and also ensures the implied roles are created in bootstrap. Depends-on: https://review.opendev.org/900138 Change-Id: I36ef3ddfcb2f60bdca8674ea8055b6f57a149512
This commit is contained in:
parent
df9ce566c6
commit
01ffd0e4c3
77
lib/puppet/provider/keystone_implied_role/openstack.rb
Normal file
77
lib/puppet/provider/keystone_implied_role/openstack.rb
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
require File.join(File.dirname(__FILE__), '..','..','..', 'puppet/provider/keystone')
|
||||||
|
require File.join(File.dirname(__FILE__), '..','..','..', 'puppet_x/keystone/composite_namevar')
|
||||||
|
|
||||||
|
Puppet::Type.type(:keystone_implied_role).provide(
|
||||||
|
:openstack,
|
||||||
|
:parent => Puppet::Provider::Keystone
|
||||||
|
) do
|
||||||
|
|
||||||
|
desc 'Provider for keystone implied roles.'
|
||||||
|
|
||||||
|
@credentials = Puppet::Provider::Openstack::CredentialsV3.new
|
||||||
|
|
||||||
|
include PuppetX::Keystone::CompositeNamevar::Helpers
|
||||||
|
|
||||||
|
def initialize(value={})
|
||||||
|
super(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.do_not_manage
|
||||||
|
@do_not_manage
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.do_not_manage=(value)
|
||||||
|
@do_not_manage = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
if self.class.do_not_manage
|
||||||
|
fail("Not managing Keystone_implied_role[#{@resource[:role]}@#{@resource[:implied_role]}] due to earlier Keystone API failures.")
|
||||||
|
end
|
||||||
|
self.class.system_request('implied role', 'create', [@resource[:role], '--implied-role', @resource[:implied_role]])
|
||||||
|
@property_hash[:ensure] = :present
|
||||||
|
@property_hash[:role] = @resource[:role]
|
||||||
|
@property_hash[:implied_role] = @resource[:implied_role]
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
if self.class.do_not_manage
|
||||||
|
fail("Not managing Keystone_implied_role[#{@resource[:role]}@#{@resource[:implied_role]}] due to earlier Keystone API failures.")
|
||||||
|
end
|
||||||
|
self.class.system_request('implied role', 'delete', [@resource[:role], '--implied-role', @resource[:implied_role]])
|
||||||
|
@property_hash.clear
|
||||||
|
end
|
||||||
|
|
||||||
|
def exists?
|
||||||
|
@property_hash[:ensure] == :present
|
||||||
|
end
|
||||||
|
|
||||||
|
mk_resource_methods
|
||||||
|
|
||||||
|
[
|
||||||
|
:role,
|
||||||
|
:implied_role,
|
||||||
|
].each do |attr|
|
||||||
|
define_method(attr.to_s + "=") do |value|
|
||||||
|
fail("Property #{attr.to_s} does not support being updated")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.instances
|
||||||
|
self.do_not_manage = true
|
||||||
|
list = system_request('implied role', 'list')
|
||||||
|
reallist = list.collect do |role|
|
||||||
|
new(
|
||||||
|
:ensure => :present,
|
||||||
|
:role => role[:prior_role_name].downcase,
|
||||||
|
:implied_role => role[:implied_role_name].downcase,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
self.do_not_manage = false
|
||||||
|
reallist
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.prefetch(resources)
|
||||||
|
prefetch_composite(resources)
|
||||||
|
end
|
||||||
|
end
|
@ -11,7 +11,6 @@ Puppet::Type.type(:keystone_role).provide(
|
|||||||
|
|
||||||
def initialize(value={})
|
def initialize(value={})
|
||||||
super(value)
|
super(value)
|
||||||
@property_flush = {}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.do_not_manage
|
def self.do_not_manage
|
||||||
|
44
lib/puppet/type/keystone_implied_role.rb
Normal file
44
lib/puppet/type/keystone_implied_role.rb
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# LP#1408531
|
||||||
|
File.expand_path('../..', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
|
||||||
|
File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
|
||||||
|
|
||||||
|
Puppet::Type.newtype(:keystone_implied_role) do
|
||||||
|
|
||||||
|
desc <<-EOT
|
||||||
|
This is currently used to model the creation of
|
||||||
|
keystone implied roles.
|
||||||
|
EOT
|
||||||
|
|
||||||
|
ensurable
|
||||||
|
|
||||||
|
newparam(:role) do
|
||||||
|
isnamevar
|
||||||
|
newvalues(/\S+/)
|
||||||
|
end
|
||||||
|
|
||||||
|
newparam(:implied_role) do
|
||||||
|
isnamevar
|
||||||
|
newvalues(/\S+/)
|
||||||
|
end
|
||||||
|
|
||||||
|
# we should not do anything until the keystone service is started
|
||||||
|
autorequire(:anchor) do
|
||||||
|
['keystone::service::end']
|
||||||
|
end
|
||||||
|
|
||||||
|
autorequire(:keystone_role) do
|
||||||
|
[self[:role], self[:implied_role]]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.title_patterns
|
||||||
|
[
|
||||||
|
[
|
||||||
|
/^(\S+)@(\S+)$/,
|
||||||
|
[
|
||||||
|
[:role],
|
||||||
|
[:implied_role],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
@ -116,7 +116,17 @@ class keystone::bootstrap (
|
|||||||
# use the below resources to make sure the current resources are
|
# use the below resources to make sure the current resources are
|
||||||
# correct so if some value was updated we set that.
|
# correct so if some value was updated we set that.
|
||||||
|
|
||||||
ensure_resource('keystone_role', $role_name, {
|
ensure_resource('keystone_role',
|
||||||
|
[$role_name, 'manager', 'member', 'reader', 'service'], {
|
||||||
|
'ensure' => 'present',
|
||||||
|
})
|
||||||
|
|
||||||
|
ensure_resource('keystone_implied_role',
|
||||||
|
[
|
||||||
|
"${role_name}@manager",
|
||||||
|
'manager@member',
|
||||||
|
'member@reader',
|
||||||
|
], {
|
||||||
'ensure' => 'present',
|
'ensure' => 'present',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
4
releasenotes/notes/implied-role-894ec2595b94aed7.yaml
Normal file
4
releasenotes/notes/implied-role-894ec2595b94aed7.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The new ``keystone_implied_role`` resource type has been added.
|
@ -33,6 +33,14 @@ describe 'keystone::bootstrap' do
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
it { is_expected.to contain_keystone_role('admin').with_ensure('present') }
|
it { is_expected.to contain_keystone_role('admin').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_role('manager').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_role('member').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_role('reader').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_role('service').with_ensure('present') }
|
||||||
|
|
||||||
|
it { is_expected.to contain_keystone_implied_role('admin@manager').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_implied_role('manager@member').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_implied_role('member@reader').with_ensure('present') }
|
||||||
|
|
||||||
it { is_expected.to contain_keystone_user('admin').with(
|
it { is_expected.to contain_keystone_user('admin').with(
|
||||||
:ensure => 'present',
|
:ensure => 'present',
|
||||||
@ -137,6 +145,14 @@ describe 'keystone::bootstrap' do
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
it { is_expected.to contain_keystone_role('adminrole').with_ensure('present') }
|
it { is_expected.to contain_keystone_role('adminrole').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_role('manager').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_role('member').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_role('reader').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_role('service').with_ensure('present') }
|
||||||
|
|
||||||
|
it { is_expected.to contain_keystone_implied_role('adminrole@manager').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_implied_role('manager@member').with_ensure('present') }
|
||||||
|
it { is_expected.to contain_keystone_implied_role('member@reader').with_ensure('present') }
|
||||||
|
|
||||||
it { is_expected.to contain_keystone_user('user').with(
|
it { is_expected.to contain_keystone_user('user').with(
|
||||||
:ensure => 'present',
|
:ensure => 'present',
|
||||||
|
89
spec/unit/provider/keystone_implied_role/openstack_spec.rb
Normal file
89
spec/unit/provider/keystone_implied_role/openstack_spec.rb
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
require 'puppet'
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'puppet/provider/keystone_implied_role/openstack'
|
||||||
|
|
||||||
|
provider_class = Puppet::Type.type(:keystone_implied_role).provider(:openstack)
|
||||||
|
|
||||||
|
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'
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
set_env
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when creating an implied role' do
|
||||||
|
let(:implied_role_attrs) do
|
||||||
|
{
|
||||||
|
:title => 'foo@bar',
|
||||||
|
:ensure => 'present',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:resource) do
|
||||||
|
Puppet::Type::Keystone_implied_role.new(implied_role_attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:provider) do
|
||||||
|
provider_class.new(resource)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#create' do
|
||||||
|
it 'creates an implied role' do
|
||||||
|
expect(provider.class).to receive(:openstack)
|
||||||
|
.with('implied role', 'create', '--format', 'shell',
|
||||||
|
['foo', '--implied-role', 'bar'])
|
||||||
|
.and_return('implies="54d545116da64b68bb75244130ba51b2"
|
||||||
|
prior_role="3553ab20c4dd497a867dd822913b6d30"
|
||||||
|
')
|
||||||
|
provider.create
|
||||||
|
expect(provider.exists?).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#destroy' do
|
||||||
|
it 'destroys an implied role' do
|
||||||
|
expect(provider.class).to receive(:openstack)
|
||||||
|
.with('implied role', 'delete',
|
||||||
|
['foo', '--implied-role', 'bar'])
|
||||||
|
provider.destroy
|
||||||
|
expect(provider.exists?).to be_falsey
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#exists' do
|
||||||
|
context 'when implied role does not exist' do
|
||||||
|
subject(:response) do
|
||||||
|
response = provider.exists?
|
||||||
|
end
|
||||||
|
it { is_expected.to be_falsey }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#instances' do
|
||||||
|
it 'finds every role' do
|
||||||
|
expect(provider.class).to receive(:openstack)
|
||||||
|
.with('implied role', 'list', '--quiet', '--format', 'csv', [])
|
||||||
|
.and_return('"Prior Role ID","Prior Role Name","Implied Role ID","Implied Role Name"
|
||||||
|
"1d7f28c7d646463dba7b0c6c5851c59b","admin","da9eac51634e41fa902de65e4ec7f165","manager"
|
||||||
|
"d00138e69f7c427693e437f33e3765af","member","906b88ee8a824e96aa93ea887337d8ac","reader"
|
||||||
|
"da9eac51634e41fa902de65e4ec7f165","manager","d00138e69f7c427693e437f33e3765af","member"
|
||||||
|
')
|
||||||
|
instances = Puppet::Type::Keystone_implied_role::ProviderOpenstack.instances
|
||||||
|
expect(instances.count).to eq(3)
|
||||||
|
expect(instances[0].role).to eq('admin')
|
||||||
|
expect(instances[0].implied_role).to eq('manager')
|
||||||
|
expect(instances[1].role).to eq('member')
|
||||||
|
expect(instances[1].implied_role).to eq('reader')
|
||||||
|
expect(instances[2].role).to eq('manager')
|
||||||
|
expect(instances[2].implied_role).to eq('member')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
36
spec/unit/type/keystone_implied_role_spec.rb
Normal file
36
spec/unit/type/keystone_implied_role_spec.rb
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
require 'puppet'
|
||||||
|
require 'puppet/type/keystone_implied_role'
|
||||||
|
|
||||||
|
describe Puppet::Type.type(:keystone_implied_role) do
|
||||||
|
|
||||||
|
describe 'role@implied_role' do
|
||||||
|
include_examples 'parse title correctly',
|
||||||
|
:role => 'role',
|
||||||
|
:implied_role => 'implied_role'
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#autorequire' do
|
||||||
|
let(:child) do
|
||||||
|
Puppet::Type.type(:keystone_role).new(:title => 'child')
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:parent) do
|
||||||
|
Puppet::Type.type(:keystone_role).new(:title => 'parent')
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:another) do
|
||||||
|
Puppet::Type.type(:keystone_role).new(:title => 'another')
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'role autorequire from title' do
|
||||||
|
let(:implied_role) do
|
||||||
|
Puppet::Type.type(:keystone_implied_role).new(:title => 'child@parent')
|
||||||
|
end
|
||||||
|
describe 'should require the correct domain' do
|
||||||
|
let(:resources) { [implied_role, child, parent, another] }
|
||||||
|
include_examples 'autorequire the correct resources'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user