]> git.donarmstrong.com Git - dsa-puppet.git/blob - 3rdparty/modules/keystone/lib/puppet/provider/keystone_user_role/openstack.rb
Update to Kilo
[dsa-puppet.git] / 3rdparty / modules / keystone / lib / puppet / provider / keystone_user_role / openstack.rb
1 require 'puppet/provider/keystone'
2 require 'puppet/provider/keystone/util'
3
4 Puppet::Type.type(:keystone_user_role).provide(
5   :openstack,
6   :parent => Puppet::Provider::Keystone
7 ) do
8
9   desc "Provider to manage keystone role assignments to users."
10
11   @credentials = Puppet::Provider::Openstack::CredentialsV3.new
12
13   def initialize(value={})
14     super(value)
15     @property_flush = {}
16   end
17
18   def create
19     if resource[:roles]
20       resource[:roles].each do |role|
21         self.class.request('role', 'add', [role] + properties)
22       end
23     end
24   end
25
26   def destroy
27     if @property_hash[:roles]
28       @property_hash[:roles].each do |role|
29         self.class.request('role', 'remove', [role] + properties)
30       end
31     end
32     @property_hash[:ensure] = :absent
33   end
34
35   def exists?
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
41       # and destroy methods
42       @property_hash[:name] = resource[:name]
43       if roles.empty?
44         @property_hash[:ensure] = :absent
45       else
46         @property_hash[:ensure] = :present
47         @property_hash[:roles]  = roles.collect do |role|
48           role[:name]
49         end
50       end
51     end
52     return @property_hash[:ensure] == :present
53   end
54
55   def roles
56     @property_hash[:roles]
57   end
58
59   def roles=(value)
60     current_roles = 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)
66     end
67     remove.each do |role_name|
68       self.class.request('role', 'remove', [role_name] + properties)
69     end
70   end
71
72   def self.instances
73     instances = build_user_role_hash
74     instances.collect do |title, roles|
75       new(
76         :name   => title,
77         :ensure => :present,
78         :roles  => roles
79       )
80     end
81   end
82
83   private
84
85   def properties
86     properties = []
87     if get_project_id
88       properties << '--project' << get_project_id
89     elsif get_domain
90       properties << '--domain' << get_domain
91     else
92       error("No project or domain specified for role")
93     end
94     properties << '--user' << get_user_id
95     properties
96   end
97
98   def get_user
99     resource[:name].rpartition('@').first
100   end
101
102   def get_project
103     resource[:name].rpartition('@').last
104   end
105
106   # if the role is for a domain, it will be specified as
107   # user@::domain - the "project" part will be empty
108   def get_domain
109     # use defined because @domain may be nil
110     return @domain if defined?(@domain)
111     projname, domname = Util.split_domain(get_project)
112     if projname.nil?
113       @domain = domname # no project specified, so must be a domain
114     else
115       @domain = nil # not a domain specific role
116     end
117     @domain
118   end
119
120   def get_user_id
121     @user_id ||= Puppet::Resource.indirection.find("Keystone_user/#{get_user}")[:id]
122   end
123
124   def get_project_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)
128     if projname.nil?
129       @project_id = nil
130     else
131       @project_id ||= Puppet::Resource.indirection.find("Keystone_tenant/#{get_project}")[:id]
132     end
133     @project_id
134   end
135
136   def self.get_projects
137     request('project', 'list', '--long').collect do |project|
138       {
139         :id        => project[:id],
140         :name      => project[:name],
141         :domain_id => project[:domain_id],
142         :domain    => domain_name_from_id(project[:domain_id])
143       }
144     end
145   end
146
147   def self.get_users(project_id=nil, domain_id=nil)
148     properties = ['--long']
149     if project_id
150       properties << '--project' << project_id
151     elsif domain_id
152       properties << '--domain' << domain_id
153     end
154     request('user', 'list', properties).collect do |user|
155       {
156         :id        => user[:id],
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])
161       }
162     end
163   end
164
165   def self.user_role_hash
166     @user_role_hash
167   end
168
169   def self.set_user_role_hash(user_role_hash)
170     @user_role_hash = user_role_hash
171   end
172
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.
180     project_hash = {}
181     Puppet::Type.type(:keystone_tenant).provider(:openstack).instances.each do |project|
182       project_hash[project.id] = project.name
183     end
184     # Need a mapping of user id to names.
185     user_hash = {}
186     Puppet::Type.type(:keystone_user).provider(:openstack).instances.each do |user|
187       user_hash[user.id] = user.name
188     end
189     # need a mapping of role id to name
190     role_hash = {}
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|
194       if assignment[:user]
195         if assignment[:project]
196           hash["#{user_hash[assignment[:user]]}@#{project_hash[assignment[:project]]}"] << role_hash[assignment[:role]]
197         else
198           domainname = domain_id_to_name(assignment[:domain])
199           hash["#{user_hash[assignment[:user]]}@::#{domainname}"] << role_hash[assignment[:role]]
200         end
201       end
202     end
203     set_user_role_hash(hash)
204     hash
205   end
206 end