From da8a3aa022b5f44783589b3b1762dccba2610d87 Mon Sep 17 00:00:00 2001 From: Denis Egorenko Date: Wed, 16 Mar 2016 18:46:32 +0300 Subject: [PATCH] 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 --- .../glance_glare_config/ini_setting.rb | 10 + .../glance_glare_paste_ini/ini_setting.rb | 10 + lib/puppet/type/glance_glare_config.rb | 57 ++++ lib/puppet/type/glance_glare_paste_ini.rb | 56 ++++ manifests/glare.pp | 262 ++++++++++++++++ manifests/glare/db.pp | 91 ++++++ manifests/glare/logging.pp | 145 +++++++++ manifests/params.pp | 4 + ...glance_glare_service-2cd8231e1e7d097b.yaml | 5 + spec/acceptance/basic_glance_spec.rb | 6 + spec/classes/glance_glare_db_spec.rb | 95 ++++++ spec/classes/glance_glare_logging_spec.rb | 142 +++++++++ spec/classes/glance_glare_spec.rb | 295 ++++++++++++++++++ .../glance_glare_config/ini_setting_spec.rb | 71 +++++ .../ini_setting_spec.rb | 63 ++++ spec/unit/type/glance_glare_config_spec.rb | 41 +++ spec/unit/type/glance_glare_paste_ini_spec.rb | 87 ++++++ 17 files changed, 1440 insertions(+) create mode 100644 lib/puppet/provider/glance_glare_config/ini_setting.rb create mode 100644 lib/puppet/provider/glance_glare_paste_ini/ini_setting.rb create mode 100644 lib/puppet/type/glance_glare_config.rb create mode 100644 lib/puppet/type/glance_glare_paste_ini.rb create mode 100644 manifests/glare.pp create mode 100644 manifests/glare/db.pp create mode 100644 manifests/glare/logging.pp create mode 100644 releasenotes/notes/glance_glare_service-2cd8231e1e7d097b.yaml create mode 100644 spec/classes/glance_glare_db_spec.rb create mode 100644 spec/classes/glance_glare_logging_spec.rb create mode 100644 spec/classes/glance_glare_spec.rb create mode 100644 spec/unit/provider/glance_glare_config/ini_setting_spec.rb create mode 100644 spec/unit/provider/glance_glare_paste_ini/ini_setting_spec.rb create mode 100644 spec/unit/type/glance_glare_config_spec.rb create mode 100644 spec/unit/type/glance_glare_paste_ini_spec.rb diff --git a/lib/puppet/provider/glance_glare_config/ini_setting.rb b/lib/puppet/provider/glance_glare_config/ini_setting.rb new file mode 100644 index 00000000..5d8d2458 --- /dev/null +++ b/lib/puppet/provider/glance_glare_config/ini_setting.rb @@ -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 diff --git a/lib/puppet/provider/glance_glare_paste_ini/ini_setting.rb b/lib/puppet/provider/glance_glare_paste_ini/ini_setting.rb new file mode 100644 index 00000000..e32e9cfd --- /dev/null +++ b/lib/puppet/provider/glance_glare_paste_ini/ini_setting.rb @@ -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 diff --git a/lib/puppet/type/glance_glare_config.rb b/lib/puppet/type/glance_glare_config.rb new file mode 100644 index 00000000..b4a1593d --- /dev/null +++ b/lib/puppet/type/glance_glare_config.rb @@ -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('') + end + + autorequire(:package) do + if Facter.value(:osfamily) == 'Debian' + 'glance-glare' + elsif Facter.value(:osfamily) == 'RedHat' + 'openstack-glance' + end + end + +end diff --git a/lib/puppet/type/glance_glare_paste_ini.rb b/lib/puppet/type/glance_glare_paste_ini.rb new file mode 100644 index 00000000..8e96ead7 --- /dev/null +++ b/lib/puppet/type/glance_glare_paste_ini.rb @@ -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('') + end + + autorequire(:package) do + if Facter.value(:osfamily) == 'Debian' + 'glance-glare' + elsif Facter.value(:osfamily) == 'RedHat' + 'openstack-glance' + end + end + +end diff --git a/manifests/glare.pp b/manifests/glare.pp new file mode 100644 index 00000000..a74f758c --- /dev/null +++ b/manifests/glare.pp @@ -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', + } +} diff --git a/manifests/glare/db.pp b/manifests/glare/db.pp new file mode 100644 index 00000000..053ce435 --- /dev/null +++ b/manifests/glare/db.pp @@ -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; + } + +} diff --git a/manifests/glare/logging.pp b/manifests/glare/logging.pp new file mode 100644 index 00000000..2858cb67 --- /dev/null +++ b/manifests/glare/logging.pp @@ -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; + } + +} diff --git a/manifests/params.pp b/manifests/params.pp index 08f56329..4cdbdabf 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -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' diff --git a/releasenotes/notes/glance_glare_service-2cd8231e1e7d097b.yaml b/releasenotes/notes/glance_glare_service-2cd8231e1e7d097b.yaml new file mode 100644 index 00000000..550e7c0a --- /dev/null +++ b/releasenotes/notes/glance_glare_service-2cd8231e1e7d097b.yaml @@ -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. diff --git a/spec/acceptance/basic_glance_spec.rb b/spec/acceptance/basic_glance_spec.rb index fc0a03f5..eb3f620c 100644 --- a/spec/acceptance/basic_glance_spec.rb +++ b/spec/acceptance/basic_glance_spec.rb @@ -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, diff --git a/spec/classes/glance_glare_db_spec.rb b/spec/classes/glance_glare_db_spec.rb new file mode 100644 index 00000000..20f157cc --- /dev/null +++ b/spec/classes/glance_glare_db_spec.rb @@ -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('') } + it { is_expected.to contain_glance_glare_config('database/min_pool_size').with_value('') } + it { is_expected.to contain_glance_glare_config('database/max_retries').with_value('') } + it { is_expected.to contain_glance_glare_config('database/retry_interval').with_value('') } + it { is_expected.to contain_glance_glare_config('database/max_pool_size').with_value('') } + it { is_expected.to contain_glance_glare_config('database/max_overflow').with_value('') } + 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 + diff --git a/spec/classes/glance_glare_logging_spec.rb b/spec/classes/glance_glare_logging_spec.rb new file mode 100644 index 00000000..1bb569e2 --- /dev/null +++ b/spec/classes/glance_glare_logging_spec.rb @@ -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 => '') + is_expected.to contain_glance_glare_config('DEFAULT/use_stderr').with(:value => '') + 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 => '') + is_expected.to contain_glance_glare_config('DEFAULT/debug').with(:value => '') + 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('') } + } + 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 diff --git a/spec/classes/glance_glare_spec.rb b/spec/classes/glance_glare_spec.rb new file mode 100644 index 00000000..97d6c783 --- /dev/null +++ b/spec/classes/glance_glare_spec.rb @@ -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 => '', + :enabled => true, + :manage_service => true, + :backlog => '4096', + :workers => '7', + :keystone_tenant => 'services', + :keystone_user => 'glance', + :keystone_password => 'ChangeMe', + :token_cache_time => '', + :memcached_servers => '', + :stores => false, + :default_store => false, + :os_region_name => 'RegionOne', + :signing_dir => '', + :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('') + is_expected.to contain_glance_glare_config('DEFAULT/cert_file').with_value('') + is_expected.to contain_glance_glare_config('DEFAULT/key_file').with_value('') + 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 diff --git a/spec/unit/provider/glance_glare_config/ini_setting_spec.rb b/spec/unit/provider/glance_glare_config/ini_setting_spec.rb new file mode 100644 index 00000000..78ef6f0a --- /dev/null +++ b/spec/unit/provider/glance_glare_config/ini_setting_spec.rb @@ -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 is specified as a value' do + resource = Puppet::Type::Glance_glare_config.new( + {:name => 'dude/foo', :value => ''} + ) + 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 diff --git a/spec/unit/provider/glance_glare_paste_ini/ini_setting_spec.rb b/spec/unit/provider/glance_glare_paste_ini/ini_setting_spec.rb new file mode 100644 index 00000000..f817a01e --- /dev/null +++ b/spec/unit/provider/glance_glare_paste_ini/ini_setting_spec.rb @@ -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 is specified as a value' do + resource = Puppet::Type::Glance_glare_paste_ini.new( + {:name => 'dude/foo', :value => ''} + ) + 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 diff --git a/spec/unit/type/glance_glare_config_spec.rb b/spec/unit/type/glance_glare_config_spec.rb new file mode 100644 index 00000000..157e1b40 --- /dev/null +++ b/spec/unit/type/glance_glare_config_spec.rb @@ -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 diff --git a/spec/unit/type/glance_glare_paste_ini_spec.rb b/spec/unit/type/glance_glare_paste_ini_spec.rb new file mode 100644 index 00000000..c24448c5 --- /dev/null +++ b/spec/unit/type/glance_glare_paste_ini_spec.rb @@ -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