packages feed

DOH 0.1.1.1 → 0.1.2.0

raw patch · 5 files changed

+53/−20 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Network.DigitalOcean.Types: instance Control.Monad.Error.Class.MonadError GHC.Base.String Network.DigitalOcean.Types.DO
- Network.DigitalOcean.Types: type DoErr = Text
+ Network.DigitalOcean.Types: ActionNotAllowed :: DoErrType
+ Network.DigitalOcean.Types: AuthenticationError :: DoErrType
+ Network.DigitalOcean.Types: DoErr :: DoErrType -> Text -> Text -> DoErr
+ Network.DigitalOcean.Types: HttpError :: DoErrType
+ Network.DigitalOcean.Types: InternalError :: DoErrType
+ Network.DigitalOcean.Types: JSONConversionError :: DoErrType
+ Network.DigitalOcean.Types: UnknownError :: DoErrType
+ Network.DigitalOcean.Types: [errBody] :: DoErr -> Text
+ Network.DigitalOcean.Types: [errTitle] :: DoErr -> Text
+ Network.DigitalOcean.Types: [errType] :: DoErr -> DoErrType
+ Network.DigitalOcean.Types: data DoErr
+ Network.DigitalOcean.Types: data DoErrType
+ Network.DigitalOcean.Types: instance Control.Monad.Error.Class.MonadError Network.DigitalOcean.Types.DoErr Network.DigitalOcean.Types.DO
+ Network.DigitalOcean.Types: instance GHC.Show.Show Network.DigitalOcean.Types.DoErr
+ Network.DigitalOcean.Types: instance GHC.Show.Show Network.DigitalOcean.Types.DoErrType
- Network.DigitalOcean.Types: DO :: ReaderT Client (ExceptT String IO) a -> DO a
+ Network.DigitalOcean.Types: DO :: ReaderT Client (ExceptT DoErr IO) a -> DO a
- Network.DigitalOcean.Types: [runDO] :: DO a -> ReaderT Client (ExceptT String IO) a
+ Network.DigitalOcean.Types: [runDO] :: DO a -> ReaderT Client (ExceptT DoErr IO) a

Files

