module PuppetDB.Rest where
import qualified PuppetDB.Query as PDB
import Network.HTTP.Conduit
import qualified Network.HTTP.Types as W
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Char8 as BC
import Data.Aeson
import qualified Codec.Text.IConv as IConv
import qualified Control.Exception as X
import Control.Monad.Error
import Puppet.Utils
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
runRequest req = do
let doRequest = withManager (fmap responseBody . httpLbs req) :: IO L.ByteString
eHandler :: X.SomeException -> IO (Either String L.ByteString)
eHandler e = return $ Left $ show e ++ ", with queryString " ++ BC.unpack (queryString req)
mo <- liftIO (fmap Right doRequest `X.catch` eHandler)
case mo of
Right o -> do
let utf8 = IConv.convert "LATIN1" "UTF-8" o
case decode' utf8 of
Just x -> return x
Nothing -> throwError "Json decoding has failed"
Left err -> throwError err
pdbRequest :: (FromJSON a) => T.Text -> T.Text -> PDB.Query -> IO (Either String a)
pdbRequest url querytype qquery = rawRequest url querytype (PDB.showQuery qquery)
rawRequest :: (FromJSON a) => T.Text -> T.Text -> T.Text -> IO (Either String a)
rawRequest url querytype query = runErrorT $ do
unless (querytype `elem` ["resources", "nodes", "facts"]) (throwError $ "Invalid query type " ++ T.unpack querytype)
let q = case querytype of
"facts" -> T.cons '/' query
_ -> "?" <> T.decodeUtf8 (W.renderSimpleQuery False [("query", T.encodeUtf8 query)])
fullurl = T.unpack $ url <> "/v1/" <> querytype <> q
initReq <- case (parseUrl fullurl :: Maybe (Request a)) of
Just x -> return x
Nothing -> throwError "Something failed when parsing the PuppetDB URL"
let req = initReq { requestHeaders = [("Accept", "application/json")] }
runRequest req