diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,367 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,48 @@
+# Amazon EC2 Container Registry SDK
+
+* [Version](#version)
+* [Description](#description)
+* [Contribute](#contribute)
+* [Licence](#licence)
+
+
+## Version
+
+`1.4.0`
+
+
+## Description
+
+Amazon EC2 Container Registry (Amazon ECR) is a managed AWS Docker
+registry service. Customers can use the familiar Docker CLI to push,
+pull, and manage images. Amazon ECR provides a secure, scalable, and
+reliable registry. Amazon ECR supports private Docker repositories with
+resource-based permissions using AWS IAM so that specific users or
+Amazon EC2 instances can access repositories and images. Developers can
+use the Docker CLI to author and manage images.
+
+Documentation is available via [Hackage](http://hackage.haskell.org/package/amazonka-ecr)
+and the [AWS API Reference](https://aws.amazon.com/documentation/).
+
+The types from this library are intended to be used with [amazonka](http://hackage.haskell.org/package/amazonka),
+which provides mechanisms for specifying AuthN/AuthZ information and sending requests.
+
+Use of lenses is required for constructing and manipulating types.
+This is due to the amount of nesting of AWS types and transparency regarding
+de/serialisation into more palatable Haskell values.
+The provided lenses should be compatible with any of the major lens libraries
+[lens](http://hackage.haskell.org/package/lens) or [lens-family-core](http://hackage.haskell.org/package/lens-family-core).
+
+## Contribute
+
+For any problems, comments, or feedback please create an issue [here on GitHub](https://github.com/brendanhay/amazonka/issues).
+
+> _Note:_ this library is an auto-generated Haskell package. Please see `amazonka-gen` for more information.
+
+
+## Licence
+
+`amazonka-ecr` is released under the [Mozilla Public License Version 2.0](http://www.mozilla.org/MPL/).
+
+Parts of the code are derived from AWS service descriptions, licensed under Apache 2.0.
+Source files subject to this contain an additional licensing clause in their header.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import           Distribution.Simple
+main = defaultMain
diff --git a/amazonka-ecr.cabal b/amazonka-ecr.cabal
new file mode 100644
--- /dev/null
+++ b/amazonka-ecr.cabal
@@ -0,0 +1,103 @@
+name:                  amazonka-ecr
+version:               1.4.0
+synopsis:              Amazon EC2 Container Registry SDK.
+homepage:              https://github.com/brendanhay/amazonka
+bug-reports:           https://github.com/brendanhay/amazonka/issues
+license:               OtherLicense
+license-file:          LICENSE
+author:                Brendan Hay
+maintainer:            Brendan Hay <brendan.g.hay@gmail.com>
+copyright:             Copyright (c) 2013-2016 Brendan Hay
+category:              Network, AWS, Cloud, Distributed Computing
+build-type:            Simple
+cabal-version:         >= 1.10
+extra-source-files:    README.md fixture/*.yaml fixture/*.proto
+description:
+    Amazon EC2 Container Registry (Amazon ECR) is a managed AWS Docker
+    registry service. Customers can use the familiar Docker CLI to push,
+    pull, and manage images. Amazon ECR provides a secure, scalable, and
+    reliable registry. Amazon ECR supports private Docker repositories with
+    resource-based permissions using AWS IAM so that specific users or
+    Amazon EC2 instances can access repositories and images. Developers can
+    use the Docker CLI to author and manage images.
+    .
+    The types from this library are intended to be used with
+    <http://hackage.haskell.org/package/amazonka amazonka>, which provides
+    mechanisms for specifying AuthN/AuthZ information and sending requests.
+    .
+    Use of lenses is required for constructing and manipulating types.
+    This is due to the amount of nesting of AWS types and transparency regarding
+    de/serialisation into more palatable Haskell values.
+    The provided lenses should be compatible with any of the major lens libraries
+    such as <http://hackage.haskell.org/package/lens lens> or
+    <http://hackage.haskell.org/package/lens-family-core lens-family-core>.
+    .
+    See "Network.AWS.ECR" or <https://aws.amazon.com/documentation/ the AWS Documentation>
+    to get started.
+
+source-repository head
+    type:     git
+    location: git://github.com/brendanhay/amazonka.git
+
+library
+    default-language:  Haskell2010
+    hs-source-dirs:    src gen
+
+    ghc-options:       -Wall
+
+    exposed-modules:
+          Network.AWS.ECR
+        , Network.AWS.ECR.BatchCheckLayerAvailability
+        , Network.AWS.ECR.BatchDeleteImage
+        , Network.AWS.ECR.BatchGetImage
+        , Network.AWS.ECR.CompleteLayerUpload
+        , Network.AWS.ECR.CreateRepository
+        , Network.AWS.ECR.DeleteRepository
+        , Network.AWS.ECR.DeleteRepositoryPolicy
+        , Network.AWS.ECR.DescribeRepositories
+        , Network.AWS.ECR.GetAuthorizationToken
+        , Network.AWS.ECR.GetDownloadURLForLayer
+        , Network.AWS.ECR.GetRepositoryPolicy
+        , Network.AWS.ECR.InitiateLayerUpload
+        , Network.AWS.ECR.ListImages
+        , Network.AWS.ECR.PutImage
+        , Network.AWS.ECR.SetRepositoryPolicy
+        , Network.AWS.ECR.Types
+        , Network.AWS.ECR.UploadLayerPart
+        , Network.AWS.ECR.Waiters
+
+    other-modules:
+          Network.AWS.ECR.Types.Product
+        , Network.AWS.ECR.Types.Sum
+
+    build-depends:
+          amazonka-core == 1.4.0.*
+        , base          >= 4.7     && < 5
+
+test-suite amazonka-ecr-test
+    type:              exitcode-stdio-1.0
+    default-language:  Haskell2010
+    hs-source-dirs:    test
+    main-is:           Main.hs
+
+    ghc-options:       -Wall -threaded
+
+    -- This section is encoded by the template and any modules added by
+    -- hand outside these namespaces will not correctly be added to the
+    -- distribution package.
+    other-modules:
+          Test.AWS.ECR
+        , Test.AWS.Gen.ECR
+        , Test.AWS.ECR.Internal
+
+    build-depends:
+          amazonka-core == 1.4.0.*
+        , amazonka-test == 1.4.0.*
+        , amazonka-ecr == 1.4.0.*
+        , base
+        , bytestring
+        , tasty
+        , tasty-hunit
+        , text
+        , time
+        , unordered-containers
diff --git a/fixture/BatchCheckLayerAvailability.yaml b/fixture/BatchCheckLayerAvailability.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/BatchCheckLayerAvailability.yaml
diff --git a/fixture/BatchCheckLayerAvailabilityResponse.proto b/fixture/BatchCheckLayerAvailabilityResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/BatchCheckLayerAvailabilityResponse.proto
diff --git a/fixture/BatchDeleteImage.yaml b/fixture/BatchDeleteImage.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/BatchDeleteImage.yaml
diff --git a/fixture/BatchDeleteImageResponse.proto b/fixture/BatchDeleteImageResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/BatchDeleteImageResponse.proto
diff --git a/fixture/BatchGetImage.yaml b/fixture/BatchGetImage.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/BatchGetImage.yaml
diff --git a/fixture/BatchGetImageResponse.proto b/fixture/BatchGetImageResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/BatchGetImageResponse.proto
diff --git a/fixture/CompleteLayerUpload.yaml b/fixture/CompleteLayerUpload.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/CompleteLayerUpload.yaml
diff --git a/fixture/CompleteLayerUploadResponse.proto b/fixture/CompleteLayerUploadResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/CompleteLayerUploadResponse.proto
diff --git a/fixture/CreateRepository.yaml b/fixture/CreateRepository.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/CreateRepository.yaml
diff --git a/fixture/CreateRepositoryResponse.proto b/fixture/CreateRepositoryResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/CreateRepositoryResponse.proto
diff --git a/fixture/DeleteRepository.yaml b/fixture/DeleteRepository.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/DeleteRepository.yaml
diff --git a/fixture/DeleteRepositoryPolicy.yaml b/fixture/DeleteRepositoryPolicy.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/DeleteRepositoryPolicy.yaml
diff --git a/fixture/DeleteRepositoryPolicyResponse.proto b/fixture/DeleteRepositoryPolicyResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/DeleteRepositoryPolicyResponse.proto
diff --git a/fixture/DeleteRepositoryResponse.proto b/fixture/DeleteRepositoryResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/DeleteRepositoryResponse.proto
diff --git a/fixture/DescribeRepositories.yaml b/fixture/DescribeRepositories.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/DescribeRepositories.yaml
diff --git a/fixture/DescribeRepositoriesResponse.proto b/fixture/DescribeRepositoriesResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/DescribeRepositoriesResponse.proto
diff --git a/fixture/GetAuthorizationToken.yaml b/fixture/GetAuthorizationToken.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/GetAuthorizationToken.yaml
diff --git a/fixture/GetAuthorizationTokenResponse.proto b/fixture/GetAuthorizationTokenResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/GetAuthorizationTokenResponse.proto
diff --git a/fixture/GetDownloadURLForLayer.yaml b/fixture/GetDownloadURLForLayer.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/GetDownloadURLForLayer.yaml
diff --git a/fixture/GetDownloadURLForLayerResponse.proto b/fixture/GetDownloadURLForLayerResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/GetDownloadURLForLayerResponse.proto
diff --git a/fixture/GetRepositoryPolicy.yaml b/fixture/GetRepositoryPolicy.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/GetRepositoryPolicy.yaml
diff --git a/fixture/GetRepositoryPolicyResponse.proto b/fixture/GetRepositoryPolicyResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/GetRepositoryPolicyResponse.proto
diff --git a/fixture/InitiateLayerUpload.yaml b/fixture/InitiateLayerUpload.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/InitiateLayerUpload.yaml
diff --git a/fixture/InitiateLayerUploadResponse.proto b/fixture/InitiateLayerUploadResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/InitiateLayerUploadResponse.proto
diff --git a/fixture/ListImages.yaml b/fixture/ListImages.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/ListImages.yaml
diff --git a/fixture/ListImagesResponse.proto b/fixture/ListImagesResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/ListImagesResponse.proto
diff --git a/fixture/PutImage.yaml b/fixture/PutImage.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/PutImage.yaml
diff --git a/fixture/PutImageResponse.proto b/fixture/PutImageResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/PutImageResponse.proto
diff --git a/fixture/SetRepositoryPolicy.yaml b/fixture/SetRepositoryPolicy.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/SetRepositoryPolicy.yaml
diff --git a/fixture/SetRepositoryPolicyResponse.proto b/fixture/SetRepositoryPolicyResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/SetRepositoryPolicyResponse.proto
diff --git a/fixture/UploadLayerPart.yaml b/fixture/UploadLayerPart.yaml
new file mode 100644
--- /dev/null
+++ b/fixture/UploadLayerPart.yaml
diff --git a/fixture/UploadLayerPartResponse.proto b/fixture/UploadLayerPartResponse.proto
new file mode 100644
--- /dev/null
+++ b/fixture/UploadLayerPartResponse.proto
diff --git a/gen/Network/AWS/ECR.hs b/gen/Network/AWS/ECR.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR.hs
@@ -0,0 +1,239 @@
+{-# OPTIONS_GHC -fno-warn-unused-imports    #-}
+{-# OPTIONS_GHC -fno-warn-duplicate-exports #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Amazon EC2 Container Registry (Amazon ECR) is a managed AWS Docker
+-- registry service. Customers can use the familiar Docker CLI to push,
+-- pull, and manage images. Amazon ECR provides a secure, scalable, and
+-- reliable registry. Amazon ECR supports private Docker repositories with
+-- resource-based permissions using AWS IAM so that specific users or
+-- Amazon EC2 instances can access repositories and images. Developers can
+-- use the Docker CLI to author and manage images.
+module Network.AWS.ECR
+    (
+    -- * Service Configuration
+      ecr
+
+    -- * Errors
+    -- $errors
+
+    -- ** LayersNotFoundException
+    , _LayersNotFoundException
+
+    -- ** InvalidParameterException
+    , _InvalidParameterException
+
+    -- ** LayerAlreadyExistsException
+    , _LayerAlreadyExistsException
+
+    -- ** ServerException
+    , _ServerException
+
+    -- ** LayerInaccessibleException
+    , _LayerInaccessibleException
+
+    -- ** InvalidLayerException
+    , _InvalidLayerException
+
+    -- ** LayerPartTooSmallException
+    , _LayerPartTooSmallException
+
+    -- ** ImageAlreadyExistsException
+    , _ImageAlreadyExistsException
+
+    -- ** RepositoryNotFoundException
+    , _RepositoryNotFoundException
+
+    -- ** UploadNotFoundException
+    , _UploadNotFoundException
+
+    -- ** InvalidLayerPartException
+    , _InvalidLayerPartException
+
+    -- ** RepositoryNotEmptyException
+    , _RepositoryNotEmptyException
+
+    -- ** RepositoryAlreadyExistsException
+    , _RepositoryAlreadyExistsException
+
+    -- ** RepositoryPolicyNotFoundException
+    , _RepositoryPolicyNotFoundException
+
+    -- ** EmptyUploadException
+    , _EmptyUploadException
+
+    -- ** LimitExceededException
+    , _LimitExceededException
+
+    -- * Waiters
+    -- $waiters
+
+    -- * Operations
+    -- $operations
+
+    -- ** GetRepositoryPolicy
+    , module Network.AWS.ECR.GetRepositoryPolicy
+
+    -- ** BatchDeleteImage
+    , module Network.AWS.ECR.BatchDeleteImage
+
+    -- ** BatchCheckLayerAvailability
+    , module Network.AWS.ECR.BatchCheckLayerAvailability
+
+    -- ** DeleteRepositoryPolicy
+    , module Network.AWS.ECR.DeleteRepositoryPolicy
+
+    -- ** CreateRepository
+    , module Network.AWS.ECR.CreateRepository
+
+    -- ** CompleteLayerUpload
+    , module Network.AWS.ECR.CompleteLayerUpload
+
+    -- ** DescribeRepositories
+    , module Network.AWS.ECR.DescribeRepositories
+
+    -- ** UploadLayerPart
+    , module Network.AWS.ECR.UploadLayerPart
+
+    -- ** BatchGetImage
+    , module Network.AWS.ECR.BatchGetImage
+
+    -- ** SetRepositoryPolicy
+    , module Network.AWS.ECR.SetRepositoryPolicy
+
+    -- ** InitiateLayerUpload
+    , module Network.AWS.ECR.InitiateLayerUpload
+
+    -- ** DeleteRepository
+    , module Network.AWS.ECR.DeleteRepository
+
+    -- ** PutImage
+    , module Network.AWS.ECR.PutImage
+
+    -- ** ListImages
+    , module Network.AWS.ECR.ListImages
+
+    -- ** GetAuthorizationToken
+    , module Network.AWS.ECR.GetAuthorizationToken
+
+    -- ** GetDownloadURLForLayer
+    , module Network.AWS.ECR.GetDownloadURLForLayer
+
+    -- * Types
+
+    -- ** ImageFailureCode
+    , ImageFailureCode (..)
+
+    -- ** LayerAvailability
+    , LayerAvailability (..)
+
+    -- ** LayerFailureCode
+    , LayerFailureCode (..)
+
+    -- ** AuthorizationData
+    , AuthorizationData
+    , authorizationData
+    , adExpiresAt
+    , adProxyEndpoint
+    , adAuthorizationToken
+
+    -- ** Image
+    , Image
+    , image
+    , iRegistryId
+    , iImageId
+    , iRepositoryName
+    , iImageManifest
+
+    -- ** ImageFailure
+    , ImageFailure
+    , imageFailure
+    , ifFailureReason
+    , ifFailureCode
+    , ifImageId
+
+    -- ** ImageIdentifier
+    , ImageIdentifier
+    , imageIdentifier
+    , iiImageDigest
+    , iiImageTag
+
+    -- ** Layer
+    , Layer
+    , layer
+    , lLayerDigest
+    , lLayerSize
+    , lLayerAvailability
+
+    -- ** LayerFailure
+    , LayerFailure
+    , layerFailure
+    , lfFailureReason
+    , lfFailureCode
+    , lfLayerDigest
+
+    -- ** Repository
+    , Repository
+    , repository
+    , rRepositoryARN
+    , rRegistryId
+    , rRepositoryName
+    ) where
+
+import           Network.AWS.ECR.BatchCheckLayerAvailability
+import           Network.AWS.ECR.BatchDeleteImage
+import           Network.AWS.ECR.BatchGetImage
+import           Network.AWS.ECR.CompleteLayerUpload
+import           Network.AWS.ECR.CreateRepository
+import           Network.AWS.ECR.DeleteRepository
+import           Network.AWS.ECR.DeleteRepositoryPolicy
+import           Network.AWS.ECR.DescribeRepositories
+import           Network.AWS.ECR.GetAuthorizationToken
+import           Network.AWS.ECR.GetDownloadURLForLayer
+import           Network.AWS.ECR.GetRepositoryPolicy
+import           Network.AWS.ECR.InitiateLayerUpload
+import           Network.AWS.ECR.ListImages
+import           Network.AWS.ECR.PutImage
+import           Network.AWS.ECR.SetRepositoryPolicy
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.UploadLayerPart
+import           Network.AWS.ECR.Waiters
+
+{- $errors
+Error matchers are designed for use with the functions provided by
+<http://hackage.haskell.org/package/lens/docs/Control-Exception-Lens.html Control.Exception.Lens>.
+This allows catching (and rethrowing) service specific errors returned
+by 'ECR'.
+-}
+
+{- $operations
+Some AWS operations return results that are incomplete and require subsequent
+requests in order to obtain the entire result set. The process of sending
+subsequent requests to continue where a previous request left off is called
+pagination. For example, the 'ListObjects' operation of Amazon S3 returns up to
+1000 objects at a time, and you must send subsequent requests with the
+appropriate Marker in order to retrieve the next page of results.
+
+Operations that have an 'AWSPager' instance can transparently perform subsequent
+requests, correctly setting Markers and other request facets to iterate through
+the entire result set of a truncated API operation. Operations which support
+this have an additional note in the documentation.
+
+Many operations have the ability to filter results on the server side. See the
+individual operation parameters for details.
+-}
+
+{- $waiters
+Waiters poll by repeatedly sending a request until some remote success condition
+configured by the 'Wait' specification is fulfilled. The 'Wait' specification
+determines how many attempts should be made, in addition to delay and retry strategies.
+-}
diff --git a/gen/Network/AWS/ECR/BatchCheckLayerAvailability.hs b/gen/Network/AWS/ECR/BatchCheckLayerAvailability.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/BatchCheckLayerAvailability.hs
@@ -0,0 +1,170 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.BatchCheckLayerAvailability
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Check the availability of multiple image layers in a specified registry
+-- and repository.
+--
+-- This operation is used by the Amazon ECR proxy, and it is not intended
+-- for general use by customers. Use the 'docker' CLI to pull, tag, and
+-- push images.
+module Network.AWS.ECR.BatchCheckLayerAvailability
+    (
+    -- * Creating a Request
+      batchCheckLayerAvailability
+    , BatchCheckLayerAvailability
+    -- * Request Lenses
+    , bclaRegistryId
+    , bclaRepositoryName
+    , bclaLayerDigests
+
+    -- * Destructuring the Response
+    , batchCheckLayerAvailabilityResponse
+    , BatchCheckLayerAvailabilityResponse
+    -- * Response Lenses
+    , bclarsFailures
+    , bclarsLayers
+    , bclarsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'batchCheckLayerAvailability' smart constructor.
+data BatchCheckLayerAvailability = BatchCheckLayerAvailability'
+    { _bclaRegistryId     :: !(Maybe Text)
+    , _bclaRepositoryName :: !Text
+    , _bclaLayerDigests   :: !(List1 Text)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'BatchCheckLayerAvailability' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'bclaRegistryId'
+--
+-- * 'bclaRepositoryName'
+--
+-- * 'bclaLayerDigests'
+batchCheckLayerAvailability
+    :: Text -- ^ 'bclaRepositoryName'
+    -> NonEmpty Text -- ^ 'bclaLayerDigests'
+    -> BatchCheckLayerAvailability
+batchCheckLayerAvailability pRepositoryName_ pLayerDigests_ =
+    BatchCheckLayerAvailability'
+    { _bclaRegistryId = Nothing
+    , _bclaRepositoryName = pRepositoryName_
+    , _bclaLayerDigests = _List1 # pLayerDigests_
+    }
+
+-- | The AWS account ID associated with the registry that contains the image
+-- layers to check. If you do not specify a registry, the default registry
+-- is assumed.
+bclaRegistryId :: Lens' BatchCheckLayerAvailability (Maybe Text)
+bclaRegistryId = lens _bclaRegistryId (\ s a -> s{_bclaRegistryId = a});
+
+-- | The name of the repository that is associated with the image layers to
+-- check.
+bclaRepositoryName :: Lens' BatchCheckLayerAvailability Text
+bclaRepositoryName = lens _bclaRepositoryName (\ s a -> s{_bclaRepositoryName = a});
+
+-- | The digests of the image layers to check.
+bclaLayerDigests :: Lens' BatchCheckLayerAvailability (NonEmpty Text)
+bclaLayerDigests = lens _bclaLayerDigests (\ s a -> s{_bclaLayerDigests = a}) . _List1;
+
+instance AWSRequest BatchCheckLayerAvailability where
+        type Rs BatchCheckLayerAvailability =
+             BatchCheckLayerAvailabilityResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 BatchCheckLayerAvailabilityResponse' <$>
+                   (x .?> "failures" .!@ mempty) <*>
+                     (x .?> "layers" .!@ mempty)
+                     <*> (pure (fromEnum s)))
+
+instance Hashable BatchCheckLayerAvailability
+
+instance ToHeaders BatchCheckLayerAvailability where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.BatchCheckLayerAvailability"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON BatchCheckLayerAvailability where
+        toJSON BatchCheckLayerAvailability'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _bclaRegistryId,
+                  Just ("repositoryName" .= _bclaRepositoryName),
+                  Just ("layerDigests" .= _bclaLayerDigests)])
+
+instance ToPath BatchCheckLayerAvailability where
+        toPath = const "/"
+
+instance ToQuery BatchCheckLayerAvailability where
+        toQuery = const mempty
+
+-- | /See:/ 'batchCheckLayerAvailabilityResponse' smart constructor.
+data BatchCheckLayerAvailabilityResponse = BatchCheckLayerAvailabilityResponse'
+    { _bclarsFailures       :: !(Maybe [LayerFailure])
+    , _bclarsLayers         :: !(Maybe [Layer])
+    , _bclarsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'BatchCheckLayerAvailabilityResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'bclarsFailures'
+--
+-- * 'bclarsLayers'
+--
+-- * 'bclarsResponseStatus'
+batchCheckLayerAvailabilityResponse
+    :: Int -- ^ 'bclarsResponseStatus'
+    -> BatchCheckLayerAvailabilityResponse
+batchCheckLayerAvailabilityResponse pResponseStatus_ =
+    BatchCheckLayerAvailabilityResponse'
+    { _bclarsFailures = Nothing
+    , _bclarsLayers = Nothing
+    , _bclarsResponseStatus = pResponseStatus_
+    }
+
+-- | Any failures associated with the call.
+bclarsFailures :: Lens' BatchCheckLayerAvailabilityResponse [LayerFailure]
+bclarsFailures = lens _bclarsFailures (\ s a -> s{_bclarsFailures = a}) . _Default . _Coerce;
+
+-- | A list of image layer objects corresponding to the image layer
+-- references in the request.
+bclarsLayers :: Lens' BatchCheckLayerAvailabilityResponse [Layer]
+bclarsLayers = lens _bclarsLayers (\ s a -> s{_bclarsLayers = a}) . _Default . _Coerce;
+
+-- | The response status code.
+bclarsResponseStatus :: Lens' BatchCheckLayerAvailabilityResponse Int
+bclarsResponseStatus = lens _bclarsResponseStatus (\ s a -> s{_bclarsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/BatchDeleteImage.hs b/gen/Network/AWS/ECR/BatchDeleteImage.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/BatchDeleteImage.hs
@@ -0,0 +1,167 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.BatchDeleteImage
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Deletes a list of specified images within a specified repository. Images
+-- are specified with either 'imageTag' or 'imageDigest'.
+module Network.AWS.ECR.BatchDeleteImage
+    (
+    -- * Creating a Request
+      batchDeleteImage
+    , BatchDeleteImage
+    -- * Request Lenses
+    , bdiRegistryId
+    , bdiRepositoryName
+    , bdiImageIds
+
+    -- * Destructuring the Response
+    , batchDeleteImageResponse
+    , BatchDeleteImageResponse
+    -- * Response Lenses
+    , bdirsFailures
+    , bdirsImageIds
+    , bdirsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | Deletes specified images within a specified repository. Images are
+-- specified with either the 'imageTag' or 'imageDigest'.
+--
+-- /See:/ 'batchDeleteImage' smart constructor.
+data BatchDeleteImage = BatchDeleteImage'
+    { _bdiRegistryId     :: !(Maybe Text)
+    , _bdiRepositoryName :: !Text
+    , _bdiImageIds       :: !(List1 ImageIdentifier)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'BatchDeleteImage' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'bdiRegistryId'
+--
+-- * 'bdiRepositoryName'
+--
+-- * 'bdiImageIds'
+batchDeleteImage
+    :: Text -- ^ 'bdiRepositoryName'
+    -> NonEmpty ImageIdentifier -- ^ 'bdiImageIds'
+    -> BatchDeleteImage
+batchDeleteImage pRepositoryName_ pImageIds_ =
+    BatchDeleteImage'
+    { _bdiRegistryId = Nothing
+    , _bdiRepositoryName = pRepositoryName_
+    , _bdiImageIds = _List1 # pImageIds_
+    }
+
+-- | The AWS account ID associated with the registry that contains the image
+-- to delete. If you do not specify a registry, the default registry is
+-- assumed.
+bdiRegistryId :: Lens' BatchDeleteImage (Maybe Text)
+bdiRegistryId = lens _bdiRegistryId (\ s a -> s{_bdiRegistryId = a});
+
+-- | The repository that contains the image to delete.
+bdiRepositoryName :: Lens' BatchDeleteImage Text
+bdiRepositoryName = lens _bdiRepositoryName (\ s a -> s{_bdiRepositoryName = a});
+
+-- | A list of image ID references that correspond to images to delete. The
+-- format of the 'imageIds' reference is 'imageTag=tag' or
+-- 'imageDigest=digest'.
+bdiImageIds :: Lens' BatchDeleteImage (NonEmpty ImageIdentifier)
+bdiImageIds = lens _bdiImageIds (\ s a -> s{_bdiImageIds = a}) . _List1;
+
+instance AWSRequest BatchDeleteImage where
+        type Rs BatchDeleteImage = BatchDeleteImageResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 BatchDeleteImageResponse' <$>
+                   (x .?> "failures" .!@ mempty) <*> (x .?> "imageIds")
+                     <*> (pure (fromEnum s)))
+
+instance Hashable BatchDeleteImage
+
+instance ToHeaders BatchDeleteImage where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.BatchDeleteImage"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON BatchDeleteImage where
+        toJSON BatchDeleteImage'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _bdiRegistryId,
+                  Just ("repositoryName" .= _bdiRepositoryName),
+                  Just ("imageIds" .= _bdiImageIds)])
+
+instance ToPath BatchDeleteImage where
+        toPath = const "/"
+
+instance ToQuery BatchDeleteImage where
+        toQuery = const mempty
+
+-- | /See:/ 'batchDeleteImageResponse' smart constructor.
+data BatchDeleteImageResponse = BatchDeleteImageResponse'
+    { _bdirsFailures       :: !(Maybe [ImageFailure])
+    , _bdirsImageIds       :: !(Maybe (List1 ImageIdentifier))
+    , _bdirsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'BatchDeleteImageResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'bdirsFailures'
+--
+-- * 'bdirsImageIds'
+--
+-- * 'bdirsResponseStatus'
+batchDeleteImageResponse
+    :: Int -- ^ 'bdirsResponseStatus'
+    -> BatchDeleteImageResponse
+batchDeleteImageResponse pResponseStatus_ =
+    BatchDeleteImageResponse'
+    { _bdirsFailures = Nothing
+    , _bdirsImageIds = Nothing
+    , _bdirsResponseStatus = pResponseStatus_
+    }
+
+-- | Any failures associated with the call.
+bdirsFailures :: Lens' BatchDeleteImageResponse [ImageFailure]
+bdirsFailures = lens _bdirsFailures (\ s a -> s{_bdirsFailures = a}) . _Default . _Coerce;
+
+-- | The image IDs of the deleted images.
+bdirsImageIds :: Lens' BatchDeleteImageResponse (Maybe (NonEmpty ImageIdentifier))
+bdirsImageIds = lens _bdirsImageIds (\ s a -> s{_bdirsImageIds = a}) . mapping _List1;
+
+-- | The response status code.
+bdirsResponseStatus :: Lens' BatchDeleteImageResponse Int
+bdirsResponseStatus = lens _bdirsResponseStatus (\ s a -> s{_bdirsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/BatchGetImage.hs b/gen/Network/AWS/ECR/BatchGetImage.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/BatchGetImage.hs
@@ -0,0 +1,167 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.BatchGetImage
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Gets detailed information for specified images within a specified
+-- repository. Images are specified with either 'imageTag' or
+-- 'imageDigest'.
+module Network.AWS.ECR.BatchGetImage
+    (
+    -- * Creating a Request
+      batchGetImage
+    , BatchGetImage
+    -- * Request Lenses
+    , bgiRegistryId
+    , bgiRepositoryName
+    , bgiImageIds
+
+    -- * Destructuring the Response
+    , batchGetImageResponse
+    , BatchGetImageResponse
+    -- * Response Lenses
+    , bgirsImages
+    , bgirsFailures
+    , bgirsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'batchGetImage' smart constructor.
+data BatchGetImage = BatchGetImage'
+    { _bgiRegistryId     :: !(Maybe Text)
+    , _bgiRepositoryName :: !Text
+    , _bgiImageIds       :: !(List1 ImageIdentifier)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'BatchGetImage' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'bgiRegistryId'
+--
+-- * 'bgiRepositoryName'
+--
+-- * 'bgiImageIds'
+batchGetImage
+    :: Text -- ^ 'bgiRepositoryName'
+    -> NonEmpty ImageIdentifier -- ^ 'bgiImageIds'
+    -> BatchGetImage
+batchGetImage pRepositoryName_ pImageIds_ =
+    BatchGetImage'
+    { _bgiRegistryId = Nothing
+    , _bgiRepositoryName = pRepositoryName_
+    , _bgiImageIds = _List1 # pImageIds_
+    }
+
+-- | The AWS account ID associated with the registry that contains the images
+-- to describe. If you do not specify a registry, the default registry is
+-- assumed.
+bgiRegistryId :: Lens' BatchGetImage (Maybe Text)
+bgiRegistryId = lens _bgiRegistryId (\ s a -> s{_bgiRegistryId = a});
+
+-- | The repository that contains the images to describe.
+bgiRepositoryName :: Lens' BatchGetImage Text
+bgiRepositoryName = lens _bgiRepositoryName (\ s a -> s{_bgiRepositoryName = a});
+
+-- | A list of image ID references that correspond to images to describe. The
+-- format of the 'imageIds' reference is 'imageTag=tag' or
+-- 'imageDigest=digest'.
+bgiImageIds :: Lens' BatchGetImage (NonEmpty ImageIdentifier)
+bgiImageIds = lens _bgiImageIds (\ s a -> s{_bgiImageIds = a}) . _List1;
+
+instance AWSRequest BatchGetImage where
+        type Rs BatchGetImage = BatchGetImageResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 BatchGetImageResponse' <$>
+                   (x .?> "images" .!@ mempty) <*>
+                     (x .?> "failures" .!@ mempty)
+                     <*> (pure (fromEnum s)))
+
+instance Hashable BatchGetImage
+
+instance ToHeaders BatchGetImage where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.BatchGetImage"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON BatchGetImage where
+        toJSON BatchGetImage'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _bgiRegistryId,
+                  Just ("repositoryName" .= _bgiRepositoryName),
+                  Just ("imageIds" .= _bgiImageIds)])
+
+instance ToPath BatchGetImage where
+        toPath = const "/"
+
+instance ToQuery BatchGetImage where
+        toQuery = const mempty
+
+-- | /See:/ 'batchGetImageResponse' smart constructor.
+data BatchGetImageResponse = BatchGetImageResponse'
+    { _bgirsImages         :: !(Maybe [Image])
+    , _bgirsFailures       :: !(Maybe [ImageFailure])
+    , _bgirsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'BatchGetImageResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'bgirsImages'
+--
+-- * 'bgirsFailures'
+--
+-- * 'bgirsResponseStatus'
+batchGetImageResponse
+    :: Int -- ^ 'bgirsResponseStatus'
+    -> BatchGetImageResponse
+batchGetImageResponse pResponseStatus_ =
+    BatchGetImageResponse'
+    { _bgirsImages = Nothing
+    , _bgirsFailures = Nothing
+    , _bgirsResponseStatus = pResponseStatus_
+    }
+
+-- | A list of image objects corresponding to the image references in the
+-- request.
+bgirsImages :: Lens' BatchGetImageResponse [Image]
+bgirsImages = lens _bgirsImages (\ s a -> s{_bgirsImages = a}) . _Default . _Coerce;
+
+-- | Any failures associated with the call.
+bgirsFailures :: Lens' BatchGetImageResponse [ImageFailure]
+bgirsFailures = lens _bgirsFailures (\ s a -> s{_bgirsFailures = a}) . _Default . _Coerce;
+
+-- | The response status code.
+bgirsResponseStatus :: Lens' BatchGetImageResponse Int
+bgirsResponseStatus = lens _bgirsResponseStatus (\ s a -> s{_bgirsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/CompleteLayerUpload.hs b/gen/Network/AWS/ECR/CompleteLayerUpload.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/CompleteLayerUpload.hs
@@ -0,0 +1,201 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.CompleteLayerUpload
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Inform Amazon ECR that the image layer upload for a specified registry,
+-- repository name, and upload ID, has completed. You can optionally
+-- provide a 'sha256' digest of the image layer for data validation
+-- purposes.
+--
+-- This operation is used by the Amazon ECR proxy, and it is not intended
+-- for general use by customers. Use the 'docker' CLI to pull, tag, and
+-- push images.
+module Network.AWS.ECR.CompleteLayerUpload
+    (
+    -- * Creating a Request
+      completeLayerUpload
+    , CompleteLayerUpload
+    -- * Request Lenses
+    , cluRegistryId
+    , cluRepositoryName
+    , cluUploadId
+    , cluLayerDigests
+
+    -- * Destructuring the Response
+    , completeLayerUploadResponse
+    , CompleteLayerUploadResponse
+    -- * Response Lenses
+    , clursRegistryId
+    , clursLayerDigest
+    , clursRepositoryName
+    , clursUploadId
+    , clursResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'completeLayerUpload' smart constructor.
+data CompleteLayerUpload = CompleteLayerUpload'
+    { _cluRegistryId     :: !(Maybe Text)
+    , _cluRepositoryName :: !Text
+    , _cluUploadId       :: !Text
+    , _cluLayerDigests   :: !(List1 Text)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'CompleteLayerUpload' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'cluRegistryId'
+--
+-- * 'cluRepositoryName'
+--
+-- * 'cluUploadId'
+--
+-- * 'cluLayerDigests'
+completeLayerUpload
+    :: Text -- ^ 'cluRepositoryName'
+    -> Text -- ^ 'cluUploadId'
+    -> NonEmpty Text -- ^ 'cluLayerDigests'
+    -> CompleteLayerUpload
+completeLayerUpload pRepositoryName_ pUploadId_ pLayerDigests_ =
+    CompleteLayerUpload'
+    { _cluRegistryId = Nothing
+    , _cluRepositoryName = pRepositoryName_
+    , _cluUploadId = pUploadId_
+    , _cluLayerDigests = _List1 # pLayerDigests_
+    }
+
+-- | The AWS account ID associated with the registry to which to upload
+-- layers. If you do not specify a registry, the default registry is
+-- assumed.
+cluRegistryId :: Lens' CompleteLayerUpload (Maybe Text)
+cluRegistryId = lens _cluRegistryId (\ s a -> s{_cluRegistryId = a});
+
+-- | The name of the repository to associate with the image layer.
+cluRepositoryName :: Lens' CompleteLayerUpload Text
+cluRepositoryName = lens _cluRepositoryName (\ s a -> s{_cluRepositoryName = a});
+
+-- | The upload ID from a previous < InitiateLayerUpload> operation to
+-- associate with the image layer.
+cluUploadId :: Lens' CompleteLayerUpload Text
+cluUploadId = lens _cluUploadId (\ s a -> s{_cluUploadId = a});
+
+-- | The 'sha256' digest of the image layer.
+cluLayerDigests :: Lens' CompleteLayerUpload (NonEmpty Text)
+cluLayerDigests = lens _cluLayerDigests (\ s a -> s{_cluLayerDigests = a}) . _List1;
+
+instance AWSRequest CompleteLayerUpload where
+        type Rs CompleteLayerUpload =
+             CompleteLayerUploadResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 CompleteLayerUploadResponse' <$>
+                   (x .?> "registryId") <*> (x .?> "layerDigest") <*>
+                     (x .?> "repositoryName")
+                     <*> (x .?> "uploadId")
+                     <*> (pure (fromEnum s)))
+
+instance Hashable CompleteLayerUpload
+
+instance ToHeaders CompleteLayerUpload where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.CompleteLayerUpload"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON CompleteLayerUpload where
+        toJSON CompleteLayerUpload'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _cluRegistryId,
+                  Just ("repositoryName" .= _cluRepositoryName),
+                  Just ("uploadId" .= _cluUploadId),
+                  Just ("layerDigests" .= _cluLayerDigests)])
+
+instance ToPath CompleteLayerUpload where
+        toPath = const "/"
+
+instance ToQuery CompleteLayerUpload where
+        toQuery = const mempty
+
+-- | /See:/ 'completeLayerUploadResponse' smart constructor.
+data CompleteLayerUploadResponse = CompleteLayerUploadResponse'
+    { _clursRegistryId     :: !(Maybe Text)
+    , _clursLayerDigest    :: !(Maybe Text)
+    , _clursRepositoryName :: !(Maybe Text)
+    , _clursUploadId       :: !(Maybe Text)
+    , _clursResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'CompleteLayerUploadResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'clursRegistryId'
+--
+-- * 'clursLayerDigest'
+--
+-- * 'clursRepositoryName'
+--
+-- * 'clursUploadId'
+--
+-- * 'clursResponseStatus'
+completeLayerUploadResponse
+    :: Int -- ^ 'clursResponseStatus'
+    -> CompleteLayerUploadResponse
+completeLayerUploadResponse pResponseStatus_ =
+    CompleteLayerUploadResponse'
+    { _clursRegistryId = Nothing
+    , _clursLayerDigest = Nothing
+    , _clursRepositoryName = Nothing
+    , _clursUploadId = Nothing
+    , _clursResponseStatus = pResponseStatus_
+    }
+
+-- | The registry ID associated with the request.
+clursRegistryId :: Lens' CompleteLayerUploadResponse (Maybe Text)
+clursRegistryId = lens _clursRegistryId (\ s a -> s{_clursRegistryId = a});
+
+-- | The 'sha256' digest of the image layer.
+clursLayerDigest :: Lens' CompleteLayerUploadResponse (Maybe Text)
+clursLayerDigest = lens _clursLayerDigest (\ s a -> s{_clursLayerDigest = a});
+
+-- | The repository name associated with the request.
+clursRepositoryName :: Lens' CompleteLayerUploadResponse (Maybe Text)
+clursRepositoryName = lens _clursRepositoryName (\ s a -> s{_clursRepositoryName = a});
+
+-- | The upload ID associated with the layer.
+clursUploadId :: Lens' CompleteLayerUploadResponse (Maybe Text)
+clursUploadId = lens _clursUploadId (\ s a -> s{_clursUploadId = a});
+
+-- | The response status code.
+clursResponseStatus :: Lens' CompleteLayerUploadResponse Int
+clursResponseStatus = lens _clursResponseStatus (\ s a -> s{_clursResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/CreateRepository.hs b/gen/Network/AWS/ECR/CreateRepository.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/CreateRepository.hs
@@ -0,0 +1,131 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.CreateRepository
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Creates an image repository.
+module Network.AWS.ECR.CreateRepository
+    (
+    -- * Creating a Request
+      createRepository
+    , CreateRepository
+    -- * Request Lenses
+    , crRepositoryName
+
+    -- * Destructuring the Response
+    , createRepositoryResponse
+    , CreateRepositoryResponse
+    -- * Response Lenses
+    , crrsRepository
+    , crrsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'createRepository' smart constructor.
+newtype CreateRepository = CreateRepository'
+    { _crRepositoryName :: Text
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'CreateRepository' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'crRepositoryName'
+createRepository
+    :: Text -- ^ 'crRepositoryName'
+    -> CreateRepository
+createRepository pRepositoryName_ =
+    CreateRepository'
+    { _crRepositoryName = pRepositoryName_
+    }
+
+-- | The name to use for the repository. The repository name may be specified
+-- on its own (such as 'nginx-web-app') or it can be prepended with a
+-- namespace to group the repository into a category (such as
+-- 'project-a\/nginx-web-app').
+crRepositoryName :: Lens' CreateRepository Text
+crRepositoryName = lens _crRepositoryName (\ s a -> s{_crRepositoryName = a});
+
+instance AWSRequest CreateRepository where
+        type Rs CreateRepository = CreateRepositoryResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 CreateRepositoryResponse' <$>
+                   (x .?> "repository") <*> (pure (fromEnum s)))
+
+instance Hashable CreateRepository
+
+instance ToHeaders CreateRepository where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.CreateRepository"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON CreateRepository where
+        toJSON CreateRepository'{..}
+          = object
+              (catMaybes
+                 [Just ("repositoryName" .= _crRepositoryName)])
+
+instance ToPath CreateRepository where
+        toPath = const "/"
+
+instance ToQuery CreateRepository where
+        toQuery = const mempty
+
+-- | /See:/ 'createRepositoryResponse' smart constructor.
+data CreateRepositoryResponse = CreateRepositoryResponse'
+    { _crrsRepository     :: !(Maybe Repository)
+    , _crrsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'CreateRepositoryResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'crrsRepository'
+--
+-- * 'crrsResponseStatus'
+createRepositoryResponse
+    :: Int -- ^ 'crrsResponseStatus'
+    -> CreateRepositoryResponse
+createRepositoryResponse pResponseStatus_ =
+    CreateRepositoryResponse'
+    { _crrsRepository = Nothing
+    , _crrsResponseStatus = pResponseStatus_
+    }
+
+-- | Undocumented member.
+crrsRepository :: Lens' CreateRepositoryResponse (Maybe Repository)
+crrsRepository = lens _crrsRepository (\ s a -> s{_crrsRepository = a});
+
+-- | The response status code.
+crrsResponseStatus :: Lens' CreateRepositoryResponse Int
+crrsResponseStatus = lens _crrsResponseStatus (\ s a -> s{_crrsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/DeleteRepository.hs b/gen/Network/AWS/ECR/DeleteRepository.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/DeleteRepository.hs
@@ -0,0 +1,151 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.DeleteRepository
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Deletes an existing image repository. If a repository contains images,
+-- you must use the 'force' option to delete it.
+module Network.AWS.ECR.DeleteRepository
+    (
+    -- * Creating a Request
+      deleteRepository
+    , DeleteRepository
+    -- * Request Lenses
+    , dForce
+    , dRegistryId
+    , dRepositoryName
+
+    -- * Destructuring the Response
+    , deleteRepositoryResponse
+    , DeleteRepositoryResponse
+    -- * Response Lenses
+    , drsRepository
+    , drsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'deleteRepository' smart constructor.
+data DeleteRepository = DeleteRepository'
+    { _dForce          :: !(Maybe Bool)
+    , _dRegistryId     :: !(Maybe Text)
+    , _dRepositoryName :: !Text
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'DeleteRepository' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'dForce'
+--
+-- * 'dRegistryId'
+--
+-- * 'dRepositoryName'
+deleteRepository
+    :: Text -- ^ 'dRepositoryName'
+    -> DeleteRepository
+deleteRepository pRepositoryName_ =
+    DeleteRepository'
+    { _dForce = Nothing
+    , _dRegistryId = Nothing
+    , _dRepositoryName = pRepositoryName_
+    }
+
+-- | Force the deletion of the repository if it contains images.
+dForce :: Lens' DeleteRepository (Maybe Bool)
+dForce = lens _dForce (\ s a -> s{_dForce = a});
+
+-- | The AWS account ID associated with the registry that contains the
+-- repository to delete. If you do not specify a registry, the default
+-- registry is assumed.
+dRegistryId :: Lens' DeleteRepository (Maybe Text)
+dRegistryId = lens _dRegistryId (\ s a -> s{_dRegistryId = a});
+
+-- | The name of the repository to delete.
+dRepositoryName :: Lens' DeleteRepository Text
+dRepositoryName = lens _dRepositoryName (\ s a -> s{_dRepositoryName = a});
+
+instance AWSRequest DeleteRepository where
+        type Rs DeleteRepository = DeleteRepositoryResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 DeleteRepositoryResponse' <$>
+                   (x .?> "repository") <*> (pure (fromEnum s)))
+
+instance Hashable DeleteRepository
+
+instance ToHeaders DeleteRepository where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.DeleteRepository"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON DeleteRepository where
+        toJSON DeleteRepository'{..}
+          = object
+              (catMaybes
+                 [("force" .=) <$> _dForce,
+                  ("registryId" .=) <$> _dRegistryId,
+                  Just ("repositoryName" .= _dRepositoryName)])
+
+instance ToPath DeleteRepository where
+        toPath = const "/"
+
+instance ToQuery DeleteRepository where
+        toQuery = const mempty
+
+-- | /See:/ 'deleteRepositoryResponse' smart constructor.
+data DeleteRepositoryResponse = DeleteRepositoryResponse'
+    { _drsRepository     :: !(Maybe Repository)
+    , _drsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'DeleteRepositoryResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'drsRepository'
+--
+-- * 'drsResponseStatus'
+deleteRepositoryResponse
+    :: Int -- ^ 'drsResponseStatus'
+    -> DeleteRepositoryResponse
+deleteRepositoryResponse pResponseStatus_ =
+    DeleteRepositoryResponse'
+    { _drsRepository = Nothing
+    , _drsResponseStatus = pResponseStatus_
+    }
+
+-- | Undocumented member.
+drsRepository :: Lens' DeleteRepositoryResponse (Maybe Repository)
+drsRepository = lens _drsRepository (\ s a -> s{_drsRepository = a});
+
+-- | The response status code.
+drsResponseStatus :: Lens' DeleteRepositoryResponse Int
+drsResponseStatus = lens _drsResponseStatus (\ s a -> s{_drsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/DeleteRepositoryPolicy.hs b/gen/Network/AWS/ECR/DeleteRepositoryPolicy.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/DeleteRepositoryPolicy.hs
@@ -0,0 +1,162 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.DeleteRepositoryPolicy
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Deletes the repository policy from a specified repository.
+module Network.AWS.ECR.DeleteRepositoryPolicy
+    (
+    -- * Creating a Request
+      deleteRepositoryPolicy
+    , DeleteRepositoryPolicy
+    -- * Request Lenses
+    , drpRegistryId
+    , drpRepositoryName
+
+    -- * Destructuring the Response
+    , deleteRepositoryPolicyResponse
+    , DeleteRepositoryPolicyResponse
+    -- * Response Lenses
+    , drprsRegistryId
+    , drprsRepositoryName
+    , drprsPolicyText
+    , drprsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'deleteRepositoryPolicy' smart constructor.
+data DeleteRepositoryPolicy = DeleteRepositoryPolicy'
+    { _drpRegistryId     :: !(Maybe Text)
+    , _drpRepositoryName :: !Text
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'DeleteRepositoryPolicy' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'drpRegistryId'
+--
+-- * 'drpRepositoryName'
+deleteRepositoryPolicy
+    :: Text -- ^ 'drpRepositoryName'
+    -> DeleteRepositoryPolicy
+deleteRepositoryPolicy pRepositoryName_ =
+    DeleteRepositoryPolicy'
+    { _drpRegistryId = Nothing
+    , _drpRepositoryName = pRepositoryName_
+    }
+
+-- | The AWS account ID associated with the registry that contains the
+-- repository policy to delete. If you do not specify a registry, the
+-- default registry is assumed.
+drpRegistryId :: Lens' DeleteRepositoryPolicy (Maybe Text)
+drpRegistryId = lens _drpRegistryId (\ s a -> s{_drpRegistryId = a});
+
+-- | The name of the repository that is associated with the repository policy
+-- to delete.
+drpRepositoryName :: Lens' DeleteRepositoryPolicy Text
+drpRepositoryName = lens _drpRepositoryName (\ s a -> s{_drpRepositoryName = a});
+
+instance AWSRequest DeleteRepositoryPolicy where
+        type Rs DeleteRepositoryPolicy =
+             DeleteRepositoryPolicyResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 DeleteRepositoryPolicyResponse' <$>
+                   (x .?> "registryId") <*> (x .?> "repositoryName") <*>
+                     (x .?> "policyText")
+                     <*> (pure (fromEnum s)))
+
+instance Hashable DeleteRepositoryPolicy
+
+instance ToHeaders DeleteRepositoryPolicy where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.DeleteRepositoryPolicy"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON DeleteRepositoryPolicy where
+        toJSON DeleteRepositoryPolicy'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _drpRegistryId,
+                  Just ("repositoryName" .= _drpRepositoryName)])
+
+instance ToPath DeleteRepositoryPolicy where
+        toPath = const "/"
+
+instance ToQuery DeleteRepositoryPolicy where
+        toQuery = const mempty
+
+-- | /See:/ 'deleteRepositoryPolicyResponse' smart constructor.
+data DeleteRepositoryPolicyResponse = DeleteRepositoryPolicyResponse'
+    { _drprsRegistryId     :: !(Maybe Text)
+    , _drprsRepositoryName :: !(Maybe Text)
+    , _drprsPolicyText     :: !(Maybe Text)
+    , _drprsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'DeleteRepositoryPolicyResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'drprsRegistryId'
+--
+-- * 'drprsRepositoryName'
+--
+-- * 'drprsPolicyText'
+--
+-- * 'drprsResponseStatus'
+deleteRepositoryPolicyResponse
+    :: Int -- ^ 'drprsResponseStatus'
+    -> DeleteRepositoryPolicyResponse
+deleteRepositoryPolicyResponse pResponseStatus_ =
+    DeleteRepositoryPolicyResponse'
+    { _drprsRegistryId = Nothing
+    , _drprsRepositoryName = Nothing
+    , _drprsPolicyText = Nothing
+    , _drprsResponseStatus = pResponseStatus_
+    }
+
+-- | The registry ID associated with the request.
+drprsRegistryId :: Lens' DeleteRepositoryPolicyResponse (Maybe Text)
+drprsRegistryId = lens _drprsRegistryId (\ s a -> s{_drprsRegistryId = a});
+
+-- | The repository name associated with the request.
+drprsRepositoryName :: Lens' DeleteRepositoryPolicyResponse (Maybe Text)
+drprsRepositoryName = lens _drprsRepositoryName (\ s a -> s{_drprsRepositoryName = a});
+
+-- | The JSON repository policy that was deleted from the repository.
+drprsPolicyText :: Lens' DeleteRepositoryPolicyResponse (Maybe Text)
+drprsPolicyText = lens _drprsPolicyText (\ s a -> s{_drprsPolicyText = a});
+
+-- | The response status code.
+drprsResponseStatus :: Lens' DeleteRepositoryPolicyResponse Int
+drprsResponseStatus = lens _drprsResponseStatus (\ s a -> s{_drprsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/DescribeRepositories.hs b/gen/Network/AWS/ECR/DescribeRepositories.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/DescribeRepositories.hs
@@ -0,0 +1,187 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.DescribeRepositories
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Describes image repositories in a registry.
+module Network.AWS.ECR.DescribeRepositories
+    (
+    -- * Creating a Request
+      describeRepositories
+    , DescribeRepositories
+    -- * Request Lenses
+    , drRegistryId
+    , drRepositoryNames
+    , drNextToken
+    , drMaxResults
+
+    -- * Destructuring the Response
+    , describeRepositoriesResponse
+    , DescribeRepositoriesResponse
+    -- * Response Lenses
+    , drrsRepositories
+    , drrsNextToken
+    , drrsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'describeRepositories' smart constructor.
+data DescribeRepositories = DescribeRepositories'
+    { _drRegistryId      :: !(Maybe Text)
+    , _drRepositoryNames :: !(Maybe (List1 Text))
+    , _drNextToken       :: !(Maybe Text)
+    , _drMaxResults      :: !(Maybe Nat)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'DescribeRepositories' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'drRegistryId'
+--
+-- * 'drRepositoryNames'
+--
+-- * 'drNextToken'
+--
+-- * 'drMaxResults'
+describeRepositories
+    :: DescribeRepositories
+describeRepositories =
+    DescribeRepositories'
+    { _drRegistryId = Nothing
+    , _drRepositoryNames = Nothing
+    , _drNextToken = Nothing
+    , _drMaxResults = Nothing
+    }
+
+-- | The AWS account ID associated with the registry that contains the
+-- repositories to be described. If you do not specify a registry, the
+-- default registry is assumed.
+drRegistryId :: Lens' DescribeRepositories (Maybe Text)
+drRegistryId = lens _drRegistryId (\ s a -> s{_drRegistryId = a});
+
+-- | A list of repositories to describe. If this parameter is omitted, then
+-- all repositories in a registry are described.
+drRepositoryNames :: Lens' DescribeRepositories (Maybe (NonEmpty Text))
+drRepositoryNames = lens _drRepositoryNames (\ s a -> s{_drRepositoryNames = a}) . mapping _List1;
+
+-- | The 'nextToken' value returned from a previous paginated
+-- 'DescribeRepositories' request where 'maxResults' was used and the
+-- results exceeded the value of that parameter. Pagination continues from
+-- the end of the previous results that returned the 'nextToken' value.
+-- This value is 'null' when there are no more results to return.
+drNextToken :: Lens' DescribeRepositories (Maybe Text)
+drNextToken = lens _drNextToken (\ s a -> s{_drNextToken = a});
+
+-- | The maximum number of repository results returned by
+-- 'DescribeRepositories' in paginated output. When this parameter is used,
+-- 'DescribeRepositories' only returns 'maxResults' results in a single
+-- page along with a 'nextToken' response element. The remaining results of
+-- the initial request can be seen by sending another
+-- 'DescribeRepositories' request with the returned 'nextToken' value. This
+-- value can be between 1 and 100. If this parameter is not used, then
+-- 'DescribeRepositories' returns up to 100 results and a 'nextToken'
+-- value, if applicable.
+drMaxResults :: Lens' DescribeRepositories (Maybe Natural)
+drMaxResults = lens _drMaxResults (\ s a -> s{_drMaxResults = a}) . mapping _Nat;
+
+instance AWSRequest DescribeRepositories where
+        type Rs DescribeRepositories =
+             DescribeRepositoriesResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 DescribeRepositoriesResponse' <$>
+                   (x .?> "repositories" .!@ mempty) <*>
+                     (x .?> "nextToken")
+                     <*> (pure (fromEnum s)))
+
+instance Hashable DescribeRepositories
+
+instance ToHeaders DescribeRepositories where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.DescribeRepositories"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON DescribeRepositories where
+        toJSON DescribeRepositories'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _drRegistryId,
+                  ("repositoryNames" .=) <$> _drRepositoryNames,
+                  ("nextToken" .=) <$> _drNextToken,
+                  ("maxResults" .=) <$> _drMaxResults])
+
+instance ToPath DescribeRepositories where
+        toPath = const "/"
+
+instance ToQuery DescribeRepositories where
+        toQuery = const mempty
+
+-- | /See:/ 'describeRepositoriesResponse' smart constructor.
+data DescribeRepositoriesResponse = DescribeRepositoriesResponse'
+    { _drrsRepositories   :: !(Maybe [Repository])
+    , _drrsNextToken      :: !(Maybe Text)
+    , _drrsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'DescribeRepositoriesResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'drrsRepositories'
+--
+-- * 'drrsNextToken'
+--
+-- * 'drrsResponseStatus'
+describeRepositoriesResponse
+    :: Int -- ^ 'drrsResponseStatus'
+    -> DescribeRepositoriesResponse
+describeRepositoriesResponse pResponseStatus_ =
+    DescribeRepositoriesResponse'
+    { _drrsRepositories = Nothing
+    , _drrsNextToken = Nothing
+    , _drrsResponseStatus = pResponseStatus_
+    }
+
+-- | A list of repository objects corresponding to valid repositories.
+drrsRepositories :: Lens' DescribeRepositoriesResponse [Repository]
+drrsRepositories = lens _drrsRepositories (\ s a -> s{_drrsRepositories = a}) . _Default . _Coerce;
+
+-- | The 'nextToken' value to include in a future 'DescribeRepositories'
+-- request. When the results of a 'DescribeRepositories' request exceed
+-- 'maxResults', this value can be used to retrieve the next page of
+-- results. This value is 'null' when there are no more results to return.
+drrsNextToken :: Lens' DescribeRepositoriesResponse (Maybe Text)
+drrsNextToken = lens _drrsNextToken (\ s a -> s{_drrsNextToken = a});
+
+-- | The response status code.
+drrsResponseStatus :: Lens' DescribeRepositoriesResponse Int
+drrsResponseStatus = lens _drrsResponseStatus (\ s a -> s{_drrsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/GetAuthorizationToken.hs b/gen/Network/AWS/ECR/GetAuthorizationToken.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/GetAuthorizationToken.hs
@@ -0,0 +1,139 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.GetAuthorizationToken
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Retrieves a token that is valid for a specified registry for 12 hours.
+-- This command allows you to use the 'docker' CLI to push and pull images
+-- with Amazon ECR. If you do not specify a registry, the default registry
+-- is assumed.
+--
+-- The 'authorizationToken' returned for each registry specified is a
+-- base64 encoded string that can be decoded and used in a 'docker login'
+-- command to authenticate to a registry. The AWS CLI offers an
+-- 'aws ecr get-login' command that simplifies the login process.
+module Network.AWS.ECR.GetAuthorizationToken
+    (
+    -- * Creating a Request
+      getAuthorizationToken
+    , GetAuthorizationToken
+    -- * Request Lenses
+    , gatRegistryIds
+
+    -- * Destructuring the Response
+    , getAuthorizationTokenResponse
+    , GetAuthorizationTokenResponse
+    -- * Response Lenses
+    , gatrsAuthorizationData
+    , gatrsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'getAuthorizationToken' smart constructor.
+newtype GetAuthorizationToken = GetAuthorizationToken'
+    { _gatRegistryIds :: Maybe (List1 Text)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'GetAuthorizationToken' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'gatRegistryIds'
+getAuthorizationToken
+    :: GetAuthorizationToken
+getAuthorizationToken =
+    GetAuthorizationToken'
+    { _gatRegistryIds = Nothing
+    }
+
+-- | A list of AWS account IDs that are associated with the registries for
+-- which to get authorization tokens. If you do not specify a registry, the
+-- default registry is assumed.
+gatRegistryIds :: Lens' GetAuthorizationToken (Maybe (NonEmpty Text))
+gatRegistryIds = lens _gatRegistryIds (\ s a -> s{_gatRegistryIds = a}) . mapping _List1;
+
+instance AWSRequest GetAuthorizationToken where
+        type Rs GetAuthorizationToken =
+             GetAuthorizationTokenResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 GetAuthorizationTokenResponse' <$>
+                   (x .?> "authorizationData" .!@ mempty) <*>
+                     (pure (fromEnum s)))
+
+instance Hashable GetAuthorizationToken
+
+instance ToHeaders GetAuthorizationToken where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.GetAuthorizationToken"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON GetAuthorizationToken where
+        toJSON GetAuthorizationToken'{..}
+          = object
+              (catMaybes [("registryIds" .=) <$> _gatRegistryIds])
+
+instance ToPath GetAuthorizationToken where
+        toPath = const "/"
+
+instance ToQuery GetAuthorizationToken where
+        toQuery = const mempty
+
+-- | /See:/ 'getAuthorizationTokenResponse' smart constructor.
+data GetAuthorizationTokenResponse = GetAuthorizationTokenResponse'
+    { _gatrsAuthorizationData :: !(Maybe [AuthorizationData])
+    , _gatrsResponseStatus    :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'GetAuthorizationTokenResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'gatrsAuthorizationData'
+--
+-- * 'gatrsResponseStatus'
+getAuthorizationTokenResponse
+    :: Int -- ^ 'gatrsResponseStatus'
+    -> GetAuthorizationTokenResponse
+getAuthorizationTokenResponse pResponseStatus_ =
+    GetAuthorizationTokenResponse'
+    { _gatrsAuthorizationData = Nothing
+    , _gatrsResponseStatus = pResponseStatus_
+    }
+
+-- | A list of authorization token data objects that correspond to the
+-- 'registryIds' values in the request.
+gatrsAuthorizationData :: Lens' GetAuthorizationTokenResponse [AuthorizationData]
+gatrsAuthorizationData = lens _gatrsAuthorizationData (\ s a -> s{_gatrsAuthorizationData = a}) . _Default . _Coerce;
+
+-- | The response status code.
+gatrsResponseStatus :: Lens' GetAuthorizationTokenResponse Int
+gatrsResponseStatus = lens _gatrsResponseStatus (\ s a -> s{_gatrsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/GetDownloadURLForLayer.hs b/gen/Network/AWS/ECR/GetDownloadURLForLayer.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/GetDownloadURLForLayer.hs
@@ -0,0 +1,169 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.GetDownloadURLForLayer
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Retrieves the pre-signed Amazon S3 download URL corresponding to an
+-- image layer. You can only get URLs for image layers that are referenced
+-- in an image.
+--
+-- This operation is used by the Amazon ECR proxy, and it is not intended
+-- for general use by customers. Use the 'docker' CLI to pull, tag, and
+-- push images.
+module Network.AWS.ECR.GetDownloadURLForLayer
+    (
+    -- * Creating a Request
+      getDownloadURLForLayer
+    , GetDownloadURLForLayer
+    -- * Request Lenses
+    , gduflRegistryId
+    , gduflRepositoryName
+    , gduflLayerDigest
+
+    -- * Destructuring the Response
+    , getDownloadURLForLayerResponse
+    , GetDownloadURLForLayerResponse
+    -- * Response Lenses
+    , gduflrsLayerDigest
+    , gduflrsDownloadURL
+    , gduflrsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'getDownloadURLForLayer' smart constructor.
+data GetDownloadURLForLayer = GetDownloadURLForLayer'
+    { _gduflRegistryId     :: !(Maybe Text)
+    , _gduflRepositoryName :: !Text
+    , _gduflLayerDigest    :: !Text
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'GetDownloadURLForLayer' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'gduflRegistryId'
+--
+-- * 'gduflRepositoryName'
+--
+-- * 'gduflLayerDigest'
+getDownloadURLForLayer
+    :: Text -- ^ 'gduflRepositoryName'
+    -> Text -- ^ 'gduflLayerDigest'
+    -> GetDownloadURLForLayer
+getDownloadURLForLayer pRepositoryName_ pLayerDigest_ =
+    GetDownloadURLForLayer'
+    { _gduflRegistryId = Nothing
+    , _gduflRepositoryName = pRepositoryName_
+    , _gduflLayerDigest = pLayerDigest_
+    }
+
+-- | The AWS account ID associated with the registry that contains the image
+-- layer to download. If you do not specify a registry, the default
+-- registry is assumed.
+gduflRegistryId :: Lens' GetDownloadURLForLayer (Maybe Text)
+gduflRegistryId = lens _gduflRegistryId (\ s a -> s{_gduflRegistryId = a});
+
+-- | The name of the repository that is associated with the image layer to
+-- download.
+gduflRepositoryName :: Lens' GetDownloadURLForLayer Text
+gduflRepositoryName = lens _gduflRepositoryName (\ s a -> s{_gduflRepositoryName = a});
+
+-- | The digest of the image layer to download.
+gduflLayerDigest :: Lens' GetDownloadURLForLayer Text
+gduflLayerDigest = lens _gduflLayerDigest (\ s a -> s{_gduflLayerDigest = a});
+
+instance AWSRequest GetDownloadURLForLayer where
+        type Rs GetDownloadURLForLayer =
+             GetDownloadURLForLayerResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 GetDownloadURLForLayerResponse' <$>
+                   (x .?> "layerDigest") <*> (x .?> "downloadUrl") <*>
+                     (pure (fromEnum s)))
+
+instance Hashable GetDownloadURLForLayer
+
+instance ToHeaders GetDownloadURLForLayer where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.GetDownloadUrlForLayer"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON GetDownloadURLForLayer where
+        toJSON GetDownloadURLForLayer'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _gduflRegistryId,
+                  Just ("repositoryName" .= _gduflRepositoryName),
+                  Just ("layerDigest" .= _gduflLayerDigest)])
+
+instance ToPath GetDownloadURLForLayer where
+        toPath = const "/"
+
+instance ToQuery GetDownloadURLForLayer where
+        toQuery = const mempty
+
+-- | /See:/ 'getDownloadURLForLayerResponse' smart constructor.
+data GetDownloadURLForLayerResponse = GetDownloadURLForLayerResponse'
+    { _gduflrsLayerDigest    :: !(Maybe Text)
+    , _gduflrsDownloadURL    :: !(Maybe Text)
+    , _gduflrsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'GetDownloadURLForLayerResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'gduflrsLayerDigest'
+--
+-- * 'gduflrsDownloadURL'
+--
+-- * 'gduflrsResponseStatus'
+getDownloadURLForLayerResponse
+    :: Int -- ^ 'gduflrsResponseStatus'
+    -> GetDownloadURLForLayerResponse
+getDownloadURLForLayerResponse pResponseStatus_ =
+    GetDownloadURLForLayerResponse'
+    { _gduflrsLayerDigest = Nothing
+    , _gduflrsDownloadURL = Nothing
+    , _gduflrsResponseStatus = pResponseStatus_
+    }
+
+-- | The digest of the image layer to download.
+gduflrsLayerDigest :: Lens' GetDownloadURLForLayerResponse (Maybe Text)
+gduflrsLayerDigest = lens _gduflrsLayerDigest (\ s a -> s{_gduflrsLayerDigest = a});
+
+-- | The pre-signed Amazon S3 download URL for the requested layer.
+gduflrsDownloadURL :: Lens' GetDownloadURLForLayerResponse (Maybe Text)
+gduflrsDownloadURL = lens _gduflrsDownloadURL (\ s a -> s{_gduflrsDownloadURL = a});
+
+-- | The response status code.
+gduflrsResponseStatus :: Lens' GetDownloadURLForLayerResponse Int
+gduflrsResponseStatus = lens _gduflrsResponseStatus (\ s a -> s{_gduflrsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/GetRepositoryPolicy.hs b/gen/Network/AWS/ECR/GetRepositoryPolicy.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/GetRepositoryPolicy.hs
@@ -0,0 +1,161 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.GetRepositoryPolicy
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Retrieves the repository policy for a specified repository.
+module Network.AWS.ECR.GetRepositoryPolicy
+    (
+    -- * Creating a Request
+      getRepositoryPolicy
+    , GetRepositoryPolicy
+    -- * Request Lenses
+    , grpRegistryId
+    , grpRepositoryName
+
+    -- * Destructuring the Response
+    , getRepositoryPolicyResponse
+    , GetRepositoryPolicyResponse
+    -- * Response Lenses
+    , grprsRegistryId
+    , grprsRepositoryName
+    , grprsPolicyText
+    , grprsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'getRepositoryPolicy' smart constructor.
+data GetRepositoryPolicy = GetRepositoryPolicy'
+    { _grpRegistryId     :: !(Maybe Text)
+    , _grpRepositoryName :: !Text
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'GetRepositoryPolicy' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'grpRegistryId'
+--
+-- * 'grpRepositoryName'
+getRepositoryPolicy
+    :: Text -- ^ 'grpRepositoryName'
+    -> GetRepositoryPolicy
+getRepositoryPolicy pRepositoryName_ =
+    GetRepositoryPolicy'
+    { _grpRegistryId = Nothing
+    , _grpRepositoryName = pRepositoryName_
+    }
+
+-- | The AWS account ID associated with the registry that contains the
+-- repository. If you do not specify a registry, the default registry is
+-- assumed.
+grpRegistryId :: Lens' GetRepositoryPolicy (Maybe Text)
+grpRegistryId = lens _grpRegistryId (\ s a -> s{_grpRegistryId = a});
+
+-- | The name of the repository whose policy you want to retrieve.
+grpRepositoryName :: Lens' GetRepositoryPolicy Text
+grpRepositoryName = lens _grpRepositoryName (\ s a -> s{_grpRepositoryName = a});
+
+instance AWSRequest GetRepositoryPolicy where
+        type Rs GetRepositoryPolicy =
+             GetRepositoryPolicyResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 GetRepositoryPolicyResponse' <$>
+                   (x .?> "registryId") <*> (x .?> "repositoryName") <*>
+                     (x .?> "policyText")
+                     <*> (pure (fromEnum s)))
+
+instance Hashable GetRepositoryPolicy
+
+instance ToHeaders GetRepositoryPolicy where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.GetRepositoryPolicy"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON GetRepositoryPolicy where
+        toJSON GetRepositoryPolicy'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _grpRegistryId,
+                  Just ("repositoryName" .= _grpRepositoryName)])
+
+instance ToPath GetRepositoryPolicy where
+        toPath = const "/"
+
+instance ToQuery GetRepositoryPolicy where
+        toQuery = const mempty
+
+-- | /See:/ 'getRepositoryPolicyResponse' smart constructor.
+data GetRepositoryPolicyResponse = GetRepositoryPolicyResponse'
+    { _grprsRegistryId     :: !(Maybe Text)
+    , _grprsRepositoryName :: !(Maybe Text)
+    , _grprsPolicyText     :: !(Maybe Text)
+    , _grprsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'GetRepositoryPolicyResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'grprsRegistryId'
+--
+-- * 'grprsRepositoryName'
+--
+-- * 'grprsPolicyText'
+--
+-- * 'grprsResponseStatus'
+getRepositoryPolicyResponse
+    :: Int -- ^ 'grprsResponseStatus'
+    -> GetRepositoryPolicyResponse
+getRepositoryPolicyResponse pResponseStatus_ =
+    GetRepositoryPolicyResponse'
+    { _grprsRegistryId = Nothing
+    , _grprsRepositoryName = Nothing
+    , _grprsPolicyText = Nothing
+    , _grprsResponseStatus = pResponseStatus_
+    }
+
+-- | The registry ID associated with the request.
+grprsRegistryId :: Lens' GetRepositoryPolicyResponse (Maybe Text)
+grprsRegistryId = lens _grprsRegistryId (\ s a -> s{_grprsRegistryId = a});
+
+-- | The repository name associated with the request.
+grprsRepositoryName :: Lens' GetRepositoryPolicyResponse (Maybe Text)
+grprsRepositoryName = lens _grprsRepositoryName (\ s a -> s{_grprsRepositoryName = a});
+
+-- | The JSON repository policy text associated with the repository.
+grprsPolicyText :: Lens' GetRepositoryPolicyResponse (Maybe Text)
+grprsPolicyText = lens _grprsPolicyText (\ s a -> s{_grprsPolicyText = a});
+
+-- | The response status code.
+grprsResponseStatus :: Lens' GetRepositoryPolicyResponse Int
+grprsResponseStatus = lens _grprsResponseStatus (\ s a -> s{_grprsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/InitiateLayerUpload.hs b/gen/Network/AWS/ECR/InitiateLayerUpload.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/InitiateLayerUpload.hs
@@ -0,0 +1,157 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.InitiateLayerUpload
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Notify Amazon ECR that you intend to upload an image layer.
+--
+-- This operation is used by the Amazon ECR proxy, and it is not intended
+-- for general use by customers. Use the 'docker' CLI to pull, tag, and
+-- push images.
+module Network.AWS.ECR.InitiateLayerUpload
+    (
+    -- * Creating a Request
+      initiateLayerUpload
+    , InitiateLayerUpload
+    -- * Request Lenses
+    , iluRegistryId
+    , iluRepositoryName
+
+    -- * Destructuring the Response
+    , initiateLayerUploadResponse
+    , InitiateLayerUploadResponse
+    -- * Response Lenses
+    , ilursPartSize
+    , ilursUploadId
+    , ilursResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'initiateLayerUpload' smart constructor.
+data InitiateLayerUpload = InitiateLayerUpload'
+    { _iluRegistryId     :: !(Maybe Text)
+    , _iluRepositoryName :: !Text
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'InitiateLayerUpload' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'iluRegistryId'
+--
+-- * 'iluRepositoryName'
+initiateLayerUpload
+    :: Text -- ^ 'iluRepositoryName'
+    -> InitiateLayerUpload
+initiateLayerUpload pRepositoryName_ =
+    InitiateLayerUpload'
+    { _iluRegistryId = Nothing
+    , _iluRepositoryName = pRepositoryName_
+    }
+
+-- | The AWS account ID associated with the registry that you intend to
+-- upload layers to. If you do not specify a registry, the default registry
+-- is assumed.
+iluRegistryId :: Lens' InitiateLayerUpload (Maybe Text)
+iluRegistryId = lens _iluRegistryId (\ s a -> s{_iluRegistryId = a});
+
+-- | The name of the repository that you intend to upload layers to.
+iluRepositoryName :: Lens' InitiateLayerUpload Text
+iluRepositoryName = lens _iluRepositoryName (\ s a -> s{_iluRepositoryName = a});
+
+instance AWSRequest InitiateLayerUpload where
+        type Rs InitiateLayerUpload =
+             InitiateLayerUploadResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 InitiateLayerUploadResponse' <$>
+                   (x .?> "partSize") <*> (x .?> "uploadId") <*>
+                     (pure (fromEnum s)))
+
+instance Hashable InitiateLayerUpload
+
+instance ToHeaders InitiateLayerUpload where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.InitiateLayerUpload"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON InitiateLayerUpload where
+        toJSON InitiateLayerUpload'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _iluRegistryId,
+                  Just ("repositoryName" .= _iluRepositoryName)])
+
+instance ToPath InitiateLayerUpload where
+        toPath = const "/"
+
+instance ToQuery InitiateLayerUpload where
+        toQuery = const mempty
+
+-- | /See:/ 'initiateLayerUploadResponse' smart constructor.
+data InitiateLayerUploadResponse = InitiateLayerUploadResponse'
+    { _ilursPartSize       :: !(Maybe Nat)
+    , _ilursUploadId       :: !(Maybe Text)
+    , _ilursResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'InitiateLayerUploadResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'ilursPartSize'
+--
+-- * 'ilursUploadId'
+--
+-- * 'ilursResponseStatus'
+initiateLayerUploadResponse
+    :: Int -- ^ 'ilursResponseStatus'
+    -> InitiateLayerUploadResponse
+initiateLayerUploadResponse pResponseStatus_ =
+    InitiateLayerUploadResponse'
+    { _ilursPartSize = Nothing
+    , _ilursUploadId = Nothing
+    , _ilursResponseStatus = pResponseStatus_
+    }
+
+-- | The size, in bytes, that Amazon ECR expects future layer part uploads to
+-- be.
+ilursPartSize :: Lens' InitiateLayerUploadResponse (Maybe Natural)
+ilursPartSize = lens _ilursPartSize (\ s a -> s{_ilursPartSize = a}) . mapping _Nat;
+
+-- | The upload ID for the layer upload. This parameter is passed to further
+-- < UploadLayerPart> and < CompleteLayerUpload> operations.
+ilursUploadId :: Lens' InitiateLayerUploadResponse (Maybe Text)
+ilursUploadId = lens _ilursUploadId (\ s a -> s{_ilursUploadId = a});
+
+-- | The response status code.
+ilursResponseStatus :: Lens' InitiateLayerUploadResponse Int
+ilursResponseStatus = lens _ilursResponseStatus (\ s a -> s{_ilursResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/ListImages.hs b/gen/Network/AWS/ECR/ListImages.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/ListImages.hs
@@ -0,0 +1,184 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.ListImages
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Lists all the image IDs for a given repository.
+module Network.AWS.ECR.ListImages
+    (
+    -- * Creating a Request
+      listImages
+    , ListImages
+    -- * Request Lenses
+    , liRegistryId
+    , liNextToken
+    , liMaxResults
+    , liRepositoryName
+
+    -- * Destructuring the Response
+    , listImagesResponse
+    , ListImagesResponse
+    -- * Response Lenses
+    , lirsImageIds
+    , lirsNextToken
+    , lirsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'listImages' smart constructor.
+data ListImages = ListImages'
+    { _liRegistryId     :: !(Maybe Text)
+    , _liNextToken      :: !(Maybe Text)
+    , _liMaxResults     :: !(Maybe Nat)
+    , _liRepositoryName :: !Text
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'ListImages' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'liRegistryId'
+--
+-- * 'liNextToken'
+--
+-- * 'liMaxResults'
+--
+-- * 'liRepositoryName'
+listImages
+    :: Text -- ^ 'liRepositoryName'
+    -> ListImages
+listImages pRepositoryName_ =
+    ListImages'
+    { _liRegistryId = Nothing
+    , _liNextToken = Nothing
+    , _liMaxResults = Nothing
+    , _liRepositoryName = pRepositoryName_
+    }
+
+-- | The AWS account ID associated with the registry that contains the
+-- repository to list images in. If you do not specify a registry, the
+-- default registry is assumed.
+liRegistryId :: Lens' ListImages (Maybe Text)
+liRegistryId = lens _liRegistryId (\ s a -> s{_liRegistryId = a});
+
+-- | The 'nextToken' value returned from a previous paginated 'ListImages'
+-- request where 'maxResults' was used and the results exceeded the value
+-- of that parameter. Pagination continues from the end of the previous
+-- results that returned the 'nextToken' value. This value is 'null' when
+-- there are no more results to return.
+liNextToken :: Lens' ListImages (Maybe Text)
+liNextToken = lens _liNextToken (\ s a -> s{_liNextToken = a});
+
+-- | The maximum number of image results returned by 'ListImages' in
+-- paginated output. When this parameter is used, 'ListImages' only returns
+-- 'maxResults' results in a single page along with a 'nextToken' response
+-- element. The remaining results of the initial request can be seen by
+-- sending another 'ListImages' request with the returned 'nextToken'
+-- value. This value can be between 1 and 100. If this parameter is not
+-- used, then 'ListImages' returns up to 100 results and a 'nextToken'
+-- value, if applicable.
+liMaxResults :: Lens' ListImages (Maybe Natural)
+liMaxResults = lens _liMaxResults (\ s a -> s{_liMaxResults = a}) . mapping _Nat;
+
+-- | The repository whose image IDs are to be listed.
+liRepositoryName :: Lens' ListImages Text
+liRepositoryName = lens _liRepositoryName (\ s a -> s{_liRepositoryName = a});
+
+instance AWSRequest ListImages where
+        type Rs ListImages = ListImagesResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 ListImagesResponse' <$>
+                   (x .?> "imageIds") <*> (x .?> "nextToken") <*>
+                     (pure (fromEnum s)))
+
+instance Hashable ListImages
+
+instance ToHeaders ListImages where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.ListImages" ::
+                       ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON ListImages where
+        toJSON ListImages'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _liRegistryId,
+                  ("nextToken" .=) <$> _liNextToken,
+                  ("maxResults" .=) <$> _liMaxResults,
+                  Just ("repositoryName" .= _liRepositoryName)])
+
+instance ToPath ListImages where
+        toPath = const "/"
+
+instance ToQuery ListImages where
+        toQuery = const mempty
+
+-- | /See:/ 'listImagesResponse' smart constructor.
+data ListImagesResponse = ListImagesResponse'
+    { _lirsImageIds       :: !(Maybe (List1 ImageIdentifier))
+    , _lirsNextToken      :: !(Maybe Text)
+    , _lirsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'ListImagesResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'lirsImageIds'
+--
+-- * 'lirsNextToken'
+--
+-- * 'lirsResponseStatus'
+listImagesResponse
+    :: Int -- ^ 'lirsResponseStatus'
+    -> ListImagesResponse
+listImagesResponse pResponseStatus_ =
+    ListImagesResponse'
+    { _lirsImageIds = Nothing
+    , _lirsNextToken = Nothing
+    , _lirsResponseStatus = pResponseStatus_
+    }
+
+-- | The list of image IDs for the requested repository.
+lirsImageIds :: Lens' ListImagesResponse (Maybe (NonEmpty ImageIdentifier))
+lirsImageIds = lens _lirsImageIds (\ s a -> s{_lirsImageIds = a}) . mapping _List1;
+
+-- | The 'nextToken' value to include in a future 'ListImages' request. When
+-- the results of a 'ListImages' request exceed 'maxResults', this value
+-- can be used to retrieve the next page of results. This value is 'null'
+-- when there are no more results to return.
+lirsNextToken :: Lens' ListImagesResponse (Maybe Text)
+lirsNextToken = lens _lirsNextToken (\ s a -> s{_lirsNextToken = a});
+
+-- | The response status code.
+lirsResponseStatus :: Lens' ListImagesResponse Int
+lirsResponseStatus = lens _lirsResponseStatus (\ s a -> s{_lirsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/PutImage.hs b/gen/Network/AWS/ECR/PutImage.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/PutImage.hs
@@ -0,0 +1,155 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.PutImage
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Creates or updates the image manifest associated with an image.
+--
+-- This operation is used by the Amazon ECR proxy, and it is not intended
+-- for general use by customers. Use the 'docker' CLI to pull, tag, and
+-- push images.
+module Network.AWS.ECR.PutImage
+    (
+    -- * Creating a Request
+      putImage
+    , PutImage
+    -- * Request Lenses
+    , piRegistryId
+    , piRepositoryName
+    , piImageManifest
+
+    -- * Destructuring the Response
+    , putImageResponse
+    , PutImageResponse
+    -- * Response Lenses
+    , pirsImage
+    , pirsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'putImage' smart constructor.
+data PutImage = PutImage'
+    { _piRegistryId     :: !(Maybe Text)
+    , _piRepositoryName :: !Text
+    , _piImageManifest  :: !Text
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'PutImage' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'piRegistryId'
+--
+-- * 'piRepositoryName'
+--
+-- * 'piImageManifest'
+putImage
+    :: Text -- ^ 'piRepositoryName'
+    -> Text -- ^ 'piImageManifest'
+    -> PutImage
+putImage pRepositoryName_ pImageManifest_ =
+    PutImage'
+    { _piRegistryId = Nothing
+    , _piRepositoryName = pRepositoryName_
+    , _piImageManifest = pImageManifest_
+    }
+
+-- | The AWS account ID associated with the registry that contains the
+-- repository in which to put the image. If you do not specify a registry,
+-- the default registry is assumed.
+piRegistryId :: Lens' PutImage (Maybe Text)
+piRegistryId = lens _piRegistryId (\ s a -> s{_piRegistryId = a});
+
+-- | The name of the repository in which to put the image.
+piRepositoryName :: Lens' PutImage Text
+piRepositoryName = lens _piRepositoryName (\ s a -> s{_piRepositoryName = a});
+
+-- | The image manifest corresponding to the image to be uploaded.
+piImageManifest :: Lens' PutImage Text
+piImageManifest = lens _piImageManifest (\ s a -> s{_piImageManifest = a});
+
+instance AWSRequest PutImage where
+        type Rs PutImage = PutImageResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 PutImageResponse' <$>
+                   (x .?> "image") <*> (pure (fromEnum s)))
+
+instance Hashable PutImage
+
+instance ToHeaders PutImage where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.PutImage" ::
+                       ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON PutImage where
+        toJSON PutImage'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _piRegistryId,
+                  Just ("repositoryName" .= _piRepositoryName),
+                  Just ("imageManifest" .= _piImageManifest)])
+
+instance ToPath PutImage where
+        toPath = const "/"
+
+instance ToQuery PutImage where
+        toQuery = const mempty
+
+-- | /See:/ 'putImageResponse' smart constructor.
+data PutImageResponse = PutImageResponse'
+    { _pirsImage          :: !(Maybe Image)
+    , _pirsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'PutImageResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'pirsImage'
+--
+-- * 'pirsResponseStatus'
+putImageResponse
+    :: Int -- ^ 'pirsResponseStatus'
+    -> PutImageResponse
+putImageResponse pResponseStatus_ =
+    PutImageResponse'
+    { _pirsImage = Nothing
+    , _pirsResponseStatus = pResponseStatus_
+    }
+
+-- | Details of the image uploaded.
+pirsImage :: Lens' PutImageResponse (Maybe Image)
+pirsImage = lens _pirsImage (\ s a -> s{_pirsImage = a});
+
+-- | The response status code.
+pirsResponseStatus :: Lens' PutImageResponse Int
+pirsResponseStatus = lens _pirsResponseStatus (\ s a -> s{_pirsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/SetRepositoryPolicy.hs b/gen/Network/AWS/ECR/SetRepositoryPolicy.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/SetRepositoryPolicy.hs
@@ -0,0 +1,186 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.SetRepositoryPolicy
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Applies a repository policy on a specified repository to control access
+-- permissions.
+module Network.AWS.ECR.SetRepositoryPolicy
+    (
+    -- * Creating a Request
+      setRepositoryPolicy
+    , SetRepositoryPolicy
+    -- * Request Lenses
+    , srpForce
+    , srpRegistryId
+    , srpRepositoryName
+    , srpPolicyText
+
+    -- * Destructuring the Response
+    , setRepositoryPolicyResponse
+    , SetRepositoryPolicyResponse
+    -- * Response Lenses
+    , srprsRegistryId
+    , srprsRepositoryName
+    , srprsPolicyText
+    , srprsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'setRepositoryPolicy' smart constructor.
+data SetRepositoryPolicy = SetRepositoryPolicy'
+    { _srpForce          :: !(Maybe Bool)
+    , _srpRegistryId     :: !(Maybe Text)
+    , _srpRepositoryName :: !Text
+    , _srpPolicyText     :: !Text
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'SetRepositoryPolicy' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'srpForce'
+--
+-- * 'srpRegistryId'
+--
+-- * 'srpRepositoryName'
+--
+-- * 'srpPolicyText'
+setRepositoryPolicy
+    :: Text -- ^ 'srpRepositoryName'
+    -> Text -- ^ 'srpPolicyText'
+    -> SetRepositoryPolicy
+setRepositoryPolicy pRepositoryName_ pPolicyText_ =
+    SetRepositoryPolicy'
+    { _srpForce = Nothing
+    , _srpRegistryId = Nothing
+    , _srpRepositoryName = pRepositoryName_
+    , _srpPolicyText = pPolicyText_
+    }
+
+-- | If the policy you are attempting to set on a repository policy would
+-- prevent you from setting another policy in the future, you must force
+-- the < SetRepositoryPolicy> operation. This is intended to prevent
+-- accidental repository lock outs.
+srpForce :: Lens' SetRepositoryPolicy (Maybe Bool)
+srpForce = lens _srpForce (\ s a -> s{_srpForce = a});
+
+-- | The AWS account ID associated with the registry that contains the
+-- repository. If you do not specify a registry, the default registry is
+-- assumed.
+srpRegistryId :: Lens' SetRepositoryPolicy (Maybe Text)
+srpRegistryId = lens _srpRegistryId (\ s a -> s{_srpRegistryId = a});
+
+-- | The name of the repository to receive the policy.
+srpRepositoryName :: Lens' SetRepositoryPolicy Text
+srpRepositoryName = lens _srpRepositoryName (\ s a -> s{_srpRepositoryName = a});
+
+-- | The JSON repository policy text to apply to the repository.
+srpPolicyText :: Lens' SetRepositoryPolicy Text
+srpPolicyText = lens _srpPolicyText (\ s a -> s{_srpPolicyText = a});
+
+instance AWSRequest SetRepositoryPolicy where
+        type Rs SetRepositoryPolicy =
+             SetRepositoryPolicyResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 SetRepositoryPolicyResponse' <$>
+                   (x .?> "registryId") <*> (x .?> "repositoryName") <*>
+                     (x .?> "policyText")
+                     <*> (pure (fromEnum s)))
+
+instance Hashable SetRepositoryPolicy
+
+instance ToHeaders SetRepositoryPolicy where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.SetRepositoryPolicy"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON SetRepositoryPolicy where
+        toJSON SetRepositoryPolicy'{..}
+          = object
+              (catMaybes
+                 [("force" .=) <$> _srpForce,
+                  ("registryId" .=) <$> _srpRegistryId,
+                  Just ("repositoryName" .= _srpRepositoryName),
+                  Just ("policyText" .= _srpPolicyText)])
+
+instance ToPath SetRepositoryPolicy where
+        toPath = const "/"
+
+instance ToQuery SetRepositoryPolicy where
+        toQuery = const mempty
+
+-- | /See:/ 'setRepositoryPolicyResponse' smart constructor.
+data SetRepositoryPolicyResponse = SetRepositoryPolicyResponse'
+    { _srprsRegistryId     :: !(Maybe Text)
+    , _srprsRepositoryName :: !(Maybe Text)
+    , _srprsPolicyText     :: !(Maybe Text)
+    , _srprsResponseStatus :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'SetRepositoryPolicyResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'srprsRegistryId'
+--
+-- * 'srprsRepositoryName'
+--
+-- * 'srprsPolicyText'
+--
+-- * 'srprsResponseStatus'
+setRepositoryPolicyResponse
+    :: Int -- ^ 'srprsResponseStatus'
+    -> SetRepositoryPolicyResponse
+setRepositoryPolicyResponse pResponseStatus_ =
+    SetRepositoryPolicyResponse'
+    { _srprsRegistryId = Nothing
+    , _srprsRepositoryName = Nothing
+    , _srprsPolicyText = Nothing
+    , _srprsResponseStatus = pResponseStatus_
+    }
+
+-- | The registry ID associated with the request.
+srprsRegistryId :: Lens' SetRepositoryPolicyResponse (Maybe Text)
+srprsRegistryId = lens _srprsRegistryId (\ s a -> s{_srprsRegistryId = a});
+
+-- | The repository name associated with the request.
+srprsRepositoryName :: Lens' SetRepositoryPolicyResponse (Maybe Text)
+srprsRepositoryName = lens _srprsRepositoryName (\ s a -> s{_srprsRepositoryName = a});
+
+-- | The JSON repository policy text applied to the repository.
+srprsPolicyText :: Lens' SetRepositoryPolicyResponse (Maybe Text)
+srprsPolicyText = lens _srprsPolicyText (\ s a -> s{_srprsPolicyText = a});
+
+-- | The response status code.
+srprsResponseStatus :: Lens' SetRepositoryPolicyResponse Int
+srprsResponseStatus = lens _srprsResponseStatus (\ s a -> s{_srprsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/Types.hs b/gen/Network/AWS/ECR/Types.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/Types.hs
@@ -0,0 +1,219 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.Types
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+module Network.AWS.ECR.Types
+    (
+    -- * Service Configuration
+      ecr
+
+    -- * Errors
+    , _LayersNotFoundException
+    , _InvalidParameterException
+    , _LayerAlreadyExistsException
+    , _ServerException
+    , _LayerInaccessibleException
+    , _InvalidLayerException
+    , _LayerPartTooSmallException
+    , _ImageAlreadyExistsException
+    , _RepositoryNotFoundException
+    , _UploadNotFoundException
+    , _InvalidLayerPartException
+    , _RepositoryNotEmptyException
+    , _RepositoryAlreadyExistsException
+    , _RepositoryPolicyNotFoundException
+    , _EmptyUploadException
+    , _LimitExceededException
+
+    -- * ImageFailureCode
+    , ImageFailureCode (..)
+
+    -- * LayerAvailability
+    , LayerAvailability (..)
+
+    -- * LayerFailureCode
+    , LayerFailureCode (..)
+
+    -- * AuthorizationData
+    , AuthorizationData
+    , authorizationData
+    , adExpiresAt
+    , adProxyEndpoint
+    , adAuthorizationToken
+
+    -- * Image
+    , Image
+    , image
+    , iRegistryId
+    , iImageId
+    , iRepositoryName
+    , iImageManifest
+
+    -- * ImageFailure
+    , ImageFailure
+    , imageFailure
+    , ifFailureReason
+    , ifFailureCode
+    , ifImageId
+
+    -- * ImageIdentifier
+    , ImageIdentifier
+    , imageIdentifier
+    , iiImageDigest
+    , iiImageTag
+
+    -- * Layer
+    , Layer
+    , layer
+    , lLayerDigest
+    , lLayerSize
+    , lLayerAvailability
+
+    -- * LayerFailure
+    , LayerFailure
+    , layerFailure
+    , lfFailureReason
+    , lfFailureCode
+    , lfLayerDigest
+
+    -- * Repository
+    , Repository
+    , repository
+    , rRepositoryARN
+    , rRegistryId
+    , rRepositoryName
+    ) where
+
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.ECR.Types.Sum
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Sign.V4
+
+-- | API version '2015-09-21' of the Amazon EC2 Container Registry SDK configuration.
+ecr :: Service
+ecr =
+    Service
+    { _svcAbbrev = "ECR"
+    , _svcSigner = v4
+    , _svcPrefix = "ecr"
+    , _svcVersion = "2015-09-21"
+    , _svcEndpoint = defaultEndpoint ecr
+    , _svcTimeout = Just 70
+    , _svcCheck = statusSuccess
+    , _svcError = parseJSONError
+    , _svcRetry = retry
+    }
+  where
+    retry =
+        Exponential
+        { _retryBase = 5.0e-2
+        , _retryGrowth = 2
+        , _retryAttempts = 5
+        , _retryCheck = check
+        }
+    check e
+      | has (hasStatus 429) e = Just "too_many_requests"
+      | has (hasCode "ThrottlingException" . hasStatus 400) e =
+          Just "throttling_exception"
+      | has (hasCode "Throttling" . hasStatus 400) e = Just "throttling"
+      | has (hasStatus 503) e = Just "service_unavailable"
+      | has (hasStatus 500) e = Just "general_server_error"
+      | has (hasStatus 509) e = Just "limit_exceeded"
+      | otherwise = Nothing
+
+-- | The specified layers could not be found, or the specified layer is not
+-- valid for this repository.
+_LayersNotFoundException :: AsError a => Getting (First ServiceError) a ServiceError
+_LayersNotFoundException = _ServiceError . hasCode "LayersNotFoundException"
+
+-- | The specified parameter is invalid. Review the available parameters for
+-- the API request.
+_InvalidParameterException :: AsError a => Getting (First ServiceError) a ServiceError
+_InvalidParameterException =
+    _ServiceError . hasCode "InvalidParameterException"
+
+-- | The image layer already exists in the associated repository.
+_LayerAlreadyExistsException :: AsError a => Getting (First ServiceError) a ServiceError
+_LayerAlreadyExistsException =
+    _ServiceError . hasCode "LayerAlreadyExistsException"
+
+-- | These errors are usually caused by a server-side issue.
+_ServerException :: AsError a => Getting (First ServiceError) a ServiceError
+_ServerException = _ServiceError . hasCode "ServerException"
+
+-- | The specified layer is not available because it is not associated with
+-- an image. Unassociated image layers may be cleaned up at any time.
+_LayerInaccessibleException :: AsError a => Getting (First ServiceError) a ServiceError
+_LayerInaccessibleException =
+    _ServiceError . hasCode "LayerInaccessibleException"
+
+-- | The layer digest calculation performed by Amazon ECR upon receipt of the
+-- image layer does not match the digest specified.
+_InvalidLayerException :: AsError a => Getting (First ServiceError) a ServiceError
+_InvalidLayerException = _ServiceError . hasCode "InvalidLayerException"
+
+-- | Layer parts must be at least 5 MiB in size.
+_LayerPartTooSmallException :: AsError a => Getting (First ServiceError) a ServiceError
+_LayerPartTooSmallException =
+    _ServiceError . hasCode "LayerPartTooSmallException"
+
+-- | The specified image has already been pushed, and there are no changes to
+-- the manifest or image tag since the last push.
+_ImageAlreadyExistsException :: AsError a => Getting (First ServiceError) a ServiceError
+_ImageAlreadyExistsException =
+    _ServiceError . hasCode "ImageAlreadyExistsException"
+
+-- | The specified repository could not be found. Check the spelling of the
+-- specified repository and ensure that you are performing operations on
+-- the correct registry.
+_RepositoryNotFoundException :: AsError a => Getting (First ServiceError) a ServiceError
+_RepositoryNotFoundException =
+    _ServiceError . hasCode "RepositoryNotFoundException"
+
+-- | The upload could not be found, or the specified upload id is not valid
+-- for this repository.
+_UploadNotFoundException :: AsError a => Getting (First ServiceError) a ServiceError
+_UploadNotFoundException = _ServiceError . hasCode "UploadNotFoundException"
+
+-- | The layer part size is not valid, or the first byte specified is not
+-- consecutive to the last byte of a previous layer part upload.
+_InvalidLayerPartException :: AsError a => Getting (First ServiceError) a ServiceError
+_InvalidLayerPartException =
+    _ServiceError . hasCode "InvalidLayerPartException"
+
+-- | The specified repository contains images. To delete a repository that
+-- contains images, you must force the deletion with the 'force' parameter.
+_RepositoryNotEmptyException :: AsError a => Getting (First ServiceError) a ServiceError
+_RepositoryNotEmptyException =
+    _ServiceError . hasCode "RepositoryNotEmptyException"
+
+-- | The specified repository already exists in the specified registry.
+_RepositoryAlreadyExistsException :: AsError a => Getting (First ServiceError) a ServiceError
+_RepositoryAlreadyExistsException =
+    _ServiceError . hasCode "RepositoryAlreadyExistsException"
+
+-- | The specified repository and registry combination does not have an
+-- associated repository policy.
+_RepositoryPolicyNotFoundException :: AsError a => Getting (First ServiceError) a ServiceError
+_RepositoryPolicyNotFoundException =
+    _ServiceError . hasCode "RepositoryPolicyNotFoundException"
+
+-- | The specified layer upload does not contain any layer parts.
+_EmptyUploadException :: AsError a => Getting (First ServiceError) a ServiceError
+_EmptyUploadException = _ServiceError . hasCode "EmptyUploadException"
+
+-- | The operation did not succeed because it would have exceeded a service
+-- limit for your account. For more information, see
+-- <http://docs.aws.amazon.com/AmazonECR/latest/userguide/service_limits.html Amazon ECR Default Service Limits>
+-- in the Amazon EC2 Container Registry User Guide.
+_LimitExceededException :: AsError a => Getting (First ServiceError) a ServiceError
+_LimitExceededException = _ServiceError . hasCode "LimitExceededException"
diff --git a/gen/Network/AWS/ECR/Types/Product.hs b/gen/Network/AWS/ECR/Types/Product.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/Types/Product.hs
@@ -0,0 +1,378 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.Types.Product
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+module Network.AWS.ECR.Types.Product where
+
+import           Network.AWS.ECR.Types.Sum
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+
+-- | An object representing authorization data for an Amazon ECR registry.
+--
+-- /See:/ 'authorizationData' smart constructor.
+data AuthorizationData = AuthorizationData'
+    { _adExpiresAt          :: !(Maybe POSIX)
+    , _adProxyEndpoint      :: !(Maybe Text)
+    , _adAuthorizationToken :: !(Maybe Text)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'AuthorizationData' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'adExpiresAt'
+--
+-- * 'adProxyEndpoint'
+--
+-- * 'adAuthorizationToken'
+authorizationData
+    :: AuthorizationData
+authorizationData =
+    AuthorizationData'
+    { _adExpiresAt = Nothing
+    , _adProxyEndpoint = Nothing
+    , _adAuthorizationToken = Nothing
+    }
+
+-- | The Unix time in seconds and milliseconds when the authorization token
+-- expires. Authorization tokens are valid for 12 hours.
+adExpiresAt :: Lens' AuthorizationData (Maybe UTCTime)
+adExpiresAt = lens _adExpiresAt (\ s a -> s{_adExpiresAt = a}) . mapping _Time;
+
+-- | The registry URL to use for this authorization token in a 'docker login'
+-- command. The Amazon ECR registry URL format is
+-- 'https:\/\/aws_account_id.dkr.ecr.region.amazonaws.com'. For example,
+-- 'https:\/\/012345678910.dkr.ecr.us-east-1.amazonaws.com'.
+adProxyEndpoint :: Lens' AuthorizationData (Maybe Text)
+adProxyEndpoint = lens _adProxyEndpoint (\ s a -> s{_adProxyEndpoint = a});
+
+-- | A base64-encoded string that contains authorization data for the
+-- specified Amazon ECR registry. When the string is decoded, it is
+-- presented in the format 'user:password' for private registry
+-- authentication using 'docker login'.
+adAuthorizationToken :: Lens' AuthorizationData (Maybe Text)
+adAuthorizationToken = lens _adAuthorizationToken (\ s a -> s{_adAuthorizationToken = a});
+
+instance FromJSON AuthorizationData where
+        parseJSON
+          = withObject "AuthorizationData"
+              (\ x ->
+                 AuthorizationData' <$>
+                   (x .:? "expiresAt") <*> (x .:? "proxyEndpoint") <*>
+                     (x .:? "authorizationToken"))
+
+instance Hashable AuthorizationData
+
+-- | Object representing an image.
+--
+-- /See:/ 'image' smart constructor.
+data Image = Image'
+    { _iRegistryId     :: !(Maybe Text)
+    , _iImageId        :: !(Maybe ImageIdentifier)
+    , _iRepositoryName :: !(Maybe Text)
+    , _iImageManifest  :: !(Maybe Text)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'Image' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'iRegistryId'
+--
+-- * 'iImageId'
+--
+-- * 'iRepositoryName'
+--
+-- * 'iImageManifest'
+image
+    :: Image
+image =
+    Image'
+    { _iRegistryId = Nothing
+    , _iImageId = Nothing
+    , _iRepositoryName = Nothing
+    , _iImageManifest = Nothing
+    }
+
+-- | The AWS account ID associated with the registry containing the image.
+iRegistryId :: Lens' Image (Maybe Text)
+iRegistryId = lens _iRegistryId (\ s a -> s{_iRegistryId = a});
+
+-- | An object containing the image tag and image digest associated with an
+-- image.
+iImageId :: Lens' Image (Maybe ImageIdentifier)
+iImageId = lens _iImageId (\ s a -> s{_iImageId = a});
+
+-- | The name of the repository associated with the image.
+iRepositoryName :: Lens' Image (Maybe Text)
+iRepositoryName = lens _iRepositoryName (\ s a -> s{_iRepositoryName = a});
+
+-- | The image manifest associated with the image.
+iImageManifest :: Lens' Image (Maybe Text)
+iImageManifest = lens _iImageManifest (\ s a -> s{_iImageManifest = a});
+
+instance FromJSON Image where
+        parseJSON
+          = withObject "Image"
+              (\ x ->
+                 Image' <$>
+                   (x .:? "registryId") <*> (x .:? "imageId") <*>
+                     (x .:? "repositoryName")
+                     <*> (x .:? "imageManifest"))
+
+instance Hashable Image
+
+-- | /See:/ 'imageFailure' smart constructor.
+data ImageFailure = ImageFailure'
+    { _ifFailureReason :: !(Maybe Text)
+    , _ifFailureCode   :: !(Maybe ImageFailureCode)
+    , _ifImageId       :: !(Maybe ImageIdentifier)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'ImageFailure' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'ifFailureReason'
+--
+-- * 'ifFailureCode'
+--
+-- * 'ifImageId'
+imageFailure
+    :: ImageFailure
+imageFailure =
+    ImageFailure'
+    { _ifFailureReason = Nothing
+    , _ifFailureCode = Nothing
+    , _ifImageId = Nothing
+    }
+
+-- | The reason for the failure.
+ifFailureReason :: Lens' ImageFailure (Maybe Text)
+ifFailureReason = lens _ifFailureReason (\ s a -> s{_ifFailureReason = a});
+
+-- | The code associated with the failure.
+ifFailureCode :: Lens' ImageFailure (Maybe ImageFailureCode)
+ifFailureCode = lens _ifFailureCode (\ s a -> s{_ifFailureCode = a});
+
+-- | The image ID associated with the failure.
+ifImageId :: Lens' ImageFailure (Maybe ImageIdentifier)
+ifImageId = lens _ifImageId (\ s a -> s{_ifImageId = a});
+
+instance FromJSON ImageFailure where
+        parseJSON
+          = withObject "ImageFailure"
+              (\ x ->
+                 ImageFailure' <$>
+                   (x .:? "failureReason") <*> (x .:? "failureCode") <*>
+                     (x .:? "imageId"))
+
+instance Hashable ImageFailure
+
+-- | /See:/ 'imageIdentifier' smart constructor.
+data ImageIdentifier = ImageIdentifier'
+    { _iiImageDigest :: !(Maybe Text)
+    , _iiImageTag    :: !(Maybe Text)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'ImageIdentifier' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'iiImageDigest'
+--
+-- * 'iiImageTag'
+imageIdentifier
+    :: ImageIdentifier
+imageIdentifier =
+    ImageIdentifier'
+    { _iiImageDigest = Nothing
+    , _iiImageTag = Nothing
+    }
+
+-- | The 'sha256' digest of the image manifest.
+iiImageDigest :: Lens' ImageIdentifier (Maybe Text)
+iiImageDigest = lens _iiImageDigest (\ s a -> s{_iiImageDigest = a});
+
+-- | The tag used for the image.
+iiImageTag :: Lens' ImageIdentifier (Maybe Text)
+iiImageTag = lens _iiImageTag (\ s a -> s{_iiImageTag = a});
+
+instance FromJSON ImageIdentifier where
+        parseJSON
+          = withObject "ImageIdentifier"
+              (\ x ->
+                 ImageIdentifier' <$>
+                   (x .:? "imageDigest") <*> (x .:? "imageTag"))
+
+instance Hashable ImageIdentifier
+
+instance ToJSON ImageIdentifier where
+        toJSON ImageIdentifier'{..}
+          = object
+              (catMaybes
+                 [("imageDigest" .=) <$> _iiImageDigest,
+                  ("imageTag" .=) <$> _iiImageTag])
+
+-- | /See:/ 'layer' smart constructor.
+data Layer = Layer'
+    { _lLayerDigest       :: !(Maybe Text)
+    , _lLayerSize         :: !(Maybe Integer)
+    , _lLayerAvailability :: !(Maybe LayerAvailability)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'Layer' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'lLayerDigest'
+--
+-- * 'lLayerSize'
+--
+-- * 'lLayerAvailability'
+layer
+    :: Layer
+layer =
+    Layer'
+    { _lLayerDigest = Nothing
+    , _lLayerSize = Nothing
+    , _lLayerAvailability = Nothing
+    }
+
+-- | The 'sha256' digest of the image layer.
+lLayerDigest :: Lens' Layer (Maybe Text)
+lLayerDigest = lens _lLayerDigest (\ s a -> s{_lLayerDigest = a});
+
+-- | The size, in bytes, of the image layer.
+lLayerSize :: Lens' Layer (Maybe Integer)
+lLayerSize = lens _lLayerSize (\ s a -> s{_lLayerSize = a});
+
+-- | The availability status of the image layer. Valid values are 'AVAILABLE'
+-- and 'UNAVAILABLE'.
+lLayerAvailability :: Lens' Layer (Maybe LayerAvailability)
+lLayerAvailability = lens _lLayerAvailability (\ s a -> s{_lLayerAvailability = a});
+
+instance FromJSON Layer where
+        parseJSON
+          = withObject "Layer"
+              (\ x ->
+                 Layer' <$>
+                   (x .:? "layerDigest") <*> (x .:? "layerSize") <*>
+                     (x .:? "layerAvailability"))
+
+instance Hashable Layer
+
+-- | /See:/ 'layerFailure' smart constructor.
+data LayerFailure = LayerFailure'
+    { _lfFailureReason :: !(Maybe Text)
+    , _lfFailureCode   :: !(Maybe LayerFailureCode)
+    , _lfLayerDigest   :: !(Maybe Text)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'LayerFailure' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'lfFailureReason'
+--
+-- * 'lfFailureCode'
+--
+-- * 'lfLayerDigest'
+layerFailure
+    :: LayerFailure
+layerFailure =
+    LayerFailure'
+    { _lfFailureReason = Nothing
+    , _lfFailureCode = Nothing
+    , _lfLayerDigest = Nothing
+    }
+
+-- | The reason for the failure.
+lfFailureReason :: Lens' LayerFailure (Maybe Text)
+lfFailureReason = lens _lfFailureReason (\ s a -> s{_lfFailureReason = a});
+
+-- | The failure code associated with the failure.
+lfFailureCode :: Lens' LayerFailure (Maybe LayerFailureCode)
+lfFailureCode = lens _lfFailureCode (\ s a -> s{_lfFailureCode = a});
+
+-- | The layer digest associated with the failure.
+lfLayerDigest :: Lens' LayerFailure (Maybe Text)
+lfLayerDigest = lens _lfLayerDigest (\ s a -> s{_lfLayerDigest = a});
+
+instance FromJSON LayerFailure where
+        parseJSON
+          = withObject "LayerFailure"
+              (\ x ->
+                 LayerFailure' <$>
+                   (x .:? "failureReason") <*> (x .:? "failureCode") <*>
+                     (x .:? "layerDigest"))
+
+instance Hashable LayerFailure
+
+-- | Object representing a repository.
+--
+-- /See:/ 'repository' smart constructor.
+data Repository = Repository'
+    { _rRepositoryARN  :: !(Maybe Text)
+    , _rRegistryId     :: !(Maybe Text)
+    , _rRepositoryName :: !(Maybe Text)
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'Repository' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'rRepositoryARN'
+--
+-- * 'rRegistryId'
+--
+-- * 'rRepositoryName'
+repository
+    :: Repository
+repository =
+    Repository'
+    { _rRepositoryARN = Nothing
+    , _rRegistryId = Nothing
+    , _rRepositoryName = Nothing
+    }
+
+-- | The Amazon Resource Name (ARN) that identifies the repository. The ARN
+-- contains the 'arn:aws:ecr' namespace, followed by the region of the
+-- repository, the AWS account ID of the repository owner, the repository
+-- namespace, and then the repository name. For example,
+-- 'arn:aws:ecr:region:012345678910:repository\/test'.
+rRepositoryARN :: Lens' Repository (Maybe Text)
+rRepositoryARN = lens _rRepositoryARN (\ s a -> s{_rRepositoryARN = a});
+
+-- | The AWS account ID associated with the registry that contains the
+-- repository.
+rRegistryId :: Lens' Repository (Maybe Text)
+rRegistryId = lens _rRegistryId (\ s a -> s{_rRegistryId = a});
+
+-- | The name of the repository.
+rRepositoryName :: Lens' Repository (Maybe Text)
+rRepositoryName = lens _rRepositoryName (\ s a -> s{_rRepositoryName = a});
+
+instance FromJSON Repository where
+        parseJSON
+          = withObject "Repository"
+              (\ x ->
+                 Repository' <$>
+                   (x .:? "repositoryArn") <*> (x .:? "registryId") <*>
+                     (x .:? "repositoryName"))
+
+instance Hashable Repository
diff --git a/gen/Network/AWS/ECR/Types/Sum.hs b/gen/Network/AWS/ECR/Types/Sum.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/Types/Sum.hs
@@ -0,0 +1,104 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE LambdaCase         #-}
+{-# LANGUAGE OverloadedStrings  #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.Types.Sum
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+module Network.AWS.ECR.Types.Sum where
+
+import           Network.AWS.Prelude
+
+data ImageFailureCode
+    = ImageNotFound
+    | ImageTagDoesNotMatchDigest
+    | InvalidImageDigest
+    | InvalidImageTag
+    | MissingDigestAndTag
+    deriving (Eq,Ord,Read,Show,Enum,Bounded,Data,Typeable,Generic)
+
+instance FromText ImageFailureCode where
+    parser = takeLowerText >>= \case
+        "imagenotfound" -> pure ImageNotFound
+        "imagetagdoesnotmatchdigest" -> pure ImageTagDoesNotMatchDigest
+        "invalidimagedigest" -> pure InvalidImageDigest
+        "invalidimagetag" -> pure InvalidImageTag
+        "missingdigestandtag" -> pure MissingDigestAndTag
+        e -> fromTextError $ "Failure parsing ImageFailureCode from value: '" <> e
+           <> "'. Accepted values: ImageNotFound, ImageTagDoesNotMatchDigest, InvalidImageDigest, InvalidImageTag, MissingDigestAndTag"
+
+instance ToText ImageFailureCode where
+    toText = \case
+        ImageNotFound -> "ImageNotFound"
+        ImageTagDoesNotMatchDigest -> "ImageTagDoesNotMatchDigest"
+        InvalidImageDigest -> "InvalidImageDigest"
+        InvalidImageTag -> "InvalidImageTag"
+        MissingDigestAndTag -> "MissingDigestAndTag"
+
+instance Hashable     ImageFailureCode
+instance ToByteString ImageFailureCode
+instance ToQuery      ImageFailureCode
+instance ToHeader     ImageFailureCode
+
+instance FromJSON ImageFailureCode where
+    parseJSON = parseJSONText "ImageFailureCode"
+
+data LayerAvailability
+    = Available
+    | Unavailable
+    deriving (Eq,Ord,Read,Show,Enum,Bounded,Data,Typeable,Generic)
+
+instance FromText LayerAvailability where
+    parser = takeLowerText >>= \case
+        "available" -> pure Available
+        "unavailable" -> pure Unavailable
+        e -> fromTextError $ "Failure parsing LayerAvailability from value: '" <> e
+           <> "'. Accepted values: AVAILABLE, UNAVAILABLE"
+
+instance ToText LayerAvailability where
+    toText = \case
+        Available -> "AVAILABLE"
+        Unavailable -> "UNAVAILABLE"
+
+instance Hashable     LayerAvailability
+instance ToByteString LayerAvailability
+instance ToQuery      LayerAvailability
+instance ToHeader     LayerAvailability
+
+instance FromJSON LayerAvailability where
+    parseJSON = parseJSONText "LayerAvailability"
+
+data LayerFailureCode
+    = InvalidLayerDigest
+    | MissingLayerDigest
+    deriving (Eq,Ord,Read,Show,Enum,Bounded,Data,Typeable,Generic)
+
+instance FromText LayerFailureCode where
+    parser = takeLowerText >>= \case
+        "invalidlayerdigest" -> pure InvalidLayerDigest
+        "missinglayerdigest" -> pure MissingLayerDigest
+        e -> fromTextError $ "Failure parsing LayerFailureCode from value: '" <> e
+           <> "'. Accepted values: InvalidLayerDigest, MissingLayerDigest"
+
+instance ToText LayerFailureCode where
+    toText = \case
+        InvalidLayerDigest -> "InvalidLayerDigest"
+        MissingLayerDigest -> "MissingLayerDigest"
+
+instance Hashable     LayerFailureCode
+instance ToByteString LayerFailureCode
+instance ToQuery      LayerFailureCode
+instance ToHeader     LayerFailureCode
+
+instance FromJSON LayerFailureCode where
+    parseJSON = parseJSONText "LayerFailureCode"
diff --git a/gen/Network/AWS/ECR/UploadLayerPart.hs b/gen/Network/AWS/ECR/UploadLayerPart.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/UploadLayerPart.hs
@@ -0,0 +1,225 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE TypeFamilies       #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.UploadLayerPart
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+-- Uploads an image layer part to Amazon ECR.
+--
+-- This operation is used by the Amazon ECR proxy, and it is not intended
+-- for general use by customers. Use the 'docker' CLI to pull, tag, and
+-- push images.
+module Network.AWS.ECR.UploadLayerPart
+    (
+    -- * Creating a Request
+      uploadLayerPart
+    , UploadLayerPart
+    -- * Request Lenses
+    , ulpRegistryId
+    , ulpRepositoryName
+    , ulpUploadId
+    , ulpPartFirstByte
+    , ulpPartLastByte
+    , ulpLayerPartBlob
+
+    -- * Destructuring the Response
+    , uploadLayerPartResponse
+    , UploadLayerPartResponse
+    -- * Response Lenses
+    , ulprsRegistryId
+    , ulprsLastByteReceived
+    , ulprsRepositoryName
+    , ulprsUploadId
+    , ulprsResponseStatus
+    ) where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.ECR.Types.Product
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Request
+import           Network.AWS.Response
+
+-- | /See:/ 'uploadLayerPart' smart constructor.
+data UploadLayerPart = UploadLayerPart'
+    { _ulpRegistryId     :: !(Maybe Text)
+    , _ulpRepositoryName :: !Text
+    , _ulpUploadId       :: !Text
+    , _ulpPartFirstByte  :: !Nat
+    , _ulpPartLastByte   :: !Nat
+    , _ulpLayerPartBlob  :: !Base64
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'UploadLayerPart' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'ulpRegistryId'
+--
+-- * 'ulpRepositoryName'
+--
+-- * 'ulpUploadId'
+--
+-- * 'ulpPartFirstByte'
+--
+-- * 'ulpPartLastByte'
+--
+-- * 'ulpLayerPartBlob'
+uploadLayerPart
+    :: Text -- ^ 'ulpRepositoryName'
+    -> Text -- ^ 'ulpUploadId'
+    -> Natural -- ^ 'ulpPartFirstByte'
+    -> Natural -- ^ 'ulpPartLastByte'
+    -> ByteString -- ^ 'ulpLayerPartBlob'
+    -> UploadLayerPart
+uploadLayerPart pRepositoryName_ pUploadId_ pPartFirstByte_ pPartLastByte_ pLayerPartBlob_ =
+    UploadLayerPart'
+    { _ulpRegistryId = Nothing
+    , _ulpRepositoryName = pRepositoryName_
+    , _ulpUploadId = pUploadId_
+    , _ulpPartFirstByte = _Nat # pPartFirstByte_
+    , _ulpPartLastByte = _Nat # pPartLastByte_
+    , _ulpLayerPartBlob = _Base64 # pLayerPartBlob_
+    }
+
+-- | The AWS account ID associated with the registry that you are uploading
+-- layer parts to. If you do not specify a registry, the default registry
+-- is assumed.
+ulpRegistryId :: Lens' UploadLayerPart (Maybe Text)
+ulpRegistryId = lens _ulpRegistryId (\ s a -> s{_ulpRegistryId = a});
+
+-- | The name of the repository that you are uploading layer parts to.
+ulpRepositoryName :: Lens' UploadLayerPart Text
+ulpRepositoryName = lens _ulpRepositoryName (\ s a -> s{_ulpRepositoryName = a});
+
+-- | The upload ID from a previous < InitiateLayerUpload> operation to
+-- associate with the layer part upload.
+ulpUploadId :: Lens' UploadLayerPart Text
+ulpUploadId = lens _ulpUploadId (\ s a -> s{_ulpUploadId = a});
+
+-- | The integer value of the first byte of the layer part.
+ulpPartFirstByte :: Lens' UploadLayerPart Natural
+ulpPartFirstByte = lens _ulpPartFirstByte (\ s a -> s{_ulpPartFirstByte = a}) . _Nat;
+
+-- | The integer value of the last byte of the layer part.
+ulpPartLastByte :: Lens' UploadLayerPart Natural
+ulpPartLastByte = lens _ulpPartLastByte (\ s a -> s{_ulpPartLastByte = a}) . _Nat;
+
+-- | The base64-encoded layer part payload.
+--
+-- /Note:/ This 'Lens' automatically encodes and decodes Base64 data,
+-- despite what the AWS documentation might say.
+-- The underlying isomorphism will encode to Base64 representation during
+-- serialisation, and decode from Base64 representation during deserialisation.
+-- This 'Lens' accepts and returns only raw unencoded data.
+ulpLayerPartBlob :: Lens' UploadLayerPart ByteString
+ulpLayerPartBlob = lens _ulpLayerPartBlob (\ s a -> s{_ulpLayerPartBlob = a}) . _Base64;
+
+instance AWSRequest UploadLayerPart where
+        type Rs UploadLayerPart = UploadLayerPartResponse
+        request = postJSON ecr
+        response
+          = receiveJSON
+              (\ s h x ->
+                 UploadLayerPartResponse' <$>
+                   (x .?> "registryId") <*> (x .?> "lastByteReceived")
+                     <*> (x .?> "repositoryName")
+                     <*> (x .?> "uploadId")
+                     <*> (pure (fromEnum s)))
+
+instance Hashable UploadLayerPart
+
+instance ToHeaders UploadLayerPart where
+        toHeaders
+          = const
+              (mconcat
+                 ["X-Amz-Target" =#
+                    ("AmazonEC2ContainerRegistry_V20150921.UploadLayerPart"
+                       :: ByteString),
+                  "Content-Type" =#
+                    ("application/x-amz-json-1.1" :: ByteString)])
+
+instance ToJSON UploadLayerPart where
+        toJSON UploadLayerPart'{..}
+          = object
+              (catMaybes
+                 [("registryId" .=) <$> _ulpRegistryId,
+                  Just ("repositoryName" .= _ulpRepositoryName),
+                  Just ("uploadId" .= _ulpUploadId),
+                  Just ("partFirstByte" .= _ulpPartFirstByte),
+                  Just ("partLastByte" .= _ulpPartLastByte),
+                  Just ("layerPartBlob" .= _ulpLayerPartBlob)])
+
+instance ToPath UploadLayerPart where
+        toPath = const "/"
+
+instance ToQuery UploadLayerPart where
+        toQuery = const mempty
+
+-- | /See:/ 'uploadLayerPartResponse' smart constructor.
+data UploadLayerPartResponse = UploadLayerPartResponse'
+    { _ulprsRegistryId       :: !(Maybe Text)
+    , _ulprsLastByteReceived :: !(Maybe Nat)
+    , _ulprsRepositoryName   :: !(Maybe Text)
+    , _ulprsUploadId         :: !(Maybe Text)
+    , _ulprsResponseStatus   :: !Int
+    } deriving (Eq,Read,Show,Data,Typeable,Generic)
+
+-- | Creates a value of 'UploadLayerPartResponse' with the minimum fields required to make a request.
+--
+-- Use one of the following lenses to modify other fields as desired:
+--
+-- * 'ulprsRegistryId'
+--
+-- * 'ulprsLastByteReceived'
+--
+-- * 'ulprsRepositoryName'
+--
+-- * 'ulprsUploadId'
+--
+-- * 'ulprsResponseStatus'
+uploadLayerPartResponse
+    :: Int -- ^ 'ulprsResponseStatus'
+    -> UploadLayerPartResponse
+uploadLayerPartResponse pResponseStatus_ =
+    UploadLayerPartResponse'
+    { _ulprsRegistryId = Nothing
+    , _ulprsLastByteReceived = Nothing
+    , _ulprsRepositoryName = Nothing
+    , _ulprsUploadId = Nothing
+    , _ulprsResponseStatus = pResponseStatus_
+    }
+
+-- | The registry ID associated with the request.
+ulprsRegistryId :: Lens' UploadLayerPartResponse (Maybe Text)
+ulprsRegistryId = lens _ulprsRegistryId (\ s a -> s{_ulprsRegistryId = a});
+
+-- | The integer value of the last byte received in the request.
+ulprsLastByteReceived :: Lens' UploadLayerPartResponse (Maybe Natural)
+ulprsLastByteReceived = lens _ulprsLastByteReceived (\ s a -> s{_ulprsLastByteReceived = a}) . mapping _Nat;
+
+-- | The repository name associated with the request.
+ulprsRepositoryName :: Lens' UploadLayerPartResponse (Maybe Text)
+ulprsRepositoryName = lens _ulprsRepositoryName (\ s a -> s{_ulprsRepositoryName = a});
+
+-- | The upload ID associated with the request.
+ulprsUploadId :: Lens' UploadLayerPartResponse (Maybe Text)
+ulprsUploadId = lens _ulprsUploadId (\ s a -> s{_ulprsUploadId = a});
+
+-- | The response status code.
+ulprsResponseStatus :: Lens' UploadLayerPartResponse Int
+ulprsResponseStatus = lens _ulprsResponseStatus (\ s a -> s{_ulprsResponseStatus = a});
diff --git a/gen/Network/AWS/ECR/Waiters.hs b/gen/Network/AWS/ECR/Waiters.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/ECR/Waiters.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeFamilies      #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Network.AWS.ECR.Waiters
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+module Network.AWS.ECR.Waiters where
+
+import           Network.AWS.ECR.Types
+import           Network.AWS.Lens
+import           Network.AWS.Prelude
+import           Network.AWS.Waiter
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,21 @@
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
+-- |
+-- Module      : Main
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+module Main (main) where
+
+import Test.Tasty
+import Test.AWS.ECR
+import Test.AWS.ECR.Internal
+
+main :: IO ()
+main = defaultMain $ testGroup "ECR"
+    [ testGroup "tests"    tests
+    , testGroup "fixtures" fixtures
+    ]
diff --git a/test/Test/AWS/ECR.hs b/test/Test/AWS/ECR.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/AWS/ECR.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell   #-}
+
+-- |
+-- Module      : Test.AWS.ECR
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : experimental
+-- Portability : non-portable (GHC extensions)
+--
+module Test.AWS.ECR
+    ( tests
+    , fixtures
+    ) where
+
+import           Test.AWS.Prelude
+
+tests :: [TestTree]
+tests = []
+
+fixtures :: [TestTree]
+fixtures = []
diff --git a/test/Test/AWS/ECR/Internal.hs b/test/Test/AWS/ECR/Internal.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/AWS/ECR/Internal.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
+-- |
+-- Module      : Test.AWS.ECR.Internal
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : experimental
+-- Portability : non-portable (GHC extensions)
+--
+
+module Test.AWS.ECR.Internal where
+
+import           Test.AWS.Prelude
diff --git a/test/Test/AWS/Gen/ECR.hs b/test/Test/AWS/Gen/ECR.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/AWS/Gen/ECR.hs
@@ -0,0 +1,327 @@
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-orphans        #-}
+
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- |
+-- Module      : Test.AWS.Gen.ECR
+-- Copyright   : (c) 2013-2016 Brendan Hay
+-- License     : Mozilla Public License, v. 2.0.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : auto-generated
+-- Portability : non-portable (GHC extensions)
+--
+module Test.AWS.Gen.ECR where
+
+import Data.Proxy
+import Test.AWS.Fixture
+import Test.AWS.Prelude
+import Test.Tasty
+import Network.AWS.ECR
+import Test.AWS.ECR.Internal
+
+-- Auto-generated: the actual test selection needs to be manually placed into
+-- the top-level so that real test data can be incrementally added.
+--
+-- This commented snippet is what the entire set should look like:
+
+-- fixtures :: TestTree
+-- fixtures =
+--     [ testGroup "request"
+--         [ testGetRepositoryPolicy $
+--             getRepositoryPolicy
+--
+--         , testBatchDeleteImage $
+--             batchDeleteImage
+--
+--         , testBatchCheckLayerAvailability $
+--             batchCheckLayerAvailability
+--
+--         , testDeleteRepositoryPolicy $
+--             deleteRepositoryPolicy
+--
+--         , testCreateRepository $
+--             createRepository
+--
+--         , testCompleteLayerUpload $
+--             completeLayerUpload
+--
+--         , testDescribeRepositories $
+--             describeRepositories
+--
+--         , testUploadLayerPart $
+--             uploadLayerPart
+--
+--         , testBatchGetImage $
+--             batchGetImage
+--
+--         , testSetRepositoryPolicy $
+--             setRepositoryPolicy
+--
+--         , testInitiateLayerUpload $
+--             initiateLayerUpload
+--
+--         , testDeleteRepository $
+--             deleteRepository
+--
+--         , testPutImage $
+--             putImage
+--
+--         , testListImages $
+--             listImages
+--
+--         , testGetAuthorizationToken $
+--             getAuthorizationToken
+--
+--         , testGetDownloadURLForLayer $
+--             getDownloadURLForLayer
+--
+--           ]
+
+--     , testGroup "response"
+--         [ testGetRepositoryPolicyResponse $
+--             getRepositoryPolicyResponse
+--
+--         , testBatchDeleteImageResponse $
+--             batchDeleteImageResponse
+--
+--         , testBatchCheckLayerAvailabilityResponse $
+--             batchCheckLayerAvailabilityResponse
+--
+--         , testDeleteRepositoryPolicyResponse $
+--             deleteRepositoryPolicyResponse
+--
+--         , testCreateRepositoryResponse $
+--             createRepositoryResponse
+--
+--         , testCompleteLayerUploadResponse $
+--             completeLayerUploadResponse
+--
+--         , testDescribeRepositoriesResponse $
+--             describeRepositoriesResponse
+--
+--         , testUploadLayerPartResponse $
+--             uploadLayerPartResponse
+--
+--         , testBatchGetImageResponse $
+--             batchGetImageResponse
+--
+--         , testSetRepositoryPolicyResponse $
+--             setRepositoryPolicyResponse
+--
+--         , testInitiateLayerUploadResponse $
+--             initiateLayerUploadResponse
+--
+--         , testDeleteRepositoryResponse $
+--             deleteRepositoryResponse
+--
+--         , testPutImageResponse $
+--             putImageResponse
+--
+--         , testListImagesResponse $
+--             listImagesResponse
+--
+--         , testGetAuthorizationTokenResponse $
+--             getAuthorizationTokenResponse
+--
+--         , testGetDownloadURLForLayerResponse $
+--             getDownloadURLForLayerResponse
+--
+--           ]
+--     ]
+
+-- Requests
+
+testGetRepositoryPolicy :: GetRepositoryPolicy -> TestTree
+testGetRepositoryPolicy = req
+    "GetRepositoryPolicy"
+    "fixture/GetRepositoryPolicy.yaml"
+
+testBatchDeleteImage :: BatchDeleteImage -> TestTree
+testBatchDeleteImage = req
+    "BatchDeleteImage"
+    "fixture/BatchDeleteImage.yaml"
+
+testBatchCheckLayerAvailability :: BatchCheckLayerAvailability -> TestTree
+testBatchCheckLayerAvailability = req
+    "BatchCheckLayerAvailability"
+    "fixture/BatchCheckLayerAvailability.yaml"
+
+testDeleteRepositoryPolicy :: DeleteRepositoryPolicy -> TestTree
+testDeleteRepositoryPolicy = req
+    "DeleteRepositoryPolicy"
+    "fixture/DeleteRepositoryPolicy.yaml"
+
+testCreateRepository :: CreateRepository -> TestTree
+testCreateRepository = req
+    "CreateRepository"
+    "fixture/CreateRepository.yaml"
+
+testCompleteLayerUpload :: CompleteLayerUpload -> TestTree
+testCompleteLayerUpload = req
+    "CompleteLayerUpload"
+    "fixture/CompleteLayerUpload.yaml"
+
+testDescribeRepositories :: DescribeRepositories -> TestTree
+testDescribeRepositories = req
+    "DescribeRepositories"
+    "fixture/DescribeRepositories.yaml"
+
+testUploadLayerPart :: UploadLayerPart -> TestTree
+testUploadLayerPart = req
+    "UploadLayerPart"
+    "fixture/UploadLayerPart.yaml"
+
+testBatchGetImage :: BatchGetImage -> TestTree
+testBatchGetImage = req
+    "BatchGetImage"
+    "fixture/BatchGetImage.yaml"
+
+testSetRepositoryPolicy :: SetRepositoryPolicy -> TestTree
+testSetRepositoryPolicy = req
+    "SetRepositoryPolicy"
+    "fixture/SetRepositoryPolicy.yaml"
+
+testInitiateLayerUpload :: InitiateLayerUpload -> TestTree
+testInitiateLayerUpload = req
+    "InitiateLayerUpload"
+    "fixture/InitiateLayerUpload.yaml"
+
+testDeleteRepository :: DeleteRepository -> TestTree
+testDeleteRepository = req
+    "DeleteRepository"
+    "fixture/DeleteRepository.yaml"
+
+testPutImage :: PutImage -> TestTree
+testPutImage = req
+    "PutImage"
+    "fixture/PutImage.yaml"
+
+testListImages :: ListImages -> TestTree
+testListImages = req
+    "ListImages"
+    "fixture/ListImages.yaml"
+
+testGetAuthorizationToken :: GetAuthorizationToken -> TestTree
+testGetAuthorizationToken = req
+    "GetAuthorizationToken"
+    "fixture/GetAuthorizationToken.yaml"
+
+testGetDownloadURLForLayer :: GetDownloadURLForLayer -> TestTree
+testGetDownloadURLForLayer = req
+    "GetDownloadURLForLayer"
+    "fixture/GetDownloadURLForLayer.yaml"
+
+-- Responses
+
+testGetRepositoryPolicyResponse :: GetRepositoryPolicyResponse -> TestTree
+testGetRepositoryPolicyResponse = res
+    "GetRepositoryPolicyResponse"
+    "fixture/GetRepositoryPolicyResponse.proto"
+    ecr
+    (Proxy :: Proxy GetRepositoryPolicy)
+
+testBatchDeleteImageResponse :: BatchDeleteImageResponse -> TestTree
+testBatchDeleteImageResponse = res
+    "BatchDeleteImageResponse"
+    "fixture/BatchDeleteImageResponse.proto"
+    ecr
+    (Proxy :: Proxy BatchDeleteImage)
+
+testBatchCheckLayerAvailabilityResponse :: BatchCheckLayerAvailabilityResponse -> TestTree
+testBatchCheckLayerAvailabilityResponse = res
+    "BatchCheckLayerAvailabilityResponse"
+    "fixture/BatchCheckLayerAvailabilityResponse.proto"
+    ecr
+    (Proxy :: Proxy BatchCheckLayerAvailability)
+
+testDeleteRepositoryPolicyResponse :: DeleteRepositoryPolicyResponse -> TestTree
+testDeleteRepositoryPolicyResponse = res
+    "DeleteRepositoryPolicyResponse"
+    "fixture/DeleteRepositoryPolicyResponse.proto"
+    ecr
+    (Proxy :: Proxy DeleteRepositoryPolicy)
+
+testCreateRepositoryResponse :: CreateRepositoryResponse -> TestTree
+testCreateRepositoryResponse = res
+    "CreateRepositoryResponse"
+    "fixture/CreateRepositoryResponse.proto"
+    ecr
+    (Proxy :: Proxy CreateRepository)
+
+testCompleteLayerUploadResponse :: CompleteLayerUploadResponse -> TestTree
+testCompleteLayerUploadResponse = res
+    "CompleteLayerUploadResponse"
+    "fixture/CompleteLayerUploadResponse.proto"
+    ecr
+    (Proxy :: Proxy CompleteLayerUpload)
+
+testDescribeRepositoriesResponse :: DescribeRepositoriesResponse -> TestTree
+testDescribeRepositoriesResponse = res
+    "DescribeRepositoriesResponse"
+    "fixture/DescribeRepositoriesResponse.proto"
+    ecr
+    (Proxy :: Proxy DescribeRepositories)
+
+testUploadLayerPartResponse :: UploadLayerPartResponse -> TestTree
+testUploadLayerPartResponse = res
+    "UploadLayerPartResponse"
+    "fixture/UploadLayerPartResponse.proto"
+    ecr
+    (Proxy :: Proxy UploadLayerPart)
+
+testBatchGetImageResponse :: BatchGetImageResponse -> TestTree
+testBatchGetImageResponse = res
+    "BatchGetImageResponse"
+    "fixture/BatchGetImageResponse.proto"
+    ecr
+    (Proxy :: Proxy BatchGetImage)
+
+testSetRepositoryPolicyResponse :: SetRepositoryPolicyResponse -> TestTree
+testSetRepositoryPolicyResponse = res
+    "SetRepositoryPolicyResponse"
+    "fixture/SetRepositoryPolicyResponse.proto"
+    ecr
+    (Proxy :: Proxy SetRepositoryPolicy)
+
+testInitiateLayerUploadResponse :: InitiateLayerUploadResponse -> TestTree
+testInitiateLayerUploadResponse = res
+    "InitiateLayerUploadResponse"
+    "fixture/InitiateLayerUploadResponse.proto"
+    ecr
+    (Proxy :: Proxy InitiateLayerUpload)
+
+testDeleteRepositoryResponse :: DeleteRepositoryResponse -> TestTree
+testDeleteRepositoryResponse = res
+    "DeleteRepositoryResponse"
+    "fixture/DeleteRepositoryResponse.proto"
+    ecr
+    (Proxy :: Proxy DeleteRepository)
+
+testPutImageResponse :: PutImageResponse -> TestTree
+testPutImageResponse = res
+    "PutImageResponse"
+    "fixture/PutImageResponse.proto"
+    ecr
+    (Proxy :: Proxy PutImage)
+
+testListImagesResponse :: ListImagesResponse -> TestTree
+testListImagesResponse = res
+    "ListImagesResponse"
+    "fixture/ListImagesResponse.proto"
+    ecr
+    (Proxy :: Proxy ListImages)
+
+testGetAuthorizationTokenResponse :: GetAuthorizationTokenResponse -> TestTree
+testGetAuthorizationTokenResponse = res
+    "GetAuthorizationTokenResponse"
+    "fixture/GetAuthorizationTokenResponse.proto"
+    ecr
+    (Proxy :: Proxy GetAuthorizationToken)
+
+testGetDownloadURLForLayerResponse :: GetDownloadURLForLayerResponse -> TestTree
+testGetDownloadURLForLayerResponse = res
+    "GetDownloadURLForLayerResponse"
+    "fixture/GetDownloadURLForLayerResponse.proto"
+    ecr
+    (Proxy :: Proxy GetDownloadURLForLayer)
