{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} module PuppetDB.Remote (pdbConnect) where import XPrelude import Network.HTTP.Client (Manager) import Servant.API import Servant.Client import Facter import Puppet.Language import PuppetDB.Core type PDBAPIv3 = "nodes" :> QueryParam "query" (Query NodeField) :> Get '[JSON] [NodeInfo] :<|> "nodes" :> Capture "resourcename" Text :> "resources" :> QueryParam "query" (Query ResourceField) :> Get '[JSON] [Resource] :<|> "facts" :> QueryParam "query" (Query FactField) :> Get '[JSON] [FactInfo] :<|> "resources" :> QueryParam "query" (Query ResourceField) :> Get '[JSON] [Resource] type PDBAPI = "v3" :> PDBAPIv3 api :: Proxy PDBAPI api = Proxy #if !MIN_VERSION_servant(0,13,0) mkClientEnv :: Manager -> BaseUrl -> ClientEnv mkClientEnv = ClientEnv #endif #if !MIN_VERSION_servant_client(0,16,0) #define ClientError ServantError #endif -- | Given an URL (ie. @http://localhost:8080@), will return an incomplete 'PuppetDBAPI'. pdbConnect :: Manager -> String -> IO (Either PrettyError (PuppetDBAPI IO)) pdbConnect mgr url = do url' <- parseBaseUrl url let env = mkClientEnv mgr url' pure $ Right $ PuppetDBAPI (return (ppline $ fromString url)) (const (throwError "operation not supported")) (const (throwError "operation not supported")) (const (throwError "operation not supported")) (\q -> prettyError $ runClientM (sgetFacts (Just q)) env) (\q -> prettyError $ runClientM (sgetResources (Just q)) env) (\q -> prettyError $ runClientM (sgetNodes (Just q)) env) (throwError "operation not supported") (\node q -> prettyError $ runClientM (sgetNodeResources node (Just q)) env) where sgetNodes :: Maybe (Query NodeField) -> ClientM [NodeInfo] sgetNodeResources :: Text -> Maybe (Query ResourceField) -> ClientM [Resource] sgetFacts :: Maybe (Query FactField) -> ClientM [FactInfo] sgetResources :: Maybe (Query ResourceField) -> ClientM [Resource] (sgetNodes :<|> sgetNodeResources :<|> sgetFacts :<|> sgetResources) = client api prettyError :: IO (Either ClientError b) -> ExceptT PrettyError IO b prettyError = ExceptT . fmap (_Left %~ PrettyError . pplines . show)