Add keystone::bootstrap class

This class combines the keystone-manage bootstrap command
from init, the keystone::endpoint functionality that manages
the keystone endpoints and the keystone::roles::admin class
that manages users and projects.

This is one of the steps to make sure we only have a single
point of entry for bootstrapping (keystone-manage bootstrap)
and then only managing resources after that.

This is especially required since we are getting rid of the
admin token and cannot manage resources before keystone-manage
bootstrap has created the user, project, service and endpoints
for us.

These resources should always be in the default domain and
deployments should manage domain specific configuration themselves
using the provider resources.

This class uses the default values from the keystone-manage
bootstrap command.

In the past puppet-keystone has always created a openstack project
that is assumed as a admin project even though the bootstrap command
creates the admin project. Since this uses the default values from
the bootstrap command we should move away from having an openstack
project, if we need that in testing it should be created there and
not in the default deployment.

Depends-On: https://review.opendev.org/#/c/698528/
Change-Id: I683fcdd743bddf6d4e989dd7e7c553db745934db
This commit is contained in:
Tobias Urdin 2019-11-02 12:32:24 +01:00 committed by Alex Schultz
parent 48ef9708cc
commit bc1ff1d7cb
27 changed files with 878 additions and 831 deletions

View File

@ -53,21 +53,14 @@ To utilize the keystone module's functionality you will need to declare multiple
```puppet ```puppet
class { 'keystone': class { 'keystone':
catalog_type => 'sql', catalog_type => 'sql',
admin_token => 'random_uuid',
database_connection => 'mysql://keystone_admin:super_secret_db_password@openstack-controller.example.com/keystone', database_connection => 'mysql://keystone_admin:super_secret_db_password@openstack-controller.example.com/keystone',
} }
# Adds the admin credential to keystone. class { 'keystone::bootstrap':
class { 'keystone::roles::admin':
email => 'admin@example.com',
password => 'super_secret', password => 'super_secret',
} public_url => 'http://10.16.0.101:5000',
admin_url => 'http://10.16.1.101:5000',
# Installs the service user endpoint. internal_url => 'http://10.16.2.101:5000',
class { 'keystone::endpoint':
public_url => 'http://10.16.0.101:5000/v2.0',
admin_url => 'http://10.16.1.101:5000/v2.0',
internal_url => 'http://10.16.2.101:5000/v2.0',
region => 'example-1', region => 'example-1',
} }
``` ```

View File

@ -28,16 +28,12 @@ class { 'keystone':
debug => true, debug => true,
database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone', database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone',
catalog_type => 'sql', catalog_type => 'sql',
admin_token => 'admin_token',
enabled => false, enabled => false,
} }
class { 'keystone::roles::admin': class { 'keystone::bootstrap':
email => 'test@puppetlabs.com', password => 'ChangeMe',
password => 'ChangeMe', public_url => "https://${::fqdn}:5000",
} admin_url => "https://${::fqdn}:5000",
class { 'keystone::endpoint':
public_url => "https://${::fqdn}:5000/",
admin_url => "https://${::fqdn}:5000/",
} }
keystone_config { 'ssl/enable': value => true } keystone_config { 'ssl/enable': value => true }

View File

@ -28,17 +28,13 @@ class { 'keystone':
debug => true, debug => true,
database_connection => 'mysql://keystone_admin:keystone@127.0.0.1/keystone', database_connection => 'mysql://keystone_admin:keystone@127.0.0.1/keystone',
catalog_type => 'sql', catalog_type => 'sql',
admin_token => 'admin_token',
enabled => true, enabled => true,
} }
class { 'keystone::cron::token_flush': } class { 'keystone::cron::token_flush': }
class { 'keystone::roles::admin': class { 'keystone::bootstrap':
email => 'test@puppetlabs.com', password => 'ChangeMe',
password => 'ChangeMe', public_url => "https://${::fqdn}:443/main",
} admin_url => "https://${::fqdn}:443/admin",
class { 'keystone::endpoint':
public_url => "https://${::fqdn}:443/main/",
admin_url => "https://${::fqdn}:443/admin/",
} }
keystone_config { 'ssl/enable': ensure => absent } keystone_config { 'ssl/enable': ensure => absent }

View File

@ -45,18 +45,13 @@ class { 'keystone':
debug => true, debug => true,
database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone', database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone',
catalog_type => 'sql', catalog_type => 'sql',
admin_token => 'admin_token',
enabled => false, enabled => false,
} }
class { 'keystone::roles::admin': class { 'keystone::bootstrap':
email => 'test@puppetlabs.com', password => 'ChangeMe',
password => 'ChangeMe', public_url => "https://${::fqdn}:5000",
} admin_url => "https://${::fqdn}:5000",
class { 'keystone::endpoint':
public_url => "https://${::fqdn}:5000/",
admin_url => "https://${::fqdn}:5000/",
} }
keystone_config { 'ssl/enable': value => true } keystone_config { 'ssl/enable': value => true }

View File

