Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add type/provider for autoprimary #162

Merged
merged 2 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,21 @@ Remark: if the target\_zone is not managed with powerdns\_zone resource, powerdn

Passwords can be passed either as plain-text strings or as [Puppet's Sensitive type](https://www.puppet.com/docs/puppet/7/lang_data_sensitive.html) when appropriate encrypted backend is configured on Puppet server.

### Manage autoprimaries (automatic provisioning of secondaries)
It's possible to manage the the 'autoprimaries' with puppet (For a decription of the autoprimary functionality in
powerdns see [powerdns manual](https://doc.powerdns.com/authoritative/modes-of-operation.html#autoprimary-automatic-provisioning-of-secondaries).
The autoprimaries are set with the powerdns\_autoprimary resource. As an example we add the primary 1.2.3.4 named ns1.example.org whith the account 'test'
``` yaml
powerdns_autoprimary{'[email protected]':
ensure => 'present',
account => 'test',
}
```
As an alternative, you can set the autoprimaries parameter of the powerdns class to achive the same (eg. if you use hiera).

For removal of an autoprimary set ensure to 'absent' or set the parameter purge\_autoprimaries of the powerdns class to true which willa
remove all autoprimaries that are not present in the puppet manifest.

## Reference

### Parameters
Expand Down
64 changes: 64 additions & 0 deletions lib/puppet/provider/powerdns_autoprimary/pdnsutil.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# frozen_string_literal: true

Puppet::Type.type(:powerdns_autoprimary).provide(:pdnsutil) do
desc "@summary provider which provides autprimary,
using the pdnsutil command."

commands pdnsutil: 'pdnsutil'

def initialize(value = {})
super(value)
@property_flush = {}
end

def self.instances
pdnsutil('list-autoprimaries').split("\n").map do |line|
raise Puppet::Error, "Cannot parse invalid autoprimary line: #{line}" unless line =~ %r{^IP=(\S+),\s+NS=(\S+),\s+account=(\S*)$}
new(
ensure: :present,
name: Regexp.last_match(1) + '@' + Regexp.last_match(2),
account: Regexp.last_match(3),
)
end
end

def self.prefetch(resources)
autoprimaries = instances
resources.each_key do |name|
if (provider = autoprimaries.find { |aprim| aprim.name == name })
resources[name].provider = provider
end
end
end

def create
pdnsutil('add-autoprimary', resource[:name].split('@'), resource[:account])
@property_hash[:ensure] = :present
end

def destroy
pdnsutil('remove-autoprimary', resource[:name].split('@'))
@property_hash[:ensure] = :absent
end

def account
@property_hash[:account]
end

def account=(account)
pdnsutil('remove-autoprimary', resource[:name].split('@'))
pdnsutil('add-autoprimary', resource[:name].split('@'), account)
@property_hash[:ensure] = account
end

def exists?
@property_hash[:ensure] == :present
end

def flush
return if @property_flush.empty?
content = @property_flush[:content] || @resource[:content]
virsh_define(content)
@property_flush.clear
end
end
33 changes: 33 additions & 0 deletions lib/puppet/type/powerdns_autoprimary.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

require 'puppet/parameter/boolean'

Puppet::Type.newtype(:powerdns_autoprimary) do
@doc = 'ensures autoprimary servers (for automatic provisioning of secondaries)
'

ensurable do
desc 'Manage the state of this type.'
defaultvalues
defaultto :present
end

newparam(:name, namevar: true) do
desc 'name of the autoprimary in the format IP@NAMESERVER'

newvalues(%r{^\S+@\S+$})
end

newproperty(:account) do
desc 'account to ensure (default to no account)'
defaultto ''

validate do |value|
raise ArgumentError, 'ip needs to be a string' unless value.is_a?(String)
end
end

autorequire(:service) do
['pdns']
end
end
15 changes: 15 additions & 0 deletions manifests/init.pp
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# powerdns
#
# @param autoprimaries
# 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
#
class powerdns (
Boolean $authoritative = true,
Boolean $recursor = false,
Expand All @@ -25,6 +31,8 @@
String[1] $mysql_schema_file = $powerdns::params::mysql_schema_file,
String[1] $pgsql_schema_file = $powerdns::params::pgsql_schema_file,
Hash $forward_zones = {},
Powerdns::Autoprimaries $autoprimaries = {},
Boolean $purge_autoprimaries = false,
) inherits powerdns::params {
# Do some additional checks. In certain cases, some parameters are no longer optional.
if $authoritative {
Expand Down Expand Up @@ -68,4 +76,11 @@
$powerdns_recursor_defaults = { 'type' => 'recursor' }
create_resources(powerdns::config, $powerdns_recursor_config, $powerdns_recursor_defaults)
}

if $purge_autoprimaries {
resources { 'powerdns_autoprimary':
purge => true,
}
}
create_resources('powerdns_autoprimary', $autoprimaries)
}
34 changes: 34 additions & 0 deletions spec/type_aliases/autoprimaries_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require 'spec_helper'

describe 'Powerdns::Autoprimaries' do
describe 'valid types' do
context 'with valid types' do
[
{},
{ '[email protected]' => {} },
{ '2001:db8::[email protected]' => { 'account' => 'test' } },
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
end
end
end

describe 'invalid types' do
context 'with garbage inputs' do
[
true,
nil,
{ 'foo' => 'bar' },
'55555',
{ '@ns1.example.org' => {} },
{ '1.2.3.4@' => {} },
].each do |value|
describe value.inspect do
it { is_expected.not_to allow_value(value) }
end
end
end
end
end
20 changes: 20 additions & 0 deletions spec/unit/puppet/provider/powerdns_autoprimary/pdnsutil_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

require 'spec_helper'

provider_class = Puppet::Type.type(:powerdns_autoprimary).provider(:pdnsutil)

describe provider_class do
let(:resource) do
Puppet::Type::Powerdns_autoprimary.new(
name: '[email protected]',
provider: described_class.name,
)
end

let(:provider) { provider_class.new(resource) }

it 'has its name set' do
expect(resource[:name]).to eq('[email protected]')
end
end
13 changes: 13 additions & 0 deletions spec/unit/puppet/type/powerdns_autoprimary_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require 'puppet'
require 'puppet/type/powerdns_autoprimary'

describe Puppet::Type.type(:powerdns_autoprimary) do
let!(:autoprimary) { Puppet::Type.type(:powerdns_autoprimary).new(name: '[email protected]') }

it 'has its name set' do
expect(autoprimary[:name]).to eq('[email protected]')
end
it 'has set account to empty string' do
expect(autoprimary[:account]).to eq('')
end
end
6 changes: 6 additions & 0 deletions types/autoprimaries.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type Powerdns::Autoprimaries=Hash[
Pattern[/.+@.+/],
Struct[{
account => Optional[String],
}]
]
Loading