packages feed

amazonka 1.4.5 → 1.5.0

raw patch · 13 files changed

+459/−217 lines, 13 filesdep ~amazonka-corePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: amazonka-core

API changes (from Hackage documentation)

+ Control.Monad.Trans.AWS: FromContainer :: Credentials
+ Control.Monad.Trans.AWS: London :: Region
+ Control.Monad.Trans.AWS: Montreal :: Region
+ Control.Monad.Trans.AWS: _MatchServiceError :: AsError a => Service -> ErrorCode -> Getting (First ServiceError) a ServiceError
+ Control.Monad.Trans.AWS: hasCode :: (Applicative f, Choice p) => ErrorCode -> Optic' * * p f ServiceError ServiceError
+ Control.Monad.Trans.AWS: hasService :: (Applicative f, Choice p) => Service -> Optic' * * p f ServiceError ServiceError
+ Control.Monad.Trans.AWS: hasStatus :: (Applicative f, Choice p) => Int -> Optic' * * p f ServiceError ServiceError
+ Network.AWS: FromContainer :: Credentials
+ Network.AWS: London :: Region
+ Network.AWS: Montreal :: Region
+ Network.AWS: _MatchServiceError :: AsError a => Service -> ErrorCode -> Getting (First ServiceError) a ServiceError
+ Network.AWS: chunkedFileRange :: MonadIO m => ChunkSize -> FilePath -> Integer -> Integer -> m RqBody
+ Network.AWS: hasCode :: (Applicative f, Choice p) => ErrorCode -> Optic' * * p f ServiceError ServiceError
+ Network.AWS: hasService :: (Applicative f, Choice p) => Service -> Optic' * * p f ServiceError ServiceError
+ Network.AWS: hasStatus :: (Applicative f, Choice p) => Int -> Optic' * * p f ServiceError ServiceError
+ Network.AWS: hashedFileRange :: MonadIO m => FilePath -> Integer -> Integer -> m HashedBody
+ Network.AWS.Auth: Auth :: AuthEnv -> Auth
+ Network.AWS.Auth: FromContainer :: Credentials
+ Network.AWS.Auth: Ref :: ThreadId -> IORef AuthEnv -> Auth
+ Network.AWS.Auth: fromContainer :: (MonadIO m, MonadThrow m) => Manager -> m (Auth, Maybe Region)
+ Network.AWS.Auth: fromTemporarySession :: AccessKey -> SecretKey -> SessionToken -> UTCTime -> Auth
- Control.Monad.Trans.AWS: _Error :: Prism' a Error
+ Control.Monad.Trans.AWS: _Error :: AsError a => Prism' a Error
- Control.Monad.Trans.AWS: _SerializeError :: Prism' a SerializeError
+ Control.Monad.Trans.AWS: _SerializeError :: AsError a => Prism' a SerializeError
- Control.Monad.Trans.AWS: _ServiceError :: Prism' a ServiceError
+ Control.Monad.Trans.AWS: _ServiceError :: AsError a => Prism' a ServiceError
- Control.Monad.Trans.AWS: _TransportError :: Prism' a HttpException
+ Control.Monad.Trans.AWS: _TransportError :: AsError a => Prism' a HttpException
- Control.Monad.Trans.AWS: toBody :: a -> RqBody
+ Control.Monad.Trans.AWS: toBody :: ToBody a => a -> RqBody
- Control.Monad.Trans.AWS: toHashed :: a -> HashedBody
+ Control.Monad.Trans.AWS: toHashed :: ToHashedBody a => a -> HashedBody
- Network.AWS: _Error :: Prism' a Error
+ Network.AWS: _Error :: AsError a => Prism' a Error
- Network.AWS: _SerializeError :: Prism' a SerializeError
+ Network.AWS: _SerializeError :: AsError a => Prism' a SerializeError
- Network.AWS: _ServiceError :: Prism' a ServiceError
+ Network.AWS: _ServiceError :: AsError a => Prism' a ServiceError
- Network.AWS: _TransportError :: Prism' a HttpException
+ Network.AWS: _TransportError :: AsError a => Prism' a HttpException
- Network.AWS: toBody :: a -> RqBody
+ Network.AWS: toBody :: ToBody a => a -> RqBody
- Network.AWS: toHashed :: a -> HashedBody
+ Network.AWS: toHashed :: ToHashedBody a => a -> HashedBody
- Network.AWS.Data: build :: a -> Builder
+ Network.AWS.Data: build :: ToLog a => a -> Builder
- Network.AWS.Data: parser :: Parser a
+ Network.AWS.Data: parser :: FromText a => Parser a
- Network.AWS.Data: toBS :: a -> ByteString
+ Network.AWS.Data: toBS :: ToByteString a => a -> ByteString
- Network.AWS.Data: toText :: a -> Text
+ Network.AWS.Data: toText :: ToText a => a -> Text

Files