@ -1,7 +1,6 @@
class { 'keystone': class { 'keystone':
debug => true, debug => true,
database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone', database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone',
admin_token => 'admin_token',
enabled => true, enabled => true,
# helper for using domains # helper for using domains
using_domain_config => true using_domain_config => true
@ -9,19 +8,13 @@ class { 'keystone':
# Ensure this matches what is in LDAP or keystone will try to recreate # Ensure this matches what is in LDAP or keystone will try to recreate
# the admin user # the admin user
class { 'keystone::roles::admin': class { 'keystone::bootstrap':
email => 'test@example.com', password => 'ChangeMe',
password => 'ChangeMe',
admin_user_domain => 'domain_1',
admin_project_domain => 'domain_1',
service_project_domain => 'domain_1',
} }
# Waiting to have keystone::roles::admin being a define instead of a
# class to make the admin for domain_2.
keystone_domain { 'domain_2': ensure => present } keystone_domain { 'domain_2': ensure => present }
keystone::ldap_backend { 'domain_1': keystone::ldap_backend { 'Default':
url => 'ldap://ldap.example.com:389', url => 'ldap://ldap.example.com:389',
user => 'uid=bind,cn=users,cn=accounts,dc=example,dc=com', user => 'uid=bind,cn=users,cn=accounts,dc=example,dc=com',
password => 'SecretPass', password => 'SecretPass',

View File

@ -3,8 +3,7 @@
# Ensure this matches what is in LDAP or keystone will try to recreate # Ensure this matches what is in LDAP or keystone will try to recreate
# the admin user # the admin user
class { 'keystone::roles::admin': class { 'keystone::bootstrap':
email => 'test@example.com',
password => 'ChangeMe', password => 'ChangeMe',
} }

View File

@ -3,8 +3,7 @@
# Ensure this matches what is in LDAP or keystone will try to recreate # Ensure this matches what is in LDAP or keystone will try to recreate
# the admin user # the admin user
class { 'keystone::roles::admin': class { 'keystone::bootstrap':
email => 'test@example.com',
password => 'ChangeMe', password => 'ChangeMe',
} }

View File

@ -1,24 +1,3 @@
# Example using v3 domains. The admin user is created in the domain
# named 'admin_domain', and assigned the role 'admin' in the 'admin'
# project in the domain 'admin_domain'. The keystone service account is
# created in default domain, and assigned the
# role 'admin' in the project 'services' in the default domain.
# NOTE: Until all of the other services support using Keystone v3
# with keystone_authtoken middleware that supports v3, they cannot
# specify a domain for authentication, and so have to be in the
# default domain.
#
# To be sure everything is working, run:
# $ export OS_IDENTITY_API_VERSION=3
# $ export OS_USERNAME=admin
# $ export OS_USER_DOMAIN_NAME=admin_domain
# $ export OS_PASSWORD=ChangeMe
# $ export OS_PROJECT_NAME=admin
# $ export OS_PROJECT_DOMAIN_NAME=admin_domain
# $ export OS_AUTH_URL=http://keystone.local:5000/v3
# $ openstack user list
#
Exec { logoutput => 'on_failure' } Exec { logoutput => 'on_failure' }
@ -29,18 +8,8 @@ class { 'keystone::db::mysql':
class { 'keystone': class { 'keystone':
debug => true, debug => true,
database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone', database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone',
admin_token => 'admin_token',
enabled => true, enabled => true,
} }
class { 'keystone::roles::admin': class { 'keystone::bootstrap':
email => 'test@example.tld', password => 'a_big_secret',
password => 'a_big_secret',
admin => 'admin', # username
admin_tenant => 'admin', # project name
admin_user_domain => 'admin', # domain for user
admin_tenant_domain => 'admin', # domain for project
}
class { 'keystone::endpoint':
public_url => 'http://127.0.0.1:5000/',
admin_url => 'http://127.0.0.1:5000/',
} }

View File

@ -1,8 +1,3 @@
# Example using v3 domain configuration. This setup a directory where
# the domain configurations will be and adjust the keystone.
# For the rest of the configuration check v3_basic.pp.
#
Exec { logoutput => 'on_failure' } Exec { logoutput => 'on_failure' }
class { 'mysql::server': } class { 'mysql::server': }
@ -12,18 +7,14 @@ class { 'keystone::db::mysql':
class { 'keystone': class { 'keystone':
debug => true, debug => true,
database_connection => 'mysql://keystone:keystone@192.168.1.1/keystone', database_connection => 'mysql://keystone:keystone@192.168.1.1/keystone',
admin_token => 'admin_token',
enabled => true, enabled => true,
# The domain configuration setup at keystone level # The domain configuration setup at keystone level
using_domain_config => true, using_domain_config => true,
} }
class { 'keystone::roles::admin': class { 'keystone::bootstrap':
email => 'test@example.tld', password => 'a_big_secret',
password => 'a_big_secret', public_url => 'http://192.168.1.1:5000',
} admin_url => 'http://192.168.1.1:5000',
class { 'keystone::endpoint':
public_url => 'http://192.168.1.1:5000/',
admin_url => 'http://192.168.1.1:5000/',
} }
# Creates the /etc/keystone/domains/keystone.my_domain.conf file and # Creates the /etc/keystone/domains/keystone.my_domain.conf file and

View File

@ -13,12 +13,60 @@ class Puppet::Provider::Keystone < Puppet::Provider::Openstack
@@default_domain_id = nil @@default_domain_id = nil
def self.public_endpoint def self.conf_filename
@public_endpoint ||= get_public_endpoint '/etc/keystone/puppet.conf'
end end
def self.admin_token def self.keystone_puppet_conf
@admin_token ||= get_admin_token return @keystone_puppet_conf if @keystone_puppet_conf
@keystone_puppet_conf = Puppet::Util::IniConfig::File.new
@keystone_puppet_conf.read(conf_filename)
@keystone_puppet_conf
end
def self.get_keystone_puppet_credentials
auth_keys = ['auth_url', 'project_name', 'username',
'password']
conf = keystone_puppet_conf
if conf and conf['keystone_authtoken'] and
auth_keys.all?{|k| !conf['keystone_authtoken'][k].nil?}
creds = Hash[ auth_keys.map \
{ |k| [k, conf['keystone_authtoken'][k].strip] } ]
if conf['project_domain_name']
creds['project_domain_name'] = conf['project_domain_name']
else
creds['project_domain_name'] = 'Default'
end
if conf['user_domain_name']
creds['user_domain_name'] = conf['user_domain_name']
else
creds['user_domain_name'] = 'Default'
end
if conf['keystone_authtoken']['region_name']
creds['region_name'] = conf['keystone_authtoken']['region_name']
end
return creds
else
raise(Puppet::Error, "File: #{conf_filename} does not contain all " +
"required configuration keys. Cannot authenticate to Keystone.")
end
end
def self.keystone_puppet_credentials
@keystone_puppet_credentials ||= get_keystone_puppet_credentials
end
def keystone_puppet_credentials
self.class.keystone_puppet_credentials
end
def self.get_auth_endpoint
q = keystone_puppet_credentials
"#{q['auth_url']}"
end
def self.auth_endpoint
@auth_endpoint ||= get_auth_endpoint
end end
def self.default_domain_from_ini_file def self.default_domain_from_ini_file
@ -152,50 +200,17 @@ class Puppet::Provider::Keystone < Puppet::Provider::Openstack
raise e unless e.message =~ /No user with a name or ID/ raise e unless e.message =~ /No user with a name or ID/
end end
def self.get_public_endpoint
endpoint = nil
if url = get_section('DEFAULT', 'public_endpoint')
endpoint = url.chomp('/')
end
return endpoint
end
def self.get_admin_token
get_section('DEFAULT', 'admin_token')
end
def self.get_auth_url def self.get_auth_url
auth_url = nil auth_url = nil
if ENV['OS_AUTH_URL'] if ENV['OS_AUTH_URL']
auth_url = ENV['OS_AUTH_URL'].dup auth_url = ENV['OS_AUTH_URL'].dup
elsif auth_url = get_os_vars_from_rcfile(rc_filename)['OS_AUTH_URL'] elsif auth_url = get_os_vars_from_rcfile(rc_filename)['OS_AUTH_URL']
else else
auth_url = public_endpoint auth_url = auth_endpoint
end end
return auth_url return auth_url
end end
def self.get_section(group, name)
if keystone_file && keystone_file[group] && keystone_file[group][name]
return keystone_file[group][name].strip
end
return nil
end
def self.get_service_url
service_url = nil
if ENV['OS_ENDPOINT']
service_url = ENV['OS_ENDPOINT'].dup
# Compatibility with pre-4.0.0 openstackclient
elsif ENV['OS_URL']
service_url = ENV['OS_URL'].dup
elsif public_endpoint
service_url = public_endpoint
service_url << "/v#{@credentials.version}"
end
return service_url
end
def self.ini_filename def self.ini_filename
INI_FILENAME INI_FILENAME
end end
@ -212,27 +227,32 @@ class Puppet::Provider::Keystone < Puppet::Provider::Openstack
def self.request(service, action, properties=nil, options={}) def self.request(service, action, properties=nil, options={})
super super
rescue Puppet::Error::OpenstackAuthInputError, Puppet::Error::OpenstackUnauthorizedError => error rescue Puppet::Error::OpenstackAuthInputError, Puppet::Error::OpenstackUnauthorizedError => error
request_by_service_token(service, action, error, properties, options=options) keystone_request(service, action, error, properties)
end end
def self.request_by_service_token(service, action, error, properties=nil, options={}) def self.keystone_request(service, action, error, properties=nil)
properties ||= [] properties ||= []
@credentials.token = admin_token @credentials.username = keystone_puppet_credentials['username']
@credentials.endpoint = service_url @credentials.password = keystone_puppet_credentials['password']
raise error unless @credentials.service_token_set? @credentials.project_name = keystone_puppet_credentials['project_name']
@credentials.auth_url = auth_endpoint
if keystone_puppet_credentials['region_name']
@credentials.region_name = keystone_puppet_credentials['region_name']
end
if @credentials.version == '3'
@credentials.user_domain_name = keystone_puppet_credentials['user_domain_name']
@credentials.project_domain_name = keystone_puppet_credentials['project_domain_name']
end
raise error unless @credentials.set?
begin begin
Puppet::Provider::Openstack.request(service, action, properties, @credentials, options) Puppet::Provider::Openstack.request(service, action, properties, @credentials)
rescue Puppet::ExecutionFailure, Puppet::Error::OpenstackUnauthorizedError rescue Puppet::ExecutionFailure, Puppet::Error::OpenstackUnauthorizedError
# openstackclient < 4.0.0 does not support --os-endpoint and requires --os-url # openstackclient < 4.0.0 does not support --os-endpoint and requires --os-url
@credentials.url = service_url @credentials.url = auth_endpoint
Puppet::Provider::Openstack.request(service, action, properties, @credentials, options) Puppet::Provider::Openstack.request(service, action, properties, @credentials)
end end
end end
def self.service_url
@service_url ||= get_service_url
end
def self.set_domain_for_name(name, domain_name) def self.set_domain_for_name(name, domain_name)
if domain_name.nil? || domain_name.empty? if domain_name.nil? || domain_name.empty?
raise(Puppet::Error, "Missing domain name for resource #{name}") raise(Puppet::Error, "Missing domain name for resource #{name}")

View File

@ -0,0 +1,8 @@
Puppet::Type.type(:keystone_puppet_config).provide(
:ini_setting,
:parent => Puppet::Type.type(:openstack_config).provider(:ini_setting)
) do
def self.file_path
'/etc/keystone/puppet.conf'
end
end

View File

@ -0,0 +1,12 @@
Puppet::Type.newtype(:keystone_puppet_config) do
require File.expand_path(File.join(
File.dirname(__FILE__), '..', '..',
'puppet_x', 'keystone_config', 'ini_setting'))
extend PuppetX::KeystoneConfig::IniSetting
create_parameters
autorequire(:file) do
['/etc/keystone/puppet.conf']
end
end

307
manifests/bootstrap.pp Normal file
View File

@ -0,0 +1,307 @@
# == Class: keystone::bootstrap
#
# Bootstrap keystone with keystone-manage bootstrap.
#
# === Parameters
#
# [*password*]
# (Optional) The password for the user.
# WARNING: This parameter will be required in a future release.
# Defaults to undef
#
# [*username*]
# (Optional) The username.
# Defaults to 'admin'
#
# [*email*]
# (Optional) The email for the user.
# Defaults to 'admin@localhost'
#
# [*project_name*]
# (Optional) The project name.
# Defaults to 'admin'
#
# [*service_project_name*]
# (Optional) The service project name.
# Defaults to 'services'
#
# [*role_name*]
# (Optional) The role name.
# Defaults to 'admin'
#
# [*service_name*]
# (Optional) The service name.
# Defaults to 'keystone'
#
# [*admin_url*]
# (Optional) Admin URL for Keystone endpoint.
# This url should *not* contain any version or trailing '/'.
# Defaults to 'http://127.0.0.1:5000'
#
# [*public_url*]
# (Optional) Public URL for Keystone endpoint.
# This URL should *not* contain any version or trailing '/'.
# Defaults to 'http://127.0.0.1:5000'
#
# [*internal_url*]
# (Optional) Internal URL for Keystone endpoint.
# This URL should *not* contain any version or trailing '/'.
# Defaults to $public_url
#
# [*region*]
# (Optional) Region for endpoint.
# Defaults to 'RegionOne'
#
# [*interface*]
# (Optional) Which interface endpoint should be used.
# Defaults to 'public'
#
class keystone::bootstrap (
# TODO(tobias-urdin): Make the password required when compat is removed.
$password = undef,
$username = 'admin',
$email = 'admin@localhost',
$project_name = 'admin',
$service_project_name = 'services',
$role_name = 'admin',
$service_name = 'keystone',
$admin_url = 'http://127.0.0.1:5000',
$public_url = 'http://127.0.0.1:5000',
$internal_url = undef,
$region = 'RegionOne',
$interface = 'public',
) inherits keystone::params {
include ::keystone::deps
# TODO(tobias-urdin): Remove compat layer.
if $password == undef {
if defined('$::keystone::admin_password') and $::keystone::admin_password != undef {
$password_real = $::keystone::admin_password
warning('Using deprecated keystone::admin_password as admin password')
# Check if we differ from the roles admin pw
if defined('$::keystone::roles::admin::password') and $::keystone::roles::admin::password != $password_real {
warning('The keystone::admin_password and keystone::roles::admin::password differs and will cause a flip-flopping\
behaviour and authentication issues for the admin user.')
}
} elsif defined('$::keystone::admin_token') and $::keystone::admin_token != undef {
$password_real = $::keystone::admin_token
warning('Using deprecated keystone::admin_token as admin password')
# Check if we differ from the roles admin pw
if defined('$::keystone::roles::admin::password') and $::keystone::roles::admin::password != $password_real {
warning('The keystone::admin_token and keystone::roles::admin::password differs and will cause a flip-flopping\
behaviour and authentication issues for the admin user.')
}
} else {
# Check the keystone::roles::admin class as well.
if defined('$::keystone::roles::admin::password') and $::keystone::roles::admin::password != undef {
$password_real = $::keystone::roles::admin::password
warning('Using deprecated keystone::roles::admin::password as admin password')
} else {
fail('keystone::bootstrap::password is undef, could not resolve a password')
}
}
} else {
$password_real = $password
}
if defined('$::keystone::endpoint::public_url') and $::keystone::endpoint::public_url != undef {
$public_url_real = $::keystone::endpoint::public_url
$using_deprecated_public_url = true
warning('Using deprecated keystone::endpoint::public_url, please update to using keystone::bootstrap')
} else {
$public_url_real = $public_url
$using_deprecated_public_url = false
}
if defined('$::keystone::endpoint::internal_url') and $::keystone::endpoint::internal_url != undef {
$internal_url_final = $::keystone::endpoint::internal_url
$using_deprecated_internal_url = true
warning('Using deprecated keystone::endpoint::internal_url, please update to using keystone::bootstrap')
} else {
$internal_url_final = $internal_url
$using_deprecated_internal_url = false
}
if defined('$::keystone::endpoint::admin_url') and $::keystone::endpoint::admin_url != undef {
$admin_url_real = $::keystone::endpoint::admin_url
warning('Using deprecated keystone::endpoint::admin_url, please update to using keystone::bootstrap')
} else {
$admin_url_real = $admin_url
}
if defined('$::keystone::endpoint::region') and $::keystone::endpoint::region != undef {
$region_real = $::keystone::endpoint::region
warning('Using deprecated keystone::endpoint::region, please update to using keystone::bootstrap')
} else {
$region_real = $region
}
if !$using_deprecated_internal_url and $internal_url == undef and $using_deprecated_public_url {
warning('Using deprecated keystone::endpoint::public_url for keystone::bootstrap::internal_url')
}
if defined('$::keystone::roles::admin::admin') and $::keystone::roles::admin::admin != undef {
$username_real = $::keystone::roles::admin::admin
if $username_real != $username and $username == 'admin' {
warning('Using keystone::roles::admin::admin as username, the keystone::bootstrap::username default is different\
dont forget to set that later')
}
} else {
$username_real = $username
}
if defined('$::keystone::roles::admin::email') and $::keystone::roles::admin::email != undef {
$email_real = $::keystone::roles::admin::email
if $email_real != $email and $email == 'admin@localhost' {
warning('Using keystone::roles::admin::email as email, the keystone::bootstrap::email default is different\
dont forget to set that later')
}
} else {
$email_real = $email
}
if defined('$::keystone::roles::admin::admin_roles') and $::keystone::roles::admin::admin_roles != undef {
$role_name_real = $::keystone::roles::admin::admin_roles
warning("Using keystone::roles::admin::admin_roles with value ${role_name_real} note that the\
keystone::bootstrap when used will only set a single role, by default the 'admin' role.")
warning('Will use the first value in admin_roles for bootstrap and all (if multiple) for all other resources!')
if is_array($role_name_real) {
$bootstrap_role_name = $role_name_real[0]
} else {
$bootstrap_role_name = $role_name_real
}
} else {
$role_name_real = [$role_name]
$bootstrap_role_name = $role_name
}
if defined('$::keystone::roles::admin::admin_tenant') {
$admin_tenant = $::keystone::roles::admin::admin_tenant
if ($admin_tenant == undef or $admin_tenant == 'openstack') {
# Try to keep the backward compatible creation of the openstack project.
# We still create the 'admin' project with the bootstrap process below.
# This is a best effort, we still ignore the description and default domain.
ensure_resource('keystone_tenant', 'openstack', {
'ensure' => 'present',
'enabled' => true,
})
ensure_resource('keystone_user_role', "${username_real}@openstack", {
'ensure' => 'present',
'roles' => $role_name_real,
})
# Use the default value so we create the "admin" project
$project_name_real = $project_name
} else {
warning('Using keystone::roles::admin::admin_tenant as project name for admin')
$project_name_real = $admin_tenant
}
} else {
$project_name_real = $project_name
}
if defined('$::keystone::roles::admin::service_tenant') and $::keystone::roles::admin::service_tenant != undef {
warning('Using keystone::roles::admin::service_tenant as service project name')
$service_project_name_real = $::keystone::roles::admin::service_tenant
} else {
$service_project_name_real = $service_project_name
}
# Compat code ends here.
$internal_url_real = $internal_url_final ? {
undef => $public_url_real,
default => $internal_url_final
}
if defined('$::keystone::keystone_user') {
$keystone_user = $::keystone::keystone_user
} else {
$keystone_user = $::keystone::params::keystone_user
}
# The initial bootstrap that creates all resources required but
# only subscribes to notifies from the keystone::dbsync::end anchor
# which means this is not guaranteed to execute on each run.
exec { 'keystone bootstrap':
command => 'keystone-manage bootstrap',
environment => [
"OS_BOOTSTRAP_USERNAME=${username_real}",
"OS_BOOTSTRAP_PASSWORD=${password_real}",
"OS_BOOTSTRAP_PROJECT_NAME=${project_name_real}",
"OS_BOOTSTRAP_ROLE_NAME=${bootstrap_role_name}",
"OS_BOOTSTRAP_SERVICE_NAME=${service_name}",
"OS_BOOTSTRAP_ADMIN_URL=${admin_url_real}",
"OS_BOOTSTRAP_PUBLIC_URL=${public_url_real}",
"OS_BOOTSTRAP_INTERNAL_URL=${internal_url_real}",
"OS_BOOTSTRAP_REGION_ID=${region_real}",
],
user => $keystone_user,
path => '/usr/bin',
refreshonly => true,
subscribe => Anchor['keystone::dbsync::end'],
notify => Anchor['keystone::service::begin'],
tag => 'keystone-bootstrap',
}
# Since the bootstrap is not guaranteed to execute on each run we
# use the below resources to make sure the current resources are
# correct so if some value was updated we set that.
ensure_resource('keystone_role', $role_name_real, {
'ensure' => 'present',
})
ensure_resource('keystone_user', $username_real, {
'ensure' => 'present',
'enabled' => true,
'email' => $email_real,
'password' => $password_real,
})
ensure_resource('keystone_tenant', $service_project_name_real, {
'ensure' => 'present',
'enabled' => true,
})
ensure_resource('keystone_tenant', $project_name_real, {
'ensure' => 'present',
'enabled' => true,
})
ensure_resource('keystone_user_role', "${username_real}@${project_name_real}", {
'ensure' => 'present',
'roles' => $role_name_real,
})
ensure_resource('keystone_service', "${service_name}::identity", {
'ensure' => 'present',
})
ensure_resource('keystone_endpoint', "${region_real}/${service_name}::identity", {
'ensure' => 'present',
'public_url' => $public_url_real,
'admin_url' => $admin_url_real,
'internal_url' => $internal_url_real,
})
# The below creates and populates the /etc/keystone/puppet.conf file that contains
# the credentials that can be loaded by providers. Ensure it has the proper owner,
# group and mode so that it cannot be read by anything other than root.
file { '/etc/keystone/puppet.conf':
ensure => 'present',
replace => false,
content => '',
owner => 'root',
group => 'root',
mode => '0600',
require => Anchor['keystone::install::end'],
}
if $interface == 'admin' {
$auth_url_real = $admin_url_real
} elsif $interface == 'internal' {
$auth_url_real = $internal_url_real
} else {
$auth_url_real = $public_url_real
}
keystone::resource::authtoken { 'keystone_puppet_config':
username => $username_real,
password => $password_real,
auth_url => $auth_url_real,
project_name => $project_name_real,
region_name => $region_real,
interface => $interface,
}
}

View File

@ -1,26 +1,29 @@
# == Class: keystone::endpoint # == Class: keystone::endpoint
# #
# DEPRECATED!
#
# Creates the auth endpoints for keystone # Creates the auth endpoints for keystone
# #
# === Parameters # === Parameters
# #
# [*public_url*] # [*public_url*]
# (optional) Public url for keystone endpoint. # (optional) Public url for keystone endpoint.
# Defaults to 'http://127.0.0.1:5000' # Defaults to undef
# This url should *not* contain any version or trailing '/'. # This url should *not* contain any version or trailing '/'.
# #
# [*internal_url*] # [*internal_url*]
# (optional) Internal url for keystone endpoint. # (optional) Internal url for keystone endpoint.
# Defaults to $public_url # Defaults to undef
# This url should *not* contain any version or trailing '/'. # This url should *not* contain any version or trailing '/'.
# #
# [*admin_url*] # [*admin_url*]
# (optional) Admin url for keystone endpoint. # (optional) Admin url for keystone endpoint.
# Defaults to 'http://127.0.0.1:5000' # Defaults to undef
# This url should *not* contain any version or trailing '/'. # This url should *not* contain any version or trailing '/'.
# #
# [*region*] # [*region*]
# (optional) Region for endpoint. (Defaults to 'RegionOne') # (optional) Region for endpoint.
# Defaults to undef
# #
# [*user_domain*] # [*user_domain*]
# (Optional) Domain for $auth_name # (Optional) Domain for $auth_name
@ -38,10 +41,7 @@
# #
# [*version*] # [*version*]
# (optional) API version for endpoint. # (optional) API version for endpoint.
# Defaults to ''. Valid values are 'v2.0', 'v3', or the empty string ''. # Defaults to undef.
# If the version is set to the empty string (''), then it won't be
# used. This is the expected behaviour since Keystone V3 handles API versions
# from the context.
# #
# === Examples # === Examples
# #
@ -52,59 +52,23 @@
# } # }
# #
class keystone::endpoint ( class keystone::endpoint (
$public_url = 'http://127.0.0.1:5000', $public_url = undef,
$internal_url = undef, $internal_url = undef,
$admin_url = 'http://127.0.0.1:5000', $admin_url = undef,
$region = 'RegionOne', $region = undef,
$user_domain = undef, $user_domain = undef,
$project_domain = undef, $project_domain = undef,
$default_domain = undef, $default_domain = undef,
$version = '', $version = undef,
) { ) {
include keystone::deps warning('The keystone::endpoint class has been replaced with keystone::bootstrap class\
will try to use the backward compatible approach')
if $version == 'unset' { if !defined('$::keystone::roles::admin::admin_tenant') {
warning('keystone::endpoint::version parameter is deprecated and will be removed in a future release.') fail('You are using the backward compatible approach instead of keystone::bootstrap\
$_version = 'v2.0' you need to ensure that keystone::roles::admin is defined BEFORE keystone::endpoint in your manifest')
} else {
$_version = $version
}
if empty($_version) {
$admin_url_real = $admin_url
$public_url_real = $public_url
if $internal_url {
$internal_url_real = $internal_url
}
else {
$internal_url_real = $public_url
}
}
else {
$public_url_real = "${public_url}/${_version}"
$admin_url_real = "${admin_url}/${_version}"
if $internal_url {
$internal_url_real = "${internal_url}/${_version}"
}
else {
$internal_url_real = "${public_url}/${_version}"
}
} }
keystone::resource::service_identity { 'keystone': include keystone::bootstrap
configure_user => false,
configure_user_role => false,
service_type => 'identity',
service_description => 'OpenStack Identity Service',
public_url => $public_url_real,
admin_url => $admin_url_real,
internal_url => $internal_url_real,
region => $region,
user_domain => $user_domain,
project_domain => $project_domain,
default_domain => $default_domain,
}
Keystone::Resource::Service_identity['keystone'] -> File<| tag == 'openrc' |>
} }

View File

@ -13,18 +13,6 @@
# accepts latest or specific versions. # accepts latest or specific versions.
# Defaults to present. # Defaults to present.
# #
# [*admin_token*]
# Admin token that can be used to authenticate as a keystone
# admin. This is not the password for the admin user
# in the Keystone database. This is a token that bypasses authentication.
# The admin_token has been deprecated by the Keystone service and this
# will be deprecated in a future changeset. Required.
#
# [*admin_password*]
# Keystone password for the admin user. This is not the admin_token.
# This is the password that the admin user signs into keystone with.
# Required.
#
# [*catalog_type*] # [*catalog_type*]
# (Optional) Type of catalog that keystone uses to store endpoints,services. # (Optional) Type of catalog that keystone uses to store endpoints,services.
# Defaults to sql. (Also accepts template) # Defaults to sql. (Also accepts template)
@ -403,12 +391,6 @@
# Otherwise Puppet will manage keys with File resource. # Otherwise Puppet will manage keys with File resource.
# Defaults to false # Defaults to false
# #
# [*enable_bootstrap*]
# (Optional) Enable keystone bootstrapping.
# This option to true will automatically bootstrap the default domain
# user by running 'keystone-manage bootstrap'.
# Defaults to true
#
# [*default_domain*] # [*default_domain*]
# (Optional) When Keystone v3 support is enabled, v2 clients will need # (Optional) When Keystone v3 support is enabled, v2 clients will need
# to have a domain assigned for certain operations. For example, # to have a domain assigned for certain operations. For example,
@ -565,25 +547,22 @@
# (Optional) The url to validate keystone against # (Optional) The url to validate keystone against
# Defaults to undef # Defaults to undef
# #
# == Dependencies # [*admin_token*]
# None # Admin token that can be used to authenticate as a keystone
# admin. This is not the password for the admin user
# in the Keystone database. This is a token that bypasses authentication.
# Defaults to undef
# #
# == Examples # [*admin_password*]
# Keystone password for the admin user. This is not the admin_token.
# This is the password that the admin user signs into keystone with.
# Defaults to undef
# #
# class { 'keystone': # [*enable_bootstrap*]
# admin_token => 'my_special_token', # (Optional) Enable keystone bootstrapping.
# } # This option to true will automatically bootstrap the default domain
# # user by running 'keystone-manage bootstrap'.
# OR # Defaults to undef
#
# class { 'keystone':
# ...
# service_name => 'httpd',
# ...
# }
# class { 'keystone::wsgi::apache':
# ...
# }
# #
# == Authors # == Authors
# #
@ -594,8 +573,6 @@
# Copyright 2012 Puppetlabs Inc, unless otherwise noted. # Copyright 2012 Puppetlabs Inc, unless otherwise noted.
# #
class keystone( class keystone(
$admin_token,
$admin_password = undef,
$package_ensure = 'present', $package_ensure = 'present',
$client_package_ensure = 'present', $client_package_ensure = 'present',
$log_dir = undef, $log_dir = undef,
@ -668,7 +645,6 @@ class keystone(
$default_domain = undef, $default_domain = undef,
$member_role_id = $::os_service_default, $member_role_id = $::os_service_default,
$member_role_name = $::os_service_default, $member_role_name = $::os_service_default,
$enable_bootstrap = true,
$memcache_dead_retry = $::os_service_default, $memcache_dead_retry = $::os_service_default,
$memcache_socket_timeout = $::os_service_default, $memcache_socket_timeout = $::os_service_default,
$memcache_pool_maxsize = $::os_service_default, $memcache_pool_maxsize = $::os_service_default,
@ -698,6 +674,9 @@ class keystone(
$validate_insecure = undef, $validate_insecure = undef,
$validate_auth_url = undef, $validate_auth_url = undef,
$validate_cacert = undef, $validate_cacert = undef,
$admin_token = undef,
$admin_password = undef,
$enable_bootstrap = undef,
) inherits keystone::params { ) inherits keystone::params {
include keystone::deps include keystone::deps
@ -772,14 +751,6 @@ class keystone(
$public_endpoint_real = $public_endpoint $public_endpoint_real = $public_endpoint
} }
if $admin_password == undef {
warning("admin_password is required, please set admin_password to a value != admin_token. \
admin_token will be removed in a later release")
$admin_password_real = $admin_token
} else {
$admin_password_real = $admin_password
}
if $manage_policyrcd { if $manage_policyrcd {
# openstacklib policy_rcd only affects debian based systems. # openstacklib policy_rcd only affects debian based systems.
Policy_rcd <| title == 'keystone' |> -> Package['keystone'] Policy_rcd <| title == 'keystone' |> -> Package['keystone']
@ -813,8 +784,12 @@ admin_token will be removed in a later release")
purge => $purge_config, purge => $purge_config,
} }
# TODO(tobias-urdin): Remove this when admin_token is removed.
keystone_config {
'DEFAULT/admin_token': ensure => 'absent', secret => true;
}
keystone_config { keystone_config {
'DEFAULT/admin_token': value => $admin_token, secret => true;
'DEFAULT/member_role_id': value => $member_role_id; 'DEFAULT/member_role_id': value => $member_role_id;
'DEFAULT/member_role_name': value => $member_role_name; 'DEFAULT/member_role_name': value => $member_role_name;
} }
@ -1105,21 +1080,6 @@ running as a standalone service, or httpd for being run by a httpd server")
fail('You must activate domain configuration using "using_domain_config" parameter to keystone class.') fail('You must activate domain configuration using "using_domain_config" parameter to keystone class.')
} }
if $enable_bootstrap {
# this requires the database to be up and running and configured
# and is only run once, so we don't need to notify the service
exec { 'keystone-manage bootstrap':
command => 'keystone-manage bootstrap',
environment => "OS_BOOTSTRAP_PASSWORD=${admin_password_real}",
user => $keystone_user,
path => '/usr/bin',
refreshonly => true,
notify => Anchor['keystone::service::begin'],
subscribe => Anchor['keystone::dbsync::end'],
tag => 'keystone-exec',
}
}
if $using_domain_config { if $using_domain_config {
validate_legacy(Stdlib::Absolutepath, 'validate_absolute_path', $domain_config_directory) validate_legacy(Stdlib::Absolutepath, 'validate_absolute_path', $domain_config_directory)

View File

@ -1,5 +1,7 @@
# == Class: keystone::roles::admin # == Class: keystone::roles::admin
# #
# DEPRECATED!
#
# This class implements some reasonable admin defaults for keystone. # This class implements some reasonable admin defaults for keystone.
# #
# It creates the following keystone objects: # It creates the following keystone objects:
@ -14,14 +16,15 @@
# [*password*] # [*password*]
# The admin password. Required. In a later release # The admin password. Required. In a later release
# this will default to $keystone::admin_password. # this will default to $keystone::admin_password.
# Defaults to undef
# #
# [*email*] # [*email*]
# The email address for the admin. Optional. # The email address for the admin. Optional.
# Defaults to 'admin@localhost'. # Defaults to undef
# #
# [*admin_roles*] # [*admin_roles*]
# The list of the roles with admin privileges. Optional. # The list of the roles with admin privileges. Optional.
# Defaults to ['admin']. # Defaults to undef
# #
# [*admin_tenant*] # [*admin_tenant*]
# The name of the tenant to be used for admin privileges. Optional. # The name of the tenant to be used for admin privileges. Optional.
@ -29,27 +32,27 @@
# #
# [*service_tenant*] # [*service_tenant*]
# The name of service keystone tenant. Optional. # The name of service keystone tenant. Optional.
# Defaults to 'services'. # Defaults to undef
# #
# [*admin*] # [*admin*]
# Admin user. Optional. # Admin user. Optional.
# Defaults to admin. # Defaults to undef
# #
# [*admin_tenant_desc*] # [*admin_tenant_desc*]
# Optional. Description for admin tenant, # Optional. Description for admin tenant,
# Defaults to 'admin tenant' # Defaults to undef
# #
# [*service_tenant_desc*] # [*service_tenant_desc*]
# Optional. Description for admin tenant, # Optional. Description for admin tenant,
# Defaults to 'Tenant for the openstack services' # Defaults to undef
# #
# [*configure_user*] # [*configure_user*]
# Optional. Should the admin user be created? # Optional. Should the admin user be created?
# Defaults to 'true'. # Defaults to undef
# #
# [*configure_user_role*] # [*configure_user_role*]
# Optional. Should the admin role be configured for the admin user? # Optional. Should the admin role be configured for the admin user?
# Defaults to 'true'. # Defaults to undef
# #
# [*admin_user_domain*] # [*admin_user_domain*]
# Optional. Domain of the admin user # Optional. Domain of the admin user
@ -79,85 +82,21 @@
# Copyright 2012 Puppetlabs Inc, unless otherwise noted. # Copyright 2012 Puppetlabs Inc, unless otherwise noted.
# #
class keystone::roles::admin( class keystone::roles::admin(
$password, $password = undef,
$email = 'admin@localhost', $email = undef,
$admin = 'admin', $admin = undef,
$admin_tenant = 'openstack', $admin_tenant = 'openstack',
$admin_roles = ['admin'], $admin_roles = undef,
$service_tenant = 'services', $service_tenant = undef,
$admin_tenant_desc = 'admin tenant', $admin_tenant_desc = undef,
$service_tenant_desc = 'Tenant for the openstack services', $service_tenant_desc = undef,
$configure_user = true, $configure_user = undef,
$configure_user_role = true, $configure_user_role = undef,
$admin_user_domain = undef, $admin_user_domain = undef,
$admin_project_domain = undef, $admin_project_domain = undef,
$service_project_domain = undef, $service_project_domain = undef,
$target_admin_domain = undef, $target_admin_domain = undef,
) { ) {
include keystone::deps warning('The keystone::roles::admin class has been replaced with keystone::bootstrap class')
if $password != $keystone::admin_password_real {
warning('the main class is setting the admin password differently from this\
class when calling bootstrap. This will lead to the password\
flip-flopping and cause authentication issues for the admin user.\
Please ensure that keystone::roles::admin::password and\
keystone::admin_password are set the same.')
}
$domains = unique(delete_undef_values([ $admin_user_domain, $admin_project_domain, $service_project_domain, $target_admin_domain]))
keystone_domain { $domains:
ensure => present,
enabled => true,
}
keystone_tenant { $service_tenant:
ensure => present,
enabled => true,
description => $service_tenant_desc,
domain => $service_project_domain,
}
keystone_tenant { $admin_tenant:
ensure => present,
enabled => true,
description => $admin_tenant_desc,
domain => $admin_project_domain,
}
keystone_role { 'admin':
ensure => present,
}
if $configure_user {
keystone_user { $admin:
ensure => present,
enabled => true,
email => $email,
password => $password,
domain => $admin_user_domain,
}
}
if $configure_user_role {
keystone_user_role { "${admin}@${admin_tenant}":
ensure => present,
user_domain => $admin_user_domain,
project_domain => $admin_project_domain,
roles => $admin_roles,
}
Keystone_tenant[$admin_tenant] -> Keystone_user_role["${admin}@${admin_tenant}"]
Keystone_user<| title == $admin |> -> Keystone_user_role["${admin}@${admin_tenant}"]
Keystone_user_role["${admin}@${admin_tenant}"] -> File<| tag == 'openrc' |>
if $target_admin_domain {
keystone_user_role { "${admin}@::${target_admin_domain}":
ensure => present,
user_domain => $admin_user_domain,
roles => $admin_roles,
}
Keystone_user_role["${admin}@::${target_admin_domain}"] -> File<| tag == 'openrc' |>
}
}
} }

View File

@ -0,0 +1,19 @@
---
features:
- |
Added keystone::bootstrap class.
upgrade:
- |
Now that the keystone::endpoint and keystone::roles::admin classes is deprecated
and has no effect deployments must define the new keystone::bootstrap class with
the proper data that was earlier passed to those classes. Please go through the
parameters in keystone::bootstrap carefully and define the class.
- |
If you are using a multi-domain setup where you previously relied on keystone::endpoint
and/or keystone::roles::admin to create your domains and domain scoped admin accounts
the keystone::bootstrap does not do this and you need to ensure this is managed in your
deployment using the keystone provider resources.
deprecations:
- |
The keystone::endpoint and keystone::roles::admin classes is now deprecated
and has no effect. Please read the upgrade notes carefully!

View File

@ -21,7 +21,6 @@ describe 'keystone server running with Apache/WSGI as Identity Provider' do
internal_url => 'http://127.0.0.1:1234', internal_url => 'http://127.0.0.1:1234',
} }
# v3 admin # v3 admin
# we don't use ::keystone::roles::admin but still create resources manually:
keystone_domain { 'admin_domain': keystone_domain { 'admin_domain':
ensure => present, ensure => present,
enabled => true, enabled => true,

View File

@ -21,7 +21,6 @@ describe 'keystone server running with Apache/WSGI as Service Provider with Shib
internal_url => 'http://127.0.0.1:1234', internal_url => 'http://127.0.0.1:1234',
} }
# v3 admin # v3 admin
# we don't use ::keystone::roles::admin but still create resources manually:
keystone_domain { 'admin_domain': keystone_domain { 'admin_domain':
ensure => present, ensure => present,
enabled => true, enabled => true,

View File

@ -21,7 +21,6 @@ describe 'keystone server running with Apache/WSGI with resources' do
internal_url => 'http://127.0.0.1:1234', internal_url => 'http://127.0.0.1:1234',
} }
# v3 admin # v3 admin
# we don't use ::keystone::roles::admin but still create resources manually:
keystone_domain { 'admin_domain': keystone_domain { 'admin_domain':
ensure => present, ensure => present,
enabled => true, enabled => true,

View File

@ -0,0 +1,229 @@
require 'spec_helper'
describe 'keystone::bootstrap' do
shared_examples 'keystone::bootstrap' do
context 'with required parameters' do
let :params do
{
:password => 'secret'
}
end
it { is_expected.to contain_class('keystone::deps') }
it { is_expected.to contain_exec('keystone bootstrap').with(
:command => 'keystone-manage bootstrap',
:environment => [
"OS_BOOTSTRAP_USERNAME=admin",
"OS_BOOTSTRAP_PASSWORD=secret",
"OS_BOOTSTRAP_PROJECT_NAME=admin",
"OS_BOOTSTRAP_ROLE_NAME=admin",
"OS_BOOTSTRAP_SERVICE_NAME=keystone",
"OS_BOOTSTRAP_ADMIN_URL=http://127.0.0.1:5000",
"OS_BOOTSTRAP_PUBLIC_URL=http://127.0.0.1:5000",
"OS_BOOTSTRAP_INTERNAL_URL=http://127.0.0.1:5000",
"OS_BOOTSTRAP_REGION_ID=RegionOne",
],
:user => platform_params[:keystone_user],
:path => '/usr/bin',
:refreshonly => true,
:subscribe => 'Anchor[keystone::dbsync::end]',
:notify => 'Anchor[keystone::service::begin]',
:tag => 'keystone-bootstrap',
)}
it { is_expected.to contain_keystone_role('admin').with_ensure('present') }
it { is_expected.to contain_keystone_user('admin').with(
:ensure => 'present',
:enabled => true,
:email => 'admin@localhost',
:password => 'secret',
)}
it { is_expected.to contain_keystone_tenant('services').with(
:ensure => 'present',
:enabled => true,
)}
it { is_expected.to contain_keystone_tenant('admin').with(
:ensure => 'present',
:enabled => true,
)}
it { is_expected.to contain_keystone_user_role('admin@admin').with(
:ensure => 'present',
:roles => ['admin'],
)}
it { is_expected.to contain_keystone_service('keystone::identity').with_ensure('present') }
it { is_expected.to contain_keystone_endpoint('RegionOne/keystone::identity').with(
:ensure => 'present',
:public_url => 'http://127.0.0.1:5000',
:admin_url => 'http://127.0.0.1:5000',
:internal_url => 'http://127.0.0.1:5000',
)}
it { is_expected.to contain_file('/etc/keystone/puppet.conf').with(
:ensure => 'present',
:replace => false,
:content => '',
:owner => 'root',
:group => 'root',
:mode => '0600',
:require => 'Anchor[keystone::install::end]',
)}
it { is_expected.to contain_keystone__resource__authtoken('keystone_puppet_config').with(
:username => 'admin',
:password => 'secret',
:auth_url => 'http://127.0.0.1:5000',
:project_name => 'admin',
:region_name => 'RegionOne',
:interface => 'public',
)}
end
context 'with specified parameters' do
let :params do
{
:password => 'secret',
:username => 'user',
:email => 'some@email',
:project_name => 'adminproj',
:service_project_name => 'serviceproj',
:role_name => 'adminrole',
:service_name => 'servicename',
:admin_url => 'http://admin:1234',
:public_url => 'http://public:4321',
:internal_url => 'http://internal:1342',
:region => 'RegionTwo',
:interface => 'admin'
}
end
it { is_expected.to contain_class('keystone::deps') }
it { is_expected.to contain_exec('keystone bootstrap').with(
:command => 'keystone-manage bootstrap',
:environment => [
"OS_BOOTSTRAP_USERNAME=user",
"OS_BOOTSTRAP_PASSWORD=secret",
"OS_BOOTSTRAP_PROJECT_NAME=adminproj",
"OS_BOOTSTRAP_ROLE_NAME=adminrole",
"OS_BOOTSTRAP_SERVICE_NAME=servicename",
"OS_BOOTSTRAP_ADMIN_URL=http://admin:1234",
"OS_BOOTSTRAP_PUBLIC_URL=http://public:4321",
"OS_BOOTSTRAP_INTERNAL_URL=http://internal:1342",
"OS_BOOTSTRAP_REGION_ID=RegionTwo",
],
:user => platform_params[:keystone_user],
:path => '/usr/bin',
:refreshonly => true,
:subscribe => 'Anchor[keystone::dbsync::end]',
:notify => 'Anchor[keystone::service::begin]',
:tag => 'keystone-bootstrap',
)}
it { is_expected.to contain_keystone_role('adminrole').with_ensure('present') }
it { is_expected.to contain_keystone_user('user').with(
:ensure => 'present',
:enabled => true,
:email => 'some@email',
:password => 'secret',
)}
it { is_expected.to contain_keystone_tenant('serviceproj').with(
:ensure => 'present',
:enabled => true,
)}
it { is_expected.to contain_keystone_tenant('adminproj').with(
:ensure => 'present',
:enabled => true,
)}
it { is_expected.to contain_keystone_user_role('user@adminproj').with(
:ensure => 'present',
:roles => ['adminrole'],
)}
it { is_expected.to contain_keystone_service('servicename::identity').with_ensure('present') }
it { is_expected.to contain_keystone_endpoint('RegionTwo/servicename::identity').with(
:ensure => 'present',
:public_url => 'http://public:4321',
:admin_url => 'http://admin:1234',
:internal_url => 'http://internal:1342',
)}
it { is_expected.to contain_file('/etc/keystone/puppet.conf').with(
:ensure => 'present',
:replace => false,
:content => '',
:owner => 'root',
:group => 'root',
:mode => '0600',
:require => 'Anchor[keystone::install::end]',
)}
it { is_expected.to contain_keystone__resource__authtoken('keystone_puppet_config').with(
:username => 'user',
:password => 'secret',
:auth_url => 'http://admin:1234',
:project_name => 'adminproj',
:region_name => 'RegionTwo',
:interface => 'admin',
)}
end
context 'when setting keystone_user param in keystone' do
let :params do
{
:password => 'secret'
}
end
let :pre_condition do
"class { '::keystone':
keystone_user => 'some',
}"
end
it { is_expected.to contain_exec('keystone bootstrap').with_user('some') }
end
context 'when setting interface to internal' do
let :params do
{
:password => 'secret',
:internal_url => 'http://internal:1234',
:interface => 'internal',
}
end
it { is_expected.to contain_keystone__resource__authtoken('keystone_puppet_config').with(
:auth_url => 'http://internal:1234',
:interface => 'internal',
)}
end
end
on_supported_os({
:supported_os => OSDefaults.get_supported_os
}).each do |os,facts|
context "on #{os}" do
let(:facts) do
facts.merge!(OSDefaults.get_facts())
end
let(:platform_params) do
{ :keystone_user => 'keystone' }
end
it_behaves_like 'keystone::bootstrap'
end
end
end

View File

@ -1,82 +0,0 @@
require 'spec_helper'
describe 'keystone::endpoint' do
it { is_expected.to contain_keystone_service('keystone::identity').with(
:ensure => 'present',
:description => 'OpenStack Identity Service'
)}
describe 'with default parameters' do
it { is_expected.to contain_keystone_endpoint('RegionOne/keystone::identity').with(
:ensure => 'present',
:public_url => 'http://127.0.0.1:5000',
:admin_url => 'http://127.0.0.1:5000',
:internal_url => 'http://127.0.0.1:5000',
:region => 'RegionOne'
)}
end
describe 'with overridden parameters' do
let :params do
{ :version => 'v42.6',
:public_url => 'https://identity.some.tld/the/main/endpoint',
:admin_url => 'https://identity-int.some.tld/some/admin/endpoint',
:internal_url => 'https://identity-int.some.tld/some/internal/endpoint',
:region => 'East'
}
end
it { is_expected.to contain_keystone_endpoint('East/keystone::identity').with(
:ensure => 'present',
:public_url => 'https://identity.some.tld/the/main/endpoint/v42.6',
:admin_url => 'https://identity-int.some.tld/some/admin/endpoint/v42.6',
:internal_url => 'https://identity-int.some.tld/some/internal/endpoint/v42.6',
:region => 'East'
)}
end
describe 'with unset version to test backward compatibility' do
let :params do
{ :version => 'unset' }
end
it { is_expected.to contain_keystone_endpoint('RegionOne/keystone::identity').with(
:ensure => 'present',
:public_url => 'http://127.0.0.1:5000/v2.0',
:admin_url => 'http://127.0.0.1:5000/v2.0',
:internal_url => 'http://127.0.0.1:5000/v2.0'
)}
end
describe 'without internal_url parameter' do
let :params do
{ :public_url => 'https://identity.some.tld/the/main/endpoint' }
end
it 'internal_url should default to public_url' do
is_expected.to contain_keystone_endpoint('RegionOne/keystone::identity').with(
:ensure => 'present',
:public_url => 'https://identity.some.tld/the/main/endpoint',
:internal_url => 'https://identity.some.tld/the/main/endpoint'
)
end
end
describe 'with domain parameters' do
let :params do
{ :user_domain => 'userdomain',
:project_domain => 'projectdomain',
:default_domain => 'defaultdomain' }
end
it { is_expected.to contain_keystone__resource__service_identity('keystone').with(
:user_domain => 'userdomain',
:project_domain => 'projectdomain',
:default_domain => 'defaultdomain'
)}
end
end

View File

@ -19,8 +19,6 @@ describe 'keystone' do
end end
default_params = { default_params = {
'admin_token' => 'service_token',
'admin_password' => 'special_password',
'package_ensure' => 'present', 'package_ensure' => 'present',
'client_package_ensure' => 'present', 'client_package_ensure' => 'present',
'public_bind_host' => '0.0.0.0', 'public_bind_host' => '0.0.0.0',
@ -63,8 +61,6 @@ describe 'keystone' do
'client_package_ensure' => 'latest', 'client_package_ensure' => 'latest',
'public_bind_host' => '0.0.0.0', 'public_bind_host' => '0.0.0.0',
'public_port' => '5001', 'public_port' => '5001',
'admin_token' => 'service_token_override',
'admin_password' => 'admin_openstack_password',
'catalog_type' => 'template', 'catalog_type' => 'template',
'token_provider' => 'uuid', 'token_provider' => 'uuid',
'password_hash_algorithm' => 'pbkdf2_sha512', 'password_hash_algorithm' => 'pbkdf2_sha512',
@ -125,17 +121,6 @@ describe 'keystone' do
end end
end end
it 'should bootstrap $enable_bootstrap is true' do
if param_hash['enable_bootstrap']
is_expected.to contain_exec('keystone-manage bootstrap').with(
:command => 'keystone-manage bootstrap',
:environment => 'OS_BOOTSTRAP_PASSWORD=service_password',
:user => param_hash['keystone_user'],
:refreshonly => true
)
end
end
it 'passes purge to resource' do it 'passes purge to resource' do
is_expected.to contain_resources('keystone_config').with({ is_expected.to contain_resources('keystone_config').with({
:purge => false :purge => false
@ -151,10 +136,6 @@ describe 'keystone' do
end end
end end
it 'should contain correct admin_token config' do
is_expected.to contain_keystone_config('DEFAULT/admin_token').with_value(param_hash['admin_token']).with_secret(true)
end
it 'should contain correct mysql config' do it 'should contain correct mysql config' do
is_expected.to contain_class('keystone::db') is_expected.to contain_class('keystone::db')
end end
@ -288,7 +269,6 @@ describe 'keystone' do
describe 'when ipv6 loopback is set' do describe 'when ipv6 loopback is set' do
let :params do let :params do
{ {
:admin_token => 'service_token',
:public_bind_host => '::0' :public_bind_host => '::0'
} }
end end
@ -298,7 +278,6 @@ describe 'keystone' do
describe 'when ipv4 address is set' do describe 'when ipv4 address is set' do
let :params do let :params do
{ {
:admin_token => 'service_token',
:public_bind_host => '192.168.0.1', :public_bind_host => '192.168.0.1',
:public_port => '15000' :public_port => '15000'
} }
@ -309,7 +288,6 @@ describe 'keystone' do
describe 'when unenclosed ipv6 address is set' do describe 'when unenclosed ipv6 address is set' do
let :params do let :params do
{ {
:admin_token => 'service_token',
:public_bind_host => '2001:db8::1' :public_bind_host => '2001:db8::1'
} }
end end
@ -319,7 +297,6 @@ describe 'keystone' do
describe 'when enclosed ipv6 address is set' do describe 'when enclosed ipv6 address is set' do
let :params do let :params do
{ {
:admin_token => 'service_token',
:public_bind_host => '[2001:db8::1]' :public_bind_host => '[2001:db8::1]'
} }
end end
@ -335,8 +312,7 @@ describe 'keystone' do
describe 'with disabled service managing' do describe 'with disabled service managing' do
let :params do let :params do
{ :admin_token => 'service_token', { :manage_service => false,
:manage_service => false,
:enabled => false } :enabled => false }
end end
@ -354,7 +330,6 @@ describe 'keystone' do
describe 'when configuring as UUID' do describe 'when configuring as UUID' do
let :params do let :params do
{ {
'admin_token' => 'service_token',
'token_provider' => 'keystone.token.providers.uuid.Provider' 'token_provider' => 'keystone.token.providers.uuid.Provider'
} }
end end
@ -362,8 +337,7 @@ describe 'keystone' do
describe 'with invalid catalog_type' do describe 'with invalid catalog_type' do
let :params do let :params do
{ :admin_token => 'service_token', { :catalog_type => 'invalid' }
:catalog_type => 'invalid' }
end end
it { should raise_error(Puppet::Error) } it { should raise_error(Puppet::Error) }
@ -371,8 +345,7 @@ describe 'keystone' do
describe 'when configuring catalog driver' do describe 'when configuring catalog driver' do
let :params do let :params do
{ :admin_token => 'service_token', { :catalog_driver => 'alien' }
:catalog_driver => 'alien' }
end end
it { is_expected.to contain_keystone_config('catalog/driver').with_value(params[:catalog_driver]) } it { is_expected.to contain_keystone_config('catalog/driver').with_value(params[:catalog_driver]) }
@ -382,7 +355,6 @@ describe 'keystone' do
describe 'when configuring token expiration' do describe 'when configuring token expiration' do
let :params do let :params do
{ {
'admin_token' => 'service_token',
'token_expiration' => '42', 'token_expiration' => '42',
} }
end end
@ -392,9 +364,7 @@ describe 'keystone' do
describe 'when not configuring token expiration' do describe 'when not configuring token expiration' do
let :params do let :params do
{ {}
'admin_token' => 'service_token',
}
end end
it { is_expected.to contain_keystone_config("token/expiration").with_value('3600') } it { is_expected.to contain_keystone_config("token/expiration").with_value('3600') }
@ -403,29 +373,16 @@ describe 'keystone' do
describe 'when sync_db is set to false' do describe 'when sync_db is set to false' do
let :params do let :params do
{ {
'admin_token' => 'service_token', 'sync_db' => false,
'sync_db' => false,
} }
end end
it { is_expected.not_to contain_exec('keystone-manage db_sync') } it { is_expected.not_to contain_exec('keystone-manage db_sync') }
end end
describe 'when enable_bootstrap is set to false' do
let :params do
{
'admin_token' => 'service_token',
'enable_bootstrap' => false,
}
end
it { is_expected.not_to contain_exec('keystone-manage bootstrap') }
end
describe 'configure memcache servers if set' do describe 'configure memcache servers if set' do
let :params do let :params do
{ {
'admin_token' => 'service_token',
'cache_backend' => 'dogpile.cache.memcached', 'cache_backend' => 'dogpile.cache.memcached',
'cache_backend_argument' => ['url:SERVER1:12211'], 'cache_backend_argument' => ['url:SERVER1:12211'],
'cache_memcache_servers' => 'SERVER1:11211,SERVER2:11211,[fd12:3456:789a:1::1]:11211', 'cache_memcache_servers' => 'SERVER1:11211,SERVER2:11211,[fd12:3456:789a:1::1]:11211',
@ -454,7 +411,6 @@ describe 'keystone' do
describe 'configure cache memcache servers if set' do describe 'configure cache memcache servers if set' do
let :params do let :params do
{ {
'admin_token' => 'service_token',
'cache_backend' => 'dogpile.cache.memcached', 'cache_backend' => 'dogpile.cache.memcached',
'cache_backend_argument' => ['url:SERVER3:12211'], 'cache_backend_argument' => ['url:SERVER3:12211'],
'cache_memcache_servers' => [ 'SERVER1:11211', 'SERVER2:11211', '[fd12:3456:789a:1::1]:11211' ], 'cache_memcache_servers' => [ 'SERVER1:11211', 'SERVER2:11211', '[fd12:3456:789a:1::1]:11211' ],
@ -487,7 +443,6 @@ describe 'keystone' do
describe 'configure cache enabled if set' do describe 'configure cache enabled if set' do
let :params do let :params do
{ {
'admin_token' => 'service_token',
'cache_backend' => 'dogpile.cache.memcached', 'cache_backend' => 'dogpile.cache.memcached',
'cache_backend_argument' => ['url:SERVER3:12211'], 'cache_backend_argument' => ['url:SERVER3:12211'],
'cache_enabled' => true, 'cache_enabled' => true,
@ -550,7 +505,6 @@ describe 'keystone' do
describe 'when enabling SSL' do describe 'when enabling SSL' do
let :params do let :params do
{ {
'admin_token' => 'service_token',
'enable_ssl' => true, 'enable_ssl' => true,
'public_endpoint' => 'https://localhost:5000', 'public_endpoint' => 'https://localhost:5000',
} }
@ -567,8 +521,7 @@ describe 'keystone' do
describe 'when disabling SSL' do describe 'when disabling SSL' do
let :params do let :params do
{ {
'admin_token' => 'service_token', 'enable_ssl'=> false,
'enable_ssl' => false,
} }
end end
it {is_expected.to contain_keystone_config('ssl/enable').with_value(false)} it {is_expected.to contain_keystone_config('ssl/enable').with_value(false)}
@ -706,7 +659,6 @@ describe 'keystone' do
describe 'setting default template catalog' do describe 'setting default template catalog' do
let :params do let :params do
{ {
:admin_token => 'service_token',
:catalog_type => 'template' :catalog_type => 'template'
} }
end end
@ -718,7 +670,6 @@ describe 'keystone' do
describe 'setting another template catalog' do describe 'setting another template catalog' do
let :params do let :params do
{ {
:admin_token => 'service_token',
:catalog_type => 'template', :catalog_type => 'template',
:catalog_template_file => '/some/template_file' :catalog_template_file => '/some/template_file'
} }

View File

@ -1,262 +0,0 @@
require 'spec_helper'
describe 'keystone::roles::admin' do
let :pre_condition do
"class { 'keystone':
admin_token => 'dummy',
admin_password => 'ChangeMe' }"
end
let :facts do
@default_facts.merge({
:osfamily => 'Debian',
:operatingsystem => 'Debian',
:operatingsystemrelease => '7.0',
:os_workers => 1,
:os => { :name => 'Debian', :family => 'Debian', :release => { :major => '7', :minor => '0' } },
})
end
describe 'with only the required params set' do
let :params do
{
:password => 'ChangeMe'
}
end
it { is_expected.to contain_keystone_tenant('services').with(
:ensure => 'present',
:enabled => true,
:description => 'Tenant for the openstack services'
)}
it { is_expected.to contain_keystone_tenant('openstack').with(
:ensure => 'present',
:enabled => true,
:description => 'admin tenant'
)}
it { is_expected.to contain_keystone_user('admin').with(
:ensure => 'present',
:enabled => true,
:email => 'admin@localhost',
:password => 'ChangeMe',
)}
it { is_expected.to contain_keystone_role('admin').with_ensure('present') }
it { is_expected.to contain_keystone_user_role('admin@openstack').with(
:roles => ['admin'],
:ensure => 'present',
:user_domain => nil,
:project_domain => nil,
)}
end
describe 'when overriding optional params' do
let :pre_condition do
"class { 'keystone':
admin_token => 'dummy',
admin_password => 'foo' }"
end
let :params do
{
:admin => 'admin',
:email => 'foo@baz',
:password => 'foo',
:admin_tenant => 'admin',
:admin_roles => ['admin', 'heat_stack_owner'],
:service_tenant => 'foobar',
:admin_tenant_desc => 'admin something else',
:service_tenant_desc => 'foobar description',
}
end
it { is_expected.to contain_keystone_tenant('foobar').with(
:ensure => 'present',
:enabled => true,
:description => 'foobar description'
)}
it { is_expected.to contain_keystone_tenant('admin').with(
:ensure => 'present',
:enabled => true,
:description => 'admin something else'
)}
it { is_expected.to contain_keystone_user('admin').with(
:ensure => 'present',
:enabled => true,
:email => 'foo@baz',
:password => 'foo',
)}
it { is_expected.to contain_keystone_user_role('admin@admin').with(
:roles => ['admin', 'heat_stack_owner'],
:ensure => 'present',
:user_domain => nil,
:project_domain => nil,
)}
end
describe 'when disabling user configuration' do
before do
let :params do
{
:configure_user => false
}
end
it { is_expected.to_not contain_keystone_user('keystone') }
it { is_expected.to contain_keystone_user_role('keystone@openstack') }
end
end
describe 'when disabling user and role configuration' do
before do
let :params do
{
:configure_user => false,
:configure_user_role => false
}
end
it { is_expected.to_not contain_keystone_user('keystone') }
it { is_expected.to_not contain_keystone_user_role('keystone@openstack') }
end
end
describe 'when specifying admin_user_domain and admin_project_domain' do
let :params do
{
:email => 'foo@bar',
:password => 'ChangeMe',
:admin_tenant => 'admin_tenant',
:admin_user_domain => 'admin_user_domain',
:admin_project_domain => 'admin_project_domain',
}
end
it { is_expected.to contain_keystone_user('admin').with(
:domain => 'admin_user_domain',
)}
it { is_expected.to contain_keystone_tenant('admin_tenant').with(:domain => 'admin_project_domain') }
it { is_expected.to contain_keystone_domain('admin_user_domain') }
it { is_expected.to contain_keystone_domain('admin_project_domain') }
it { is_expected.to contain_keystone_user_role('admin@admin_tenant').with(
:roles => ['admin'],
:ensure => 'present',
:user_domain => 'admin_user_domain',
:project_domain => 'admin_project_domain',
)}
end
describe 'when specifying admin_user_domain and admin_project_domain' do
let :params do
{
:email => 'foo@bar',
:password => 'ChangeMe',
:admin_tenant => 'admin_tenant::admin_project_domain',
:admin_user_domain => 'admin_user_domain',
:admin_project_domain => 'admin_project_domain',
}
end
it { is_expected.to contain_keystone_user('admin').with(
:domain => 'admin_user_domain',
)}
it { is_expected.to contain_keystone_tenant('admin_tenant::admin_project_domain').with(:domain => 'admin_project_domain') }
it { is_expected.to contain_keystone_domain('admin_user_domain') }
it { is_expected.to contain_keystone_domain('admin_project_domain') }
it { is_expected.to contain_keystone_user_role('admin@admin_tenant::admin_project_domain').with(
:roles => ['admin'],
:ensure => 'present',
:user_domain => 'admin_user_domain',
:project_domain => 'admin_project_domain',
)}
end
describe 'when specifying a service domain' do
let :params do
{
:email => 'foo@bar',
:password => 'ChangeMe',
:service_tenant => 'service_project',
:service_project_domain => 'service_domain'
}
end
it { is_expected.to contain_keystone_tenant('service_project').with(:domain => 'service_domain') }
it { is_expected.to contain_keystone_domain('service_domain') }
end
describe 'when specifying a service domain and service tenant domain' do
let :params do
{
:email => 'foo@bar',
:password => 'ChangeMe',
:service_tenant => 'service_project::service_domain',
:service_project_domain => 'service_domain'
}
end
it { is_expected.to contain_keystone_tenant('service_project::service_domain').with(:domain => 'service_domain') }
it { is_expected.to contain_keystone_domain('service_domain') }
end
describe 'when admin_user_domain and admin_project_domain are equal' do
let :params do
{
:email => 'foo@bar',
:password => 'ChangeMe',
:admin_user_domain => 'admin_domain',
:admin_project_domain => 'admin_domain',
}
end
it { is_expected.to contain_keystone_domain('admin_domain') }
end
describe 'when specifying a target admin domain' do
let :params do
{
:email => 'foo@bar',
:password => 'ChangeMe',
:admin_user_domain => 'admin_domain',
:admin_project_domain => 'admin_domain',
:target_admin_domain => 'admin_domain_target'
}
end
let :pre_condition do
["class { 'keystone':
admin_token => 'dummy',
admin_password => 'ChangeMe' }",
"file { '/root/openrc': tag => ['openrc']}"]
end
it { is_expected.to contain_keystone_domain('admin_domain_target') }
it { is_expected.to contain_keystone_user_role('admin@::admin_domain_target')
.with(
:roles => ['admin'],
:ensure => 'present',
:user_domain => 'admin_domain',
)
.that_comes_before('File[/root/openrc]')
}
end
describe 'when admin_password and password do not match' do
let :pre_condition do
"class { 'keystone':
admin_token => 'dummy',
admin_password => 'foo' }"
end
let :params do
{
:email => 'foo@bar',
:password => 'bar',
:service_tenant => 'services'
}
end
it { is_expected.to contain_keystone_role('admin').with_ensure('present') }
it { is_expected.to contain_keystone_user_role('admin@openstack').with(
:roles => ['admin'],
:ensure => 'present',
:user_domain => nil,
:project_domain => nil,
)}
end
end

View File

@ -0,0 +1,57 @@
# these tests are a little concerning b/c they are hacking around the
# modulepath, so these tests will not catch issues that may eventually arise
# related to loading these plugins.
# I could not, for the life of me, figure out how to programatcally set the modulepath
$LOAD_PATH.push(
File.join(
File.dirname(__FILE__),
'..',
'..',
'..',
'fixtures',
'modules',
'inifile',
'lib')
)
require 'spec_helper'
provider_class = Puppet::Type.type(:keystone_puppet_config).provider(:ini_setting)
describe provider_class do
it 'should default to the default setting when no other one is specified' do
resource = Puppet::Type::Keystone_puppet_config.new(
{:name => 'DEFAULT/foo', :value => 'bar'}
)
provider = provider_class.new(resource)
expect(provider.section).to eq('DEFAULT')
expect(provider.setting).to eq('foo')
end
it 'should allow setting to be set explicitly' do
resource = Puppet::Type::Keystone_puppet_config.new(
{:name => 'dude/foo', :value => 'bar'}
)
provider = provider_class.new(resource)
expect(provider.section).to eq('dude')
expect(provider.setting).to eq('foo')
end
it 'should ensure absent when <SERVICE DEFAULT> is specified as a value' do
resource = Puppet::Type::Keystone_puppet_config.new(
{:name => 'dude/foo', :value => '<SERVICE DEFAULT>'}
)
provider = provider_class.new(resource)
provider.exists?
expect(resource[:ensure]).to eq :absent
end
it 'should ensure absent when value matches ensure_absent_val' do
resource = Puppet::Type::Keystone_puppet_config.new(
{:name => 'dude/foo', :value => 'foo', :ensure_absent_val => 'foo' }
)
provider = provider_class.new(resource)
provider.exists?
expect(resource[:ensure]).to eq :absent
end
end

View File

@ -126,44 +126,13 @@ id="the_user_id"
end end
end end
describe '#get_public_endpoint' do
it 'should return nothing if there is no keystone config file' do
expect(klass.get_public_endpoint).to be_nil
end
it 'should return nothing if the keystone config file does not have a DEFAULT section' do
mock = {}
File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true)
Puppet::Util::IniConfig::File.expects(:new).returns(mock)
mock.expects(:read).with('/etc/keystone/keystone.conf')
expect(klass.get_public_endpoint).to be_nil
end
it 'should fail if the keystone config file does not contain public endpoint' do
mock = {'DEFAULT' => {}}
File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true)
Puppet::Util::IniConfig::File.expects(:new).returns(mock)
mock.expects(:read).with('/etc/keystone/keystone.conf')
expect(klass.get_public_endpoint).to be_nil
end
it 'should use the public_endpoint from keystone config file with no trailing slash' do
mock = {'DEFAULT' => {'public_endpoint' => 'https://keystone.example.com/'}}
File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true)
Puppet::Util::IniConfig::File.expects(:new).returns(mock)
mock.expects(:read).with('/etc/keystone/keystone.conf')
expect(klass.get_public_endpoint).to eq('https://keystone.example.com')
end
end
describe '#get_auth_url' do describe '#get_auth_url' do
it 'should return nothing when OS_AUTH_URL is no defined in either the environment or the openrc file and there is no keystone configuration file' do it 'should raise when OS_AUTH_URL is no defined in either the environment or the openrc file and there is no keystone puppet config file' do
home = ENV['HOME'] home = ENV['HOME']
ENV.clear ENV.clear
File.expects(:exists?).with("#{home}/openrc").returns(false) File.expects(:exists?).with("#{home}/openrc").returns(false)
File.expects(:exists?).with('/root/openrc').returns(false) File.expects(:exists?).with('/root/openrc').returns(false)
File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(false) expect { klass.get_auth_url }.to raise_error(Puppet::Error, "File: /etc/keystone/puppet.conf does not contain all required configuration keys. Cannot authenticate to Keystone.")
expect(klass.get_auth_url).to be_nil
end end
it 'should return the OS_AUTH_URL from the environment' do it 'should return the OS_AUTH_URL from the environment' do
@ -180,33 +149,14 @@ id="the_user_id"
expect(klass.get_auth_url).to eq('http://127.0.0.1:5001') expect(klass.get_auth_url).to eq('http://127.0.0.1:5001')
end end
it 'should use public_endpoint when nothing else is available' do it 'should use auth_endpoint when nothing else is available' do
ENV.clear ENV.clear
mock = 'http://127.0.0.1:5001' mock = 'http://127.0.0.1:5001'
klass.expects(:public_endpoint).returns(mock) klass.expects(:auth_endpoint).returns(mock)
expect(klass.get_auth_url).to eq('http://127.0.0.1:5001') expect(klass.get_auth_url).to eq('http://127.0.0.1:5001')
end end
end end
describe '#get_service_url when retrieving the security token' do
it 'should return nothing when OS_ENDPOINT is not defined in environment' do
ENV.clear
expect(klass.get_service_url).to be_nil
end
it 'should return the OS_ENDPOINT from the environment' do
ENV['OS_ENDPOINT'] = 'http://127.0.0.1:5001/v3'
expect(klass.get_service_url).to eq('http://127.0.0.1:5001/v3')
end
it 'should use public_endpoint with the API version number' do
ENV.clear
mock = 'http://127.0.0.1:5001'
klass.expects(:public_endpoint).twice.returns(mock)
expect(klass.get_service_url).to eq('http://127.0.0.1:5001/v3')
end
end
describe '#set_domain_for_name' do describe '#set_domain_for_name' do
it 'should raise an error if the domain is not provided' do it 'should raise an error if the domain is not provided' do
expect do expect do
@ -248,37 +198,6 @@ id="other_domain_id"
end end
end end
describe 'when retrieving the security token' do
it 'should return nothing if there is no keystone config file' do
File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(false)
expect(klass.get_admin_token).to be_nil
end
it 'should return nothing if the keystone config file does not have a DEFAULT section' do
mock = {}
File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true)
Puppet::Util::IniConfig::File.expects(:new).returns(mock)
mock.expects(:read).with('/etc/keystone/keystone.conf')
expect(klass.get_admin_token).to be_nil
end
it 'should fail if the keystone config file does not contain an admin token' do
mock = {'DEFAULT' => {'not_a_token' => 'foo'}}
File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true)
Puppet::Util::IniConfig::File.expects(:new).returns(mock)
mock.expects(:read).with('/etc/keystone/keystone.conf')
expect(klass.get_admin_token).to be_nil
end
it 'should parse the admin token if it is in the config file' do
mock = {'DEFAULT' => {'admin_token' => 'foo'}}
File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true)
Puppet::Util::IniConfig::File.expects(:new).returns(mock)
mock.expects(:read).with('/etc/keystone/keystone.conf')
expect(klass.get_admin_token).to eq('foo')
end
end
describe 'when using domains' do describe 'when using domains' do
before(:each) do before(:each) do
set_env set_env

View File

@ -0,0 +1,78 @@
require 'spec_helper'
# this hack is required for now to ensure that the path is set up correctly
# to retrieve the parent provider
$LOAD_PATH.push(
File.join(
File.dirname(__FILE__),
'..',
'..',
'fixtures',
'modules',
'inifile',
'lib')
)
require 'puppet'
require 'puppet/type/keystone_puppet_config'
describe 'Puppet::Type.type(:keystone_puppet_config)' do
before :each do
@keystone_puppet_config = Puppet::Type.type(:keystone_puppet_config).new(:name => 'DEFAULT/foo', :value => 'bar')
end
it 'should require a name' do
expect {
Puppet::Type.type(:keystone_puppet_config).new({})
}.to raise_error(Puppet::Error, 'Title or name must be provided')
end
it 'should not expect a name with whitespace' do
expect {
Puppet::Type.type(:keystone_puppet_config).new(:name => 'f oo')
}.to raise_error(Puppet::Error, /Parameter name failed/)
end
it 'should fail when there is no section' do
expect {
Puppet::Type.type(:keystone_puppet_config).new(:name => 'foo')
}.to raise_error(Puppet::Error, /Parameter name failed/)
end
it 'should not require a value when ensure is absent' do
Puppet::Type.type(:keystone_puppet_config).new(:name => 'DEFAULT/foo', :ensure => :absent)
end
it 'should accept a valid value' do
@keystone_puppet_config[:value] = 'bar'
expect(@keystone_puppet_config[:value]).to eq('bar')
end
it 'should not accept a value with whitespace' do
@keystone_puppet_config[:value] = 'b ar'
expect(@keystone_puppet_config[:value]).to eq('b ar')
end
it 'should accept valid ensure values' do
@keystone_puppet_config[:ensure] = :present
expect(@keystone_puppet_config[:ensure]).to eq(:present)
@keystone_puppet_config[:ensure] = :absent
expect(@keystone_puppet_config[:ensure]).to eq(:absent)
end
it 'should not accept invalid ensure values' do
expect {
@keystone_puppet_config[:ensure] = :latest
}.to raise_error(Puppet::Error, /Invalid value/)
end
it 'should autorequire the config file' do
catalog = Puppet::Resource::Catalog.new
config_file = Puppet::Type.type(:file).new(:name => '/etc/keystone/puppet.conf')
catalog.add_resource config_file, @keystone_puppet_config
dependency = @keystone_puppet_config.autorequire
expect(dependency.size).to eq(1)
expect(dependency[0].target).to eq(@keystone_puppet_config)
expect(dependency[0].source).to eq(config_file)
end
end