powerdns-0.2.1: PowerDNS/API/Zones.hs
-- |
-- Module: PowerDNS.API.Zones
-- Description: Zones endpoints for PowerDNS API
--
-- Implementation of the API endpoints described at [PowerDNS Zones API](https://doc.powerdns.com/authoritative/http-api/zone.html)
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TypeOperators #-}
module PowerDNS.API.Zones
(
-- * API
ZonesAPI(..)
-- * Data types
, Zone(..)
, Kind(..)
, RRSets(..)
, RRSet(..)
, Record(..)
, Comment(..)
, ChangeType(..)
, RecordType(..)
)
where
import Data.Char (toUpper)
import Data.Data (Data)
import Data.Word (Word32)
import Control.DeepSeq (NFData)
import Data.Aeson (FromJSON(..), ToJSON(..), allNullaryToStringTag,
defaultOptions, fieldLabelModifier, constructorTagModifier,
genericParseJSON, genericToJSON, omitNothingFields)
import qualified Data.Text as T
import Data.Time.Clock.POSIX (POSIXTime)
import Servant.API
import Servant.API.Generic
import PowerDNS.Internal.Utils (Empty(..), strip)
----------------------------------------------------------------------------------------
data ZonesAPI f = ZonesAPI
{ apiListZones :: f :- "servers" :> Capture "server_id" T.Text :> "zones"
:> QueryParam "zone" T.Text
:> QueryParam "dnssec" Bool
:> Get '[JSON] [Zone]
, apiCreateZone :: f :- "servers" :> Capture "server_id" T.Text :> "zones"
:> QueryParam "rrset" Bool
:> ReqBody '[JSON] Zone
:> PostCreated '[JSON] Zone
, apiGetZone :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text
:> QueryParam "rrsets" Bool
:> Get '[JSON] Zone
, apiDeleteZone :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text
:> DeleteNoContent
, apiUpdateRecords :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text
:> ReqBody '[JSON] RRSets
:> PatchNoContent
, apiUpdateZone :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text
:> ReqBody '[JSON] Zone
:> PutNoContent
, apiTriggerAxfr :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text :> "axfr-retrieve"
:> Put '[JSON] NoContent
, apiNotifySlaves :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text :> "notify"
:> Put '[JSON] NoContent
, apiGetZoneAxfr :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text :> "export"
:> Get '[JSON] T.Text
, apiRectifyZone :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text :> "rectify"
:> Put '[JSON] T.Text
} deriving Generic
----------------------------------------------------------------------------------------
-- | Zone according to [PowerDNS Documentation](https://doc.powerdns.com/authoritative/http-api/zone.html#zone).
-- All fields are optional because the PowerDNS API differs on which fields are required depending on the endpoint.
data Zone = Zone
{ zone_id :: Maybe T.Text
, zone_name :: Maybe T.Text
, zone_type :: Maybe T.Text
, zone_url :: Maybe T.Text
, zone_kind :: Maybe Kind
, zone_rrsets :: Maybe [RRSet]
, zone_serial :: Maybe Integer
, zone_notified_serial :: Maybe Integer
, zone_edited_serial :: Maybe Integer
, zone_masters :: Maybe [T.Text]
, zone_dnssec :: Maybe Bool
, zone_nsec3param :: Maybe T.Text
, zone_nsec3narrow :: Maybe Bool
, zone_presigned :: Maybe Bool
, zone_soa_edit :: Maybe T.Text
, zone_soa_edit_api :: Maybe T.Text
, zone_api_rectify :: Maybe Bool
, zone_zone :: Maybe T.Text
, zone_account :: Maybe T.Text
, zone_nameservers :: Maybe [T.Text]
, zone_master_tsig_key_ids :: Maybe [T.Text]
, zone_slave_tsig_key_ids :: Maybe [T.Text]
} deriving (Eq, Ord, Show, Generic, NFData, Data, Empty)
instance ToJSON Zone where
toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "zone_"}
instance FromJSON Zone where
parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "zone_"}
----------------------------------------------------------------------------------------
data Kind = Native | Master | Slave
deriving (Eq, Ord, Show, Generic, NFData, Data)
instance ToJSON Kind where
toJSON = genericToJSON defaultOptions { allNullaryToStringTag = True }
instance FromJSON Kind where
parseJSON = genericParseJSON defaultOptions { allNullaryToStringTag = True }
----------------------------------------------------------------------------------------
-- | A list of RRSets
data RRSets = RRSets
{ rrsets :: [RRSet]
} deriving (Eq, Ord, Show, Generic, NFData, Data)
instance ToJSON RRSets
instance FromJSON RRSets
----------------------------------------------------------------------------------------
-- | RRSet according to [PowerDNS Documentation](https://doc.powerdns.com/authoritative/http-api/zone.html#rrset).
data RRSet = RRSet
{ rrset_name :: T.Text
, rrset_type :: RecordType
, rrset_ttl :: Word32
, rrset_changetype :: Maybe ChangeType
, rrset_records :: Maybe [Record]
, rrset_comments :: Maybe [Comment]
} deriving (Eq, Ord, Show, Generic, NFData, Data)
instance ToJSON RRSet where
toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "rrset_"
, omitNothingFields = True }
instance FromJSON RRSet where
parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "rrset_"
, omitNothingFields = True }
----------------------------------------------------------------------------------------
data RecordType = A
| AAAA
| AFSDB
| ALIAS
| APL
| CAA
| CERT
| CDNSKEY
| CDS
| CNAME
| DNSKEY
| DNAME
| DS
| HINFO
| KEY
| LOC
| MX
| NAPTR
| NS
| NSEC
| NSEC3
| NSEC3PARAM
| OPENPGPKEY
| PTR
| RP
| RRSIG
| SOA
| SPF
| SSHFP
| SRV
| TKEY
| TSIG
| TLSA
| SMIMEA
| TXT
| URI
| A6
| DHCID
| DLV
| EUI48
| EUI64
| IPSECKEY
| KX
| MAILA
| MAILB
| MINFO
| MR
| RKEY
| SIG
| WKS
deriving (Eq, Ord, Show, Generic, NFData, Data)
instance ToJSON RecordType where
toJSON = genericToJSON defaultOptions { allNullaryToStringTag = True
}
instance FromJSON RecordType where
parseJSON = genericParseJSON defaultOptions { allNullaryToStringTag = True
}
----------------------------------------------------------------------------------------
-- | Whether or not an 'RRSet' replace or delete an existing entry.
-- If the 'ChangeType' is left at @Nothing@ it will create a new domain entry.
data ChangeType = Replace
| Delete
deriving (Eq, Ord, Show, Generic, NFData, Data)
instance ToJSON ChangeType where
toJSON = genericToJSON defaultOptions { constructorTagModifier = fmap toUpper
, allNullaryToStringTag = True }
instance FromJSON ChangeType where
parseJSON = genericParseJSON defaultOptions { constructorTagModifier = fmap toUpper
, allNullaryToStringTag = True }
----------------------------------------------------------------------------------------
-- | Record according to [PowerDNS Documentation](https://doc.powerdns.com/authoritative/http-api/zone.html#record)
data Record = Record
{ record_content :: T.Text
, record_disabled :: Bool
} deriving (Eq, Ord, Show, Generic, NFData, Data)
instance ToJSON Record where
toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "record_"
, omitNothingFields = True }
instance FromJSON Record where
parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "record_"
, omitNothingFields = True }
----------------------------------------------------------------------------------------
-- | Comment according to [PowerDNS Documentation](https://doc.powerdns.com/authoritative/http-api/zone.html#comment)
data Comment = Comment
{ comment_content :: Maybe T.Text
, comment_account :: Maybe T.Text
, commant_modified_at :: Maybe POSIXTime
} deriving (Eq, Ord, Show, Generic, NFData, Data, Empty)
instance ToJSON Comment where
toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "comment_" }
instance FromJSON Comment where
parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "comment_" }