Skip to content

Commit

Permalink
Merge pull request #940 from endgame/migration-guide
Browse files Browse the repository at this point in the history
Migration guide
  • Loading branch information
endgame committed Jul 26, 2023
2 parents 05886ef + fb26635 commit f3556c9
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 45 deletions.
12 changes: 9 additions & 3 deletions lib/amazonka/CHANGELOG.md
Expand Up @@ -3,11 +3,17 @@
## [2.0.0](https://github.com/brendanhay/amazonka/tree/2.0.0)
Released: **?**, Compare: [2.0.0-rc2](https://github.com/brendanhay/amazonka/compare/2.0.0-rc2...2.0.0)

### Major Changes
### Changed

- `amazonka`: Update two missing EC2 metadata keys from [instance metadata categories](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html)
[\#935](https://github.com/brendanhay/amazonka/pull/935)
- `amazonka`: Stop re-exporting a subset of EC2 metadata keys from the root `Amazonka` module.
[\#940](https://github.com/brendanhay/amazonka/pull/940)
- Metadata users should import `Amazonka.EC2.Metadata` directly.
- The functions `Amazonka.dynamic`, `Amazonka.metadata` and `Amazonka.userdata` have been removed in favour of their equivalents in `Amazonka.EC2.Metadata` which only require a HTTP `Manager`, not an entire `Env`.
- It is easy to share a single `Manager` between metadata requests and an Amazonka `Env`:
- If you create the `Env` first, you can read its `manager :: Manager` field.
- If you make metadata requests before calling `newEnv`, you must create a `Manager` youself. You can pass this `Manager` to `newEnvFromManager`.

### Fixed

Expand All @@ -29,7 +35,7 @@ Released: **10th July, 2023**, Compare: [2.0.0-rc1](https://github.com/brendanha

- The authentication code in `amazonka` got a full rewrite in PR [\#746](https://github.com/brendanhay/amazonka/pull/746).

- On Windows, the {credential,config} files are read from `%USERPROFILE%\\.aws\\{credentials,config}` to [match the AWS SDK](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/creds-file.html#creds-file-general-info).
- On Windows, the {credential,config} files are read from `%USERPROFILE%\.aws\{credentials,config}` to [match the AWS SDK](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/creds-file.html#creds-file-general-info).
- `newEnv` now takes a function of type `EnvNoAuth -> m Env`, which is to fetch credentials in an appropriate manner
- The `Credentials` type has been removed, you should instead use the following functions corresponding to the departed constructor. All are exported by `Amazonka.Auth`:

Expand Down Expand Up @@ -253,7 +259,7 @@ Released: **28nd November, 2021**, Compare: [1.6.1](https://github.com/brendanha
- CPP supporting GHC < 8.8 has been removed.
- While GHC 8.6 is not in the CI matrix, it currently builds, so packages depend on `base >= 4.12`.

- The `Control.Monad.Trans.AWS` transformer and its related instances has been removed. Functions such as `send` and `paginate` now universally take an `Env` as their first argument, so you can build your own transformer, or use your preferred effects system.
- The `AWST` transformer from `Control.Monad.Trans.AWS` and its related instances has been removed. Functions such as `send` and `paginate` now universally take an `Env` as their first argument, so you can build your own transformer, or use your preferred effects system.

- Namespace
- The core `Network.AWS` namespace has been renamed to `Amazonka`, which now matches the package name. A simple search and replace on your codebase should be sufficient for migration:
Expand Down
67 changes: 67 additions & 0 deletions lib/amazonka/README.md
Expand Up @@ -11,6 +11,73 @@ with Amazon Web Service compatible APIs. Intended to be used alongside
the types supplied by the various `amazonka-*` service libraries.


## Migrating from 1.6.1 to 2.0

`CHANGELOG.md` is extremely thorough, but these notes should get you started:

* Modules have been moved from `Network.AWS.*` to `Amazonka.*`. Perform a find/replace on your import statements, e.g.:

```sh
perl -pi -e 's/Network\.AWS/Amazonka/g' `find . -type f -name '*.hs'`
```

* The `AWST` transformer from `Control.Monad.Trans.AWS` has been removed. Functions such as `send` now take an `Env` as their first argument. You can provide an `Env` directly, or use whatever transformer or effect system you prefer.

* The `Credentials` data type no longer exists. Credential discovery methods are now represented as functions of type `EnvNoAuth -> m Env`, and common ones are exported from `Amazonka.Auth`. In most cases you can downcase the first character of a former `Credentials` constructor and it will do the right thing:

```haskell
-- 1.6.1
env <- newEnv Discover

-- 2.0
env <- newEnv discover
```

A full list of new credential providers and their 1.6.1 equivalents, if any, are listed under the "Major Changes" heading of the 2.0 RC 2 section of `CHANGELOG.md`.

* On Windows, the {credential,config} files are read from `%USERPROFILE%\.aws\{credentials,config}` to [match the AWS SDK](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/creds-file.html#creds-file-general-info).

* Many Amazonka functions now require `Typeable` instances on request/response types. If you write code which is polymorphic across requests and responses, you may need to add `Typeable a` and `Typeable (AWSResponse a)` constraints alongside each `AWSRequest a` constraint.

* Request/response data types have been simplified:

- Data type smart constructors are prefixed with `new`. Example: `Network.AWS.S3.getObject` -> `Amazonka.S3.newGetObject`.
- All generated types export their constructors, which are always the "primed" name of the base type. Example: `data GetObject = GetObject' { ... }`.
- Records also export all their fields, which no longer have any prefix.
- The recommended way to fill in additional record fields is to use a library such as [`generic-lens`](https://hackage.haskell.org/package/generic-lens) or [`optics`](https://hackage.haskell.org/package/optics), possibly with the `OverloadedLabels` extension:

```haskell
-- 1.6.1
import Network.AWS.S3
let req = getObject "my-bucket" "/foo/bar.txt" & goVersionId ?~ "some-version"

-- 2.0
{-# LANGUAGE OverloadedLabels #-}
import Amazonka.S3
import Control.Lens ((?~))
import Data.Generics.Labels ()
let req = newGetObject "my-bucket" "/foo/bar.txt" & #versionId ?~ "some-version"
```
- Generated lenses are still available, but no longer use heuristic abbreviations. Example: `Network.AWS.S3.goVersionId` is now `Amazonka.S3.Lens.getObject_versionId`
- Enums (sum types) are now `newtype` wrappers over `Text`. "Constructors" for these enums are provided as ["bundled" pattern synonyms](https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/pattern_synonyms.html#import-and-export-of-pattern-synonyms), but other values are permitted. This is especially useful for new EC2 instance types or new AWS region names. As with generated lens names, the type name is baked into the pattern synonym. Example: `InstanceType_R4_8xlarge`.

* All hand-written records in `amazonka-core` and `amazonka` now follow the conventions set by generated records: no leading underscores and no inconsistent prefixing of fields. As part of this, some functions were renamed or removed:

- `Amazonka.Env.configure` -> `Amazonka.Env.configureService` (and its re-export from `Amazonka`)
- `Amazonka.Env.override` -> `Amazonka.Env.overrideService` (and its re-export from `Amazonka`)
- `Amazonka.Env.timeout` -> `Amazonka.Env.globalTimeout` (and its re-export from `Amazonka`)
- `Amazonka.Env.within`: removed; with `AWST` gone, it is just a record update

The removal of `AWST` means that `Network.AWS.Env` functions which used to operate on an `Env` inside a `MonadReader` now operate on the `Env` directly.

* Serialisation classes like `ToText` and `ToByteString`, and their associated helper functions, are no longer directly exported from module `Amazonka`. If you need these, you may need to import `Amazonka.Data` directly.

* The interface to the EC2 Instance Metadata Service (IMDS) is no longer exported from the root `Amazonka` module. If you used this, you should should import `Amazonka.EC2.Metadata` directly.

- The functions `Amazonka.dynamic`, `Amazonka.metadata` and `Amazonka.userdata` have been removed in favour of their equivalents in `Amazonka.EC2.Metadata` which only require a HTTP `Manager`, not an entire `Env`.
- If you were using them, read the `manager :: Manager` field directly from your `Env`.


## Contribute

For any problems, comments, or feedback please create an issue [here on GitHub](https://github.com/brendanhay/amazonka/issues).
Expand Down
2 changes: 1 addition & 1 deletion lib/amazonka/amazonka.cabal
Expand Up @@ -26,7 +26,7 @@ description:
To get started, import "Amazonka" and the desired @amazonka-*@ library (such as
<http://hackage.haskell.org/package/amazonka-ml/docs/Network-AWS-MachineLearning.html Amazonka.MachineLearning>)
.
GHC 8.8.4 and higher is officially supported.
GHC 8.10.7 and higher is officially supported.

source-repository head
type: git
Expand Down
39 changes: 7 additions & 32 deletions lib/amazonka/src/Amazonka.hs
Expand Up @@ -16,9 +16,9 @@ module Amazonka
-- $usage

-- * Authentication and Environment
Env.Env' (..),
Env.Env,
Env.EnvNoAuth,
Env.Env' (..),
Env.newEnv,
Env.newEnvFromManager,
Env.newEnvNoAuth,
Expand Down Expand Up @@ -102,14 +102,6 @@ module Amazonka
presignURL,
presign,

-- * EC2 Instance Metadata
-- $metadata
EC2.Dynamic (..),
dynamic,
EC2.Metadata (..),
metadata,
userdata,

-- * Running Asynchronous Actions
-- $async

Expand Down Expand Up @@ -144,7 +136,6 @@ import Amazonka.Core hiding (presign)
import qualified Amazonka.Core.Lens.Internal as Lens
import qualified Amazonka.Crypto as Crypto
import qualified Amazonka.Data.Body as Body
import qualified Amazonka.EC2.Metadata as EC2
import qualified Amazonka.Endpoint as Endpoint
import qualified Amazonka.Env as Env
import qualified Amazonka.Error as Error
Expand Down Expand Up @@ -177,7 +168,7 @@ import Control.Monad.Trans.Resource (runResourceT)
-- satisfy. To utilise these, you will need to specify what 'Region' you wish to
-- operate in and your Amazon credentials for AuthN/AuthZ purposes.
--
-- 'Credentials' can be supplied in a number of ways. Either via explicit keys,
-- Credentials can be supplied in a number of ways. Either via explicit keys,
-- via session profiles, or have Amazonka retrieve the credentials from an
-- underlying IAM Role/Profile.
--
Expand Down Expand Up @@ -281,7 +272,8 @@ import Control.Monad.Trans.Resource (runResourceT)
-- configuration when sending 'PutItem', 'Query' and all other operations.
--
-- You can modify a specific 'Service''s default configuration by using
-- 'configure'. To modify all configurations simultaneously, see 'override'.
-- 'Amazonka.Env.configureService'. To modify all configurations simultaneously, see
-- 'Amazonka.Env.overrideService'.
--
-- An example of how you might alter default configuration using these mechanisms
-- is demonstrated below. Firstly, the default 'dynamoDB' service is configured to
Expand Down Expand Up @@ -344,10 +336,6 @@ import Control.Monad.Trans.Resource (runResourceT)
-- Presigning requires the 'Service' signer to be an instance of 'AWSPresigner'.
-- Not all signing algorithms support this.

-- $metadata
-- Metadata can be retrieved from the underlying host assuming that you're running
-- the code on an EC2 instance or have a compatible @instance-data@ endpoint available.

-- $async
-- Requests can be sent asynchronously, but due to guarantees about resource closure
-- require the use of "UnliftIO.Async".
Expand Down Expand Up @@ -385,10 +373,10 @@ import Control.Monad.Trans.Resource (runResourceT)
-- appropriate 'AsError' 'Prism' when using the non-'Either' send variants:
--
-- @
-- trying '_Error' (send $ newListObjects "bucket-name") :: Either 'Error' ListObjectsResponse
-- trying '_Error' (send $ newListObjects "bucket-name") :: Either 'Amazonka.Types.Error' ListObjectsResponse
-- trying '_TransportError' (send $ newListObjects "bucket-name") :: Either 'HttpException' ListObjectsResponse
-- trying '_SerializeError' (send $ newListObjects "bucket-name") :: Either 'SerializeError' ListObjectsResponse
-- trying '_ServiceError' (send $ newListObjects "bucket-name") :: Either 'ServiceError' ListObjectsResponse
-- trying '_SerializeError' (send $ newListObjects "bucket-name") :: Either 'Amazonka.Types.SerializeError' ListObjectsResponse
-- trying '_ServiceError' (send $ newListObjects "bucket-name") :: Either 'Amazonka.Types.ServiceError' ListObjectsResponse
-- @
--
-- Many of the individual @amazonka-*@ libraries export compatible 'Control.Lens.Fold's for
Expand Down Expand Up @@ -447,16 +435,3 @@ presign env time expires rq = withAuth (runIdentity $ Env.auth env) $ \ae ->
time
expires
rq

-- | Retrieve the specified 'Dynamic' data.
dynamic :: MonadIO m => Env -> EC2.Dynamic -> m ByteString
dynamic env = EC2.dynamic (Env.manager env)

-- | Retrieve the specified 'Metadata'.
metadata :: MonadIO m => Env -> EC2.Metadata -> m ByteString
metadata env = EC2.metadata (Env.manager env)

-- | Retrieve the user data. Returns 'Nothing' if no user data is assigned
-- to the instance.
userdata :: MonadIO m => Env -> m (Maybe ByteString)
userdata = EC2.userdata . Env.manager
5 changes: 3 additions & 2 deletions lib/amazonka/src/Amazonka/EC2/Metadata.hs
Expand Up @@ -9,9 +9,10 @@
-- Portability : non-portable (GHC extensions)
--
-- This module contains functions for retrieving various EC2 metadata from an
-- instance's local metadata endpoint.
-- instance's local metadata endpoint. It assumes that you're running the code
-- on an EC2 instance or have a compatible @instance-data@ endpoint available.
--
-- It is intended to be used when you need to make metadata calls prior to
-- It is intended to be usable when you need to make metadata calls prior to
-- initialisation of the 'Amazonka.Env.Env'.
module Amazonka.EC2.Metadata
( -- * EC2 Instance Check
Expand Down
14 changes: 7 additions & 7 deletions lib/amazonka/src/Amazonka/Env.hs
Expand Up @@ -55,7 +55,7 @@ import qualified Network.HTTP.Conduit as Client.Conduit
import System.Environment as Environment

-- | An environment with auth credentials. Most AWS requests need one
-- of these, and you can create one with 'Amazonka.Env.newEnv'
-- of these, and you can create one with 'Amazonka.Env.newEnv'.
type Env = Env' Identity

-- | An environment with no auth credentials. Used for certain
Expand Down Expand Up @@ -109,9 +109,9 @@ env_auth :: Lens (Env' withAuth) (Env' withAuth') (withAuth Auth) (withAuth' Aut
env_auth f e@Env {auth} = f auth <&> \auth' -> e {auth = auth'}

-- | Creates a new environment with a new 'Client.Manager' without
-- debug logging and uses 'getAuth' to expand/discover the supplied
-- 'Credentials'. Lenses can be used to further configure the
-- resulting 'Env'.
-- debug logging and uses the provided function to expand/discover
-- credentials. Lenses can be used to further configure the resulting
-- 'Env'.
--
-- /Since:/ @1.5.0@ - The region is now retrieved from the @AWS_REGION@ environment
-- variable (identical to official SDKs), or defaults to @us-east-1@.
Expand Down Expand Up @@ -143,11 +143,11 @@ newEnvFromManager ::
newEnvFromManager manager = (newEnvNoAuthFromManager manager >>=)

-- | Generate an environment without credentials, which may only make
-- unsigned requests. This sets the region based on the @AWS_REGION@
-- unsigned requests. Sets the region based on the @AWS_REGION@
-- environment variable, or 'NorthVirginia' if unset.
--
-- This is useful for the STS
-- <https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html AssumeRoleWithWebIdentity>
-- This lets us support calls like
-- <https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html sts:AssumeRoleWithWebIdentity>
-- operation, which needs to make an unsigned request to pass the
-- token from an identity provider.
newEnvNoAuth :: MonadIO m => m EnvNoAuth
Expand Down

0 comments on commit f3556c9

Please sign in to comment.