CHANGELOG.md view
@@ -1,7 +1,48 @@ # Change Log +## [1.5.0](https://github.com/brendanhay/amazonka/tree/1.5.0)+fReleased: **15 November, 2017**, Compare: [1.4.5](https://github.com/brendanhay/amazonka/compare/1.4.5...1.5.0)++### Fixed++- V4 Signing Metadata is now correctly calculated for chunked request bodies. [\#403](https://github.com/brendanhay/amazonka/pull/403)+- DynamoDB Query/Scan pagination will correctly return all available items. [\#392](https://github.com/brendanhay/amazonka/pull/392)+- S3 `ReplicationStatus` is now parsed correctly. [\#372](https://github.com/brendanhay/amazonka/pull/372)+- OpsWorks `LayerAttributes` now correctly returns `Maybe` for `Map` values. [\#398](https://github.com/brendanhay/amazonka/pull/398)+- `newLogger` now (correctly) does not set binary mode for any passed handle. [\#381](https://github.com/brendanhay/amazonka/pull/381)+- Improved support for handling S3's `list-type=2` query strings. [\#391](https://github.com/brendanhay/amazonka/pull/391)+- Cabal files now have their `license-field` changed from `OtherLicense` to the correct `MPL-2.0`.++### Added++- Add AWS Signer for V2 Header Authentication. [\#383](https://github.com/brendanhay/amazonka/pull/383)+- Add support for ECS credentials discovery via the ECS container agent. [\#388](https://github.com/brendanhay/amazonka/pull/388)+- Add new regions `Montreal` (ca-central-1) and `London` (eu-west-2). [\#367](https://github.com/brendanhay/amazonka/pull/367)+- Add `hashedFileRange` and `chunkedFileRange` for preparing request bodies from file ranges. [\#359](https://github.com/brendanhay/amazonka/pull/359)++### New Libraries++- `amazonka-mobile`: Add and configure features for mobile apps, including authentication, data storage, backend logic, push notifications, content delivery, and analytics. [Overview](https://aws.amazon.com/mobile)+- `amazonka-pricing`: Price lists, pricing details, and pricing overview. [Overview](https://aws.amazon.com/pricing)+- `amazonka-athena`: An interactive query service that makes it easy to analyze data in Amazon S3 using standard SQL. [Overview](https://aws.amazon.com/athena)+- `amazonka-cloudhsmv2`: The newest (incompatible) API of AWS CloudHSM. [Overview](https://aws.amazon.com/cloudhsmv2)+- `amazonka-codestar`: Use a variety of project templates to start developing applications on Amazon EC2, AWS Lambda, and AWS Elastic Beanstalk. [Overview](https://aws.amazon.com/codestar)+- `amazonka-dynamodb-dax`: DynamoDB Accelerator (DAX) is a fully managed, highly available, in-memory cache for DynamoDB that delivers up to a 10x performance improvement. [Overview](https://aws.amazon.com/dynamodb/dax)+- `amazonka-glue`: A fully managed extract, transform, and load (ETL) service that makes it easy for customers to prepare and load their data for analytics. [Overview](https://aws.amazon.com/glue)+- `amazonka-greengrass`: Run local compute, messaging, data caching, and sync capabilities for connected devices in a secure way. [Overview](https://aws.amazon.com/greengrass)+- `amazonka-lex-runtime`: Build applications using a speech or text interface powered by the same technology that powers Amazon Alexa. [Overview](https://aws.amazon.com/lex)+- `amazonka-lex-models`: Build applications using a speech or text interface powered by the same technology that powers Amazon Alexa. [Overview](https://aws.amazon.com/lex)+- `amazonka-marketplace-entitlement`: Markplace entitlements service. [Overview](https://aws.amazon.com/marketplace)+- `amazonka-resourcegroupstagging`: Group and tag AWS resources. [Overview](https://docs.aws.amazon.com/resourcegroupstagging)++### Updated Service Definitions++> All service definitions and services have been updated and regenerated.+Please see each individual library's commits for a list of changes.++ ## [1.4.5](https://github.com/brendanhay/amazonka/tree/1.4.5)-Released: **04 December, 2016**, Compare: [1.4.5](https://github.com/brendanhay/amazonka/compare/1.4.4...1.4.5)+Released: **04 December, 2016**, Compare: [1.4.4](https://github.com/brendanhay/amazonka/compare/1.4.4...1.4.5)  ### Fixed 
amazonka.cabal view
@@ -1,13 +1,13 @@ name:                  amazonka-version:               1.4.5+version:               1.5.0 synopsis:              Comprehensive Amazon Web Services SDK. homepage:              https://github.com/brendanhay/amazonka bug-reports:           https://github.com/brendanhay/amazonka/issues-license:               OtherLicense+license:               MPL-2.0 license-file:          LICENSE author:                Brendan Hay-maintainer:            Brendan Hay <brendan.g.hay@gmail.com>-copyright:             Copyright (c) 2013-2016 Brendan Hay+maintainer:            Brendan Hay <brendan.g.hay+amazonka@gmail.com>+copyright:             Copyright (c) 2013-2017 Brendan Hay category:              Network, AWS, Cloud, Distributed Computing build-type:            Simple extra-source-files:    README.md CHANGELOG.md@@ -31,14 +31,19 @@     GHC 7.8.4 and higher is officially supported.  source-repository head-    type:     git-    location: git://github.com/brendanhay/amazonka.git+    type:              git+    location:          git://github.com/brendanhay/amazonka.git+    subdir:            amazonka  library     default-language:  Haskell2010     hs-source-dirs:    src -    ghc-options:       -Wall+    ghc-options:+        -Wall+        -fwarn-incomplete-uni-patterns+        -fwarn-incomplete-record-updates+        -funbox-strict-fields      exposed-modules:           Control.Monad.Trans.AWS@@ -55,7 +60,7 @@         , Network.AWS.Internal.Logger      build-depends:-          amazonka-core       == 1.4.5.*+          amazonka-core       == 1.5.0.*         , base                >= 4.7 && < 5         , bytestring          >= 0.9         , conduit             >= 1.1
src/Control/Monad/Trans/AWS.hs view
@@ -14,9 +14,9 @@  -- | -- Module      : Control.Monad.Trans.AWS--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : provisional -- Portability : non-portable (GHC extensions) --@@ -127,6 +127,12 @@     , trying     , catching +    -- ** Building Error Prisms+    , Error._MatchServiceError+    , Error.hasService+    , Error.hasStatus+    , Error.hasCode+     -- * Logging     -- $logging @@ -150,34 +156,37 @@     , RsBody     ) where -import           Control.Applicative-import           Control.Monad.Base-import           Control.Monad.Catch-import           Control.Monad.Error.Class    (MonadError (..))-import           Control.Monad.Morph-import           Control.Monad.Reader-import           Control.Monad.State.Class-import           Control.Monad.Trans.Control-import           Control.Monad.Trans.Resource-import           Control.Monad.Writer.Class-import           Data.Conduit                 hiding (await)-import           Data.Conduit.Lazy            (MonadActive (..))-import           Data.IORef-import           Data.Monoid-import           Network.AWS.Auth-import qualified Network.AWS.EC2.Metadata     as EC2-import           Network.AWS.Env-import           Network.AWS.Internal.Body-import           Network.AWS.Internal.HTTP-import           Network.AWS.Internal.Logger-import           Network.AWS.Lens             (catching, throwingM, trying,-                                               view)-import           Network.AWS.Pager            (AWSPager (..))-import           Network.AWS.Prelude          as AWS-import qualified Network.AWS.Presign          as Sign-import           Network.AWS.Request          (requestURL)-import           Network.AWS.Types            hiding (LogLevel (..))-import           Network.AWS.Waiter           (Accept, Wait)+import Control.Applicative+import Control.Monad.Base+import Control.Monad.Catch+import Control.Monad.Error.Class    (MonadError (..))+import Control.Monad.Morph+import Control.Monad.Reader+import Control.Monad.State.Class+import Control.Monad.Trans.Control+import Control.Monad.Trans.Resource+import Control.Monad.Writer.Class++import Data.Conduit      hiding (await)+import Data.Conduit.Lazy (MonadActive (..))+import Data.IORef+import Data.Monoid++import Network.AWS.Auth+import Network.AWS.Env+import Network.AWS.Internal.Body+import Network.AWS.Internal.HTTP+import Network.AWS.Internal.Logger+import Network.AWS.Lens            (catching, throwingM, trying, view)+import Network.AWS.Pager           (AWSPager (..))+import Network.AWS.Prelude         as AWS+import Network.AWS.Request         (requestURL)+import Network.AWS.Types           hiding (LogLevel (..))+import Network.AWS.Waiter          (Accept, Wait)++import qualified Network.AWS.EC2.Metadata as EC2+import qualified Network.AWS.Error        as Error+import qualified Network.AWS.Presign      as Sign  type AWST = AWST' Env 
src/Network/AWS.hs view
@@ -6,9 +6,9 @@  -- | -- Module      : Network.AWS--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : provisional -- Portability : non-portable (GHC extensions) --@@ -78,6 +78,7 @@     -- *** Request Bodies     , ToHashedBody (..)     , hashedFile+    , hashedFileRange     , hashedBody      -- *** Chunked Request Bodies@@ -85,6 +86,7 @@     , ChunkSize    (..)     , defaultChunkSize     , chunkedFile+    , chunkedFileRange     , unsafeChunkedBody      -- *** Response Bodies@@ -123,6 +125,12 @@     , AWST.trying     , AWST.catching +    -- ** Building Error Prisms+    , AWST._MatchServiceError+    , AWST.hasService+    , AWST.hasStatus+    , AWST.hasCode+     -- * Logging     -- $logging @@ -146,39 +154,42 @@     , RsBody     ) where -import           Control.Applicative-import           Control.Monad.Catch          (MonadCatch)-import           Control.Monad.IO.Class       (MonadIO)-import           Control.Monad.Morph          (hoist)-import qualified Control.Monad.RWS.Lazy       as LRW-import qualified Control.Monad.RWS.Strict     as RW-import qualified Control.Monad.State.Lazy     as LS-import qualified Control.Monad.State.Strict   as S-import           Control.Monad.Trans.AWS      (AWST)-import qualified Control.Monad.Trans.AWS      as AWST-import           Control.Monad.Trans.Class    (lift)-import           Control.Monad.Trans.Except   (ExceptT)-import           Control.Monad.Trans.Identity (IdentityT)-import           Control.Monad.Trans.List     (ListT)-import           Control.Monad.Trans.Maybe    (MaybeT)-import           Control.Monad.Trans.Reader   (ReaderT)-import           Control.Monad.Trans.Resource-import qualified Control.Monad.Writer.Lazy    as LW-import qualified Control.Monad.Writer.Strict  as W-import           Data.Conduit                 (Source)-import           Data.Monoid-import           Network.AWS.Auth-import qualified Network.AWS.EC2.Metadata     as EC2-import           Network.AWS.Env              (Env, HasEnv (..), newEnv)-import qualified Network.AWS.Env              as Env-import           Network.AWS.Internal.Body-import           Network.AWS.Internal.Logger-import           Network.AWS.Lens             ((^.))-import           Network.AWS.Pager            (AWSPager)-import           Network.AWS.Prelude-import           Network.AWS.Types            hiding (LogLevel (..))-import           Network.AWS.Waiter           (Wait)+import Control.Applicative+import Control.Monad.Catch          (MonadCatch)+import Control.Monad.IO.Class       (MonadIO)+import Control.Monad.Morph          (hoist)+import Control.Monad.Trans.AWS      (AWST)+import Control.Monad.Trans.Class    (lift)+import Control.Monad.Trans.Except   (ExceptT)+import Control.Monad.Trans.Identity (IdentityT)+import Control.Monad.Trans.List     (ListT)+import Control.Monad.Trans.Maybe    (MaybeT)+import Control.Monad.Trans.Reader   (ReaderT)+import Control.Monad.Trans.Resource +import Data.Conduit (Source)+import Data.Monoid++import Network.AWS.Auth+import Network.AWS.Env             (Env, HasEnv (..), newEnv)+import Network.AWS.Internal.Body+import Network.AWS.Internal.Logger+import Network.AWS.Lens            ((^.))+import Network.AWS.Pager           (AWSPager)+import Network.AWS.Prelude+import Network.AWS.Types           hiding (LogLevel (..))+import Network.AWS.Waiter          (Wait)++import qualified Control.Monad.RWS.Lazy      as LRW+import qualified Control.Monad.RWS.Strict    as RW+import qualified Control.Monad.State.Lazy    as LS+import qualified Control.Monad.State.Strict  as S+import qualified Control.Monad.Trans.AWS     as AWST+import qualified Control.Monad.Writer.Lazy   as LW+import qualified Control.Monad.Writer.Strict as W+import qualified Network.AWS.EC2.Metadata    as EC2+import qualified Network.AWS.Env             as Env+ -- | A specialisation of the 'AWST' transformer. type AWS = AWST (ResourceT IO) @@ -331,8 +342,10 @@     -- as default environment variables, or an instance's IAM Profile and identity document:     env  <- newEnv Discover -    -- The payload (and hash) for the S3 object is retrieved from a 'FilePath':-    body <- sourceFileIO "local\/path\/to\/object-payload"+    -- The payload (and hash) for the S3 object is retrieved from a 'FilePath',+    -- either 'hashedFile' or 'chunkedFile' can be used, with the latter ensuring+    -- the contents of the file is enumerated exactly once, during send:+    body <- chunkedFile defaultChunkSize "local\/path\/to\/object-payload"      -- We now run the 'AWS' computation with the overriden logger, performing the     -- 'PutObject' request. 'envRegion' or 'within' can be used to set the
src/Network/AWS/Auth.hs view
@@ -3,12 +3,13 @@ {-# LANGUAGE FlexibleContexts   #-} {-# LANGUAGE LambdaCase         #-} {-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE TupleSections      #-}  -- | -- Module      : Network.AWS.Auth--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : provisional -- Portability : non-portable (GHC extensions) --@@ -23,7 +24,7 @@     -- ** Retrieving Authentication       getAuth     , Credentials  (..)-    , Auth+    , Auth         (..)      -- ** Defaults     -- *** Environment@@ -43,12 +44,14 @@      , fromKeys     , fromSession+    , fromTemporarySession     , fromEnv     , fromEnvKeys     , fromFile     , fromFilePath     , fromProfile     , fromProfileName+    , fromContainer      -- ** Keys     , AccessKey    (..)@@ -60,32 +63,36 @@     , AuthError    (..)     ) where -import           Control.Applicative-import           Control.Concurrent-import           Control.Monad-import           Control.Monad.Catch-import           Control.Monad.IO.Class-import           Control.Monad.Trans.Maybe  (MaybeT (..))+import Control.Concurrent+import Control.Monad+import Control.Monad.Catch+import Control.Monad.IO.Class+import Control.Monad.Trans.Maybe (MaybeT (..))++import Data.Char   (isSpace)+import Data.IORef+import Data.Monoid+import Data.Time   (diffUTCTime, getCurrentTime)++import Network.AWS.Data.Log+import Network.AWS.Data.JSON+import Network.AWS.EC2.Metadata+import Network.AWS.Lens         (catching, catching_, exception, throwingM,+                                 _IOException)+import Network.AWS.Lens         (Prism', prism, (<&>))+import Network.AWS.Prelude+import Network.HTTP.Conduit++import System.Directory   (doesFileExist, getHomeDirectory)+import System.Environment+import System.Mem.Weak+ import qualified Data.ByteString.Char8      as BS8 import qualified Data.ByteString.Lazy.Char8 as LBS8-import           Data.Char                  (isSpace) import qualified Data.Ini                   as INI-import           Data.IORef-import           Data.Monoid import qualified Data.Text                  as Text import qualified Data.Text.Encoding         as Text-import           Data.Time                  (diffUTCTime, getCurrentTime)-import           Network.AWS.Data.Log-import           Network.AWS.EC2.Metadata-import           Network.AWS.Lens           (catching, catching_, exception,-                                             throwingM, _IOException)-import           Network.AWS.Lens           (Prism', prism, (<&>))-import           Network.AWS.Prelude-import           Network.AWS.Types-import           Network.HTTP.Conduit-import           System.Directory           (doesFileExist, getHomeDirectory)-import           System.Environment-import           System.Mem.Weak+import qualified Network.HTTP.Conduit       as HTTP  -- | Default access key environment variable. envAccessKey :: Text -- ^ AWS_ACCESS_KEY_ID@@ -107,6 +114,11 @@ envRegion :: Text -- ^ AWS_REGION envRegion = "AWS_REGION" +-- | Path to obtain container credentials environment variable (see+-- 'FromContainer').+envContainerCredentialsURI :: Text -- ^ AWS_CONTAINER_CREDENTIALS_RELATIVE_URI+envContainerCredentialsURI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"+ -- | Credentials INI file access key variable. credAccessKey :: Text -- ^ aws_access_key_id credAccessKey = "aws_access_key_id"@@ -150,12 +162,28 @@  -- | Explicit access and secret keys. fromKeys :: AccessKey -> SecretKey -> Auth-fromKeys a s = Auth (AuthEnv a s Nothing Nothing)+fromKeys a s = Auth (AuthEnv a (Sensitive s) Nothing Nothing) --- | A session containing the access key, secret key, and a session token.+-- | Temporary credentials from a STS session consisting of+-- the access key, secret key, and session token.+--+-- /See:/ 'fromTemporarySession' fromSession :: AccessKey -> SecretKey -> SessionToken -> Auth-fromSession a s t = Auth (AuthEnv a s (Just t) Nothing)+fromSession a s t =+    Auth (AuthEnv a (Sensitive s) (Just (Sensitive t)) Nothing) +-- | Temporary credentials from a STS session consisting of+-- the access key, secret key, session token, and expiration time.+--+-- /See:/ 'fromSession'+fromTemporarySession :: AccessKey+                     -> SecretKey+                     -> SessionToken+                     -> UTCTime+                     -> Auth+fromTemporarySession a s t e =+    Auth (AuthEnv a (Sensitive s) (Just (Sensitive t)) (Just (Time e)))+ -- | Determines how AuthN/AuthZ information is retrieved. data Credentials     = FromKeys AccessKey SecretKey@@ -177,6 +205,12 @@       -- ^ A credentials profile name (the INI section) and the path to the AWS       -- <http://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs credentials> file. +    | FromContainer+      -- ^ Obtain credentials by attempting to contact the ECS container agent+      -- at <http://169.254.170.2> using the path in 'envContainerCredentialsURI'.+      -- See <http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html IAM Roles for Tasks>+      -- in the AWS documentation for more information.+     | Discover       -- ^ Attempt credentials discovery via the following steps:       --@@ -184,6 +218,9 @@       --       -- * Read the credentials file if 'credFile' exists.       --+      -- * Obtain credentials from the ECS container agent if+      -- 'envContainerCredentialsURI' is set.+      --       -- * Retrieve the first available IAM profile and read       -- the 'Region' from the instance identity document, if running on EC2.       --@@ -205,6 +242,8 @@             "FromProfile " <> build n         FromFile    n f ->             "FromFile " <> build n <> " " <> build f+        FromContainer ->+            "FromContainer"         Discover ->             "Discover"       where@@ -310,19 +349,22 @@     FromEnv     a s t r -> fromEnvKeys a s t r     FromProfile n       -> fromProfileName m n     FromFile    n f     -> fromFilePath n f+    FromContainer       -> fromContainer m     Discover            ->         -- Don't try and catch InvalidFileError, or InvalidIAMProfile,         -- let both errors propagate.         catching_ _MissingEnvError fromEnv $             -- proceed, missing env keys-            catching _MissingFileError fromFile $ \f -> do+            catching _MissingFileError fromFile $ \f ->                 -- proceed, missing credentials file-                p <- isEC2 m-                unless p $-                    -- not an EC2 instance, rethrow the previous error.-                    throwingM _MissingFileError f-                 -- proceed, check EC2 metadata for IAM information.-                fromProfile m+                catching_ _MissingEnvError (fromContainer m) $ do+                  -- proceed, missing env key+                  p <- isEC2 m+                  unless p $+                      -- not an EC2 instance, rethrow the previous error.+                      throwingM _MissingFileError f+                   -- proceed, check EC2 metadata for IAM information.+                  fromProfile m  -- | Retrieve access key, secret key, and a session token from the default -- environment variables.@@ -355,8 +397,8 @@   where     lookupKeys = AuthEnv         <$> (req access  <&> AccessKey . BS8.pack)-        <*> (req secret  <&> SecretKey . BS8.pack)-        <*> (opt session <&> fmap (SessionToken . BS8.pack))+        <*> (req secret  <&> Sensitive . SecretKey . BS8.pack)+        <*> (opt session <&> fmap (Sensitive . SessionToken . BS8.pack))         <*> return Nothing      lookupRegion :: (MonadIO m, MonadThrow m) => m (Maybe Region)@@ -405,8 +447,8 @@     ini <- either (invalidErr Nothing) return =<< liftIO (INI.readIniFile f)     env <- AuthEnv         <$> (req credAccessKey    ini <&> AccessKey)-        <*> (req credSecretKey    ini <&> SecretKey)-        <*> (opt credSessionToken ini <&> fmap SessionToken)+        <*> (req credSecretKey    ini <&> Sensitive . SecretKey)+        <*> (opt credSessionToken ini <&> fmap (Sensitive . SessionToken))         <*> return Nothing     return (Auth env, Nothing)   where@@ -447,28 +489,31 @@  -- | Lookup a specific IAM Profile by name from the local EC2 instance-data. ----- The resulting IONewRef wrapper + timer is designed so that multiple concurrent+-- Additionally starts a refresh thread for the given authentication environment.+--+-- The resulting 'IORef' wrapper + timer is designed so that multiple concurrent -- accesses of 'AuthEnv' from the 'AWS' environment are not required to calculate -- expiry and sequentially queue to update it. -- -- The forked timer ensures a singular owner and pre-emptive refresh of the--- temporary session credentials.+-- temporary session credentials before expiration. -- -- A weak reference is used to ensure that the forked thread will eventually -- terminate when 'Auth' is no longer referenced. ----- Throws 'RetrievalError' if the HTTP call fails, or 'InvalidIAMError' if--- the specified IAM profile cannot be read.+-- If no session token or expiration time is present the credentials will+-- be returned verbatim.+-- fromProfileName :: (MonadIO m, MonadCatch m)                 => Manager                 -> Text                 -> m (Auth, Maybe Region) fromProfileName m name = do-    auth <- getCredentials >>= start+    auth <- liftIO $ fetchAuthInBackground getCredentials     reg  <- getRegion     return (auth, Just reg)   where-    getCredentials :: (MonadIO m, MonadCatch m) => m AuthEnv+    getCredentials :: IO AuthEnv     getCredentials =         try (metadata m (IAM . SecurityCredentials $ Just name)) >>=             handleErr (eitherDecode' . LBS8.fromStrict) invalidIAMErr@@ -489,26 +534,80 @@         . mappend "Error parsing Instance Identity Document "         . Text.pack -    start :: MonadIO m => AuthEnv -> m Auth-    start !a = liftIO $-        case _authExpiry a of-            Nothing -> return (Auth a)-            Just x  -> do-                r <- newIORef a-                p <- myThreadId-                s <- timer r p x-                return (Ref s r)+-- | Obtain credentials exposed to a task via the ECS container agent, as+-- described in the <http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html IAM Roles for Tasks>+-- section of the AWS ECS documentation. The credentials are obtained by making+-- a request to <http://169.254.170.2> at the path contained by the+-- 'envContainerCredentialsURI' environment variable.+--+-- The ECS container agent provides an access key, secret key, session token,+-- and expiration time, but it does not include a region, so the region will+-- attempt to be determined from the 'envRegion' environment variable if it is+-- set.+--+-- Like 'fromProfileName', additionally starts a refresh thread that will+-- periodically fetch fresh credentials before the current ones expire.+--+-- Throws 'MissingEnvError' if the 'envContainerCredentialsURI' environment+-- variable is not set or 'InvalidIAMError' if the payload returned by the ECS+-- container agent is not of the expected format.+fromContainer :: (MonadIO m, MonadThrow m)+              => Manager+              -> m (Auth, Maybe Region)+fromContainer m = do+    req  <- getCredentialsURI+    auth <- liftIO $ fetchAuthInBackground (renew req)+    reg  <- getRegion+    return (auth, reg)+  where+    getCredentialsURI :: (MonadIO m, MonadThrow m) => m HTTP.Request+    getCredentialsURI = do+        mp <- liftIO (lookupEnv (Text.unpack envContainerCredentialsURI))+        p  <- maybe (throwM . MissingEnvError $ "Unable to read ENV variable: " <> envContainerCredentialsURI)+                    return+                    mp+        parseUrlThrow $ "http://169.254.170.2" <> p -    timer :: IORef AuthEnv -> ThreadId -> UTCTime -> IO ThreadId-    timer !r !p !x = forkIO $ do+    renew :: HTTP.Request -> IO AuthEnv+    renew req = do+        rs <- httpLbs req m+        either (throwM . invalidIdentityErr) return (eitherDecode (responseBody rs))++    invalidIdentityErr = InvalidIAMError+        . mappend "Error parsing Task Identity Document "+        . Text.pack++    getRegion :: MonadIO m => m (Maybe Region)+    getRegion = runMaybeT $ do+        mr <- MaybeT . liftIO $ lookupEnv (Text.unpack envRegion)+        either (const . MaybeT $ return Nothing)+               return+               (fromText (Text.pack mr))++-- | Implements the background fetching behavior used by 'fromProfileName' and+-- 'fromContainer'. Given an 'IO' action that produces an 'AuthEnv', this spawns+-- a thread that mutates the 'IORef' returned in the resulting 'Auth' to keep+-- the temporary credentials up to date.+fetchAuthInBackground :: IO AuthEnv -> IO Auth+fetchAuthInBackground menv = menv >>= \(!env) -> liftIO $+    case _authExpiry env of+        Nothing -> return (Auth env)+        Just x  -> do+          r <- newIORef env+          p <- myThreadId+          s <- timer menv r p x+          return (Ref s r)+  where+    timer :: IO AuthEnv -> IORef AuthEnv -> ThreadId -> ISO8601 -> IO ThreadId+    timer ma !r !p !x = forkIO $ do         s <- myThreadId         w <- mkWeakIORef r (killThread s)-        loop w p x+        loop ma w p x -    loop :: Weak (IORef AuthEnv) -> ThreadId -> UTCTime -> IO ()-    loop w !p !x = do+    loop :: IO AuthEnv -> Weak (IORef AuthEnv) -> ThreadId -> ISO8601 -> IO ()+    loop ma w !p !x = do         diff x <$> getCurrentTime >>= threadDelay-        env <- try getCredentials+        env <- try ma         case env of             Left   e -> throwTo p (RetrievalError e)             Right !a -> do@@ -517,8 +616,8 @@                      Nothing -> return ()                      Just  r -> do                          atomicWriteIORef r a-                         maybe (return ()) (loop w p) (_authExpiry a)+                         maybe (return ()) (loop ma w p) (_authExpiry a) -    diff !x !y = (* 1000000) $ if n > 0 then n else 1+    diff (Time !x) !y = (* 1000000) $ if n > 0 then n else 1       where         !n = truncate (diffUTCTime x y) - 60
src/Network/AWS/Data.hs view
@@ -1,8 +1,8 @@ -- | -- Module      : Network.AWS.Data--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : provisional -- Portability : non-portable (GHC extensions) --
src/Network/AWS/EC2/Metadata.hs view
@@ -7,9 +7,9 @@  -- | -- Module      : Network.AWS.EC2.Metadata--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : provisional -- Portability : non-portable (GHC extensions) --
src/Network/AWS/Env.hs view
@@ -1,15 +1,15 @@ {-# LANGUAGE FlexibleContexts  #-}-{-# LANGUAGE ViewPatterns  #-} {-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes        #-} {-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE ViewPatterns      #-}  -- | -- Module      : Network.AWS.Env--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : provisional -- Portability : non-portable (GHC extensions) --@@ -38,21 +38,23 @@     , retryConnectionFailure     ) where -import Data.Maybe (fromMaybe)-import           Control.Applicative-import           Control.Monad.Catch-import           Control.Monad.IO.Class-import           Control.Monad.Reader-import           Data.Function               (on)-import           Data.IORef-import           Data.Monoid-import           Network.AWS.Auth-import           Network.AWS.Internal.Logger-import           Network.AWS.Lens            (Getter, Lens')-import           Network.AWS.Lens            (lens, to)-import           Network.AWS.Lens            ((.~), (<>~), (?~))-import           Network.AWS.Types-import           Network.HTTP.Conduit+import Control.Applicative+import Control.Monad.Catch+import Control.Monad.IO.Class+import Control.Monad.Reader++import Data.Function (on)+import Data.IORef+import Data.Maybe    (fromMaybe)+import Data.Monoid++import Network.AWS.Auth+import Network.AWS.Internal.Logger+import Network.AWS.Lens            (Getter, Lens')+import Network.AWS.Lens            (lens, to)+import Network.AWS.Lens            ((.~), (<>~), (?~))+import Network.AWS.Types+import Network.HTTP.Conduit  -- | The environment containing the parameters required to make AWS requests. data Env = Env
src/Network/AWS/Internal/Body.hs view
@@ -1,10 +1,11 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ViewPatterns               #-}  -- | -- Module      : Network.AWS.Internal.Body--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : provisional -- Portability : non-portable (GHC extensions) --@@ -23,11 +24,11 @@  -- | Convenience function for obtaining the size of a file. getFileSize :: MonadIO m => FilePath -> m Integer-getFileSize f = liftIO (withBinaryFile f ReadMode hFileSize)+getFileSize path = liftIO (withBinaryFile path ReadMode hFileSize)  -- | Connect a 'Sink' to a response stream. sinkBody :: MonadResource m => RsBody -> Sink ByteString m a -> m a-sinkBody (RsBody s) sink = hoist liftResourceT s $$+- sink+sinkBody (RsBody body) sink = hoist liftResourceT body $$+- sink  -- | Construct a 'HashedBody' from a 'FilePath', calculating the 'SHA256' hash -- and file size.@@ -37,40 +38,81 @@ -- lastly to stream the contents to the socket during sending. -- -- /See:/ 'ToHashedBody'.-hashedFile :: MonadIO m => FilePath -> m HashedBody-hashedFile f = liftIO $ HashedStream-    <$> runResourceT (Conduit.sourceFile f $$ sinkSHA256)-    <*> getFileSize f-    <*> pure (Conduit.sourceFile f)+hashedFile :: MonadIO m+           => FilePath -- ^ The file path to read.+           -> m HashedBody+hashedFile path =+    liftIO $ HashedStream+        <$> runResourceT (Conduit.sourceFile path $$ sinkSHA256)+        <*> getFileSize path+        <*> pure (Conduit.sourceFile path) --- | Construct a 'HashedBody' from a source, manually specifying the--- 'SHA256' hash and file size.+-- | Construct a 'HashedBody' from a 'FilePath', specifying the range of bytes+-- to read. This can be useful for constructing multiple requests from a single+-- file, say for S3 multipart uploads. --+-- /See:/ 'hashedFile', 'Conduit.sourceFileRange'.+hashedFileRange :: MonadIO m+                => FilePath -- ^ The file path to read.+                -> Integer  -- ^ The byte offset at which to start reading.+                -> Integer  -- ^ The maximum number of bytes to read.+                -> m HashedBody+hashedFileRange path (Just -> offset) (Just -> len) =+    liftIO $ HashedStream+        <$> runResourceT (Conduit.sourceFileRange path offset len $$ sinkSHA256)+        <*> getFileSize path+        <*> pure (Conduit.sourceFileRange path offset len)++-- | Construct a 'HashedBody' from a 'Source', manually specifying the 'SHA256'+-- hash and file size. It's left up to the caller to calculate these correctly,+-- otherwise AWS will return signing errors.+-- -- /See:/ 'ToHashedBody'.-hashedBody :: Digest SHA256-           -> Integer+hashedBody :: Digest SHA256 -- ^ A SHA256 hash of the file contents.+           -> Integer       -- ^ The size of the stream in bytes.            -> Source (ResourceT IO) ByteString            -> HashedBody-hashedBody h n = HashedStream h n+hashedBody = HashedStream --- | Something something.+-- | Construct a 'ChunkedBody' from a 'FilePath', where the contents will be+-- read and signed incrementally in chunks if the target service supports it. -- -- Will intelligently revert to 'HashedBody' if the file is smaller than the -- specified 'ChunkSize'. ----- Add note about how it selects chunk size.--- -- /See:/ 'ToBody'. chunkedFile :: MonadIO m => ChunkSize -> FilePath -> m RqBody-chunkedFile c f = do-    n <- getFileSize f-    if n > toInteger c-        then return $ unsafeChunkedBody c n (sourceFileChunks c f)-        else Hashed `liftM` hashedFile f+chunkedFile chunk path = do+    size <- getFileSize path+    if size > toInteger chunk+        then return $ unsafeChunkedBody chunk size (sourceFileChunks chunk path)+        else Hashed `liftM` hashedFile path --- | Something something.+-- | Construct a 'ChunkedBody' from a 'FilePath', specifying the range of bytes+-- to read. This can be useful for constructing multiple requests from a single+-- file, say for S3 multipart uploads. ----- Marked as unsafe because it does nothing to enforce the chunk size.+-- /See:/ 'chunkedFile'.+chunkedFileRange :: MonadIO m+                 => ChunkSize+                    -- ^ The idealized size of chunks that will be yielded downstream.+                 -> FilePath+                    -- ^ The file path to read.+                 -> Integer+                    -- ^ The byte offset at which to start reading.+                 -> Integer+                    -- ^ The maximum number of bytes to read.+                 -> m RqBody+chunkedFileRange chunk path offset len = do+    size <- getFileSize path+    let n = min (size - offset) len+    if  n > toInteger chunk+        then return $ unsafeChunkedBody chunk n (sourceFileRangeChunks chunk path offset len)+        else Hashed `liftM` hashedFileRange path offset len++-- | Unsafely construct a 'ChunkedBody'.+--+-- This function is marked unsafe because it does nothing to enforce the chunk size. -- Typically for conduit 'IO' functions, it's whatever ByteString's -- 'defaultBufferSize' is, around 32 KB. If the chunk size is less than 8 KB, -- the request will error. 64 KB or higher chunk size is recommended for@@ -81,25 +123,55 @@ -- -- /See:/ 'ToBody'. unsafeChunkedBody :: ChunkSize+                     -- ^ The idealized size of chunks that will be yielded downstream.                   -> Integer+                     -- ^ The size of the stream in bytes.                   -> Source (ResourceT IO) ByteString                   -> RqBody-unsafeChunkedBody c n = Chunked . ChunkedBody c n+unsafeChunkedBody chunk size = Chunked . ChunkedBody chunk size --- Uses hGet with a specific buffer size, instead of hGetSome. sourceFileChunks :: MonadResource m                  => ChunkSize                  -> FilePath                  -> Source m ByteString-sourceFileChunks (ChunkSize sz) f =-    bracketP (openBinaryFile f ReadMode) hClose go+sourceFileChunks (ChunkSize chunk) path =+    bracketP (openBinaryFile path ReadMode) hClose go   where-    go h = do-        bs <- liftIO (BS.hGet h sz)+    -- Uses hGet with a specific buffer size, instead of hGetSome.+    go hd = do+        bs <- liftIO (BS.hGet hd chunk)         unless (BS.null bs) $ do             yield bs-            go h+            go hd +sourceFileRangeChunks :: MonadResource m+                      => ChunkSize+                         -- ^ The idealized size of chunks that will be yielded downstream.+                      -> FilePath+                         -- ^ The file path to read.+                      -> Integer+                         -- ^ The byte offset at which to start reading.+                      -> Integer+                         -- ^ The maximum number of bytes to read.+                      -> Source m ByteString+sourceFileRangeChunks (ChunkSize chunk) path offset len =+    bracketP acquire hClose seek+  where+    acquire = openBinaryFile path ReadMode+    seek hd = liftIO (hSeek hd AbsoluteSeek offset) >> go (fromIntegral len) hd++    go remainder hd+        | remainder <= chunk = do+            bs <- liftIO (BS.hGet hd remainder)+            unless (BS.null bs) $+                yield bs++        | otherwise          = do+            bs <- liftIO (BS.hGet hd chunk)+            unless (BS.null bs) $ do+                yield bs+                go (remainder - chunk) hd+ -- | Incrementally calculate a 'MD5' 'Digest'. sinkMD5 :: Monad m => Consumer ByteString m (Digest MD5) sinkMD5 = sinkHash@@ -113,7 +185,7 @@ sinkHash = sink hashInit   where     sink ctx = do-        b <- await-        case b of+        mbs <- await+        case mbs of             Nothing -> return $! hashFinalize ctx             Just bs -> sink $! hashUpdate ctx bs
src/Network/AWS/Internal/HTTP.hs view
@@ -9,9 +9,9 @@  -- | -- Module      : Network.AWS.Internal.HTTP--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : provisional -- Portability : non-portable (GHC extensions) --@@ -20,23 +20,25 @@     , waiter     ) where -import           Control.Arrow                (first)-import           Control.Monad-import           Control.Monad.Catch-import           Control.Monad.Reader-import           Control.Monad.Trans.Resource-import           Control.Retry-import           Data.List                    (intersperse)-import           Data.Monoid-import           Data.Proxy-import           Data.Time-import           Network.AWS.Env-import           Network.AWS.Internal.Logger-import           Network.AWS.Lens             ((%~), (&), (^.), (^?))-import           Network.AWS.Lens             (to, view, _Just)-import           Network.AWS.Prelude-import           Network.AWS.Waiter-import           Network.HTTP.Conduit         hiding (Proxy, Request, Response)+import Control.Arrow                (first)+import Control.Monad+import Control.Monad.Catch+import Control.Monad.Reader+import Control.Monad.Trans.Resource+import Control.Retry++import Data.List   (intersperse)+import Data.Monoid+import Data.Proxy+import Data.Time++import Network.AWS.Env+import Network.AWS.Internal.Logger+import Network.AWS.Lens            ((%~), (&), (^.), (^?))+import Network.AWS.Lens            (to, view, _Just)+import Network.AWS.Prelude+import Network.AWS.Waiter+import Network.HTTP.Conduit        hiding (Proxy, Request, Response)  retrier :: ( MonadCatch m            , MonadResource m
src/Network/AWS/Internal/Logger.hs view
@@ -2,9 +2,9 @@  -- | -- Module      : Network.AWS.Internal.Logger--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : provisional -- Portability : non-portable (GHC extensions) --@@ -43,7 +43,6 @@ -- should be used in production code. newLogger :: MonadIO m => LogLevel -> Handle -> m Logger newLogger x hd = liftIO $ do-    hSetBinaryMode hd True     hSetBuffering  hd LineBuffering     return $ \y b ->         when (x >= y) $
src/Network/AWS/Presign.hs view
@@ -2,9 +2,9 @@  -- | -- Module      : Network.AWS.Presign--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : provisional -- Portability : non-portable (GHC extensions) --
test/Main.hs view
@@ -1,7 +1,7 @@ -- Module      : Main--- Copyright   : (c) 2013-2016 Brendan Hay+-- Copyright   : (c) 2013-2017 Brendan Hay -- License     : Mozilla Public License, v. 2.0.--- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions)