[openstack-dev] [puppet][keystone] How to uniquely name Keystone v3 resources in puppet?

Rich Megginson rmeggins at redhat.com
Mon Jun 22 14:02:34 UTC 2015

The problem with puppet-keystone and Keystone v3 domains is naming of 
puppet resources contained within domains - users, groups, projects.

Suppose you have an admin user in domain "dom1" and an admin user in 
domain "dom2".  How do you declare these in puppet?  You can't do

keystone_user { 'admin': domain => 'dom1'}
keystone_user { 'admin': domain => 'dom2'}

AFAIK, resource names in puppet have to be unique.  I have introduced 
the string "::" as the domain delimiter in puppet code. This allows you 
to "fully qualify" resource names with the domain in all domain scoped 

keystone_user { 'admin::dom1': }
keystone_user { 'admin': domain => 'dom2'}

This is a valid puppet manifest - the resource names are unique.

How do I refer to the "admin" user?  For example, I want to have a role 

keystone_user_role { 'admin::dom2 at project::somedomain': roles => 
['adminrole'] }

How do I have an autorequire for the user?  That is, I can't know, in 
the autorequire method in the keystone_user_role.rb type code, if the 
resource name is going to be 'admin' or 'admin::dom2'.  If I just do 
autorequire for ['admin'], that will cause problems if a) there is no 
'admin' user because all 'admin' users are fully qualified b) the user 
named 'admin' is the one in dom1

I could avoid using autorequire and force the use of explicit requires 
=> 'name' in every keystone_user_role, but that would break existing 

I could use autorequire, but force manifest writers to be consistent 
with fully qualified resource naming.  That is, the manifest writer 
would have to know that the resource name of the admin user in dom1 is 
always 'admin::dom1' and the resource name of the admin user in dom2 is 
always 'admin', and they must be used that way, consistently, 
everywhere, even in deeply nested classes/defines.

Another problem is with the puppet provider self.instances method. This 
method queries all of the external resources of a given type and 
constructs something like a named puppet resource representing the 
external resource.  For example: the keystone_user self.instances does 
'openstack user list --long' and creates named puppet resources.

What happens if openstack user list --long returns admin in dom1 and 
admin in dom2?  How does self.instances name these uniquely?  If it 
always names these "fully qualified" with ::domain, this will cause 
problems.  This could be handled with some extra logic:
1) If name is unique (i.e. there is only one user named 'admin' in all 
domains), then just create the resource with the name 'admin' - no 
::domain.  This would require self.instances to keep track of every 
returned resource e.g. collect all of the list results in a hash, and 
only instantiate the resources once it is known that the name is unique.
2) If the resource is in the designated "default domain" (i.e. the 
domain id matches [identity] default_domain_id, or 'default' if 
[identity] default_domain_id not configured), then use the name without 
the domain

2 seems like the intuitive way to go - works well with existing 
manifests which are not yet domain aware, and things like puppet 
resource keystone_user [name] will almost always work as expected. But 
this means that manifest writers have to know that all puppet-keystone 
manifests and code need to know what the domain name corresponding to 
the default_domain_id is, and know that the resource in that domain 
should always be referred to as 'name', not 'name::domain'.  For 
example, if you have user 'someuser' in domain 'Default', and domain 
'Default' is the default domain with an id of 'default', all resources 
should should use keystone_user { 'name': } and keystone_user_role { 
'name at project': }

self.instances could return the fully qualified name _and_ the short 
name, where the short name is the resource in the default domain. This 
might cause confusion with puppet resource 'resource_name', when the 
user sees both 'admin' and 'admin::dom1' but at least the user will see 
one or the other, and both "puppet resource keystone_user admin" and 
"puppet resource keystone_user admin::dom1" will work.  This would 
require some minor adjustment to the currently proposed patches for the 
self.instances - self.instances would need to be aware of the default 
domain and construct short names for those resources, and self.prefetch 
would also need to know to use the shortnamed resource for the default 
domain.  In this case, the short name would be an "alias" for the fully 
qualified name, sort of like a dns query where both the shortnames and 
fqdns are returned.

More information about the OpenStack-dev mailing list