summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2023-06-08 13:07:03 +0200
committerHugo Hörnquist <hugo@lysator.liu.se>2023-06-08 13:07:03 +0200
commit1b5393f6c8e5c5707410701cceb3c6fb99fda613 (patch)
treecc731ef0136eda3ba398d611961434bb4b2ceb7a /lib
parentGot content working. (diff)
downloaddns-1b5393f6c8e5c5707410701cceb3c6fb99fda613.tar.gz
dns-1b5393f6c8e5c5707410701cceb3c6fb99fda613.tar.xz
work
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/provider/dns_record2/named.rb17
-rw-r--r--lib/puppet/provider/dns_zone2/named.rb23
-rw-r--r--lib/puppet/type/dns_record2.rb25
-rw-r--r--lib/puppet/type/dns_zone2.rb226
4 files changed, 199 insertions, 92 deletions
diff --git a/lib/puppet/provider/dns_record2/named.rb b/lib/puppet/provider/dns_record2/named.rb
index 13fe5ee..88bc73e 100644
--- a/lib/puppet/provider/dns_record2/named.rb
+++ b/lib/puppet/provider/dns_record2/named.rb
@@ -1,14 +1,8 @@
Puppet::Type.type(:dns_record2).provide(:named) do
def self.instances
- []
+ raise _('Listing DNS records not supported.')
end
- # Create and destroy don't do anything on their own,
- # See comment in type
- def create; end
-
- def destroy; end
-
def exists?
record != nil
end
@@ -25,21 +19,14 @@ Puppet::Type.type(:dns_record2).provide(:named) do
when String
t
else
- "INVALID VALUE (#{t.class}, #{t})"
+ raise "INVALID VALUE (#{t.class}, #{t})"
end
end
- # TODO: should we have this?
- def value=(v); end
-
def key
resource[:key]
end
- # def key=(v)
- # resource[:key] = v
- # end
-
def zone
resource[:zone]
end
diff --git a/lib/puppet/provider/dns_zone2/named.rb b/lib/puppet/provider/dns_zone2/named.rb
index c1e39c5..3a59c81 100644
--- a/lib/puppet/provider/dns_zone2/named.rb
+++ b/lib/puppet/provider/dns_zone2/named.rb
@@ -1,5 +1,4 @@
Puppet::Type.type(:dns_zone2).provide(:named) do
-
def self.instances
`named-checkconf -l`.split("\n").map do |record|
name, cls, view, type = record.split(' ')
@@ -7,20 +6,10 @@ Puppet::Type.type(:dns_zone2).provide(:named) do
end
end
- def create(records)
- print("Create #{resource[:name]}\n")
- end
-
- def destroy
- print("Remove #{resource[:name]}\n")
- end
-
def exists?
- # instances.find { |r| r.name == resource[:name] }
- # resource[:ensure] == :present
`named-checkconf -l`
.split("\n")
- .grep(%r{#{resource[:origin]} })
+ .grep(%r{^#{origin_rx} })
.empty?
.!
end
@@ -29,7 +18,7 @@ Puppet::Type.type(:dns_zone2).provide(:named) do
"/var/named/zones/#{resource[:name]}db"
end
- def zone_content(records)
+ def zone_content(records, serial_change)
content = <<~EOF
; File managed by Puppet.
; Local changes WILL be overwritten
@@ -39,7 +28,7 @@ Puppet::Type.type(:dns_zone2).provide(:named) do
$TTL #{resource[:default_ttl]}
@ #{resource[:soa_ttl]} IN SOA #{resource[:mname]} #{resource[:rname]} (
- #{serial + 1} ; serial
+ #{serial + serial_change} ; serial
#{resource[:refresh]} ; refresh
#{resource[:retry]} ; retry
#{resource[:expire]} ; expire
@@ -65,7 +54,13 @@ Puppet::Type.type(:dns_zone2).provide(:named) do
content
end
+ # The current (before updating) serial of the zone
def serial
`rndc zonestatus #{name} | awk -F' ' '/^serial:/ { print $2 }'`.to_i
end
+
+ # A regex matching the origin
+ def origin_rx
+ resource[:origin].gsub(%r{[.]}, '[.]')
+ end
end
diff --git a/lib/puppet/type/dns_record2.rb b/lib/puppet/type/dns_record2.rb
index 1aceaf9..098d27d 100644
--- a/lib/puppet/type/dns_record2.rb
+++ b/lib/puppet/type/dns_record2.rb
@@ -1,3 +1,4 @@
+# TODO: views
Puppet::Type.newtype(:dns_record2) do
@doc = <<~EOF
A single DNS record.
@@ -7,25 +8,9 @@ Puppet::Type.newtype(:dns_record2) do
coresponding dns_zone2 resource.
EOF
- newproperty(:ensure) do
- newvalue(:present) do
- provider.create
- end
-
- newvalue(:absent) do
- provider.destroy
- end
-
- defaultto :present
+ autonotify(:dns_zone2) { || [value(:zone)] }
- def retrieve
- if provider.exists?
- :present
- else
- :absent
- end
- end
- end
+ ensurable
def exists?
provider.exists?
@@ -89,8 +74,4 @@ Puppet::Type.newtype(:dns_record2) do
TTL of this record.
EOF
end
-
- autonotify(:dns_zone2) { || [value(:zone)] }
-
- # TODO views
end
diff --git a/lib/puppet/type/dns_zone2.rb b/lib/puppet/type/dns_zone2.rb
index ff0cf02..e21af6d 100644
--- a/lib/puppet/type/dns_zone2.rb
+++ b/lib/puppet/type/dns_zone2.rb
@@ -1,3 +1,5 @@
+require 'puppet/type/file'
+
Puppet::Type.newtype(:dns_zone2, self_refresh: true) do
@doc = <<~EOF
A complete DNS zonefile.
@@ -9,40 +11,81 @@ Puppet::Type.newtype(:dns_zone2, self_refresh: true) do
when something else has actually changed in the zone.
EOF
- newproperty(:ensure) do
- newvalue(:present) do
- # @resource.content = resource.should_content
- # provider.write_zone(resource.should_content)
- print("Present resource\n")
+ ensurable
+
+ def refresh
+ catalog.resource("File[/var/named/zones/#{self[:name]}db]")[:content] = should_content(1)
+ end
+
+ # List of all DNS records (at all)
+ #
+ # Should ideally be limited to records in this zone here instead of
+ # further down.
+ def records
+ catalog.resources.filter do |r|
+ r.is_a?(Puppet::Type.type(:dns_record2))
end
+ end
+
+ # Create the file resource for us.
+ # We also propagate some parameters and metaparameters to the
+ # underlying file here
+ def generate
+ params = {
+ ensure: self[:ensure],
+ path: provider.filename,
+ # notify: self[:notify],
+ validate_cmd: "/usr/sbin/named-checkzone #{self[:origin]} %"
+ }
- # This should ideally remove the zone. This is however managed
- # "higher" up in the puppet code.
- # dns::init has a purge on the directory, and the named
- # configuration file is fully managed by us.
- # This means that decomissioning is as simple as removing the zone
- # from the puppet environment.
- newvalue(:absent) do
- # provider.destroy
+ [:owner,
+ :group,
+ :backup,
+ :selinux_ignore_defaults,
+ :selrange,
+ :selrole,
+ :seltype,
+ :seluser,
+ :show_diff].each do |param|
+ params[param] = self[param] unless self[param].nil?
end
- defaultto :present
+ excluded_metaparams = [:before, :notify, :require, :subscribe, :tag]
- def retrieve
- if provider.exists?
- :present
- else
- :absent
+ Puppet::Type.metaparams.each do |metaparam|
+ unless self[metaparam].nil? || excluded_metaparams.include?(metaparam)
+ params[metaparam] = self[metaparam]
end
end
+
+ [Puppet::Type.type(:file).new(params)]
end
- def refresh
- print("Refreshing zone\n")
- catalog.resource("File[/var/named/zones/#{self[:name]}db]")[:content] = should_content
+ # Returning "our" file resource causes errors on the file to
+ # propagate out from us (which is NEEDED for `validate_cmd` to
+ # work).
+ #
+ # This always sets the content, but is run is *before* refresh
+ # eventns. This means that this works for creation events, but not
+ # refresh events. For refresh events we simply generate the content
+ # a second time, overriding this instance.
+ #
+ # Ideally we wouldn't generate content here, but instead in
+ # `create`. But that method isn't called
+ def eval_generate
+ catalog.resource("File[/var/named/zones/#{self[:name]}db]")[:content] = should_content(0)
+ [catalog.resource("File[#{provider.filename}]")]
+ end
+
+ def should_content(serial_change)
+ provider.zone_content(records, serial_change)
end
newparam(:origin, namevar: true) do
+ desc <<-EOF
+ Origin parameter of the source.
+ Should almost always be the same as the name of the zone.
+ EOF
munge do |value|
if value[-1] == '.'
value
@@ -53,14 +96,27 @@ Puppet::Type.newtype(:dns_zone2, self_refresh: true) do
end
newparam(:cls) do
+ desc <<-EOF
+ DNS class of the zone.
+ EOF
defaultto :IN
end
newparam(:view) do
+ desc <<-EOF
+ Named view this zone belongs to.
+ TODO: support views
+ EOF
defaultto '_default'
end
newparam(:type) do
+ desc <<-EOF
+ The type of the zone.
+ TODO: support types
+ Currently only master is tested.
+ EOF
+
newvalues(:master, :slave,
:mirror, :hint, :stub, :static_stub, :forward, :redirect)
aliasvalue :primary, :master
@@ -69,10 +125,18 @@ Puppet::Type.newtype(:dns_zone2, self_refresh: true) do
end
newparam(:default_ttl) do
+ desc <<-EOF
+ TTL for all records in zone without an explicit TTL set.
+ EOF
defaultto '300'
end
newparam(:mname) do
+ desc <<-EOF
+ Domain name of zone master.
+
+ Part of the SOA record.
+ EOF
munge do |value|
if value[-1] == '.'
value
@@ -83,6 +147,11 @@ Puppet::Type.newtype(:dns_zone2, self_refresh: true) do
end
newparam(:rname) do
+ desc <<-EOF
+ Email to the zone admin, but with the '@' replaced with a period ('.')
+
+ Part of the SOA record.
+ EOF
munge do |value|
if value[-1] == '.'
value
@@ -93,45 +162,120 @@ Puppet::Type.newtype(:dns_zone2, self_refresh: true) do
end
newparam(:soa_ttl) do
+ desc <<-EOF
+ TTL of the SOA record.
+ EOF
end
newparam(:refresh) do
+ desc <<-EOF
+ Refresh value in the SOA record.
+ EOF
end
newparam(:retry) do
+ desc <<-EOF
+ Retry value in the SOA record.
+ EOF
end
newparam(:expire) do
+ desc <<-EOF
+ Expire value in the SOA record.
+ EOF
end
newparam(:negative_ttl) do
+ desc <<-EOF
+ Negative TTL value in the SOA value.
+
+ This file is sometimes call Minimum TTL due to historical reasons.
+ EOF
end
- # List of all DNS records (at all)
- #
- # Should ideally be limited to records in this zone here instead of
- # further down.
- def records
- catalog.resources.filter do |r|
- r.is_a?(Puppet::Type.type(:dns_record2))
+ newparam(:owner, parent: Puppet::Type::File::Owner) do
+ desc <<-EOF
+ Owner of the zonefile.
+ EOF
+ end
+
+ newparam(:group, parent: Puppet::Type::File::Group) do
+ desc <<-EOF
+ Group of the zonefile.
+ EOF
+ end
+
+ newparam(:backup) do
+ desc <<-EOF
+ Should the pre-existing file be backed up.
+
+ See the file resource's documentation for details.
+ EOF
+
+ validate do |value|
+ unless [TrueClass, FalseClass, String].include?(value.class)
+ raise ArgumentError, _('Backup must be a Boolean or String')
+ end
end
end
- # Create the file resource for us.
- def generate
- print("Generate\n")
- params = {
- ensure: :present,
- path: provider.filename,
- # notify: self[:notify],
- }
+ newparam(:selinux_ignore_defaults, boolean: true, parent: Puppet::Parameter::Boolean) do
+ desc <<-EOF
+ See the file resource's documentation for details.
+ EOF
+ end
- [Puppet::Type.type(:file).new(params)]
+ newparam(:selrange) do
+ desc <<-EOF
+ See the file resource's documentation for details.
+ EOF
+
+ validate do |value|
+ unless value.is_a?(String)
+ raise ArgumentError, _('Selrange must be a String')
+ end
+ end
end
- def should_content
- print("Getting content\n")
- provider.zone_content(records)
+ newparam(:selrole) do
+ desc <<-EOF
+ See the file resource's documentation for details.
+ EOF
+
+ validate do |value|
+ unless value.is_a?(String)
+ raise ArgumentError, _('Selrole must be a String')
+ end
+ end
end
+ newparam(:seltype) do
+ desc <<-EOF
+ See the file resource's documentation for details.
+ EOF
+
+ validate do |value|
+ unless value.is_a?(String)
+ raise ArgumentError, _('Seltype must be a String')
+ end
+ end
+ end
+
+ newparam(:seluser) do
+ desc <<-EOF
+ See the file resource's documentation for details.
+ EOF
+
+ validate do |value|
+ unless value.is_a?(String)
+ raise ArgumentError, _('Seluser must be a String')
+ end
+ end
+ end
+
+ newparam(:show_diff, boolean: true, parent: Puppet::Parameter::Boolean) do
+ desc <<-EOF
+ See the file resource's documentation for details.
+ EOF
+ end
end