stackctl-1.1.0.0: src/Stackctl/AWS/Core.hs
module Stackctl.AWS.Core
(
-- * AWS via 'MonadReader'
AwsEnv
, HasAwsEnv(..)
, awsEnvDiscover
, awsSimple
, awsSend
, awsPaginate
, awsAwait
-- * Modifiers on 'AwsEnv'
, awsWithin
-- * 'Amazonka' extensions
, AccountId(..)
-- * 'Amazonka'/'ResourceT' re-exports
, Region(..)
, FromText(..)
, ToText(..)
, MonadResource
) where
import Stackctl.Prelude
import Amazonka hiding (LogLevel(..))
import qualified Amazonka as AWS
import Conduit (ConduitM)
import Control.Monad.Logger (defaultLoc, toLogStr)
import Control.Monad.Trans.Resource (MonadResource)
import Stackctl.AWS.Orphans ()
newtype AwsEnv = AwsEnv
{ unAwsEnv :: Env
}
unL :: Lens' AwsEnv Env
unL = lens unAwsEnv $ \x y -> x { unAwsEnv = y }
awsEnvDiscover :: MonadLoggerIO m => m AwsEnv
awsEnvDiscover = do
env <- liftIO $ newEnv discover
AwsEnv <$> configureLogging env
configureLogging :: MonadLoggerIO m => Env -> m Env
configureLogging env = do
loggerIO <- askLoggerIO
pure $ env
{ AWS.envLogger = \level msg -> do
loggerIO
defaultLoc -- TODO: there may be a way to get a CallStack/Loc
"Amazonka"
(case level of
AWS.Info -> LevelInfo
AWS.Error -> LevelError
AWS.Debug -> LevelDebug
AWS.Trace -> LevelOther "trace"
)
(toLogStr msg)
}
class HasAwsEnv env where
awsEnvL :: Lens' env AwsEnv
instance HasAwsEnv AwsEnv where
awsEnvL = id
awsSimple
:: (MonadResource m, MonadReader env m, HasAwsEnv env, AWSRequest a)
=> Text
-> a
-> (AWSResponse a -> Maybe b)
-> m b
awsSimple name req post = do
resp <- awsSend req
maybe (throwString err) pure $ post resp
where err = unpack name <> " successful, but processing the response failed"
awsSend
:: (MonadResource m, MonadReader env m, HasAwsEnv env, AWSRequest a)
=> a
-> m (AWSResponse a)
awsSend req = do
AwsEnv env <- view awsEnvL
send env req
awsPaginate
:: (MonadResource m, MonadReader env m, HasAwsEnv env, AWSPager a)
=> a
-> ConduitM () (AWSResponse a) m ()
awsPaginate req = do
AwsEnv env <- view awsEnvL
paginateEither env req >>= hoistEither
hoistEither :: MonadIO m => Either Error a -> m a
hoistEither = either (liftIO . throwIO) pure
awsAwait
:: (MonadResource m, MonadReader env m, HasAwsEnv env, AWSRequest a)
=> Wait a
-> a
-> m Accept
awsAwait w req = do
AwsEnv env <- view awsEnvL
await env w req
awsWithin :: (MonadReader env m, HasAwsEnv env) => Region -> m a -> m a
awsWithin r = local $ over (awsEnvL . unL) (within r)
newtype AccountId = AccountId
{ unAccountId :: Text
}
deriving newtype (Eq, Ord, ToJSON)