packages feed

powerdns 0.4.1 → 0.4.2

raw patch · 11 files changed

+305/−330 lines, 11 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ PowerDNS.API.Zones: Result :: Text -> Result
+ PowerDNS.API.Zones: data Result
+ PowerDNS.API.Zones: instance Data.Aeson.Types.FromJSON.FromJSON PowerDNS.API.Zones.Result
+ PowerDNS.API.Zones: instance Data.Aeson.Types.ToJSON.ToJSON PowerDNS.API.Zones.Result
+ PowerDNS.Client: Result :: Text -> Result
+ PowerDNS.Client: data Result
- PowerDNS.API.Zones: ZonesAPI :: (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (QueryParam "zone" Text :> (QueryParam "dnssec" Bool :> Get '[JSON] [Zone])))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (QueryParam "rrset" Bool :> (ReqBody '[JSON] Zone :> PostCreated '[JSON] Zone)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> (QueryParam "rrsets" Bool :> Get '[JSON] Zone)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> DeleteNoContent))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> (ReqBody '[JSON] RRSets :> PatchNoContent)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> (ReqBody '[JSON] Zone :> PutNoContent)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("axfr-retrieve" :> Put '[JSON] NoContent)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("notify" :> Put '[JSON] NoContent)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("export" :> Get '[JSON] Text)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("rectify" :> Put '[JSON] Text)))))) -> ZonesAPI f
+ PowerDNS.API.Zones: ZonesAPI :: (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (QueryParam "zone" Text :> (QueryParam "dnssec" Bool :> Get '[JSON] [Zone])))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (QueryParam "rrset" Bool :> (ReqBody '[JSON] Zone :> PostCreated '[JSON] Zone)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> (QueryParam "rrsets" Bool :> Get '[JSON] Zone)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> DeleteNoContent))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> (ReqBody '[JSON] RRSets :> PatchNoContent)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> (ReqBody '[JSON] Zone :> PutNoContent)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("axfr-retrieve" :> Put '[JSON] Result)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("notify" :> Put '[JSON] Result)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("export" :> Get '[JSON] Result)))))) -> (f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("rectify" :> Put '[JSON] Result)))))) -> ZonesAPI f
- PowerDNS.API.Zones: [apiGetZoneAxfr] :: ZonesAPI f -> f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("export" :> Get '[JSON] Text)))))
+ PowerDNS.API.Zones: [apiGetZoneAxfr] :: ZonesAPI f -> f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("export" :> Get '[JSON] Result)))))
- PowerDNS.API.Zones: [apiNotifySlaves] :: ZonesAPI f -> f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("notify" :> Put '[JSON] NoContent)))))
+ PowerDNS.API.Zones: [apiNotifySlaves] :: ZonesAPI f -> f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("notify" :> Put '[JSON] Result)))))
- PowerDNS.API.Zones: [apiRectifyZone] :: ZonesAPI f -> f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("rectify" :> Put '[JSON] Text)))))
+ PowerDNS.API.Zones: [apiRectifyZone] :: ZonesAPI f -> f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("rectify" :> Put '[JSON] Result)))))
- PowerDNS.API.Zones: [apiTriggerAxfr] :: ZonesAPI f -> f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("axfr-retrieve" :> Put '[JSON] NoContent)))))
+ PowerDNS.API.Zones: [apiTriggerAxfr] :: ZonesAPI f -> f :- ("servers" :> (Capture "server_id" Text :> ("zones" :> (Capture "zone_id" Text :> ("axfr-retrieve" :> Put '[JSON] Result)))))
- PowerDNS.Client: getZoneAxfr :: Text -> Text -> ClientM Text
+ PowerDNS.Client: getZoneAxfr :: Text -> Text -> ClientM Result
- PowerDNS.Client: notifySlaves :: Text -> Text -> ClientM NoContent
+ PowerDNS.Client: notifySlaves :: Text -> Text -> ClientM Result
- PowerDNS.Client: rectifyZone :: Text -> Text -> ClientM Text
+ PowerDNS.Client: rectifyZone :: Text -> Text -> ClientM Result
- PowerDNS.Client: triggerAxfr :: Text -> Text -> ClientM NoContent
+ PowerDNS.Client: triggerAxfr :: Text -> Text -> ClientM Result

Files

CHANGELOG.md view
@@ -34,3 +34,18 @@ ## 0.4.1 -- 2022-04-22  * Relax various constraints++## 0.4.1 -- 2022-04-22++* Add new datatype Result+* Fix the following endpoints to produce 'Result' rather than NoContent+    * apiTriggerAxfr+    * apiNotifySlaves+    * apiGetZoneAxfr+    * apiRectifyZone+* Fix the following client functions similarly:+    * triggerAxfr+    * notifySlaves+    * getZoneAxfr+    * rectifyZone+* Improve compilation time by switching to TH for JSON instances
PowerDNS/API.hs view
@@ -4,9 +4,9 @@ -- -- This module exports a complete servant API description of the PowerDNS. May be useful to some. -{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DataKinds     #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeOperators #-} module PowerDNS.API   ( API   , api@@ -20,18 +20,17 @@   ) where -import           GHC.Generics (Generic)-import           Data.Proxy (Proxy(..))+import Data.Proxy (Proxy(..))+import GHC.Generics (Generic) -import           Servant.API-import           Servant.API.Generic ((:-), ToServantApi)+import Servant.API -import           PowerDNS.API.Version-import           PowerDNS.API.Zones-import           PowerDNS.API.Servers-import           PowerDNS.API.Cryptokeys-import           PowerDNS.API.Metadata-import           PowerDNS.API.TSIGKeys+import PowerDNS.API.Cryptokeys+import PowerDNS.API.Metadata+import PowerDNS.API.Servers+import PowerDNS.API.TSIGKeys+import PowerDNS.API.Version+import PowerDNS.API.Zones  api :: Proxy API api = Proxy@@ -46,4 +45,3 @@   , metadata   :: f :- "api" :> "v1" :> ToServantApi MetadataAPI   , tsigkeys   :: f :- "api" :> "v1" :> ToServantApi TSIGKeysAPI   } deriving Generic-
PowerDNS/API/Cryptokeys.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric      #-} {-# LANGUAGE TypeOperators      #-}+{-# LANGUAGE TemplateHaskell    #-} module PowerDNS.API.Cryptokeys   (   -- * API@@ -22,9 +23,9 @@ import           Data.Data (Data)  import           Control.DeepSeq (NFData)-import           Data.Aeson (FromJSON(..), ToJSON(..), defaultOptions,-                             fieldLabelModifier, genericParseJSON,-                             genericToJSON)+import           Data.Aeson.TH (defaultOptions,+                             fieldLabelModifier,+                             deriveJSON) import qualified Data.Text as T import           Servant.API import           Servant.API.Generic@@ -66,8 +67,4 @@     , ck_bits :: Maybe Integer     } deriving (Eq, Ord, Show, Generic, NFData, Data, Empty) -instance ToJSON Cryptokey where-  toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "ck_"}--instance FromJSON Cryptokey where-  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "ck_"}+$(deriveJSON defaultOptions { fieldLabelModifier = strip "ck_"} ''Cryptokey)
PowerDNS/API/Metadata.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric      #-} {-# LANGUAGE TypeOperators      #-}+{-# LANGUAGE TemplateHaskell    #-} module PowerDNS.API.Metadata   (   -- * API@@ -20,10 +21,9 @@ where  import           Control.DeepSeq (NFData)-import           Data.Aeson ( FromJSON(..), ToJSON(..)-                            , defaultOptions, fieldLabelModifier-                            , genericParseJSON, genericToJSON-                            )+import           Data.Aeson.TH ( defaultOptions, fieldLabelModifier+                               , deriveJSON+                               )  import           Data.Data (Data) import qualified Data.Text as T@@ -56,8 +56,4 @@   , md_metadata :: [T.Text]   } deriving (Eq, Ord, Show, Generic, NFData, Data) -instance ToJSON Metadata where-  toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "md_"}--instance FromJSON Metadata where-  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "md_"}+$(deriveJSON defaultOptions { fieldLabelModifier = strip "md_" } ''Metadata)
PowerDNS/API/Servers.hs view
@@ -6,6 +6,7 @@  {-# LANGUAGE DataKinds          #-} {-# LANGUAGE DeriveAnyClass     #-}+{-# LANGUAGE TemplateHaskell    #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric      #-} {-# LANGUAGE TypeOperators      #-}@@ -34,13 +35,12 @@ import           Text.Read (readMaybe)  import           Control.DeepSeq (NFData)-import           Data.Aeson (FromJSON(..), ToJSON(..), defaultOptions-                            , Value(String)+import           Data.Aeson.TH (defaultOptions                             , fieldLabelModifier, constructorTagModifier-                            , genericParseJSON+                            , deriveJSON                             , allNullaryToStringTag-                            , genericToJSON-                            , (.:), (.=)+                            )+import           Data.Aeson (FromJSON(..), ToJSON(..), Value(String), (.:), (.=)                             , withObject, object                             ) import           Data.Aeson.Types (Parser)@@ -52,32 +52,6 @@  ---------------------------------------------------------------------------------------- -type QueryParamReq = QueryParam' [Required, Strict]-data ServersAPI f = ServersAPI-  { apiListServers :: f :- "servers"-                        :> Get '[JSON] [Server]--  , apiGetServer   :: f :- "servers" :> Capture "server_id" T.Text-                        :> Get '[JSON] Server--  , apiSearch      :: f :- "servers" :> Capture "server_id" T.Text :> "search-data"-                        :> QueryParamReq "q" T.Text-                        :> QueryParamReq "max" Integer-                        :> QueryParam "object_type" ObjectType-                        :> Get '[JSON] [SearchResult]--  , apiFlushCache  :: f :- "servers" :> Capture "server_id" T.Text-                        :> QueryParamReq "domain" T.Text-                        :> Put '[JSON] CacheFlushResult--  , apiStatistics  :: f :- "servers" :> Capture "server_id" T.Text :> "statistics"-                        :> QueryParam "statistic" T.Text-                        :> QueryParam "includerings" Bool-                        :> Get '[JSON] [AnyStatisticItem]-  } deriving Generic------------------------------------------------------------------------------------------- data Server = Server   { server_type :: Maybe T.Text   , server_id :: Maybe T.Text@@ -88,45 +62,18 @@   , server_zones_url :: Maybe T.Text   } deriving (Eq, Ord, Show, Generic, NFData, Data, Empty) -instance ToJSON Server where-  toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "server_"}--instance FromJSON Server where-  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "server_"}+$(deriveJSON defaultOptions { fieldLabelModifier = strip "server_" } ''Server)  ---------------------------------------------------------------------------------------- -data SearchResult = SearchResult-  { sr_content :: T.Text-  , sr_disabled :: Bool-  , sr_name :: T.Text-  , sr_object_type :: ObjectType-  , sr_zone_id :: T.Text-  , sr_zone :: T.Text-  , sr_type :: T.Text-  , sr_ttl :: Integer-  } deriving (Eq, Ord, Show, Generic, NFData, Data)--instance ToJSON SearchResult where-  toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "sr_"}--instance FromJSON SearchResult where-  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "sr_"}------------------------------------------------------------------------------------------ data ObjectType = TyAll                 | TyZone                 | TyRecord                 | TyComment                 deriving (Eq, Ord, Show, Generic, NFData, Data) -instance ToJSON ObjectType where-  toJSON = genericToJSON defaultOptions { constructorTagModifier = map1 toLower . strip "Ty"-                                        , allNullaryToStringTag = True }--instance FromJSON ObjectType where-  parseJSON = genericParseJSON defaultOptions { constructorTagModifier = map1 toLower . strip "Ty"-                                              , allNullaryToStringTag = True }+$(deriveJSON defaultOptions { constructorTagModifier = map1 toLower . strip "Ty"+                            , allNullaryToStringTag = True } ''ObjectType)  instance FromHttpApiData ObjectType where   parseQueryParam "all" = Right TyAll@@ -143,17 +90,37 @@  ---------------------------------------------------------------------------------------- +data SearchResult = SearchResult+  { sr_content :: T.Text+  , sr_disabled :: Bool+  , sr_name :: T.Text+  , sr_object_type :: ObjectType+  , sr_zone_id :: T.Text+  , sr_zone :: T.Text+  , sr_type :: T.Text+  , sr_ttl :: Integer+  } deriving (Eq, Ord, Show, Generic, NFData, Data)++$(deriveJSON defaultOptions { fieldLabelModifier = strip "sr_" } ''SearchResult)++----------------------------------------------------------------------------------------+ data CacheFlushResult = CacheFlushResult   { cfr_count :: Integer   , cfr_result :: T.Text   } deriving (Eq, Ord, Show, Generic, NFData, Data) -instance ToJSON CacheFlushResult where-  toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "cfr_"}+$(deriveJSON defaultOptions { fieldLabelModifier = strip "cfr_" } ''CacheFlushResult) -instance FromJSON CacheFlushResult where-  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "cfr_"}+---------------------------------------------------------------------------------------- +data SimpleStatisticItem = SimpleStatisticItem+  { ssi_name :: T.Text+  , ssi_value :: T.Text+  } deriving (Eq, Ord, Show, Generic, NFData, Data)++$(deriveJSON defaultOptions { fieldLabelModifier = strip "ssi_" } ''SimpleStatisticItem)+ ----------------------------------------------------------------------------------------  data AnyStatisticItem = AnyStatisticItem StatisticItem@@ -211,13 +178,28 @@   , rsi_value :: [SimpleStatisticItem]   } deriving (Eq, Ord, Show, Generic, NFData, Data) -data SimpleStatisticItem = SimpleStatisticItem-  { ssi_name :: T.Text-  , ssi_value :: T.Text-  } deriving (Eq, Ord, Show, Generic, NFData, Data)+---------------------------------------------------------------------------------------- -instance ToJSON SimpleStatisticItem where-  toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "ssi_"}+type QueryParamReq = QueryParam' [Required, Strict]+data ServersAPI f = ServersAPI+  { apiListServers :: f :- "servers"+                        :> Get '[JSON] [Server] -instance FromJSON SimpleStatisticItem where-  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "ssi_"}+  , apiGetServer   :: f :- "servers" :> Capture "server_id" T.Text+                        :> Get '[JSON] Server++  , apiSearch      :: f :- "servers" :> Capture "server_id" T.Text :> "search-data"+                        :> QueryParamReq "q" T.Text+                        :> QueryParamReq "max" Integer+                        :> QueryParam "object_type" ObjectType+                        :> Get '[JSON] [SearchResult]++  , apiFlushCache  :: f :- "servers" :> Capture "server_id" T.Text+                        :> QueryParamReq "domain" T.Text+                        :> Put '[JSON] CacheFlushResult++  , apiStatistics  :: f :- "servers" :> Capture "server_id" T.Text :> "statistics"+                        :> QueryParam "statistic" T.Text+                        :> QueryParam "includerings" Bool+                        :> Get '[JSON] [AnyStatisticItem]+  } deriving Generic
PowerDNS/API/TSIGKeys.hs view
@@ -12,6 +12,7 @@ {-# LANGUAGE OverloadedStrings  #-} {-# LANGUAGE RecordWildCards    #-} {-# LANGUAGE TypeOperators      #-}+{-# LANGUAGE TemplateHaskell    #-} module PowerDNS.API.TSIGKeys   (   -- * API@@ -30,9 +31,10 @@  import           Control.DeepSeq (NFData) import           Data.Aeson (FromJSON(..), ToJSON(..), Value(String),-                             allNullaryToStringTag, constructorTagModifier,-                             defaultOptions, genericParseJSON, genericToJSON,                              object, withObject, (.:), (.:?), (.=))++import           Data.Aeson.TH (allNullaryToStringTag, constructorTagModifier,+                                defaultOptions, deriveJSON) import qualified Data.ByteString as BS import qualified Data.ByteString.Base64 as BS64 import qualified Data.Text as T@@ -71,6 +73,25 @@   -- ^ Unlike the original PowerDNS API we do not require the key to be base64 encoded.   } deriving (Eq, Ord, Show, Generic, NFData, Data) +----------------------------------------------------------------------------------------++-- | Supported algorithms according to [PowerDNS TSIG Documentation](https://doc.powerdns.com/authoritative/tsig.html#tsig)+data TSIGAlgorithm = HMAC_MD5+                   | HMAC_SHA1+                   | HMAC_SHA224+                   | HMAC_SHA256+                   | HMAC_SHA384+                   | HMAC_SHA512+                   deriving (Eq, Ord, Show, Generic, NFData, Data)++$(deriveJSON defaultOptions { allNullaryToStringTag = True+                            , constructorTagModifier = fmap $ \c ->+                                if c == '_' then '-' else toLower c+                            } ''TSIGAlgorithm)+++----------------------------------------------------------------------------------------+ instance ToJSON TSIGKey where   toJSON key = object [ "name" .= tsk_name key                       , "id" .= tsk_id key@@ -94,27 +115,3 @@ decode64 i = case BS64.decode (T.encodeUtf8 i) of   Left err -> Fail.fail err   Right k  -> pure k---------------------------------------------------------------------------------------------- | Supported algorithms according to [PowerDNS TSIG Documentation](https://doc.powerdns.com/authoritative/tsig.html#tsig)-data TSIGAlgorithm = HMAC_MD5-                   | HMAC_SHA1-                   | HMAC_SHA224-                   | HMAC_SHA256-                   | HMAC_SHA384-                   | HMAC_SHA512-                   deriving (Eq, Ord, Show, Generic, NFData, Data)--instance ToJSON TSIGAlgorithm where-  toJSON = genericToJSON defaultOptions { allNullaryToStringTag = True-                                        , constructorTagModifier = algo-                                        }--instance FromJSON TSIGAlgorithm where-  parseJSON = genericParseJSON defaultOptions { allNullaryToStringTag = True-                                              , constructorTagModifier = algo-                                              }--algo :: String -> String-algo = fmap (\c -> if c == '_' then '-' else toLower c)
PowerDNS/API/Version.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric      #-} {-# LANGUAGE TypeOperators      #-}+{-# LANGUAGE TemplateHaskell    #-} module PowerDNS.API.Version   (   -- * API@@ -22,8 +23,7 @@ import           Data.Data (Data)  import           Control.DeepSeq (NFData)-import           Data.Aeson (FromJSON(..), ToJSON(..), defaultOptions, fieldLabelModifier,-                             genericParseJSON, genericToJSON)+import           Data.Aeson.TH (defaultOptions, fieldLabelModifier, deriveJSON)  import qualified Data.Text as T import           Servant.API@@ -40,9 +40,5 @@   , version_url :: T.Text   } deriving (Eq, Ord, Show, Generic, NFData, Data) -instance ToJSON Version where-  toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "version_" }--instance FromJSON Version where-  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "version_" }+$(deriveJSON defaultOptions { fieldLabelModifier = strip "version_" } ''Version)   
PowerDNS/API/Zones.hs view
@@ -9,6 +9,8 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric      #-} {-# LANGUAGE TypeOperators      #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE TemplateHaskell  #-} module PowerDNS.API.Zones   (   -- * API@@ -26,6 +28,7 @@    -- * Utilities   , CIText+  , Result(..)   , mkCIText   , original   , caseFolded@@ -41,10 +44,11 @@ import           Text.Read (readPrec)  import           Control.DeepSeq (NFData(..), deepseq)-import           Data.Aeson (FromJSON(..), ToJSON(..), allNullaryToStringTag,-                             constructorTagModifier, defaultOptions,-                             fieldLabelModifier, genericParseJSON,-                             genericToJSON, omitNothingFields)+import           Data.Aeson.TH (allNullaryToStringTag,+                                constructorTagModifier, defaultOptions,+                                fieldLabelModifier,+                                deriveJSON, omitNothingFields)+import           Data.Aeson (FromJSON(..), ToJSON(..), object, (.:), (.=), withObject) import           Data.Hashable (Hashable(..)) import qualified Data.Text as T import           Data.Time.Clock.POSIX (POSIXTime)@@ -55,114 +59,106 @@  ---------------------------------------------------------------------------------------- -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+-- | 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) -  } deriving Generic+$(deriveJSON defaultOptions { fieldLabelModifier = strip "record_"+                            , omitNothingFields = True } ''Record)   ---------------------------------------------------------------------------------------- --- | 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.------ Note that 'Eq' and 'Ord' use limited case-sensitivity on 'zone_name' and equivalently contained rrset names--- as per [RFC4343](https://datatracker.ietf.org/doc/html/rfc4343)-data Zone = Zone-  { zone_id :: Maybe T.Text-  , zone_name :: Maybe CIText-  , 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]+-- | 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+  , comment_modified_at :: Maybe POSIXTime   } 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_"}+$(deriveJSON defaultOptions { fieldLabelModifier = strip "comment_" } ''Comment)  ---------------------------------------------------------------------------------------- -data Kind = Native | Master | Slave-  deriving (Eq, Ord, Show, Generic, NFData, Data)+-- | 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 Kind where-  toJSON = genericToJSON defaultOptions { allNullaryToStringTag = True }+$(deriveJSON defaultOptions { constructorTagModifier = fmap toUpper+                            , allNullaryToStringTag = True } ''ChangeType) -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)+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 RRSets-instance FromJSON RRSets+$(deriveJSON defaultOptions { allNullaryToStringTag = True+                            } ''RecordType) + ----------------------------------------------------------------------------------------  -- | A wrapper for 'T.Text' implementing limited case-sensitivity as per [RFC4343](https://datatracker.ietf.org/doc/html/rfc4343). -- Use 'mkCIText' for construction. -- -- See 'original' and 'caseFolded' for extracting a 'T.Text' back.-data CIText = CIText { ciOriginal :: T.Text, ciCaseFolded :: T.Text } deriving Data +data CIText = CIText { ciOriginal :: T.Text, ciCaseFolded :: T.Text } deriving Data  -- | Obtain the original 'T.Text' from a 'CIText'. original :: CIText -> T.Text@@ -219,6 +215,8 @@            | otherwise            = x +----------------------------------------------------------------------------------------+ -- | RRSet according to [PowerDNS Documentation](https://doc.powerdns.com/authoritative/http-api/zone.html#rrset). -- -- Note that 'Eq' and 'Ord' use limited case-sensitivity on 'rrset_name' as per [RFC4343](https://datatracker.ietf.org/doc/html/rfc4343)@@ -231,118 +229,107 @@   , rrset_comments :: Maybe [Comment]   } deriving (Eq, Ord, Show, Generic, NFData, Data) -instance ToJSON RRSet where-  toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "rrset_"-                                        , omitNothingFields = True }+$(deriveJSON defaultOptions { fieldLabelModifier = strip "rrset_"+                            , omitNothingFields = True } ''RRSet) -instance FromJSON RRSet where-  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "rrset_"-                                              , omitNothingFields = True }+---------------------------------------------------------------------------------------- +-- | A list of RRSets+data RRSets = RRSets+  { rrsets :: [RRSet]+  } deriving (Eq, Ord, Show, Generic, NFData, Data)++instance ToJSON RRSets+instance FromJSON RRSets+ ---------------------------------------------------------------------------------------- -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)+data Kind = Native | Master | Slave+  deriving (Eq, Ord, Show, Generic, NFData, Data) -instance ToJSON RecordType where-  toJSON = genericToJSON defaultOptions { allNullaryToStringTag = True-                                        }+$(deriveJSON defaultOptions { allNullaryToStringTag = True } ''Kind) -instance FromJSON RecordType where-  parseJSON = genericParseJSON defaultOptions { allNullaryToStringTag = True-                                              }+---------------------------------------------------------------------------------------- +-- | 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.+--+-- Note that 'Eq' and 'Ord' use limited case-sensitivity on 'zone_name' and equivalently contained rrset names+-- as per [RFC4343](https://datatracker.ietf.org/doc/html/rfc4343)+data Zone = Zone+  { zone_id :: Maybe T.Text+  , zone_name :: Maybe CIText+  , 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)++$(deriveJSON defaultOptions { fieldLabelModifier = strip "zone_" } ''Zone)+ ---------------------------------------------------------------------------------------- --- | 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)+data ZonesAPI f = ZonesAPI+  { apiListZones     :: f :- "servers" :> Capture "server_id" T.Text :> "zones"+                          :> QueryParam "zone" T.Text+                          :> QueryParam "dnssec" Bool+                          :> Get '[JSON] [Zone] -instance ToJSON ChangeType where-  toJSON = genericToJSON defaultOptions { constructorTagModifier = fmap toUpper-                                        , allNullaryToStringTag = True }+  , apiCreateZone    :: f :- "servers" :> Capture "server_id" T.Text :> "zones"+                          :> QueryParam "rrset" Bool+                          :> ReqBody '[JSON] Zone+                          :> PostCreated '[JSON] Zone -instance FromJSON ChangeType where-  parseJSON = genericParseJSON defaultOptions { constructorTagModifier = fmap toUpper-                                              , allNullaryToStringTag = True }+  , apiGetZone       :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text+                          :> QueryParam "rrsets" Bool+                          :> Get '[JSON] Zone -------------------------------------------------------------------------------------------- | 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)+  , apiDeleteZone    :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text+                          :> DeleteNoContent -instance ToJSON Record where-  toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "record_"-                                        , omitNothingFields = True }+  , apiUpdateRecords :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text+                          :> ReqBody '[JSON] RRSets+                          :> PatchNoContent -instance FromJSON Record where-  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "record_"-                                              , omitNothingFields = True }+  , 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] Result --- | 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-  , comment_modified_at :: Maybe POSIXTime-  } deriving (Eq, Ord, Show, Generic, NFData, Data, Empty)+  , apiNotifySlaves  :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text :> "notify"+                          :> Put '[JSON] Result -instance ToJSON Comment where-  toJSON = genericToJSON defaultOptions { fieldLabelModifier = strip "comment_" }+  , apiGetZoneAxfr   :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text :> "export"+                          :> Get '[JSON] Result -instance FromJSON Comment where-  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = strip "comment_" }+  , apiRectifyZone   :: f :- "servers" :> Capture "server_id" T.Text :> "zones" :> Capture "zone_id" T.Text :> "rectify"+                          :> Put '[JSON] Result++  } deriving Generic+++data Result = Result T.Text++instance ToJSON Result where+  toJSON (Result t) = object ["result" .= t]++instance FromJSON Result where+  parseJSON = withObject "result" $ \o -> Result <$> (o .: "result")
PowerDNS/Client.hs view
@@ -52,6 +52,7 @@   , Comment(..)   , ChangeType(..)   , RecordType(..)+  , Result(..)    -- * Cryptokeys   -- | See documentation at [PowerDNS Cryptokeys API](https://doc.powerdns.com/authoritative/http-api/cryptokey.html)@@ -208,25 +209,25 @@ -- | Trigger zone transfer on a slave. See [Zones API Documentation](https://doc.powerdns.com/authoritative/http-api/zone.html#put--servers-server_id-zones-zone_id-axfr-retrieve) triggerAxfr :: T.Text       -- ^ Server name             -> T.Text       -- ^ Zone ID-            -> ClientM NoContent+            -> ClientM Result triggerAxfr = apiTriggerAxfr zonesClient  -- | Send DNS notify to slaves. See [Zones API Documentation](https://doc.powerdns.com/authoritative/http-api/zone.html#put--servers-server_id-zones-zone_id-notify) notifySlaves :: T.Text       -- ^ Server name              -> T.Text       -- ^ Zone ID-             -> ClientM NoContent+             -> ClientM Result notifySlaves = apiNotifySlaves zonesClient  -- | Return zone in AXFR format. See [Zones API Documentation](https://doc.powerdns.com/authoritative/http-api/zone.html#get--servers-server_id-zones-zone_id-export) getZoneAxfr :: T.Text         -- ^ Server name             -> T.Text         -- ^ Zone ID-            -> ClientM T.Text -- ^ Zone in AXFR format+            -> ClientM Result -- ^ Zone in AXFR format getZoneAxfr = apiGetZoneAxfr zonesClient  -- | Rectify the zone data. See [Zones API Documentation](https://doc.powerdns.com/authoritative/http-api/zone.html#put--servers-server_id-zones-zone_id-rectify) rectifyZone :: T.Text       -- ^ Server name             -> T.Text       -- ^ Zone ID-            -> ClientM T.Text+            -> ClientM Result rectifyZone = apiRectifyZone zonesClient  ----------------------------------------------------------------------------------------
powerdns.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               powerdns-version:            0.4.1+version:            0.4.2 license:            BSD-3-Clause license-file:       LICENSE copyright:          (c) 2021 Victor Nawothnig@@ -12,12 +12,12 @@ description:     PowerDNS API allows programmatic manipulation of zones and other metadata. This     library is a thin wrapper, exposing most of the idiosyncracies directly.-    .+     Users are advised to refer to the PowerDNS documentation and its source code for     the exact semantics.-    .+     All exposed API endpoints are provided.-    .+     > import qualified PowerDNS.Client as P     > import           Network.HTTP.Client (newManager, defaultManagerSettings)     > import           Servant.Client (runClientM, mkClientEnv, parseBarseUrl)@@ -58,7 +58,7 @@     ghc-options:      -Wall -Wcompat     build-depends:         aeson ^>= { 1.5.6, 2.0.3.0 },-        bytestring ^>= { 0.10.10 },+        bytestring ^>= { 0.10.10, 0.11.0 },         deepseq ^>= { 1.4.4 },         containers ^>= { 0.6.2 },         hashable ^>= { 1.3.0.0 },
spec/Spec.hs view
@@ -97,6 +97,12 @@     step "Add record to zone"     runOk (updateZone "localhost" zoneId (patch added)) +    step "Trigger notify"+    runOk (notifySlaves "localhost" zoneId)++    step "Trigger rectify"+    runOk (rectifyZone "localhost" zoneId)+     step "Delete a record"     runOk (updateZone "localhost" zoneId (patch deleted))