From ac03904702ebf183330490f9926d18c4317b6d75 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Fri, 12 Feb 2016 18:32:27 +0100 Subject: [PATCH] [inspector] create a separate database configuration for ironic-inspector This service has a separate database that can be configured. This patch is essentially a copy-paste from ironic::db. Change-Id: Ib4d3548e76a9314592d8b66707df1987d7cfc5b9 --- manifests/db/inspector_sync.pp | 21 +-- manifests/inspector.pp | 8 +- manifests/inspector/db.pp | 63 ++++++++ manifests/inspector/db/mysql.pp | 69 +++++++++ manifests/inspector/db/postgresql.pp | 47 ++++++ manifests/inspector/db/sync.pp | 22 +++ .../notes/inspector-db-ddfdc7d17628f969.yaml | 7 + spec/acceptance/ironic_wsgi_apache_spec.rb | 4 + spec/classes/inspector_db_sync_spec.rb | 44 ------ .../classes/ironic_inspector_db_mysql_spec.rb | 61 ++++++++ .../ironic_inspector_db_postgresql_spec.rb | 39 +++++ spec/classes/ironic_inspector_db_spec.rb | 135 ++++++++++++++++++ spec/classes/ironic_inspector_db_sync_spec.rb | 30 ++++ spec/classes/ironic_inspector_spec.rb | 2 - 14 files changed, 485 insertions(+), 67 deletions(-) create mode 100644 manifests/inspector/db.pp create mode 100644 manifests/inspector/db/mysql.pp create mode 100644 manifests/inspector/db/postgresql.pp create mode 100644 manifests/inspector/db/sync.pp create mode 100644 releasenotes/notes/inspector-db-ddfdc7d17628f969.yaml delete mode 100644 spec/classes/inspector_db_sync_spec.rb create mode 100644 spec/classes/ironic_inspector_db_mysql_spec.rb create mode 100644 spec/classes/ironic_inspector_db_postgresql_spec.rb create mode 100644 spec/classes/ironic_inspector_db_spec.rb create mode 100644 spec/classes/ironic_inspector_db_sync_spec.rb diff --git a/manifests/db/inspector_sync.pp b/manifests/db/inspector_sync.pp index 4b15e6f8..b26d2b20 100644 --- a/manifests/db/inspector_sync.pp +++ b/manifests/db/inspector_sync.pp @@ -1,22 +1,9 @@ # -# Class to execute ironic-inspector dbsync +# Class to execute ironic-inspector dbsync (deprecated, use +# ironic::inspector::db::sync instead). # class ironic::db::inspector_sync { + warning('ironic::db::inspector_sync is deprecated, please use ironic::inspector::db::sync') - include ::ironic::deps - include ::ironic::params - - exec { 'ironic-inspector-dbsync': - command => $::ironic::params::inspector_dbsync_command, - path => '/usr/bin', - user => 'ironic-inspector', - refreshonly => true, - logoutput => on_failure, - subscribe => [ - Anchor['ironic-inspector::install::end'], - Anchor['ironic-inspector::config::end'], - Anchor['ironic-inspector::dbsync::begin'] - ], - notify => Anchor['ironic-inspector::dbsync::end'], - } + include ::ironic::inspector::db::sync } diff --git a/manifests/inspector.pp b/manifests/inspector.pp index b6ca5408..d16ca149 100644 --- a/manifests/inspector.pp +++ b/manifests/inspector.pp @@ -53,7 +53,7 @@ # # [*db_connection*] # (optional) Location of the ironic-inspector node cache database -# Defaults to 'sqlite::////var/lib/ironic-inspector/inspector.sqlite' +# Defaults to undef # # [*ramdisk_logs_dir*] # (optional) Location to store logs retrieved from the ramdisk @@ -190,7 +190,7 @@ class ironic::inspector ( $debug = undef, $auth_strategy = 'keystone', $dnsmasq_interface = 'br-ctlplane', - $db_connection = 'sqlite:////var/lib/ironic-inspector/inspector.sqlite', + $db_connection = undef, $ramdisk_logs_dir = '/var/log/ironic-inspector/ramdisk/', $enable_setting_ipmi_credentials = false, $keep_ports = 'all', @@ -229,6 +229,7 @@ class ironic::inspector ( include ::ironic::params include ::ironic::pxe::common include ::ironic::inspector::logging + include ::ironic::inspector::db if $admin_tenant_name { warning("Parameter 'ironic::inspector::admin_tenant_name' is deprecated and will be removed in O release. \ @@ -317,7 +318,6 @@ tftpboot and httpboot setup, please include ::ironic::pxe") 'DEFAULT/listen_address': value => $listen_address; 'DEFAULT/auth_strategy': value => $auth_strategy; 'firewall/dnsmasq_interface': value => $dnsmasq_interface; - 'database/connection': value => $db_connection; 'processing/ramdisk_logs_dir': value => $ramdisk_logs_dir; 'processing/enable_setting_ipmi_credentials': value => $enable_setting_ipmi_credentials; 'processing/keep_ports': value => $keep_ports; @@ -349,7 +349,7 @@ tftpboot and httpboot setup, please include ::ironic::pxe") } if $sync_db { - include ::ironic::db::inspector_sync + include ::ironic::inspector::db::sync } if $enabled { diff --git a/manifests/inspector/db.pp b/manifests/inspector/db.pp new file mode 100644 index 00000000..bcdcdc13 --- /dev/null +++ b/manifests/inspector/db.pp @@ -0,0 +1,63 @@ +# == Class: ironic::inspector::db +# +# Configure the Ironic Inspector database +# +# === Parameters +# +# [*database_connection*] +# Url used to connect to database. +# (Optional) Defaults to 'sqlite:////var/lib/ironic-inspector/inspector.sqlite'. +# +# [*database_idle_timeout*] +# Timeout when db connections should be reaped. +# (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_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_overflow*] +# If set, use this value for max_overflow with sqlalchemy. +# (Optional) Defaults to $::os_service_default +# +class ironic::inspector::db ( + $database_connection = 'sqlite:////var/lib/ironic-inspector/inspector.sqlite', + $database_idle_timeout = $::os_service_default, + $database_max_retries = $::os_service_default, + $database_retry_interval = $::os_service_default, + $database_min_pool_size = $::os_service_default, + $database_max_pool_size = $::os_service_default, + $database_max_overflow = $::os_service_default, +) { + + include ::ironic::params + + $database_connection_real = pick($::ironic::inspector::db_connection, $database_connection) + + validate_re($database_connection_real, + '^(sqlite|mysql(\+pymysql)?|postgresql):\/\/(\S+:\S+@\S+\/\S+)?') + + oslo::db { 'ironic_inspector_config': + connection => $database_connection_real, + idle_timeout => $database_idle_timeout, + min_pool_size => $database_min_pool_size, + max_pool_size => $database_max_pool_size, + max_retries => $database_max_retries, + retry_interval => $database_retry_interval, + max_overflow => $database_max_overflow, + } + +} diff --git a/manifests/inspector/db/mysql.pp b/manifests/inspector/db/mysql.pp new file mode 100644 index 00000000..370e751c --- /dev/null +++ b/manifests/inspector/db/mysql.pp @@ -0,0 +1,69 @@ +# +# Copyright (C) 2013 eNovance SAS +# +# Author: Emilien Macchi +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# ironic::inspector::db::mysql +# +# [*password*] +# Password to use for the ironic-inspector user +# +# [*dbname*] +# (optional) The name of the database +# Defaults to 'ironic-inspector' +# +# [*user*] +# (optional) The mysql user to create +# Defaults to 'ironic-inspector' +# +# [*host*] +# (optional) The IP address of the mysql server +# Defaults to '127.0.0.1' +# +# [*charset*] +# (optional) The charset to use for the nova database +# Defaults to 'utf8' +# +# [*collate*] +# (optional) The collate to use for the nova database +# Defaults to 'utf8_general_ci' +# +# [*allowed_hosts*] +# (optional) Additional hosts that are allowed to access this DB +# Defaults to undef +# +class ironic::inspector::db::mysql ( + $password, + $dbname = 'ironic-inspector', + $user = 'ironic-inspector', + $host = '127.0.0.1', + $allowed_hosts = undef, + $charset = 'utf8', + $collate = 'utf8_general_ci', +) { + + ::openstacklib::db::mysql { 'ironic-inspector': + user => $user, + password_hash => mysql_password($password), + dbname => $dbname, + host => $host, + charset => $charset, + collate => $collate, + allowed_hosts => $allowed_hosts, + } + + ::Openstacklib::Db::Mysql['ironic-inspector'] ~> Exec<| title == 'ironic-inspector-dbsync' |> + +} diff --git a/manifests/inspector/db/postgresql.pp b/manifests/inspector/db/postgresql.pp new file mode 100644 index 00000000..612b67cc --- /dev/null +++ b/manifests/inspector/db/postgresql.pp @@ -0,0 +1,47 @@ +# == Class: ironic::db::postgresql +# +# Class that configures postgresql for ironic-inspector +# Requires the Puppetlabs postgresql module. +# +# === Parameters +# +# [*password*] +# (Required) Password to connect to the database. +# +# [*dbname*] +# (Optional) Name of the database. +# Defaults to 'ironic-inspector'. +# +# [*user*] +# (Optional) User to connect to the database. +# Defaults to 'ironic-inspector'. +# +# [*encoding*] +# (Optional) The charset to use for the database. +# Default to undef. +# +# [*privileges*] +# (Optional) Privileges given to the database user. +# Default to 'ALL' +# +class ironic::inspector::db::postgresql( + $password, + $dbname = 'ironic-inspector', + $user = 'ironic-inspector', + $encoding = undef, + $privileges = 'ALL', +) { + + Class['ironic::inspector::db::postgresql'] -> Service<| title == 'ironic-inspector' |> + + ::openstacklib::db::postgresql { 'ironic-inspector': + password_hash => postgresql_password($user, $password), + dbname => $dbname, + user => $user, + encoding => $encoding, + privileges => $privileges, + } + + ::Openstacklib::Db::Postgresql['ironic-inspector'] ~> Exec<| title == 'ironic-inspector-dbsync' |> + +} diff --git a/manifests/inspector/db/sync.pp b/manifests/inspector/db/sync.pp new file mode 100644 index 00000000..5ea6e528 --- /dev/null +++ b/manifests/inspector/db/sync.pp @@ -0,0 +1,22 @@ +# +# Class to execute ironic-inspector dbsync +# +class ironic::inspector::db::sync { + + include ::ironic::deps + include ::ironic::params + + exec { 'ironic-inspector-dbsync': + command => $::ironic::params::inspector_dbsync_command, + path => '/usr/bin', + user => 'ironic-inspector', + refreshonly => true, + logoutput => on_failure, + subscribe => [ + Anchor['ironic-inspector::install::end'], + Anchor['ironic-inspector::config::end'], + Anchor['ironic-inspector::dbsync::begin'] + ], + notify => Anchor['ironic-inspector::dbsync::end'], + } +} diff --git a/releasenotes/notes/inspector-db-ddfdc7d17628f969.yaml b/releasenotes/notes/inspector-db-ddfdc7d17628f969.yaml new file mode 100644 index 00000000..79dcd806 --- /dev/null +++ b/releasenotes/notes/inspector-db-ddfdc7d17628f969.yaml @@ -0,0 +1,7 @@ +--- +features: + - New manifest "ironic::inspector::db" for configuring ironic-inspector + oslo.db parameters. +deprecations: + - Manifest "ironic::db::inspector_sync" is deprecated, use + "ironic::inspector::db::sync" instead. diff --git a/spec/acceptance/ironic_wsgi_apache_spec.rb b/spec/acceptance/ironic_wsgi_apache_spec.rb index 740cd39c..732e11c3 100644 --- a/spec/acceptance/ironic_wsgi_apache_spec.rb +++ b/spec/acceptance/ironic_wsgi_apache_spec.rb @@ -67,6 +67,9 @@ describe 'basic ironic' do warning("Ironic inspector packaging is not ready on ${::osfamily}.") } 'RedHat': { + class { '::ironic::inspector::db::mysql': + password => 'a_big_secret', + } class { '::ironic::inspector': auth_uri => "https://${::fqdn}:5000/v2.0", identity_uri => "https://${::fqdn}:35357", @@ -74,6 +77,7 @@ describe 'basic ironic' do ironic_password => 'a_big_secret', ironic_auth_url => "https://${::fqdn}:5000/v2.0", dnsmasq_interface => 'eth0', + db_connection => 'mysql+pymysql://ironic-inspector:a_big_secret@127.0.0.1/ironic-inspector?charset=utf8', } } } diff --git a/spec/classes/inspector_db_sync_spec.rb b/spec/classes/inspector_db_sync_spec.rb deleted file mode 100644 index 429ef3ec..00000000 --- a/spec/classes/inspector_db_sync_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -require 'spec_helper' - -describe 'ironic::db::inspector_sync' do - - shared_examples_for 'inspector-dbsync' do - - it 'runs ironic-inspectror-db_sync' do - is_expected.to contain_exec('ironic-inspector-dbsync').with( - :command => 'ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade', - :path => '/usr/bin', - :user => 'ironic-inspector', - :refreshonly => 'true', - :logoutput => 'on_failure' - ) - end - - end - - context 'on a RedHat osfamily' do - let :facts do - @default_facts.merge({ - :osfamily => 'RedHat', - :operatingsystemrelease => '7.0', - :concat_basedir => '/var/lib/puppet/concat' - }) - end - - it_configures 'inspector-dbsync' - end - - context 'on a Debian osfamily' do - let :facts do - @default_facts.merge({ - :operatingsystemrelease => '7.8', - :operatingsystem => 'Debian', - :osfamily => 'Debian', - :concat_basedir => '/var/lib/puppet/concat' - }) - end - - it_configures 'inspector-dbsync' - end - -end diff --git a/spec/classes/ironic_inspector_db_mysql_spec.rb b/spec/classes/ironic_inspector_db_mysql_spec.rb new file mode 100644 index 00000000..d5301699 --- /dev/null +++ b/spec/classes/ironic_inspector_db_mysql_spec.rb @@ -0,0 +1,61 @@ +# +# Copyright (C) 2013 eNovance SAS +# +# Author: Emilien Macchi +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# Unit tests for ironic::inspector::db::mysql +# + +require 'spec_helper' + +describe 'ironic::inspector::db::mysql' do + + shared_examples_for 'ironic::inspector::db::mysql' do + let :req_params do + { :password => 'passw0rd' } + end + + let :pre_condition do + 'include mysql::server' + end + + context 'with only required parameters' do + let :params do + req_params + end + + it { is_expected.to contain_openstacklib__db__mysql('ironic-inspector').with( + :user => 'ironic-inspector', + :password_hash => '*74B1C21ACE0C2D6B0678A5E503D2A60E8F9651A3', + :charset => 'utf8', + :collate => 'utf8_general_ci', + )} + 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 'ironic::inspector::db::mysql' + end + end + +end diff --git a/spec/classes/ironic_inspector_db_postgresql_spec.rb b/spec/classes/ironic_inspector_db_postgresql_spec.rb new file mode 100644 index 00000000..db81f49d --- /dev/null +++ b/spec/classes/ironic_inspector_db_postgresql_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe 'ironic::inspector::db::postgresql' do + + shared_examples_for 'ironic::inspector::db::postgresql' do + let :req_params do + { :password => 'pw' } + end + + let :pre_condition do + 'include postgresql::server' + end + + context 'with only required parameters' do + let :params do + req_params + end + + it { is_expected.to contain_postgresql__server__db('ironic-inspector').with( + :user => 'ironic-inspector', + :password => 'md5f4da35e834f32b2deceef0dcd269e195' + )} + 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 'ironic::inspector::db::postgresql' + end + end + +end diff --git a/spec/classes/ironic_inspector_db_spec.rb b/spec/classes/ironic_inspector_db_spec.rb new file mode 100644 index 00000000..d99a9525 --- /dev/null +++ b/spec/classes/ironic_inspector_db_spec.rb @@ -0,0 +1,135 @@ +require 'spec_helper' + +describe 'ironic::inspector::db' do + + shared_examples 'ironic::inspector::db' do + + context 'with default parameters' do + + it { is_expected.to contain_ironic_inspector_config('database/connection').with_value('sqlite:////var/lib/ironic-inspector/inspector.sqlite').with_secret(true) } + it { is_expected.to contain_ironic_inspector_config('database/idle_timeout').with_value('') } + it { is_expected.to contain_ironic_inspector_config('database/min_pool_size').with_value('') } + it { is_expected.to contain_ironic_inspector_config('database/max_pool_size').with_value('') } + it { is_expected.to contain_ironic_inspector_config('database/max_overflow').with_value('') } + it { is_expected.to contain_ironic_inspector_config('database/max_retries').with_value('') } + it { is_expected.to contain_ironic_inspector_config('database/retry_interval').with_value('') } + + end + + context 'with specific parameters' do + let :params do + { :database_connection => 'mysql+pymysql://ironic:ironic@localhost/ironic', + :database_idle_timeout => '3601', + :database_min_pool_size => '2', + :database_max_pool_size => '21', + :database_max_retries => '11', + :database_max_overflow => '21', + :database_retry_interval => '11', } + end + + it { is_expected.to contain_ironic_inspector_config('database/connection').with_value('mysql+pymysql://ironic:ironic@localhost/ironic').with_secret(true) } + it { is_expected.to contain_ironic_inspector_config('database/idle_timeout').with_value('3601') } + it { is_expected.to contain_ironic_inspector_config('database/min_pool_size').with_value('2') } + it { is_expected.to contain_ironic_inspector_config('database/max_retries').with_value('11') } + it { is_expected.to contain_ironic_inspector_config('database/max_pool_size').with_value('21') } + it { is_expected.to contain_ironic_inspector_config('database/max_overflow').with_value('21') } + it { is_expected.to contain_ironic_inspector_config('database/retry_interval').with_value('11') } + + end + + context 'with MySQL-python library as backend package' do + let :params do + { :database_connection => 'mysql://ironic:ironic@localhost/ironic' } + end + + it { is_expected.to contain_ironic_inspector_config('database/connection').with_value('mysql://ironic:ironic@localhost/ironic').with_secret(true) } + end + + context 'with postgresql backend' do + let :params do + { :database_connection => 'postgresql://ironic:ironic@localhost/ironic', } + end + + it 'install the proper backend package' do + is_expected.to contain_package('python-psycopg2').with(:ensure => 'present') + end + + end + + context 'with incorrect database_connection string' do + let :params do + { :database_connection => 'redis://ironic:ironic@localhost/ironic', } + end + + it_raises 'a Puppet::Error', /validate_re/ + end + + context 'with incorrect database_connection string' do + let :params do + { :database_connection => 'foo+pymysql://ironic:ironic@localhost/ironic', } + end + + it_raises 'a Puppet::Error', /validate_re/ + end + + end + + context 'on Debian platforms' do + let :facts do + @default_facts.merge({ :osfamily => 'Debian', + :operatingsystem => 'Debian', + :operatingsystemrelease => 'jessie', + }) + end + + it_configures 'ironic::inspector::db' + + context 'using pymysql driver' do + let :params do + { :database_connection => 'mysql+pymysql://ironic:ironic@localhost/ironic' } + end + + it 'install the proper backend package' do + is_expected.to contain_package('db_backend_package').with( + :ensure => 'present', + :name => 'python-pymysql', + :tag => ['openstack'], + ) + end + end + + context 'with sqlite backend' do + let :params do + { :database_connection => 'sqlite:///var/lib/ironic-inspector/inspector.sqlite', } + end + + it 'install the proper backend package' do + is_expected.to contain_package('db_backend_package').with( + :ensure => 'present', + :name => 'python-pysqlite2', + :tag => ['openstack'], + ) + end + end + + end + + context 'on Redhat platforms' do + let :facts do + @default_facts.merge({ :osfamily => 'RedHat', + :operatingsystemrelease => '7.1', + }) + end + + it_configures 'ironic::inspector::db' + + context 'using pymysql driver' do + let :params do + { :database_connection => 'mysql+pymysql://ironic:ironic@localhost/ironic' } + end + + it { is_expected.not_to contain_package('db_backend_package') } + end + end + +end diff --git a/spec/classes/ironic_inspector_db_sync_spec.rb b/spec/classes/ironic_inspector_db_sync_spec.rb new file mode 100644 index 00000000..59f4644e --- /dev/null +++ b/spec/classes/ironic_inspector_db_sync_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe 'ironic::inspector::db::sync' do + + shared_examples_for 'inspector-dbsync' do + + it 'runs ironic-inspectror-db_sync' do + is_expected.to contain_exec('ironic-inspector-dbsync').with( + :command => 'ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade', + :path => '/usr/bin', + :user => 'ironic-inspector', + :refreshonly => 'true', + :logoutput => 'on_failure' + ) + 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 'inspector-dbsync' + end + end + +end diff --git a/spec/classes/ironic_inspector_spec.rb b/spec/classes/ironic_inspector_spec.rb index 136b9fbb..79896da9 100644 --- a/spec/classes/ironic_inspector_spec.rb +++ b/spec/classes/ironic_inspector_spec.rb @@ -32,7 +32,6 @@ describe 'ironic::inspector' do :admin_tenant_name => 'services', :identity_uri => 'http://127.0.0.1:35357/v2.0', :dnsmasq_interface => 'br-ctlplane', - :db_connection => 'sqlite:////var/lib/ironic-inspector/inspector.sqlite', :ramdisk_logs_dir => '/var/log/ironic-inspector/ramdisk/', :enable_setting_ipmi_credentials => false, :keep_ports => 'all', @@ -101,7 +100,6 @@ describe 'ironic::inspector' do is_expected.to contain_ironic_inspector_config('keystone_authtoken/password').with_value(p[:admin_password]) is_expected.to contain_ironic_inspector_config('keystone_authtoken/project_name').with_value(p[:admin_tenant_name]) is_expected.to contain_ironic_inspector_config('firewall/dnsmasq_interface').with_value(p[:dnsmasq_interface]) - is_expected.to contain_ironic_inspector_config('database/connection').with_value(p[:db_connection]) is_expected.to contain_ironic_inspector_config('processing/ramdisk_logs_dir').with_value(p[:ramdisk_logs_dir]) is_expected.to contain_ironic_inspector_config('processing/enable_setting_ipmi_credentials').with_value(p[:enable_setting_ipmi_credentials]) is_expected.to contain_ironic_inspector_config('processing/keep_ports').with_value(p[:keep_ports])