Add a new custom matcher render_config_file to test ini file content
After this, you can use below way to test ini file content: render_config_file(file).with_section_content(section, content) Change-Id: Iaed80a3fc61db02324fb2c8166b7032fd1823f60
This commit is contained in:
parent
47ba1660b9
commit
d99aacda7c
|
@ -11,6 +11,7 @@ This file is used to list changes made in each version of cookbook-openstack-com
|
||||||
* Add OS_VOLUME_API_VERSION for openrc
|
* Add OS_VOLUME_API_VERSION for openrc
|
||||||
* Removed the hardcoded PPA reference to "Precise"
|
* Removed the hardcoded PPA reference to "Precise"
|
||||||
* Added an optional automatic apt-get update for Debian based repos
|
* Added an optional automatic apt-get update for Debian based repos
|
||||||
|
* Add a new custom matcher render_config_file to test ini file content
|
||||||
|
|
||||||
## 10.1.0
|
## 10.1.0
|
||||||
* Adding identity admin bind host endpoint to allow flexibility and consistency
|
* Adding identity admin bind host endpoint to allow flexibility and consistency
|
||||||
|
|
|
@ -121,6 +121,7 @@ This cookbook exposes a set of default library routines:
|
||||||
* `db_create_with_user` -- Creates a database and database user for a named OpenStack database
|
* `db_create_with_user` -- Creates a database and database user for a named OpenStack database
|
||||||
* `secret` -- Returns the value of an encrypted data bag for a named OpenStack secret key and key-section
|
* `secret` -- Returns the value of an encrypted data bag for a named OpenStack secret key and key-section
|
||||||
* `get_password` -- Ease-of-use helper that returns the decrypted password for a named database, service or keystone user.
|
* `get_password` -- Ease-of-use helper that returns the decrypted password for a named database, service or keystone user.
|
||||||
|
* `matchers` -- A custom matcher(render_config_file) for testing ini format file section content by with_section_content.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
# encoding: UTF-8
|
||||||
|
|
||||||
|
if defined?(ChefSpec)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test method for ini format file
|
||||||
|
#
|
||||||
|
# Example file content:
|
||||||
|
#
|
||||||
|
# [section1]
|
||||||
|
# option1 = value1
|
||||||
|
# option2 = value2
|
||||||
|
# [section2]
|
||||||
|
# option1 = value2
|
||||||
|
#
|
||||||
|
# Example custom matcher that can be called in other
|
||||||
|
# dependends cookbooks.
|
||||||
|
#
|
||||||
|
# render_config_file(path).with_section_content(
|
||||||
|
# 'section1', 'option1 = value1')
|
||||||
|
# render_config_file(path).with_section_content(
|
||||||
|
# 'section1', /^option2 = value2$/)
|
||||||
|
#
|
||||||
|
def render_config_file(path)
|
||||||
|
RenderConfigFileMatcher.new(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Extend the RenderFileMatcher as RenderConfigFileMatcher,
|
||||||
|
# add a new method with_section_content for ini format file.
|
||||||
|
#
|
||||||
|
class RenderConfigFileMatcher < ChefSpec::Matchers::RenderFileMatcher
|
||||||
|
def with_section_content(section, expected_content)
|
||||||
|
@section = section
|
||||||
|
@expected_content = expected_content
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
# rubocop:disable MethodLength, CyclomaticComplexity
|
||||||
|
def matches_content?
|
||||||
|
def section?(line, section = '.*')
|
||||||
|
if line =~ /^[ \t]*\[#{section}\]/
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_section_content(content, section)
|
||||||
|
match = false
|
||||||
|
section_content = ''
|
||||||
|
content.split("\n").each do |line|
|
||||||
|
if section?(line, section)
|
||||||
|
match = true
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
section_content << "#{line}\n" if match == true && !section?(line)
|
||||||
|
|
||||||
|
break if match == true && section?(line)
|
||||||
|
end
|
||||||
|
section_content
|
||||||
|
end
|
||||||
|
|
||||||
|
return true if @expected_content.nil?
|
||||||
|
|
||||||
|
@actual_content = ChefSpec::Renderer.new(@runner, resource).content
|
||||||
|
|
||||||
|
unless @actual_content.nil?
|
||||||
|
unless @section.nil?
|
||||||
|
@actual_content = get_section_content(@actual_content, @section)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false if @actual_content.nil?
|
||||||
|
|
||||||
|
if @expected_content.is_a?(Regexp)
|
||||||
|
@actual_content =~ @expected_content
|
||||||
|
elsif RSpec::Matchers.is_a_matcher?(@expected_content)
|
||||||
|
@expected_content.matches?(@actual_content)
|
||||||
|
else
|
||||||
|
@actual_content.include?(@expected_content)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# rubocop:enable MethodLength, CyclomaticComplexity
|
||||||
|
end
|
||||||
|
end
|
|
@ -18,5 +18,6 @@ end
|
||||||
|
|
||||||
depends 'apt', '>= 2.3.8'
|
depends 'apt', '>= 2.3.8'
|
||||||
depends 'database', '>= 2.0.0'
|
depends 'database', '>= 2.0.0'
|
||||||
|
depends 'mysql', '< 6.0.0'
|
||||||
depends 'yum', '>= 3.1.4'
|
depends 'yum', '>= 3.1.4'
|
||||||
depends 'yum-epel', '>= 0.3.4'
|
depends 'yum-epel', '>= 0.3.4'
|
||||||
|
|
|
@ -46,155 +46,200 @@ describe 'openstack-common::logging' do
|
||||||
'ignore.key.1' => 'ignore.value.1',
|
'ignore.key.1' => 'ignore.value.1',
|
||||||
'ignore.key.2' => 'ignore.value.2'
|
'ignore.key.2' => 'ignore.value.2'
|
||||||
}
|
}
|
||||||
[
|
expect(chef_run).to render_config_file(file.name)
|
||||||
/^\[loggers\]$/,
|
.with_section_content('loggers', /^keys=.*ignore_key_1,ignore_key_2$/)
|
||||||
/^keys=.*ignore_key_1,ignore_key_2$/
|
|
||||||
].each do |content|
|
|
||||||
expect(chef_run).to render_file(file.name).with_content(content)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'adds specific logger ignore block' do
|
it 'adds specific logger ignore block' do
|
||||||
node.set['openstack']['logging']['ignore'] = {
|
node.set['openstack']['logging']['ignore'] = {
|
||||||
'test.nova.api.openstack.wsgi' => 'WARNING'
|
'test.nova.api.openstack.wsgi' => 'WARNING'
|
||||||
}
|
}
|
||||||
content = [
|
[
|
||||||
'[logger_test_nova_api_openstack_wsgi]',
|
|
||||||
'level = WARNING',
|
'level = WARNING',
|
||||||
'handlers = prod,debug',
|
'handlers = prod,debug',
|
||||||
'qualname = test.nova.api.openstack.wsgi'
|
'qualname = test.nova.api.openstack.wsgi'
|
||||||
]
|
].each do |line|
|
||||||
expect(chef_run).to render_file(file.name).with_content(build_section(content))
|
expect(chef_run).to render_config_file(file.name)
|
||||||
|
.with_section_content('logger_test_nova_api_openstack_wsgi', line)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'loggers' do
|
context 'loggers' do
|
||||||
it 'adds default loggers' do
|
it 'adds default loggers' do
|
||||||
[
|
{
|
||||||
['[loggers]',
|
'loggers' =>
|
||||||
'keys=root,ceilometer,cinder,glance,horizon,keystone,nova,'\
|
[
|
||||||
'neutron,swift,trove,amqplib,sqlalchemy,boto,suds,eventletwsgi,'\
|
'keys=root,ceilometer,cinder,glance,horizon,keystone,nova,'\
|
||||||
'nova_api_openstack_wsgi,nova_osapi_compute_wsgi_server'],
|
'neutron,swift,trove,amqplib,sqlalchemy,boto,suds,eventletwsgi,'\
|
||||||
['[logger_root]',
|
'nova_api_openstack_wsgi,nova_osapi_compute_wsgi_server'
|
||||||
'level=NOTSET',
|
],
|
||||||
'handlers=devel'],
|
'logger_root' =>
|
||||||
['[logger_ceilometer]',
|
[
|
||||||
'level=DEBUG',
|
'level=NOTSET',
|
||||||
'handlers=prod,debug',
|
'handlers=devel'
|
||||||
'qualname=ceilometer'],
|
],
|
||||||
['[logger_cinder]',
|
'logger_ceilometer' =>
|
||||||
'level=DEBUG',
|
[
|
||||||
'handlers=prod,debug',
|
'level=DEBUG',
|
||||||
'qualname=cinder'],
|
'handlers=prod,debug',
|
||||||
['[logger_glance]',
|
'qualname=ceilometer'
|
||||||
'level=DEBUG',
|
],
|
||||||
'handlers=prod,debug',
|
'logger_cinder' =>
|
||||||
'qualname=glance'],
|
[
|
||||||
['[logger_horizon]',
|
'level=DEBUG',
|
||||||
'level=DEBUG',
|
'handlers=prod,debug',
|
||||||
'handlers=prod,debug',
|
'qualname=cinder'
|
||||||
'qualname=horizon'],
|
],
|
||||||
['[logger_keystone]',
|
'logger_glance' =>
|
||||||
'level=DEBUG',
|
[
|
||||||
'handlers=prod,debug',
|
'level=DEBUG',
|
||||||
'qualname=keystone'],
|
'handlers=prod,debug',
|
||||||
['[logger_nova]',
|
'qualname=glance'
|
||||||
'level=DEBUG',
|
],
|
||||||
'handlers=prod,debug',
|
'logger_horizon' =>
|
||||||
'qualname=nova'],
|
[
|
||||||
['[logger_neutron]',
|
'level=DEBUG',
|
||||||
'level=DEBUG',
|
'handlers=prod,debug',
|
||||||
'handlers=prod,debug',
|
'qualname=horizon'
|
||||||
'qualname=neutron'],
|
],
|
||||||
['[logger_swift]',
|
'logger_keystone' =>
|
||||||
'level=DEBUG',
|
[
|
||||||
'handlers=prod,debug',
|
'level=DEBUG',
|
||||||
'qualname=swift'],
|
'handlers=prod,debug',
|
||||||
['[logger_trove]',
|
'qualname=keystone'
|
||||||
'level=DEBUG',
|
],
|
||||||
'handlers=prod,debug',
|
'logger_nova' =>
|
||||||
'qualname=trove'],
|
[
|
||||||
['[logger_amqplib]',
|
'level=DEBUG',
|
||||||
'level=WARNING',
|
'handlers=prod,debug',
|
||||||
'handlers=stderr',
|
'qualname=nova'
|
||||||
'qualname=amqplib'],
|
],
|
||||||
['[logger_sqlalchemy]',
|
'logger_neutron' =>
|
||||||
'level=WARNING',
|
[
|
||||||
'handlers=stderr',
|
'level=DEBUG',
|
||||||
'qualname=sqlalchemy'],
|
'handlers=prod,debug',
|
||||||
['[logger_boto]',
|
'qualname=neutron'
|
||||||
'level=WARNING',
|
],
|
||||||
'handlers=stderr',
|
'logger_swift' =>
|
||||||
'qualname=boto'],
|
[
|
||||||
['[logger_suds]',
|
'level=DEBUG',
|
||||||
'level=INFO',
|
'handlers=prod,debug',
|
||||||
'handlers=stderr',
|
'qualname=swift'
|
||||||
'qualname=suds'],
|
],
|
||||||
['[logger_eventletwsgi]',
|
'logger_trove' =>
|
||||||
'level=WARNING',
|
[
|
||||||
'handlers=stderr',
|
'level=DEBUG',
|
||||||
'qualname=eventlet.wsgi.server'],
|
'handlers=prod,debug',
|
||||||
['[logger_nova_api_openstack_wsgi]',
|
'qualname=trove'
|
||||||
'level=WARNING',
|
],
|
||||||
'handlers=prod,debug',
|
'logger_amqplib' =>
|
||||||
'qualname=nova.api.openstack.wsgi'],
|
[
|
||||||
['[logger_nova_osapi_compute_wsgi_server]',
|
'level=WARNING',
|
||||||
'level=WARNING',
|
'handlers=stderr',
|
||||||
'handlers=prod,debug',
|
'qualname=amqplib'
|
||||||
'qualname=nova.osapi_compute.wsgi.server']
|
],
|
||||||
].each do |content|
|
'logger_sqlalchemy' =>
|
||||||
expect(chef_run).to render_file(file.name).with_content(build_section(content))
|
[
|
||||||
|
'level=WARNING',
|
||||||
|
'handlers=stderr',
|
||||||
|
'qualname=sqlalchemy'
|
||||||
|
],
|
||||||
|
'logger_boto' =>
|
||||||
|
[
|
||||||
|
'level=WARNING',
|
||||||
|
'handlers=stderr',
|
||||||
|
'qualname=boto'
|
||||||
|
],
|
||||||
|
'logger_suds' =>
|
||||||
|
[
|
||||||
|
'level=INFO',
|
||||||
|
'handlers=stderr',
|
||||||
|
'qualname=suds'
|
||||||
|
],
|
||||||
|
'logger_eventletwsgi' =>
|
||||||
|
[
|
||||||
|
'level=WARNING',
|
||||||
|
'handlers=stderr',
|
||||||
|
'qualname=eventlet.wsgi.server'
|
||||||
|
],
|
||||||
|
'logger_nova_api_openstack_wsgi' =>
|
||||||
|
[
|
||||||
|
'level=WARNING',
|
||||||
|
'handlers=prod,debug',
|
||||||
|
'qualname=nova.api.openstack.wsgi'
|
||||||
|
],
|
||||||
|
'logger_nova_osapi_compute_wsgi_server' =>
|
||||||
|
[
|
||||||
|
'level=WARNING',
|
||||||
|
'handlers=prod,debug',
|
||||||
|
'qualname=nova.osapi_compute.wsgi.server'
|
||||||
|
]
|
||||||
|
}.each do |section, content|
|
||||||
|
content.each do |line|
|
||||||
|
expect(chef_run).to render_config_file(file.name).with_section_content(section, line)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'formatters' do
|
context 'formatters' do
|
||||||
it 'adds default formatters' do
|
it 'adds default formatters' do
|
||||||
[
|
{
|
||||||
['[formatters]',
|
'formatters' =>
|
||||||
'keys=normal,normal_with_name,debug,syslog_with_name,syslog_debug'],
|
'keys=normal,normal_with_name,debug,syslog_with_name,syslog_debug',
|
||||||
['[formatter_normal]',
|
'formatter_normal' =>
|
||||||
'format=%(asctime)s %(levelname)s %(message)s'],
|
'format=%(asctime)s %(levelname)s %(message)s',
|
||||||
['[formatter_normal_with_name]',
|
'formatter_normal_with_name' =>
|
||||||
'format=[%(name)s]: %(asctime)s %(levelname)s %(message)s'],
|
'format=[%(name)s]: %(asctime)s %(levelname)s %(message)s',
|
||||||
['[formatter_debug]',
|
'formatter_debug' =>
|
||||||
'format=[%(name)s]: %(asctime)s %(levelname)s %(module)s.%(funcName)s %(message)s'],
|
'format=[%(name)s]: %(asctime)s %(levelname)s %(module)s.%(funcName)s %(message)s',
|
||||||
['[formatter_syslog_with_name]',
|
'formatter_syslog_with_name' =>
|
||||||
'format=%(name)s: %(levelname)s %(message)s'],
|
'format=%(name)s: %(levelname)s %(message)s',
|
||||||
['[formatter_syslog_debug]',
|
'formatter_syslog_debug' =>
|
||||||
'format=%(name)s: %(levelname)s %(module)s.%(funcName)s %(message)s']
|
'format=%(name)s: %(levelname)s %(module)s.%(funcName)s %(message)s'
|
||||||
].each do |content|
|
}.each do |section, content|
|
||||||
expect(chef_run).to render_file(file.name).with_content(build_section(content))
|
expect(chef_run).to render_config_file(file.name).with_section_content(section, content)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'handlers' do
|
context 'handlers' do
|
||||||
it 'adds default handlers' do
|
it 'adds default handlers' do
|
||||||
[
|
{
|
||||||
['[handlers]',
|
'handlers' =>
|
||||||
'keys=stderr,devel,prod,debug'],
|
['keys=stderr,devel,prod,debug'],
|
||||||
['[handler_stderr]',
|
'handler_stderr' =>
|
||||||
'args=(sys.stderr,)',
|
[
|
||||||
'class=StreamHandler',
|
'args=(sys.stderr,)',
|
||||||
'formatter=debug'],
|
'class=StreamHandler',
|
||||||
['[handler_devel]',
|
'formatter=debug'
|
||||||
'args=(sys.stdout,)',
|
],
|
||||||
'class=StreamHandler',
|
'handler_devel' =>
|
||||||
'formatter=debug',
|
[
|
||||||
'level=NOTSET'],
|
'args=(sys.stdout,)',
|
||||||
['[handler_prod]',
|
'class=StreamHandler',
|
||||||
"args=(('/dev/log'), handlers.SysLogHandler.LOG_LOCAL0)",
|
'formatter=debug',
|
||||||
'class=handlers.SysLogHandler',
|
'level=NOTSET'
|
||||||
'formatter=syslog_with_name',
|
],
|
||||||
'level=INFO'],
|
'handler_prod' =>
|
||||||
['[handler_debug]',
|
[
|
||||||
"args=(('/dev/log'), handlers.SysLogHandler.LOG_LOCAL1)",
|
"args=(('/dev/log'), handlers.SysLogHandler.LOG_LOCAL0)",
|
||||||
'class=handlers.SysLogHandler',
|
'class=handlers.SysLogHandler',
|
||||||
'formatter=syslog_debug',
|
'formatter=syslog_with_name',
|
||||||
'level=DEBUG']
|
'level=INFO'
|
||||||
].each do |content|
|
],
|
||||||
expect(chef_run).to render_file(file.name).with_content(build_section(content))
|
'handler_debug' =>
|
||||||
|
[
|
||||||
|
"args=(('/dev/log'), handlers.SysLogHandler.LOG_LOCAL1)",
|
||||||
|
'class=handlers.SysLogHandler',
|
||||||
|
'formatter=syslog_debug',
|
||||||
|
'level=DEBUG'
|
||||||
|
]
|
||||||
|
}.each do |section, content|
|
||||||
|
content.each do |line|
|
||||||
|
expect(chef_run).to render_config_file(file.name).with_section_content(section, line)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,12 +23,6 @@ SUSE_OPTS = {
|
||||||
# We set a default platform for non-platform specific test cases
|
# We set a default platform for non-platform specific test cases
|
||||||
CHEFSPEC_OPTS = UBUNTU_OPTS
|
CHEFSPEC_OPTS = UBUNTU_OPTS
|
||||||
|
|
||||||
# Build a regex for a section of lines
|
|
||||||
def build_section(lines)
|
|
||||||
lines.map! { |line| Regexp.quote(line) }
|
|
||||||
/^#{lines.join('\n')}/
|
|
||||||
end
|
|
||||||
|
|
||||||
shared_context 'library-stubs' do
|
shared_context 'library-stubs' do
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:node).and_return(chef_run.node)
|
allow(subject).to receive(:node).and_return(chef_run.node)
|
||||||
|
|
Loading…
Reference in New Issue