diff --git a/CHANGELOG.md b/CHANGELOG.md index 88d9e89..f8cac9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added +* Add new parameter `$options` to provide additional plugin configuration + ### Fixed * Fix resource ordering: skip plugins on error diff --git a/README.md b/README.md index 551facc..0dc1f1a 100644 --- a/README.md +++ b/README.md @@ -120,10 +120,39 @@ ds_389::instance { 'example': } ``` +If you need to configure plugin options, you could provide a hash instead: + +```puppet +ds_389::instance { 'example': + root_dn => 'cn=Directory Manager', + root_dn_pass => 'supersecret', + suffix => 'dc=example,dc=com', + cert_db_pass => 'secret', + server_id => $facts['networking']['hostname'], + plugins => { + 'memberof' => { + ensure => 'enabled', + options => [ + 'set --groupattr uniqueMember', + 'set --allbackends on', + 'set --skipnested off', + ], + }, + 'posix-winsync' => 'disabled', + }, +} +``` + You can also declare those separately, by calling their define directly, but you will need to provide the server id of the instance as well as the root dn and password. ```puppet ds_389::plugin { 'memberof': + ensure => 'enabled', + options => [ + 'set --groupattr uniqueMember', + 'set --allbackends on', + 'set --skipnested off', + ], server_id => 'example', root_dn => 'cn=Directory Manager', root_dn_pass => 'supersecret', diff --git a/REFERENCE.md b/REFERENCE.md index 6b529cf..a0c1c2a 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -637,6 +637,15 @@ The desired state of the plugin. Default: 'enabled' Default value: `'enabled'` +##### `options` + +Data type: `Array` + +An array containing additional plugin options. See `man 8 dsconf` for a +complete list. Optional. + +Default value: `[]` + ##### `protocol` Data type: `Enum['ldap','ldaps']` diff --git a/manifests/instance.pp b/manifests/instance.pp index 46b2b79..e111e0b 100644 --- a/manifests/instance.pp +++ b/manifests/instance.pp @@ -415,9 +415,28 @@ # Manage plugins. if $plugins { - $plugins.each |$plugin_name, $plugin_state| { + $plugins.each |$plugin_name, $plugin_config| { + # A hash may contain optional plugin configuration. + if ($plugin_config =~ Hash) { + if ('ensure' in $plugin_config) { + $_plugin_state = $plugin_config['ensure'] + } else { + $_plugin_state = 'enabled' + } + + if ('options' in $plugin_config) { + $_plugin_options = $plugin_config['options'] + } else { + $_plugin_options = [] + } + } else { + $_plugin_state = $plugin_config + $_plugin_options = [] + } + ds_389::plugin { $plugin_name: - ensure => $plugin_state, + ensure => $_plugin_state, + options => $_plugin_options, server_id => $server_id, root_dn => $root_dn, root_dn_pass => $root_dn_pass, diff --git a/manifests/plugin.pp b/manifests/plugin.pp index a144808..506090d 100644 --- a/manifests/plugin.pp +++ b/manifests/plugin.pp @@ -20,6 +20,10 @@ # @param ensure # The desired state of the plugin. Default: 'enabled' # +# @param options +# An array containing additional plugin options. See `man 8 dsconf` for a +# complete list. Optional. +# # @param protocol # The protocol to use when calling ldapadd. Default: 'ldap' # @@ -43,6 +47,7 @@ String $root_dn, Variant[String,Sensitive[String]] $root_dn_pass, Enum['enabled','disabled'] $ensure = 'enabled', + Array $options = [], String $server_host = $facts['networking']['fqdn'], Integer $server_port = 389, Enum['ldap','ldaps'] $protocol = 'ldap', @@ -75,9 +80,49 @@ "&& touch ${plugin_done}", ], ' ') - exec { "Set plugin ${name} to ${ensure}: ${server_id}": + exec { "Set plugin ${name} state to ${ensure}: ${server_id}": command => $plugin_command, path => $ds_389::path, creates => $plugin_done, } + + if ($options and $ensure == 'enabled') { + # Store all options in a file. This way a change can be detected and + # updated options can be applied. + $plugin_options_file = "/etc/dirsrv/slapd-${server_id}/plugin_${name}_options" + file { $plugin_options_file: + ensure => file, + owner => $ds_389::user, + group => $ds_389::group, + mode => '0440', + content => inline_epp('<%= $options %>', {options => $options}), + } + + # Enable every option individually. This way conflicts can be avoided + # and failures are easier to track down. + $options.each |$option| { + # Command to set the specified plugin option. + $plugin_option_command = join([ + 'dsconf', + "-D \'${root_dn}\'", + "-w \'${root_dn_pass}\'", + "${protocol}://${server_host}:${server_port}", + 'plugin', + $name, + $option, + # Remove the options file in case of failure. This way a failed command + # is retried and if the error persists the user is encouraged to fix it. + "|| rm -f ${plugin_options_file}", + ], ' ') + + exec { "Set plugin ${name} options (${option}): ${server_id}": + command => $plugin_option_command, + path => $ds_389::path, + refreshonly => true, + subscribe => File[$plugin_options_file], + require => Exec["Set plugin ${name} state to ${ensure}: ${server_id}"], + } + + } + } } diff --git a/spec/defines/plugin_spec.rb b/spec/defines/plugin_spec.rb index d6e26a5..ab37b5b 100644 --- a/spec/defines/plugin_spec.rb +++ b/spec/defines/plugin_spec.rb @@ -24,12 +24,16 @@ it { is_expected.to compile } it { - is_expected.to contain_exec('Set plugin specplugin to enabled: specdirectory').with( + is_expected.to contain_exec('Set plugin specplugin state to enabled: specdirectory').with( command: "rm -f /etc/dirsrv/slapd-specdirectory/plugin_specplugin_disabled.done; dsconf -D 'cn=Directory Manager' -w 'supersecret' ldap://foo.example.com:389 plugin specplugin enable && touch /etc/dirsrv/slapd-specdirectory/plugin_specplugin_enabled.done", # rubocop:disable LineLength path: '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin', creates: '/etc/dirsrv/slapd-specdirectory/plugin_specplugin_enabled.done', ) } + + it { + is_expected.not_to contain_file('/etc/dirsrv/slapd-${name}/plugin_specplugin_options') + } end context 'when disabling a plugin' do @@ -45,17 +49,27 @@ it { is_expected.to compile } it { - is_expected.to contain_exec('Set plugin specplugin to disabled: specdirectory').with( + is_expected.to contain_exec('Set plugin specplugin state to disabled: specdirectory').with( command: "rm -f /etc/dirsrv/slapd-specdirectory/plugin_specplugin_enabled.done; dsconf -D 'cn=Directory Manager' -w 'supersecret' ldap://foo.example.com:389 plugin specplugin disable && touch /etc/dirsrv/slapd-specdirectory/plugin_specplugin_disabled.done", # rubocop:disable LineLength path: '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin', creates: '/etc/dirsrv/slapd-specdirectory/plugin_specplugin_disabled.done', ) } + + it { + is_expected.not_to contain_file('/etc/dirsrv/slapd-${name}/plugin_specplugin_options') + } end context 'with all params' do let(:params) do { + ensure: 'enabled', + options: [ + 'set --groupattr uniqueMember', + 'set --allbackends on', + 'set --skipnested off', + ], server_id: 'specdirectory', root_dn: 'cn=Directory Manager', root_dn_pass: 'supersecret', @@ -67,12 +81,45 @@ it { is_expected.to compile } it { - is_expected.to contain_exec('Set plugin specplugin to enabled: specdirectory').with( + is_expected.to contain_exec('Set plugin specplugin state to enabled: specdirectory').with( command: "rm -f /etc/dirsrv/slapd-specdirectory/plugin_specplugin_disabled.done; dsconf -D 'cn=Directory Manager' -w 'supersecret' ldap://ldap.test.org:1389 plugin specplugin enable && touch /etc/dirsrv/slapd-specdirectory/plugin_specplugin_enabled.done", # rubocop:disable LineLength path: '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin', creates: '/etc/dirsrv/slapd-specdirectory/plugin_specplugin_enabled.done', ) } + + it { + is_expected.to contain_file('/etc/dirsrv/slapd-specdirectory/plugin_specplugin_options').with( + ensure: 'file', + mode: '0440', + owner: 'dirsrv', + group: 'dirsrv', + content: '[set --groupattr uniqueMember, set --allbackends on, set --skipnested off]', + ) + } + + it { + is_expected.to contain_exec('Set plugin specplugin options (set --groupattr uniqueMember): specdirectory').with( + command: "dsconf -D 'cn=Directory Manager' -w 'supersecret' ldap://ldap.test.org:1389 plugin specplugin set --groupattr uniqueMember || rm -f /etc/dirsrv/slapd-specdirectory/plugin_specplugin_options", # rubocop:disable LineLength + path: '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin', + refreshonly: true, + ).that_subscribes_to('File[/etc/dirsrv/slapd-specdirectory/plugin_specplugin_options]') + #).that_requires('Exec[Set plugin specplugin state to enabled: specdirectory]').that_subscribes_to('File[/etc/dirsrv/slapd-specdirectory/plugin_specplugin_options]') + } + it { + is_expected.to contain_exec('Set plugin specplugin options (set --allbackends on): specdirectory').with( + command: "dsconf -D 'cn=Directory Manager' -w 'supersecret' ldap://ldap.test.org:1389 plugin specplugin set --allbackends on || rm -f /etc/dirsrv/slapd-specdirectory/plugin_specplugin_options", # rubocop:disable LineLength + path: '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin', + refreshonly: true, + ).that_subscribes_to('File[/etc/dirsrv/slapd-specdirectory/plugin_specplugin_options]') + } + it { + is_expected.to contain_exec('Set plugin specplugin options (set --skipnested off): specdirectory').with( + command: "dsconf -D 'cn=Directory Manager' -w 'supersecret' ldap://ldap.test.org:1389 plugin specplugin set --skipnested off || rm -f /etc/dirsrv/slapd-specdirectory/plugin_specplugin_options", # rubocop:disable LineLength + path: '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin', + refreshonly: true, + ).that_subscribes_to('File[/etc/dirsrv/slapd-specdirectory/plugin_specplugin_options]') + } end end end