Add Glance Glare API service

In Mitaka Glance v3 was moved to stand alone service [1] - now
it's called Glance Artifacts Repository (Glare).

This patch adds appropriate service managing, package installation,
configuration and related spec tests.

[1] I5b7bd4cdcc5f2a40fc4a5f74bcc422fd700c4fb0

Change-Id: I3371d1d57486e79ccfae565417f2195d3ae66bc9
Closes-bug: #1555697
This commit is contained in:
Denis Egorenko 2016-03-16 18:46:32 +03:00
parent ee7fbcf37c
commit da8a3aa022
17 changed files with 1440 additions and 0 deletions

View File

@ -0,0 +1,10 @@
Puppet::Type.type(:glance_glare_config).provide(
:ini_setting,
:parent => Puppet::Type.type(:openstack_config).provider(:ini_setting)
) do
def self.file_path
'/etc/glance/glance-glare.conf'
end
end

View File

@ -0,0 +1,10 @@
Puppet::Type.type(:glance_glare_paste_ini).provide(
:ini_setting,
:parent => Puppet::Type.type(:openstack_config).provider(:ini_setting)
) do
def self.file_path
'/etc/glance/glance-glare-paste.ini'
end
end

View File

@ -0,0 +1,57 @@
Puppet::Type.newtype(:glance_glare_config) do
ensurable
newparam(:name, :namevar => true) do
desc 'Section/setting name to manage from glance-api.conf'
newvalues(/\S+\/\S+/)
end
newproperty(:value) do
desc 'The value of the setting to be defined.'
munge do |value|
value = value.to_s.strip
value.capitalize! if value =~ /^(true|false)$/i
value
end
newvalues(/^[\S ]*$/)
def is_to_s( currentvalue )
if resource.secret?
return '[old secret redacted]'
else
return currentvalue
end
end
def should_to_s( newvalue )
if resource.secret?
return '[new secret redacted]'
else
return newvalue
end
end
end
newparam(:secret, :boolean => true) do
desc 'Whether to hide the value from Puppet logs. Defaults to `false`.'
newvalues(:true, :false)
defaultto false
end
newparam(:ensure_absent_val) do
desc 'A value that is specified as the value property will behave as if ensure => absent was specified'
defaultto('<SERVICE DEFAULT>')
end
autorequire(:package) do
if Facter.value(:osfamily) == 'Debian'
'glance-glare'
elsif Facter.value(:osfamily) == 'RedHat'
'openstack-glance'
end
end
end

View File

@ -0,0 +1,56 @@
Puppet::Type.newtype(:glance_glare_paste_ini) do
ensurable
newparam(:name, :namevar => true) do
desc 'Section/setting name to manage from glance-glare-paste.ini'
newvalues(/\S+\/\S+/)
end
newproperty(:value) do
desc 'The value of the setting to be defined.'
munge do |value|
value = value.to_s.strip
value.capitalize! if value =~ /^(true|false)$/i
value
end
def is_to_s( currentvalue )
if resource.secret?
return '[old secret redacted]'
else
return currentvalue
end
end
def should_to_s( newvalue )
if resource.secret?
return '[new secret redacted]'
else
return newvalue
end
end
end
newparam(:secret, :boolean => true) do
desc 'Whether to hide the value from Puppet logs. Defaults to `false`.'
newvalues(:true, :false)
defaultto false
end
newparam(:ensure_absent_val) do
desc 'A value that is specified as the value property will behave as if ensure => absent was specified'
defaultto('<SERVICE DEFAULT>')
end
autorequire(:package) do
if Facter.value(:osfamily) == 'Debian'
'glance-glare'
elsif Facter.value(:osfamily) == 'RedHat'
'openstack-glance'
end
end
end

262
manifests/glare.pp Normal file
View File