DOH.cabal view
@@ -2,7 +2,7 @@ -- see http://haskell.org/cabal/users-guide/  name:                DOH-version:             0.1.1.1+version:             0.1.2.0 synopsis:            Complete API bindings for DigitalOcean API V2 description:         Complete API bindings for DigitalOcean API V2                      .
README.md view
@@ -41,7 +41,7 @@   forM_ droplets $ \dropletId -> performDropletAction dropletId (TakeSnapshot (Just "bulk snapshot")) ``` -For full documentation and reference, see: http://hackage.haskell.org/package/DOH-0.1.1.0/docs/Network-DigitalOcean.html+For full documentation and reference, see: http://hackage.haskell.org/package/DOH-0.1.2.0  # Contributing What can you do?
src/Network/DigitalOcean.hs view
@@ -64,6 +64,7 @@ import           Control.Monad.Except import           Data.Bool                 (bool) import qualified Data.Set                  as Set+import qualified Data.Text                 as T ----------------------------------------------------------------- import           Network.DigitalOcean.Types import           Network.DigitalOcean.Http@@ -300,10 +301,11 @@  -} performDropletActionOnTag :: String -> DropletAction -> DO [Action] performDropletActionOnTag tag action = do-  unless (actionAllowedAsBulk action) $-    throwError $-      "Action " ++ show action ++ " not allowed as bulk. See \-      \https://developers.digitalocean.com/documentation/v2/#acting-on-tagged-droplets"+  unless (actionAllowedAsBulk action) $ throwError+    DoErr { errType  = ActionNotAllowed+          , errTitle = T.pack $ "Action " <> show action <> " not allowed as bulk"+          , errBody  = "See https://developers.digitalocean.com/documentation/v2/#acting-on-tagged-droplets"+          }   unResponse <$> post DropletsActionsEndpoint (Just [("tag_name", tag)]) action  getDropletAction :: DropletId -> ActionId -> DO Action
src/Network/DigitalOcean/Http.hs view
@@ -6,22 +6,23 @@ module Network.DigitalOcean.Http where    ------------------------------------------------------------------import qualified Data.Text                 as T-import qualified Data.ByteString           as BS-import qualified Data.ByteString.Char8     as BSC-import qualified Data.ByteString.Lazy      as LBS-import           Network.HTTP.Client       hiding (Proxy)+import qualified Data.Text                  as T+import qualified Data.ByteString            as BS+import qualified Data.ByteString.Char8      as BSC+import qualified Data.ByteString.Lazy       as LBS+import qualified Data.ByteString.Lazy.Char8 as LBSC+import           Network.HTTP.Client        hiding (Proxy) import           Network.HTTP.Client.TLS-import           System.FilePath           ((</>))+import           System.FilePath            ((</>)) import           Data.Aeson import           Data.Proxy import           Data.Monoid-import           Data.Bool                 (bool)+import           Data.Bool                  (bool) import           Control.Monad import           Control.Monad.Reader import           Control.Monad.Except import           Data.Maybe-import           Network.HTTP.Types.Status (statusCode)+import           Network.HTTP.Types.Status  (statusCode) import           Text.URI ----------------------------------------------------------------- import           Network.DigitalOcean.Types@@ -38,7 +39,11 @@ makeRequest method uri queryParams mbPayload = do   client <- ask   let uri' = uri <> maybe mempty showQueryParams queryParams-  when (isNothing $ parseURI uri') $ throwError $ "URI cannot be parsed: " <> uri'+  when (isNothing $ parseURI uri') $ throwError +    DoErr { errType  = InternalError+          , errTitle = "URI cannot be parsed:"+          , errBody  = T.pack uri'+          }   manager <- liftIO newTlsManager   initialRequest <- liftIO $ parseRequest uri'   let request = initialRequest { method = BSC.pack $ show method@@ -49,10 +54,23 @@   let request' = maybe request (\payload -> request { requestBody = RequestBodyLBS (encode payload) }) mbPayload   response <- liftIO $ httpLbs request' manager   let respStatus = statusCode $ responseStatus response-  when (respStatus < 200 || respStatus > 300) $ throwError $ "Non-success response: " <> show respStatus <> "Body:" <> show (responseBody response)+  when (respStatus == 401) $ throwError+    DoErr { errType  = AuthenticationError+          , errTitle = "Your API token is invalid"+          , errBody  = ""+          }+  when (respStatus < 200 || respStatus > 300) $ throwError+    DoErr { errType  = HttpError+          , errTitle = "Non-success response received"+          , errBody  = T.pack $ LBSC.unpack (responseBody response)+          }   let body = bool (responseBody response) "[]" (respStatus == 204)   case (eitherDecode body :: Either String a) of-    Left err -> throwError $ "Error occured for response body:" <> BSC.unpack (LBS.toStrict $ responseBody response) <> err+    Left err -> throwError+      DoErr { errType  = JSONConversionError+            , errTitle = "Error occured for response body"+            , errBody  = T.pack $ BSC.unpack (LBS.toStrict $ responseBody response) <> err+            }     Right resource -> return resource  {- `get` that is working with absolute uris -}
src/Network/DigitalOcean/Types.hs view
@@ -65,12 +65,25 @@ defaultPaginationConfig :: PaginationConfig defaultPaginationConfig = PaginationConfig 25 100 -newtype DO a = DO { runDO :: ReaderT Client (ExceptT String IO) a }-  deriving (Functor, Applicative, Monad, MonadIO, MonadError String, MonadReader Client)+newtype DO a = DO { runDO :: ReaderT Client (ExceptT DoErr IO) a }+  deriving (Functor, Applicative, Monad, MonadIO, MonadError DoErr, MonadReader Client)  newtype Client = Client { apiKey :: BS.ByteString } -type DoErr = T.Text+data DoErrType =+    HttpError+  | JSONConversionError+  | InternalError+  | ActionNotAllowed+  | AuthenticationError+  | UnknownError+  deriving Show++data DoErr = DoErr+  { errType :: DoErrType+  , errTitle :: T.Text+  , errBody :: T.Text+  } deriving Show  newtype Response a = Response { unResponse :: a } deriving (Generic, Show)