180 lines
5.3 KiB
Ruby
180 lines
5.3 KiB
Ruby
require File.join(File.dirname(__FILE__), '..','..','..', 'puppet/provider/keystone')
|
|
|
|
Puppet::Type.type(:keystone_user).provide(
|
|
:openstack,
|
|
:parent => Puppet::Provider::Keystone
|
|
) do
|
|
|
|
desc "Provider to manage keystone users."
|
|
|
|
@credentials = Puppet::Provider::Openstack::CredentialsV3.new
|
|
|
|
include PuppetX::Keystone::CompositeNamevar::Helpers
|
|
|
|
def initialize(value={})
|
|
super(value)
|
|
@property_flush = {}
|
|
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_user[#{@resource[:name]}] due to earlier Keystone API failures.")
|
|
end
|
|
user_name, user_domain = resource[:name], resource[:domain]
|
|
properties = [user_name]
|
|
if resource[:enabled] == :true
|
|
properties << '--enable'
|
|
elsif resource[:enabled] == :false
|
|
properties << '--disable'
|
|
end
|
|
if resource[:password]
|
|
properties << '--password' << resource[:password]
|
|
end
|
|
if resource[:email]
|
|
properties << '--email' << resource[:email]
|
|
end
|
|
if user_domain
|
|
properties << '--domain'
|
|
properties << user_domain
|
|
end
|
|
@property_hash = self.class.system_request('user', 'create', properties)
|
|
@property_hash[:name] = resource[:name]
|
|
@property_hash[:domain] = user_domain
|
|
@property_hash[:ensure] = :present
|
|
end
|
|
|
|
def destroy
|
|
self.class.system_request('user', 'delete', id)
|
|
@property_hash.clear
|
|
end
|
|
|
|
def flush
|
|
options = []
|
|
if @property_flush && !@property_flush.empty?
|
|
options << '--enable' if @property_flush[:enabled] == :true
|
|
options << '--disable' if @property_flush[:enabled] == :false
|
|
# There is a --description flag for the set command, but it does not work if the value is empty
|
|
options << '--password' << resource[:password] if @property_flush[:password]
|
|
options << '--email' << resource[:email] if @property_flush[:email]
|
|
# project handled in tenant= separately
|
|
unless options.empty?
|
|
options << id
|
|
self.class.system_request('user', 'set', options)
|
|
end
|
|
@property_flush.clear
|
|
end
|
|
end
|
|
|
|
mk_resource_methods
|
|
|
|
def exists?
|
|
return true if @property_hash[:ensure] == :present
|
|
domain_name = self.class.domain_id_from_name(resource[:domain])
|
|
@property_hash =
|
|
self.class.fetch_user(resource[:name], domain_name)
|
|
@property_hash ||= {}
|
|
# This can happen in bad LDAP mapping
|
|
@property_hash[:enabled] = 'true' if @property_hash[:enabled].nil?
|
|
|
|
return false if @property_hash.nil? || @property_hash[:id].nil?
|
|
true
|
|
end
|
|
|
|
# Types properties
|
|
def enabled
|
|
is_enabled = @property_hash[:enabled].downcase.chomp == 'true' ? true : false
|
|
bool_to_sym(is_enabled)
|
|
end
|
|
|
|
def enabled=(value)
|
|
@property_flush[:enabled] = value
|
|
end
|
|
|
|
def email=(value)
|
|
@property_flush[:email] = value
|
|
end
|
|
|
|
def password
|
|
passwd = nil
|
|
return passwd if resource[:password] == nil
|
|
if resource[:enabled] == :false || resource[:replace_password] == :false
|
|
# Unchanged password
|
|
passwd = resource[:password]
|
|
else
|
|
# Password validation
|
|
credentials = Puppet::Provider::Openstack::CredentialsV3.new
|
|
unless credentials.auth_url = self.class.get_auth_url
|
|
raise(Puppet::Error::OpenstackAuthInputError, "Could not find authentication url to validate user's password.")
|
|
end
|
|
credentials.password = resource[:password]
|
|
credentials.user_id = id
|
|
|
|
# NOTE: The only reason we use username is so that the openstack provider
|
|
# will know we are doing v3password auth - otherwise, it is not used. The
|
|
# user_id uniquely identifies the user including domain.
|
|
credentials.username = resource[:name]
|
|
|
|
# Need to specify a project id to get a project scoped token. List
|
|
# all of the projects for the user, and use the id for the first one
|
|
# that is enabled then fallback to domain id only.
|
|
projects = self.class.system_request('project', 'list', ['--user', id, '--long'])
|
|
first_project = nil
|
|
if projects && projects.respond_to?(:each)
|
|
first_project = projects.detect { |p| p && p[:id] && p[:enabled] == 'True' }
|
|
end
|
|
if not first_project.nil?
|
|
credentials.project_id = first_project[:id]
|
|
else
|
|
# last chance - try a domain scoped token
|
|
credentials.domain_id = domain_id
|
|
end
|
|
|
|
credentials.identity_api_version = '2' if credentials.auth_url =~ /v2\.0\/?$/
|
|
|
|
begin
|
|
token = Puppet::Provider::Openstack.request('token', 'issue', ['--format', 'value'], credentials)
|
|
rescue Puppet::Error::OpenstackUnauthorizedError
|
|
# password is invalid
|
|
else
|
|
passwd = resource[:password] unless token.empty?
|
|
end
|
|
end
|
|
return passwd
|
|
end
|
|
|
|
def password=(value)
|
|
if self.class.do_not_manage
|
|
fail("Not managing Keystone_user[#{@resource[:name]}] due to earlier Keystone API failures.")
|
|
end
|
|
@property_flush[:password] = value
|
|
end
|
|
|
|
def replace_password
|
|
@property_hash[:replace_password]
|
|
end
|
|
|
|
def replace_password=(value)
|
|
if self.class.do_not_manage
|
|
fail("Not managing Keystone_user[#{@resource[:name]}] due to earlier Keystone API failures.")
|
|
end
|
|
@property_flush[:replace_password] = value
|
|
end
|
|
|
|
def domain
|
|
@property_hash[:domain]
|
|
end
|
|
|
|
def domain_id
|
|
@property_hash[:domain_id]
|
|
end
|
|
|
|
end
|