1 require 'puppet/provider/keystone'
2 require 'puppet/provider/keystone/util'
4 Puppet::Type.type(:keystone_user_role).provide(
6 :parent => Puppet::Provider::Keystone
9 desc "Provider to manage keystone role assignments to users."
11 @credentials = Puppet::Provider::Openstack::CredentialsV3.new
13 def initialize(value={})
20 resource[:roles].each do |role|
21 self.class.request('role', 'add', [role] + properties)
27 if @property_hash[:roles]
28 @property_hash[:roles].each do |role|
29 self.class.request('role', 'remove', [role] + properties)
32 @property_hash[:ensure] = :absent
36 if self.class.user_role_hash.nil? || self.class.user_role_hash.empty?
37 roles = self.class.request('role', 'list', properties)
38 # Since requesting every combination of users, roles, and
39 # projects is so expensive, construct the property hash here
40 # instead of in self.instances so it can be used in the role
42 @property_hash[:name] = resource[:name]
44 @property_hash[:ensure] = :absent
46 @property_hash[:ensure] = :present
47 @property_hash[:roles] = roles.collect do |role|
52 return @property_hash[:ensure] == :present
56 @property_hash[:roles]
61 # determine the roles to be added and removed
62 remove = current_roles - Array(value)
63 add = Array(value) - current_roles
64 add.each do |role_name|
65 self.class.request('role', 'add', [role_name] + properties)
67 remove.each do |role_name|
68 self.class.request('role', 'remove', [role_name] + properties)
73 instances = build_user_role_hash
74 instances.collect do |title, roles|
88 properties << '--project' << get_project_id
90 properties << '--domain' << get_domain
92 error("No project or domain specified for role")
94 properties << '--user' << get_user_id
99 resource[:name].rpartition('@').first
103 resource[:name].rpartition('@').last
106 # if the role is for a domain, it will be specified as
107 # user@::domain - the "project" part will be empty
109 # use defined because @domain may be nil
110 return @domain if defined?(@domain)
111 projname, domname = Util.split_domain(get_project)
113 @domain = domname # no project specified, so must be a domain
115 @domain = nil # not a domain specific role
121 @user_id ||= Puppet::Resource.indirection.find("Keystone_user/#{get_user}")[:id]
125 # use defined because @project_id may be nil
126 return @project_id if defined?(@project_id)
127 projname, domname = Util.split_domain(get_project)
131 @project_id ||= Puppet::Resource.indirection.find("Keystone_tenant/#{get_project}")[:id]
136 def self.get_projects
137 request('project', 'list', '--long').collect do |project|
140 :name => project[:name],
141 :domain_id => project[:domain_id],
142 :domain => domain_name_from_id(project[:domain_id])
147 def self.get_users(project_id=nil, domain_id=nil)
148 properties = ['--long']
150 properties << '--project' << project_id
152 properties << '--domain' << domain_id
154 request('user', 'list', properties).collect do |user|
157 :name => user[:name],
158 # note - column is "Domain" but it is really the domain id
159 :domain_id => user[:domain],
160 :domain => domain_name_from_id(user[:domain])
165 def self.user_role_hash
169 def self.set_user_role_hash(user_role_hash)
170 @user_role_hash = user_role_hash
173 def self.build_user_role_hash
174 # The new hash will have the property that if the
175 # given key does not exist, create it with an empty
176 # array as the value for the hash key
177 hash = @user_role_hash || Hash.new{|h,k| h[k] = []}
178 return hash unless hash.empty?
179 # Need a mapping of project id to names.
181 Puppet::Type.type(:keystone_tenant).provider(:openstack).instances.each do |project|
182 project_hash[project.id] = project.name
184 # Need a mapping of user id to names.
186 Puppet::Type.type(:keystone_user).provider(:openstack).instances.each do |user|
187 user_hash[user.id] = user.name
189 # need a mapping of role id to name
191 request('role', 'list').each {|role| role_hash[role[:id]] = role[:name]}
192 # now, get all role assignments
193 request('role assignment', 'list').each do |assignment|
195 if assignment[:project]
196 hash["#{user_hash[assignment[:user]]}@#{project_hash[assignment[:project]]}"] << role_hash[assignment[:role]]
198 domainname = domain_id_to_name(assignment[:domain])
199 hash["#{user_hash[assignment[:user]]}@::#{domainname}"] << role_hash[assignment[:role]]
203 set_user_role_hash(hash)