summaryrefslogtreecommitdiff
path: root/Propellor/Property
diff options
context:
space:
mode:
authorJoey Hess2014-04-18 19:06:55 -0400
committerJoey Hess2014-04-18 19:13:22 -0400
commit8e22065deff41c3e476763ebd939a63856e6d54b (patch)
tree225977afe80478ebc3df1c71504cd46d6e474af1 /Propellor/Property
parent80caa6c09d8c15f0ed5d3ce147869b67c0c9f2a8 (diff)
better serial number offsets
Diffstat (limited to 'Propellor/Property')
-rw-r--r--Propellor/Property/Dns.hs82
1 files changed, 39 insertions, 43 deletions
diff --git a/Propellor/Property/Dns.hs b/Propellor/Property/Dns.hs
index 99a60145..cefbd712 100644
--- a/Propellor/Property/Dns.hs
+++ b/Propellor/Property/Dns.hs
@@ -3,12 +3,10 @@ module Propellor.Property.Dns (
secondary,
servingZones,
mkSOA,
- nextSerialNumber,
- incrSerialNumber,
- currentSerialNumber,
writeZoneFile,
- genZoneFile,
- genSOA,
+ nextSerialNumber,
+ adjustSerialNumber,
+ serialNumberOffset,
) where
import Propellor
@@ -19,7 +17,6 @@ import qualified Propellor.Property.Service as Service
import Utility.Applicative
import Data.List
-import Data.Time.Clock.POSIX
namedconf :: FilePath
namedconf = "/etc/bind/named.conf.local"
@@ -64,10 +61,18 @@ servingZones zs = hasContent namedconf (concatMap confStanza zs)
`onChange` Service.reloaded "bind9"
-- | Generates a SOA with some fairly sane numbers in it.
-mkSOA :: Domain -> [Record] -> SOA
-mkSOA d rs = SOA
+--
+-- The SerialNumber can be whatever serial number was used by the domain
+-- before propellor started managing it. Or 0 if the domain has only ever
+-- been managed by propellor.
+--
+-- You do not need to increment the SerialNumber when making changes!
+-- Propellor will automatically add the number of commits in the git
+-- repository to the SerialNumber.
+mkSOA :: Domain -> SerialNumber -> [Record] -> SOA
+mkSOA d sn rs = SOA
{ sDomain = AbsDomain d
- , sSerial = 1
+ , sSerial = sn
, sRefresh = hours 4
, sRetry = hours 1
, sExpire = 2419200 -- 4 weeks
@@ -102,47 +107,33 @@ rValue (TXT s) = [q] ++ filter (/= q) s ++ [q]
-- | Adjusts the serial number of the zone to
--
--- * Always be larger than the passed SerialNumber
-- * Always be larger than the serial number in the Zone record.
+-- * Always be larger than the passed SerialNumber
nextSerialNumber :: Zone -> SerialNumber -> Zone
-nextSerialNumber (Zone soa l) oldserial = Zone soa' l
- where
- soa' = soa { sSerial = succ $ max (sSerial soa) oldserial }
+nextSerialNumber z serial = adjustSerialNumber z $ \sn -> succ $ max sn serial
-incrSerialNumber :: Zone -> Zone
-incrSerialNumber (Zone soa l) = Zone soa' l
+adjustSerialNumber :: Zone -> (SerialNumber -> SerialNumber) -> Zone
+adjustSerialNumber (Zone soa l) f = Zone soa' l
where
- soa' = soa { sSerial = succ (sSerial soa) }
+ soa' = soa { sSerial = f (sSerial soa) }
--- | Propellor uses a serial number derived from the current date and time.
---
--- This ensures that, even if zone files are being generated on
--- multiple hosts, the serial numbers will not get out of sync between
--- them.
---
--- Since serial numbers are limited to 32 bits, the number of seconds
--- since the epoch is divided by 5. This will work until the year 2650,
--- at which point this stupid limit had better have been increased to
--- 128 bits. If we didn't divide by 5, it would only work up to 2106!
---
--- Dividing by 5 means that this number only changes once every 5 seconds.
--- If propellor is running more often than once every 5 seconds, you're
--- doing something wrong.
-currentSerialNumber :: IO SerialNumber
-currentSerialNumber = calc <$> getPOSIXTime
- where
- calc t = floor (t / 5)
+-- | Count the number of git commits made to the current branch.
+serialNumberOffset :: IO SerialNumber
+serialNumberOffset = fromIntegral . length . lines
+ <$> readProcess "git" ["log", "--pretty=%H"]
-- | Write a Zone out to a to a file.
--
--- The serial number that is written to the file comes from larger of the
--- Zone's SOA serial number, and the last serial number used in the file.
--- This ensures that serial number always increases, while also letting
--- a Zone contain an existing serial number, which may be quite large.
+-- The serial number in the Zone automatically has the serialNumberOffset
+-- added to it. Also, just in case, the old serial number used in the zone
+-- file is checked, and if it is somehow larger, its succ is used.
writeZoneFile :: Zone -> FilePath -> IO ()
writeZoneFile z f = do
- oldserial <- nextZoneFileSerialNumber f
- let z' = nextSerialNumber z oldserial
+ oldserial <- oldZoneFileSerialNumber f
+ offset <- serialNumberOffset
+ let z' = nextSerialNumber
+ (adjustSerialNumber z (+ offset))
+ (succ oldserial)
writeFile f (genZoneFile z')
writeZonePropellorFile f z'
@@ -152,9 +143,8 @@ writeZoneFile z f = do
zonePropellorFile :: FilePath -> FilePath
zonePropellorFile f = f ++ ".serial"
-nextZoneFileSerialNumber :: FilePath -> IO SerialNumber
-nextZoneFileSerialNumber = maybe 1 (sSerial . zSOA . incrSerialNumber)
- <$$> readZonePropellorFile
+oldZoneFileSerialNumber :: FilePath -> IO SerialNumber
+oldZoneFileSerialNumber = maybe 0 (sSerial . zSOA) <$$> readZonePropellorFile
writeZonePropellorFile :: FilePath -> Zone -> IO ()
writeZonePropellorFile f z = writeFile (zonePropellorFile f) (show z)
@@ -210,3 +200,9 @@ genSOA soa = unlines $
com :: String -> String
com s = "; " ++ s
+-- | Generates a Zone for a particular Domain from the DNS properies of all
+-- hosts that propellor knows about that are in that Domain.
+genZone :: [Host] -> Domain -> SOA -> Zone
+genZone hosts domain soa = Zone soa zhosts
+ where
+ zhosts = undefined -- TODO