From 8f942740ddc2568525810380df39370aee46ad68 Mon Sep 17 00:00:00 2001 From: Arjen Heidinga Date: Mon, 13 Jan 2025 09:06:30 +0100 Subject: [PATCH] Add lmdb backend options. --- manifests/authoritative.pp | 33 ++++++---------- manifests/backends/lmdb.pp | 54 +++++++++++++++++++++++++ manifests/init.pp | 30 +++++++++++++- manifests/params.pp | 4 ++ spec/classes/powerdns_init_spec.rb | 63 +++++++++++++++++++++++++++++- 5 files changed, 161 insertions(+), 23 deletions(-) create mode 100644 manifests/backends/lmdb.pp diff --git a/manifests/authoritative.pp b/manifests/authoritative.pp index b7240df..72fd1a1 100644 --- a/manifests/authoritative.pp +++ b/manifests/authoritative.pp @@ -10,28 +10,21 @@ stdlib::ensure_packages($install_packages) - # install the right backend - case $powerdns::backend { - 'mysql': { - include powerdns::backends::mysql - } - 'bind': { - include powerdns::backends::bind - } - 'postgresql': { - include powerdns::backends::postgresql - } - 'ldap': { - include powerdns::backends::ldap - } - 'sqlite': { - include powerdns::backends::sqlite - } - default: { - fail("${powerdns::backend} is not supported. We only support 'mysql', 'bind', 'postgresql', 'ldap' and 'sqlite' at the moment.") - } + $supported_backends = [ + 'mysql', + 'bind', + 'postgresql', + 'ldap', + 'sqlite', + 'lmdb', + ] + + unless $powerdns::backend in $supported_backends { + fail("${powerdns::backend} is not supported. We only support ${supported_backends.join(', ')} at the moment.") } + include "powerdns::backends::${powerdns::backend}" + service { 'pdns': ensure => running, name => $powerdns::params::authoritative_service, diff --git a/manifests/backends/lmdb.pp b/manifests/backends/lmdb.pp new file mode 100644 index 0000000..ab888ba --- /dev/null +++ b/manifests/backends/lmdb.pp @@ -0,0 +1,54 @@ +# lmdb backend for powerdns +class powerdns::backends::lmdb ( + $package_ensure = $powerdns::params::default_package_ensure +) inherits powerdns { + if $facts['os']['family'] == 'Debian' { + # The pdns-server package from the Debian APT repo automatically installs the bind + # backend package which we do not want when using another backend such as ldap. + package { 'pdns-backend-bind': + ensure => purged, + require => Package[$powerdns::params::authoritative_package], + } + + # The pdns-backend-lmdb package installs a configuration file that conflicts with this module's backend configuration. + file { "${powerdns::params::authoritative_configdir}/pdns.d/lmdb.conf": + ensure => absent, + require => Package[$powerdns::params::lmdb_backend_package_name], + before => Service['pdns'], + } + } + + $options = { + 'launch' => 'lmdb', + 'lmdb-filename' => $powerdns::lmdb_filename, + 'lmdb-schema-version' => $powerdns::lmdb_schema_version, + 'lmdb-shards' => $powerdns::lmdb_shards, + 'lmdb-sync-mode' => $powerdns::lmdb_sync_mode, + }.delete_undef_values() + + $options.each |$key, $value| { + powerdns::config { $key: + ensure => present, + setting => $key, + value => $value, + type => 'authoritative', + } + } + + if $powerdns::params::lmdb_backend_package_name { + # set up the powerdns backend + package { $powerdns::params::lmdb_backend_package_name: + ensure => $package_ensure, + before => Service['pdns'], + require => Package[$powerdns::params::authoritative_package], + } + } + + if $powerdns::backend_install { + fail('backend_install is not supported with lmdb') + } + + if $powerdns::backend_create_tables { + fail('backend_create_tables is not supported with lmdb') + } +} diff --git a/manifests/init.pp b/manifests/init.pp index 278f104..1984ed2 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -4,11 +4,26 @@ # Hash of autoprimaries the ensurce (with resource powerdns_autoprimary) # @param purge_autoprimaries # Set this to true if you like to purge all autoprimaries not managed with puppet +# @param lmdb_filename +# Filename for the lmdb database +# @param lmdb_schema_version +# Maximum allowed schema version to run on this DB. If a lower version is found, auto update is performed +# @param lmdb_shards +# Records database will be split into this number of shards +# @param lmdb_sync_mode +# Sync mode for LMDB. One of 'nosync', 'sync', 'nometasync', 'mapasync' # class powerdns ( Boolean $authoritative = true, Boolean $recursor = false, - Enum['ldap', 'mysql', 'bind', 'postgresql', 'sqlite'] $backend = 'mysql', + Enum[ + 'ldap', + 'mysql', + 'bind', + 'postgresql', + 'sqlite', + 'lmdb' + ] $backend = 'mysql', Boolean $backend_install = true, Boolean $backend_create_tables = true, Powerdns::Secret $db_root_password = undef, @@ -25,6 +40,17 @@ String[1] $ldap_method = 'strict', Optional[String[1]] $ldap_binddn = undef, Powerdns::Secret $ldap_secret = undef, + Stdlib::Absolutepath $lmdb_filename = '/var/lib/powerdns/pdns.lmdb', + Optional[Integer] $lmdb_schema_version = undef, + Optional[Integer] $lmdb_shards = undef, + Optional[ + Enum[ + 'nosync', + 'sync', + 'nometasync', + 'mapasync' + ] + ] $lmdb_sync_mode = undef, Boolean $custom_repo = false, Boolean $custom_epel = false, Pattern[/4\.[0-9]+/] $authoritative_version = $powerdns::params::authoritative_version, @@ -37,7 +63,7 @@ ) inherits powerdns::params { # Do some additional checks. In certain cases, some parameters are no longer optional. if $authoritative { - if ($powerdns::backend != 'bind') and ($powerdns::backend != 'ldap') and ($powerdns::backend != 'sqlite') and $require_db_password { + if $require_db_password and !($powerdns::backend in ['bind', 'ldap', 'sqlite', 'lmdb']) { assert_type(Variant[String[1], Sensitive[String[1]]], $db_password) |$expected, $actual| { fail("'db_password' must be a non-empty string when 'authoritative' == true") } diff --git a/manifests/params.pp b/manifests/params.pp index f0fb274..6811481 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -27,6 +27,7 @@ $ldap_backend_package_name = 'pdns-backend-ldap' $pgsql_backend_package_name = 'pdns-backend-postgresql' $sqlite_backend_package_name = 'pdns-backend-sqlite' + $lmdb_backend_package_name = 'pdns-backend-lmdb' $sqlite_package_name = 'sqlite' $authoritative_configdir = '/etc/pdns' $recursor_package = 'pdns-recursor' @@ -45,6 +46,7 @@ $ldap_backend_package_name = 'pdns-backend-ldap' $pgsql_backend_package_name = 'pdns-backend-pgsql' $sqlite_backend_package_name = 'pdns-backend-sqlite3' + $lmdb_backend_package_name = 'pdns-backend-lmdb' $mysql_schema_file = '/usr/share/doc/pdns-backend-mysql/schema.mysql.sql' $pgsql_schema_file = '/usr/share/doc/pdns-backend-pgsql/schema.pgsql.sql' $sqlite_schema_file = '/usr/share/doc/pdns-backend-sqlite3/schema.sqlite3.sql' @@ -91,6 +93,7 @@ $ldap_backend_package_name = undef $pgsql_backend_package_name = undef $sqlite_backend_package_name = undef + $lmdb_backend_package_name = undef $mysql_schema_file = '/usr/local/share/doc/powerdns/schema.mysql.sql' $pgsql_schema_file = '/usr/local/share/doc/powerdns/schema.pgsql.sql' $sqlite_schema_file = '/usr/local/share/doc/powerdns/schema.sqlite3.sql' @@ -118,6 +121,7 @@ $ldap_backend_package_name = undef $pgsql_backend_package_name = undef $sqlite_backend_package_name = undef + $lmdb_backend_package_name = undef $authoritative_config = '/etc/powerdns/pdns.conf' $recursor_dir = '/etc/powerdns' $recursor_config = "${recursor_dir}/recursor.conf" diff --git a/spec/classes/powerdns_init_spec.rb b/spec/classes/powerdns_init_spec.rb index 95ac9b1..e4dc67f 100644 --- a/spec/classes/powerdns_init_spec.rb +++ b/spec/classes/powerdns_init_spec.rb @@ -437,6 +437,67 @@ end end + context 'powerdns class with lmdb backend' do + let(:params) do + { + backend: 'lmdb', + lmdb_filename: '/var/lib/powerdns/pdns.lmdb', + lmdb_schema_version: 2, + lmdb_shards: 2, + lmdb_sync_mode: 'nosync', + backend_install: false, + backend_create_tables: false + } + end + + it { is_expected.to contain_class('powerdns::backends::lmdb') } + + # Test package management + case facts[:os]['family'] + when 'Debian' + it { is_expected.to contain_package('pdns-backend-bind').with('ensure' => 'purged') } + it { is_expected.to contain_package('pdns-backend-lmdb').with('ensure' => 'installed') } + it { is_expected.to contain_file('/etc/powerdns/pdns.d/lmdb.conf').with('ensure' => 'absent') } + end + + # Test LMDB configuration + it { is_expected.to contain_powerdns__config('launch').with('value' => 'lmdb') } + it { is_expected.to contain_powerdns__config('lmdb-filename').with('value' => '/var/lib/powerdns/pdns.lmdb') } + it { is_expected.to contain_powerdns__config('lmdb-schema-version').with('value' => 2) } + it { is_expected.to contain_powerdns__config('lmdb-shards').with('value' => 2) } + it { is_expected.to contain_powerdns__config('lmdb-sync-mode').with('value' => 'nosync') } + + # Test that backend_install fails + context 'with backend_install set to true' do + let(:params) do + { + backend: 'lmdb', + backend_install: true + } + end + + it 'fails with backend_install' do + is_expected.to raise_error(%r{backend_install is not supported with lmdb}) + end + end + + # Test that backend_create_tables fails + context 'with backend_create_tables set to true' do + let(:params) do + { + backend: 'lmdb', + backend_install: false, + backend_create_tables: true + } + end + + it 'fails with backend_create_tables' do + is_expected.to raise_error(%r{backend_create_tables is not supported with lmdb}) + end + end + end + + context 'powerdns class with backend_create_tables set to false' do let(:params) do { @@ -553,7 +614,7 @@ it { is_expected.to raise_error( - %r{'backend' expects a match for Enum\['bind', 'ldap', 'mysql', 'postgresql', 'sqlite'\]}, + %r{'backend' expects a match for Enum\['bind', 'ldap', 'lmdb', 'mysql', 'postgresql', 'sqlite'\]}, ) } end