@ -0,0 +1,262 @@
# == Class glance::glare
#
# Configure Glare Glare service in glance
#
# == Parameters
#
# [*package_ensure*]
# (optional) Ensure state for package. On RedHat platforms this
# setting is ignored and the setting from the glance class is used
# because there is only one glance package. Defaults to 'present'.
#
# [*bind_host*]
# (optional) The address of the host to bind to.
# Default: 0.0.0.0
#
# [*bind_port*]
# (optional) The port the server should bind to.
# Default: 9494
#
# [*backlog*]
# (optional) Backlog requests when creating socket
# Default: 4096
#
# [*workers*]
# (optional) Number of Glance Glare worker processes to start
# Default: $::processorcount
#
# [*auth_type*]
# (optional) Type is authorization being used.
# Defaults to 'keystone'
#
# [*auth_region*]
# (optional) The region for the authentication service.
# If "use_user_token" is not in effect and using keystone auth,
# then region name can be specified.
# Defaults to $::os_service_default.
#
# [*auth_uri*]
# (optional) Complete public Identity API endpoint.
# Defaults to 'http://127.0.0.1:5000/'.
#
# [*identity_uri*]
# (optional) Complete admin Identity API endpoint.
# Defaults to 'http://127.0.0.1:35357/'.
#
# [*pipeline*]
# (optional) Partial name of a pipeline in your paste configuration file with the
# service name removed.
# Defaults to 'keystone'.
#
# [*keystone_tenant*]
# (optional) Tenant to authenticate to.
# Defaults to services.
#
# [*keystone_user*]
# (optional) User to authenticate as with keystone.
# Defaults to 'glance'.
#
# [*keystone_password*]
# (optional) Password used to authentication.
# Defaults to false.
#
# [*manage_service*]
# (optional) If Puppet should manage service startup / shutdown.
# Defaults to true.
#
# [*enabled*]
# (optional) Whether to enable services.
# Defaults to true.
#
# [*cert_file*]
# (optinal) Certificate file to use when starting API server securely
# Defaults to $::os_service_default
#
# [*key_file*]
# (optional) Private key file to use when starting API server securely
# Defaults to $::os_service_default
#
# [*ca_file*]
# (optional) CA certificate file to use to verify connecting clients
# Defaults to $::os_service_default
#
# [*stores*]
# (optional) List of which store classes and store class locations are
# currently known to glance at startup.
# Defaults to false.
# Example: ['glance.store.filesystem.Store','glance.store.http.Store']
#
# [*default_store*]
# (optional) The default backend store, should be given as a string. Value
# must be provided if more than one store is listed in 'stores'.
# Defaults to undef
#
# [*multi_store*]
# (optional) Boolean describing if multiple backends will be configured
# Defaults to false
#
# [*os_region_name*]
# (optional) Sets the keystone region to use.
# Defaults to 'RegionOne'.
#
# [*signing_dir*]
# (optional) Directory used to cache files related to PKI tokens.
# Defaults to $::os_service_default.
#
# [*memcached_servers*]
# (optinal) a list of memcached server(s) to use for caching. If left undefined,
# tokens will instead be cached in-process.
# Defaults to $::os_service_default.
#
# [*token_cache_time*]
# (optional) In order to prevent excessive effort spent validating tokens,
# the middleware caches previously-seen tokens for a configurable duration (in seconds).
# Set to -1 to disable caching completely.
# Defaults to $::os_service_default.
#
class glance::glare(
$package_ensure = 'present',
$bind_host = '0.0.0.0',
$bind_port = '9494',
$backlog = '4096',
$workers = $::processorcount,
$auth_type = 'keystone',
$auth_region = $::os_service_default,
$auth_uri = 'http://127.0.0.1:5000/',
$identity_uri = 'http://127.0.0.1:35357/',
$memcached_servers = $::os_service_default,
$pipeline = 'keystone',
$keystone_tenant = 'services',
$keystone_user = 'glance',
$keystone_password = false,
$manage_service = true,
$enabled = true,
$cert_file = $::os_service_default,
$key_file = $::os_service_default,
$ca_file = $::os_service_default,
$stores = false,
$default_store = undef,
$multi_store = false,
$os_region_name = 'RegionOne',
$signing_dir = $::os_service_default,
$token_cache_time = $::os_service_default,
) inherits glance {
include ::glance::policy
include ::glance::glare::db
include ::glance::glare::logging
if ( $glance::params::glare_package_name != $glance::params::registry_package_name ) {
ensure_packages('glance-glare', {
ensure => $package_ensure,
tag => ['openstack', 'glance-package'],
})
}
Package[$::glance::params::glare_package_name] -> Class['glance::policy']
Glance_glare_config<||> ~> Service['glance-glare']
Class['glance::policy'] ~> Service['glance-glare']
glance_glare_config {
'DEFAULT/bind_host': value => $bind_host;
'DEFAULT/bind_port': value => $bind_port;
'DEFAULT/backlog': value => $backlog;
'DEFAULT/workers': value => $workers;
'DEFAULT/auth_region': value => $auth_region;
'glance_store/os_region_name': value => $os_region_name;
}
if $default_store {
$default_store_real = $default_store
}
if $stores {
validate_array($stores)
$stores_real = $stores
}
if !empty($stores_real) {
$final_stores_real = join($stores_real, ',')
if !$default_store_real {
warning("default_store not provided, it will be automatically set to ${stores_real[0]}")
$default_store_real = $stores_real[0]
}
} elsif $default_store_real {
$final_stores_real = $default_store
} else {
warning('Glance-Glare is being provisioned without any stores configured')
}
if $default_store_real and $multi_store {
glance_glare_config {
'glance_store/default_store': value => $default_store_real;
}
} elsif $multi_store {
glance_glare_config {
'glance_store/default_store': ensure => absent;
}
}
if $final_stores_real {
glance_glare_config {
'glance_store/stores': value => $final_stores_real;
}
} else {
glance_glare_config {
'glance_store/stores': ensure => absent;
}
}
if $pipeline != '' {
validate_re($pipeline, '^(\w+([+]\w+)*)*$')
glance_glare_config {
'paste_deploy/flavor':
ensure => present,
value => $pipeline,
}
} else {
glance_glare_config { 'paste_deploy/flavor': ensure => absent }
}
# keystone config
if $auth_type == 'keystone' {
if ! $keystone_password {
fail('Parameter keystone_password must be provided, when auth_type is keystone')
}
glance_glare_config {
'keystone_authtoken/admin_tenant_name': value => $keystone_tenant;
'keystone_authtoken/admin_user': value => $keystone_user;
'keystone_authtoken/admin_password': value => $keystone_password, secret => true;
'keystone_authtoken/token_cache_time': value => $token_cache_time;
'keystone_authtoken/signing_dir': value => $signing_dir;
'keystone_authtoken/auth_uri': value => $auth_uri;
'keystone_authtoken/identity_uri': value => $identity_uri;
'keystone_authtoken/memcached_servers': value => join(any2array($memcached_servers), ',');
}
}
# SSL Options
glance_glare_config {
'DEFAULT/cert_file': value => $cert_file;
'DEFAULT/key_file' : value => $key_file;
'DEFAULT/ca_file' : value => $ca_file;
}
if $manage_service {
if $enabled {
$service_ensure = 'running'
} else {
$service_ensure = 'stopped'
}
}
service { 'glance-glare':
ensure => $service_ensure,
name => $::glance::params::glare_service_name,
enable => $enabled,
hasstatus => true,
hasrestart => true,
tag => 'glance-service',
}
}

91
manifests/glare/db.pp Normal file
View File

@ -0,0 +1,91 @@
# == Class: glance::glare::db
#
# Configure the Glance Glare database
#
# === Parameters
#
# [*database_connection*]
# Url used to connect to database.
# (Optional) Defaults to 'sqlite:///var/lib/glance/glance.sqlite'.
#
# [*database_idle_timeout*]
# Timeout when db connections should be reaped.
# (Optional) Defaults to $::os_service_default.
#
# [*database_min_pool_size*]
# Minimum number of SQL connections to keep open in a pool.
# (Optional) Defaults to $::os_service_default.
#
# [*database_max_pool_size*]
# Maximum number of SQL connections to keep open in a pool.
# (Optional) Defaults to $::os_service_default.
#
# [*database_max_retries*]
# Maximum db connection retries during startup.
# Setting -1 implies an infinite retry count.
# (Optional) Defaults to $::os_service_default.
#
# [*database_retry_interval*]
# Interval between retries of opening a sql connection.
# (Optional) Defaults to $::os_service_default.
#
# [*database_max_overflow*]
# If set, use this value for max_overflow with sqlalchemy.
# (Optional) Defaults to $::os_service_default.
#
class glance::glare::db (
$database_connection = 'sqlite:///var/lib/glance/glance.sqlite',
$database_idle_timeout = $::os_service_default,
$database_min_pool_size = $::os_service_default,
$database_max_pool_size = $::os_service_default,
$database_max_retries = $::os_service_default,
$database_retry_interval = $::os_service_default,
$database_max_overflow = $::os_service_default,
) {
include ::glance::params
validate_re($database_connection,
'^(sqlite|mysql(\+pymysql)?|postgresql):\/\/(\S+:\S+@\S+\/\S+)?')
case $database_connection {
/^mysql(\+pymysql)?:\/\//: {
require 'mysql::bindings'
require 'mysql::bindings::python'
if $database_connection =~ /^mysql\+pymysql/ {
$backend_package = $::glance::params::pymysql_package_name
} else {
$backend_package = false
}
}
/^postgresql:\/\//: {
$backend_package = false
require 'postgresql::lib::python'
}
/^sqlite:\/\//: {
$backend_package = $::glance::params::sqlite_package_name
}
default: {
fail('Unsupported backend configured')
}
}
if $backend_package and !defined(Package[$backend_package]) {
package {'glance-backend-package':
ensure => present,
name => $backend_package,
tag => 'openstack',
}
}
glance_glare_config {
'database/connection': value => $database_connection, secret => true;
'database/idle_timeout': value => $database_idle_timeout;
'database/min_pool_size': value => $database_min_pool_size;
'database/max_retries': value => $database_max_retries;
'database/retry_interval': value => $database_retry_interval;
'database/max_pool_size': value => $database_max_pool_size;
'database/max_overflow': value => $database_max_overflow;
}
}

145
manifests/glare/logging.pp Normal file
View File

@ -0,0 +1,145 @@
# == Class glance::glare::logging
#
# glance glare extended logging configuration
#
# === Parameters
#
# [*verbose*]
# (Optional) Should the daemons log verbose messages.
# Defaults to $::os_service_default.
#
# [*debug*]
# (Optional) Should the daemons log debug messages.
# Defaults to $::os_service_default.
#
# [*use_syslog*]
# (Optional) Use syslog for logging.
# Defaults to $::os_service_default.
#
# [*use_stderr*]
# (optional) Use stderr for logging.
# Defaults to $::os_service_default.
#
# [*log_facility*]
# (Optional) Syslog facility to receive log lines.
# Defaults to $::os_service_default.
#
# [*log_dir*]
# (optional) Directory where logs should be stored.
# If set to boolean false, it will not log to any directory.
# Defaults to '/var/log/glance'
#
# [*log_file*]
# (optional) File where logs should be stored.
# Defaults to '/var/log/glance/glare.log'
#
# [*logging_context_format_string*]
# (optional) Format string to use for log messages with context.
# Defaults to $::os_service_default
# Example: '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s\
# [%(request_id)s %(user_identity)s] %(instance)s%(message)s'
#
# [*logging_default_format_string*]
# (optional) Format string to use for log messages without context.
# Defaults to $::os_service_default.
# Example: '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s\
# [-] %(instance)s%(message)s'
#
# [*logging_debug_format_suffix*]
# (optional) Formatted data to append to log format when level is DEBUG.
# Defaults to $::os_service_default.
# Example: '%(funcName)s %(pathname)s:%(lineno)d'
#
# [*logging_exception_prefix*]
# (optional) Prefix each line of exception output with this format.
# Defaults to $::os_service_default.
# Example: '%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s'
#
# [*log_config_append*]
# The name of an additional logging configuration file.
# Defaults to $::os_service_default.
# See https://docs.python.org/2/howto/logging.html
#
# [*default_log_levels*]
# (optional) Hash of logger (keys) and level (values) pairs.
# Defaults to $::os_service_default.
# Example:
# {'amqp' => 'WARN', 'amqplib' => 'WARN', 'boto' => 'WARN',
# 'qpid' => 'WARN', 'sqlalchemy' => 'WARN', 'suds' => 'INFO',
# 'iso8601' => 'WARN',
# 'requests.packages.urllib3.connectionpool' => 'WARN' }
#
# [*publish_errors*]
# (optional) Publish error events (boolean value).
# Defaults to $::os_service_default.
#
# [*fatal_deprecations*]
# (optional) Make deprecations fatal (boolean value).
# Defaults to $::os_service_default.
#
# [*instance_format*]
# (optional) If an instance is passed with the log message, format it
# like this (string value).
# Defaults to $::os_service_default.
# Example: '[instance: %(uuid)s] '
#
# [*instance_uuid_format*]
# (optional) If an instance UUID is passed with the log message, format
# It like this (string value).
# Defaults to $::os_service_default.
# Example: instance_uuid_format='[instance: %(uuid)s] '
# [*log_date_format*]
# (optional) Format string for %%(asctime)s in log records.
# Defaults to $::os_service_default.
# Example: 'Y-%m-%d %H:%M:%S'
#
class glance::glare::logging(
$use_syslog = $::os_service_default,
$use_stderr = $::os_service_default,
$log_facility = $::os_service_default,
$log_dir = '/var/log/glance',
$log_file = '/var/log/glance/glare.log',
$verbose = $::os_service_default,
$debug = $::os_service_default,
$logging_context_format_string = $::os_service_default,
$logging_default_format_string = $::os_service_default,
$logging_debug_format_suffix = $::os_service_default,
$logging_exception_prefix = $::os_service_default,
$log_config_append = $::os_service_default,
$default_log_levels = $::os_service_default,
$publish_errors = $::os_service_default,
$fatal_deprecations = $::os_service_default,
$instance_format = $::os_service_default,
$instance_uuid_format = $::os_service_default,
$log_date_format = $::os_service_default,
) {
if is_service_default($default_log_levels) {
$default_log_levels_real = $default_log_levels
} else {
$default_log_levels_real = join(sort(join_keys_to_values($default_log_levels, '=')), ',')
}
glance_glare_config {
'DEFAULT/debug': value => $debug;
'DEFAULT/verbose': value => $verbose;
'DEFAULT/use_stderr': value => $use_stderr;
'DEFAULT/use_syslog': value => $use_syslog;
'DEFAULT/log_dir': value => $log_dir;
'DEFAULT/log_file': value => $log_file;
'DEFAULT/syslog_log_facility': value => $log_facility;
'DEFAULT/default_log_levels': value => $default_log_levels_real;
'DEFAULT/logging_context_format_string': value => $logging_context_format_string;
'DEFAULT/logging_default_format_string': value => $logging_default_format_string;
'DEFAULT/logging_debug_format_suffix': value => $logging_debug_format_suffix;
'DEFAULT/logging_exception_prefix': value => $logging_exception_prefix;
'DEFAULT/log_config_append': value => $log_config_append;
'DEFAULT/publish_errors': value => $publish_errors;
'DEFAULT/fatal_deprecations': value => $fatal_deprecations;
'DEFAULT/instance_format': value => $instance_format;
'DEFAULT/instance_uuid_format': value => $instance_uuid_format;
'DEFAULT/log_date_format': value => $log_date_format;
}
}

View File

@ -10,8 +10,10 @@ class glance::params {
case $::osfamily {
'RedHat': {
$api_package_name = 'openstack-glance'
$glare_package_name = 'openstack-glance'
$registry_package_name = 'openstack-glance'
$api_service_name = 'openstack-glance-api'
$glare_service_name = 'openstack-glance-glare'
$registry_service_name = 'openstack-glance-registry'
if ($::operatingsystem != 'fedora' and versioncmp($::operatingsystemrelease, '7') < 0) {
$pyceph_package_name = 'python-ceph'
@ -23,8 +25,10 @@ class glance::params {
}
'Debian': {
$api_package_name = 'glance-api'
$glare_package_name = 'glance-glare'
$registry_package_name = 'glance-registry'
$api_service_name = 'glance-api'
$glare_service_name = 'glance-glare'
$registry_service_name = 'glance-registry'
$pyceph_package_name = 'python-ceph'
$sqlite_package_name = 'python-pysqlite2'

View File

@ -0,0 +1,5 @@
---
features:
- Introduce glance::glare service. Glance V3 experimental
API has been removed in Mitaka in favour of standalone
Glance Artifacts Repository (GLARE) API.

View File

@ -31,6 +31,12 @@ describe 'glance class' do
verbose => false,
keystone_password => 'a_big_secret',
}
class { '::glance::glare::db':
database_connection => 'mysql+pymysql://glance:a_big_secret@127.0.0.1/glance?charset=utf8',
}
class { '::glance::glare':
keystone_password => 'a_big_secret',
}
glance_image { 'test_image':
ensure => present,

View File

@ -0,0 +1,95 @@
require 'spec_helper'
describe 'glance::glare::db' do
shared_examples 'glance::glare::db' do
context 'with default parameters' do
it { is_expected.to contain_glance_glare_config('database/connection').with_value('sqlite:///var/lib/glance/glance.sqlite').with_secret(true) }
it { is_expected.to contain_glance_glare_config('database/idle_timeout').with_value('<SERVICE DEFAULT>') }
it { is_expected.to contain_glance_glare_config('database/min_pool_size').with_value('<SERVICE DEFAULT>') }
it { is_expected.to contain_glance_glare_config('database/max_retries').with_value('<SERVICE DEFAULT>') }
it { is_expected.to contain_glance_glare_config('database/retry_interval').with_value('<SERVICE DEFAULT>') }
it { is_expected.to contain_glance_glare_config('database/max_pool_size').with_value('<SERVICE DEFAULT>') }
it { is_expected.to contain_glance_glare_config('database/max_overflow').with_value('<SERVICE DEFAULT>') }
end
context 'with specific parameters' do
let :params do
{ :database_connection => 'mysql+pymysql://glance_glare:glance@localhost/glance',
:database_idle_timeout => '3601',
:database_min_pool_size => '2',
:database_max_retries => '11',
:database_retry_interval => '11',
:database_max_pool_size => '11',
:database_max_overflow => '21',
}
end
it { is_expected.to contain_glance_glare_config('database/connection').with_value('mysql+pymysql://glance_glare:glance@localhost/glance').with_secret(true) }
it { is_expected.to contain_glance_glare_config('database/idle_timeout').with_value('3601') }
it { is_expected.to contain_glance_glare_config('database/min_pool_size').with_value('2') }
it { is_expected.to contain_glance_glare_config('database/max_retries').with_value('11') }
it { is_expected.to contain_glance_glare_config('database/retry_interval').with_value('11') }
it { is_expected.to contain_glance_glare_config('database/max_pool_size').with_value('11') }
it { is_expected.to contain_glance_glare_config('database/max_overflow').with_value('21') }
end
context 'with MySQL-python library as backend package' do
let :params do
{ :database_connection => 'mysql://glance_glare:glance@localhost/glance' }
end
it { is_expected.to contain_package('python-mysqldb').with(:ensure => 'present') }
end
context 'with incorrect pymysql database_connection string' do
let :params do
{ :database_connection => 'foo+pymysql://glance_glare:glance@localhost/glance', }
end
it_raises 'a Puppet::Error', /validate_re/
end
end
shared_examples_for 'glance::glare::db Debian' do
context 'using pymysql driver' do
let :params do
{ :database_connection => 'mysql+pymysql://glance_glare:glance@localhost/glance', }
end
it 'install the proper backend package' do
is_expected.to contain_package('glance-backend-package').with(
:ensure => 'present',
:name => 'python-pymysql',
:tag => 'openstack'
)
end
end
end
shared_examples_for 'glance::glare::db RedHat' do
context 'using pymysql driver' do
let :params do
{ :database_connection => 'mysql+pymysql://glance_glare:glance@localhost/glance', }
end
it { is_expected.not_to contain_package('glance-backend-package') }
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
it_configures 'glance::glare::db'
it_configures "glance::glare::db #{facts[:osfamily]}"
end
end
end

View File

@ -0,0 +1,142 @@
require 'spec_helper'
describe 'glance::glare::logging' do
let :params do
{
}
end
let :log_params do
{
:logging_context_format_string => '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s',
:logging_default_format_string => '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s',
:logging_debug_format_suffix => '%(funcName)s %(pathname)s:%(lineno)d',
:logging_exception_prefix => '%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s',
:log_config_append => '/etc/glance/logging.conf',
:publish_errors => true,
:default_log_levels => {
'amqp' => 'WARN', 'amqplib' => 'WARN', 'boto' => 'WARN',
'qpid' => 'WARN', 'sqlalchemy' => 'WARN', 'suds' => 'INFO',
'iso8601' => 'WARN',
'requests.packages.urllib3.connectionpool' => 'WARN' },
:fatal_deprecations => true,
:instance_format => '[instance: %(uuid)s] ',
:instance_uuid_format => '[instance: %(uuid)s] ',
:log_date_format => '%Y-%m-%d %H:%M:%S',
:use_syslog => true,
:use_stderr => false,
:log_facility => 'LOG_FOO',
:log_dir => '/var/log',
:log_file => '/var/tmp/glance_glare_random.log',
:verbose => true,
:debug => true,
}
end
shared_examples_for 'glance-glare-logging' do
context 'with basic logging options and default settings' do
it_configures 'basic default logging settings'
end
context 'with basic logging options and non-default settings' do
before { params.merge!( log_params ) }
it_configures 'basic non-default logging settings'
end
context 'with extended logging options' do
before { params.merge!( log_params ) }
it_configures 'logging params set'
end
context 'without extended logging options' do
it_configures 'logging params unset'
end
end
shared_examples 'basic default logging settings' do
it 'configures glance logging settins with default values' do
is_expected.to contain_glance_glare_config('DEFAULT/use_syslog').with(:value => '<SERVICE DEFAULT>')
is_expected.to contain_glance_glare_config('DEFAULT/use_stderr').with(:value => '<SERVICE DEFAULT>')
is_expected.to contain_glance_glare_config('DEFAULT/log_dir').with(:value => '/var/log/glance')
is_expected.to contain_glance_glare_config('DEFAULT/log_file').with(:value => '/var/log/glance/glare.log')
is_expected.to contain_glance_glare_config('DEFAULT/verbose').with(:value => '<SERVICE DEFAULT>')
is_expected.to contain_glance_glare_config('DEFAULT/debug').with(:value => '<SERVICE DEFAULT>')
end
end
shared_examples 'basic non-default logging settings' do
it 'configures glance logging settins with non-default values' do
is_expected.to contain_glance_glare_config('DEFAULT/use_syslog').with(:value => 'true')
is_expected.to contain_glance_glare_config('DEFAULT/use_stderr').with(:value => 'false')
is_expected.to contain_glance_glare_config('DEFAULT/syslog_log_facility').with(:value => 'LOG_FOO')
is_expected.to contain_glance_glare_config('DEFAULT/log_dir').with(:value => '/var/log')
is_expected.to contain_glance_glare_config('DEFAULT/log_file').with(:value => '/var/tmp/glance_glare_random.log')
is_expected.to contain_glance_glare_config('DEFAULT/verbose').with(:value => 'true')
is_expected.to contain_glance_glare_config('DEFAULT/debug').with(:value => 'true')
end
end
shared_examples_for 'logging params set' do
it 'enables logging params' do
is_expected.to contain_glance_glare_config('DEFAULT/logging_context_format_string').with_value(
'%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s')
is_expected.to contain_glance_glare_config('DEFAULT/logging_default_format_string').with_value(
'%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s')
is_expected.to contain_glance_glare_config('DEFAULT/logging_debug_format_suffix').with_value(
'%(funcName)s %(pathname)s:%(lineno)d')
is_expected.to contain_glance_glare_config('DEFAULT/logging_exception_prefix').with_value(
'%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s')
is_expected.to contain_glance_glare_config('DEFAULT/log_config_append').with_value(
'/etc/glance/logging.conf')
is_expected.to contain_glance_glare_config('DEFAULT/publish_errors').with_value(
true)
is_expected.to contain_glance_glare_config('DEFAULT/default_log_levels').with_value(
'amqp=WARN,amqplib=WARN,boto=WARN,iso8601=WARN,qpid=WARN,requests.packages.urllib3.connectionpool=WARN,sqlalchemy=WARN,suds=INFO')
is_expected.to contain_glance_glare_config('DEFAULT/fatal_deprecations').with_value(
true)
is_expected.to contain_glance_glare_config('DEFAULT/instance_format').with_value(
'[instance: %(uuid)s] ')
is_expected.to contain_glance_glare_config('DEFAULT/instance_uuid_format').with_value(
'[instance: %(uuid)s] ')
is_expected.to contain_glance_glare_config('DEFAULT/log_date_format').with_value(
'%Y-%m-%d %H:%M:%S')
end
end
shared_examples_for 'logging params unset' do
[ :logging_context_format_string, :logging_default_format_string,
:logging_debug_format_suffix, :logging_exception_prefix,
:log_config_append, :publish_errors,
:default_log_levels, :fatal_deprecations,
:instance_format, :instance_uuid_format,
:log_date_format, ].each { |param|
it { is_expected.to contain_glance_glare_config("DEFAULT/#{param}").with_value('<SERVICE DEFAULT>') }
}
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
it_configures 'glance-glare-logging'
end
end
end

View File

@ -0,0 +1,295 @@
require 'spec_helper'
describe 'glance::glare' do
let :default_params do
{
:bind_host => '0.0.0.0',
:bind_port => '9494',
:auth_type => 'keystone',
:auth_region => '<SERVICE DEFAULT>',
:enabled => true,
:manage_service => true,
:backlog => '4096',
:workers => '7',
:keystone_tenant => 'services',
:keystone_user => 'glance',
:keystone_password => 'ChangeMe',
:token_cache_time => '<SERVICE DEFAULT>',
:memcached_servers => '<SERVICE DEFAULT>',
:stores => false,
:default_store => false,
:os_region_name => 'RegionOne',
:signing_dir => '<SERVICE DEFAULT>',
:pipeline => 'keystone',
:auth_uri => 'http://127.0.0.1:5000/',
:identity_uri => 'http://127.0.0.1:35357/',
}
end
shared_examples_for 'glance::glare' do
[
{
:bind_host => '127.0.0.1',
:bind_port => '9222',
:auth_type => 'not_keystone',
:auth_region => 'RegionOne2',
:enabled => false,
:backlog => '4095',
:workers => '5',
:keystone_tenant => 'admin2',
:keystone_user => 'admin2',
:keystone_password => 'ChangeMe2',
:token_cache_time => '300',
:os_region_name => 'RegionOne2',
:signing_dir => '/path/to/dir',
:pipeline => 'keystone2',
:auth_uri => 'http://127.0.0.1:5000/v2.0',
:identity_uri => 'http://127.0.0.1:35357/v2.0',
}
].each do |param_set|
describe "when #{param_set == {:keystone_password => 'ChangeMe'} ? "using default" : "specifying"} class parameters" do
let :param_hash do
default_params.merge(param_set)
end
let :params do
param_set
end
it { is_expected.to contain_class 'glance' }
it { is_expected.to contain_class 'glance::policy' }
it { is_expected.to contain_class 'glance::glare::logging' }
it { is_expected.to contain_class 'glance::glare::db' }
it { is_expected.to contain_service('glance-glare').with(
'ensure' => (param_hash[:manage_service] && param_hash[:enabled]) ? 'running': 'stopped',
'enable' => param_hash[:enabled],
'hasstatus' => true,
'hasrestart' => true,
'tag' => 'glance-service',
) }
it { is_expected.to contain_glance_glare_config("paste_deploy/flavor").with_value(param_hash[:pipeline]) }
it 'is_expected.to lay down default glare config' do
[
'bind_host',
'bind_port',
'auth_region'
].each do |config|
is_expected.to contain_glance_glare_config("DEFAULT/#{config}").with_value(param_hash[config.intern])
end
end
it 'is_expected.to lay down default glance_store glare and cache config' do
[
'os_region_name',
].each do |config|
is_expected.to contain_glance_glare_config("glance_store/#{config}").with_value(param_hash[config.intern])
end
end
it 'is_expected.to have no ssl options' do
is_expected.to contain_glance_glare_config('DEFAULT/ca_file').with_value('<SERVICE DEFAULT>')
is_expected.to contain_glance_glare_config('DEFAULT/cert_file').with_value('<SERVICE DEFAULT>')
is_expected.to contain_glance_glare_config('DEFAULT/key_file').with_value('<SERVICE DEFAULT>')
end
it 'is_expected.to configure itself for keystone if that is the auth_type' do
if params[:auth_type] == 'keystone'
is_expected.to contain('paste_deploy/flavor').with_value('keystone+cachemanagement')
is_expected.to contain_glance_glare_config('keystone_authtoken/memcached_servers').with_value(param_hash[:memcached_servers])
['admin_tenant_name', 'admin_user', 'admin_password', 'token_cache_time', 'signing_dir', 'auth_uri', 'identity_uri'].each do |config|
is_expected.to contain_glance_glare_config("keystone_authtoken/#{config}").with_value(param_hash[config.intern])
end
is_expected.to contain_glance_glare_config('keystone_authtoken/admin_password').with_value(param_hash[:keystone_password]).with_secret(true)
end
end
end
end
describe 'with disabled service managing' do
let :params do
{
:keystone_password => 'ChangeMe',
:manage_service => false,
:enabled => false,
}
end
it { is_expected.to contain_service('glance-glare').with(
'ensure' => nil,
'enable' => false,
'hasstatus' => true,
'hasrestart' => true,
'tag' => 'glance-service',
) }
end
describe 'with overridden pipeline' do
let :params do
{
:keystone_password => 'ChangeMe',
:pipeline => 'something',
}
end
it { is_expected.to contain_glance_glare_config('paste_deploy/flavor').with_value('something') }
end
describe 'with blank pipeline' do
let :params do
{
:keystone_password => 'ChangeMe',
:pipeline => '',
}
end
it { is_expected.to contain_glance_glare_config('paste_deploy/flavor').with_ensure('absent') }
end
[
'keystone/',
'keystone+',
'+keystone',
'keystone+cachemanagement+',
'+'
].each do |pipeline|
describe "with pipeline incorrect value #{pipeline}" do
let :params do
{
:keystone_password => 'ChangeMe',
:pipeline => pipeline
}
end
it { expect { is_expected.to contain_glance_glare_config('filter:paste_deploy/flavor') }.to\
raise_error(Puppet::Error, /validate_re\(\): .* does not match/) }
end
end
describe 'with ssl options' do
let :params do
default_params.merge({
:ca_file => '/tmp/ca_file',
:cert_file => '/tmp/cert_file',
:key_file => '/tmp/key_file',
})
end
context 'with ssl options' do
it { is_expected.to contain_glance_glare_config('DEFAULT/ca_file').with_value('/tmp/ca_file') }
it { is_expected.to contain_glance_glare_config('DEFAULT/cert_file').with_value('/tmp/cert_file') }
it { is_expected.to contain_glance_glare_config('DEFAULT/key_file').with_value('/tmp/key_file') }
end
end
describe 'with stores by default' do
let :params do
default_params
end
it { is_expected.to_not contain_glance_glare_config('glance_store/stores').with_value('false') }
end
describe 'with stores override' do
let :params do
default_params.merge({
:default_store => 'glance.store.filesystem.Store',
:stores => ['glance.store.filesystem.Store','glance.store.http.Store'],
:multi_store => true,
})
end
it { is_expected.to contain_glance_glare_config('glance_store/default_store').with_value('glance.store.filesystem.Store') }
it { is_expected.to contain_glance_glare_config('glance_store/stores').with_value('glance.store.filesystem.Store,glance.store.http.Store') }
end
describe 'with single store override and no default store' do
let :params do
default_params.merge({
:stores => ['glance.store.filesystem.Store'],
:multi_store => true,
})
end
it { is_expected.to contain_glance_glare_config('glance_store/default_store').with_value('glance.store.filesystem.Store') }
it { is_expected.to contain_glance_glare_config('glance_store/stores').with_value('glance.store.filesystem.Store') }
end
describe 'with multiple stores override and no default store' do
let :params do
default_params.merge({
:stores => ['glance.store.filesystem.Store', 'glance.store.http.Store'],
:multi_store => true,
})
end
it { is_expected.to contain_glance_glare_config('glance_store/default_store').with_value('glance.store.filesystem.Store') }
it { is_expected.to contain_glance_glare_config('glance_store/stores').with_value('glance.store.filesystem.Store,glance.store.http.Store') }
end
describe 'with wrong format of stores provided' do
let :params do
default_params.merge({
:stores => 'glance.store.filesystem.Store',
})
end
it { is_expected.to raise_error(Puppet::Error, /is not an Array/) }
end
describe 'with known_stores not set but with default_store' do
let :params do
default_params.merge({
:default_store => 'glance.store.filesystem.Store',
:multi_store => true,
})
end
it { is_expected.to contain_glance_glare_config('glance_store/default_store').with_value('glance.store.filesystem.Store') }
it { is_expected.to contain_glance_glare_config('glance_store/stores').with_value('glance.store.filesystem.Store') }
end
end
shared_examples_for 'glance::glare Debian' do
let(:params) { default_params }
# We only test this on Debian platforms, since on RedHat there isn't a
# separate package for glance GLARE.
['present', 'latest'].each do |package_ensure|
context "with package_ensure '#{package_ensure}'" do
let(:params) { default_params.merge({ :package_ensure => package_ensure }) }
it { is_expected.to contain_package('glance-glare').with(
:ensure => package_ensure,
:tag => ['openstack', 'glance-package']
)}
end
end
end
shared_examples_for 'glance::glare RedHat' do
let(:params) { default_params }
it { is_expected.to contain_package('openstack-glance').with(
:tag => ['openstack', 'glance-package'],
)}
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
it_configures 'glance::glare'
it_configures "glance::glare #{facts[:osfamily]}"
end
end
end

View File

@ -0,0 +1,71 @@
$LOAD_PATH.push(
File.join(
File.dirname(__FILE__),
'..',
'..',
'..',
'fixtures',
'modules',
'inifile',
'lib')
)
$LOAD_PATH.push(
File.join(
File.dirname(__FILE__),
'..',
'..',
'..',
'fixtures',
'modules',
'openstacklib',
'lib')
)
require 'spec_helper'
provider_class = Puppet::Type.type(:glance_glare_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::Glance_glare_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::Glance_glare_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::Glance_glare_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::Glance_glare_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

@ -0,0 +1,63 @@
$LOAD_PATH.push(
File.join(
File.dirname(__FILE__),
'..',
'..',
'..',
'fixtures',
'modules',
'inifile',
'lib')
)
$LOAD_PATH.push(
File.join(
File.dirname(__FILE__),
'..',
'..',
'..',
'fixtures',
'modules',
'openstacklib',
'lib')
)
require 'spec_helper'
provider_class = Puppet::Type.type(:glance_glare_paste_ini).provider(:ini_setting)
describe provider_class do
it 'should default to the default setting when no other one is specified' do
resource = Puppet::Type::Glance_glare_paste_ini.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::Glance_glare_paste_ini.new(
{:name => 'dude/whoa', :value => 'bar'}
)
provider = provider_class.new(resource)
expect(provider.section).to eq('dude')
expect(provider.setting).to eq('whoa')
end
it 'should ensure absent when <SERVICE DEFAULT> is specified as a value' do
resource = Puppet::Type::Glance_glare_paste_ini.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::Glance_glare_paste_ini.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

@ -0,0 +1,41 @@
require 'puppet'
require 'puppet/type/glance_glare_config'
describe 'Puppet::Type.type(:glance_glare_config)' do
before :each do
Puppet::Type.rmtype(:glance_glare_config)
Facter.fact(:osfamily).stubs(:value).returns(platform_params[:osfamily])
@glance_glare_config = Puppet::Type.type(:glance_glare_config).new(:name => 'DEFAULT/foo', :value => 'bar')
end
shared_examples_for 'glance_glare_config' do
it 'should autorequire the package that install the file' do
catalog = Puppet::Resource::Catalog.new
package = Puppet::Type.type(:package).new(:name => platform_params[:package_name])
catalog.add_resource package, @glance_glare_config
dependency = @glance_glare_config.autorequire
expect(dependency.size).to eq(1)
expect(dependency[0].target).to eq(@glance_glare_config)
expect(dependency[0].source).to eq(package)
end
end
context 'on Debian platforms' do
let :platform_params do
{ :package_name => 'glance-glare',
:osfamily => 'Debian' }
end
it_behaves_like 'glance_glare_config'
end
context 'on RedHat platforms' do
let :platform_params do
{ :package_name => 'openstack-glance',
:osfamily => 'RedHat'}
end
it_behaves_like 'glance_glare_config'
end
end

View File

@ -0,0 +1,87 @@
require 'puppet'
require 'puppet/type/glance_glare_paste_ini'
describe 'Puppet::Type.type(:glance_glare_paste_ini)' do
before :each do
Puppet::Type.rmtype(:glance_glare_paste_ini)
Facter.fact(:osfamily).stubs(:value).returns(platform_params[:osfamily])
@glance_glare_paste_ini = Puppet::Type.type(:glance_glare_paste_ini).new(:name => 'DEFAULT/foo', :value => 'bar')
end
shared_examples_for 'glance_glare_paste_ini' do
it 'should require a name' do
expect {
Puppet::Type.type(:glance_glare_paste_ini).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(:glance_glare_paste_ini).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(:glance_glare_paste_ini).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(:glance_glare_paste_ini).new(:name => 'DEFAULT/foo', :ensure => :absent)
end
it 'should accept a valid value' do
@glance_glare_paste_ini[:value] = 'bar'
expect(@glance_glare_paste_ini[:value]).to eq('bar')
end
it 'should not accept a value with whitespace' do
@glance_glare_paste_ini[:value] = 'b ar'
expect(@glance_glare_paste_ini[:value]).to eq('b ar')
end
it 'should accept valid ensure values' do
@glance_glare_paste_ini[:ensure] = :present
expect(@glance_glare_paste_ini[:ensure]).to eq(:present)
@glance_glare_paste_ini[:ensure] = :absent
expect(@glance_glare_paste_ini[:ensure]).to eq(:absent)
end
it 'should not accept invalid ensure values' do
expect {
@glance_glare_paste_ini[:ensure] = :latest
}.to raise_error(Puppet::Error, /Invalid value/)
end
it 'should autorequire the package that install the file' do
catalog = Puppet::Resource::Catalog.new
package = Puppet::Type.type(:package).new(:name => platform_params[:package_name])
catalog.add_resource package, @glance_glare_paste_ini
dependency = @glance_glare_paste_ini.autorequire
expect(dependency.size).to eq(1)
expect(dependency[0].target).to eq(@glance_glare_paste_ini)
expect(dependency[0].source).to eq(package)
end
end
context 'on Debian platforms' do
let :platform_params do
{ :package_name => 'glance-glare',
:osfamily => 'Debian' }
end
it_behaves_like 'glance_glare_paste_ini'
end
context 'on RedHat platforms' do
let :platform_params do
{ :package_name => 'openstack-glance',
:osfamily => 'RedHat'}
end
it_behaves_like 'glance_glare_paste_ini'
end
end