diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,6 @@
+# Change Log
+
+## 0.1 (initial release)
+
+* Initial release with all Template components implemented along with a huge
+  set of Resources.
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,19 @@
+Copyright (c) 2016 David Reaver
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,160 @@
+# Stratosphere: AWS CloudFormation in Haskell
+
+[![Build Status](https://travis-ci.org/frontrowed/stratosphere.svg?branch=master)](https://travis-ci.org/frontrowed/stratosphere)
+
+AWS CloudFormation is a system that provisions and updates Amazon Web Services
+(AWS) resources based on declarative templates. Common criticisms of
+CloudFormation include the use of JSON as the template language and limited
+error-checking, often only available in the form of run-time errors and stack
+rollbacks. By wrapping templates in Haskell, we are able to easily construct
+them and help ensure correctness.
+
+The goals of stratosphere are to:
+* Build a Haskell EDSL to specify CloudFormation templates. Since it is
+  embedded in Haskell, it is type-checked and generally much easier to work
+  with than raw JSON.
+* Have a simple checking/linting system outside of the types that can find
+  common errors in templates.
+* Be able to also read valid CloudFormation JSON templates so they can be
+  type-checked. This also gives us free integration tests by using the huge
+  amount of example templates available in the AWS docs.
+
+## Example
+
+Here is an example of a `Template` that creates an EC2 instance, along with the
+JSON output:
+
+```haskell
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Main where
+
+import qualified Data.ByteString.Lazy.Char8 as B
+import Stratosphere
+
+main :: IO ()
+main = B.putStrLn $ encodeTemplate instanceTemplate
+
+instanceTemplate :: Template
+instanceTemplate =
+  template
+  [ resource "EC2Instance" (
+    EC2InstanceProperties $
+    ec2Instance
+    "ami-22111148"
+    & eciKeyName ?~ (Ref "KeyName")
+    )
+    & deletionPolicy ?~ Retain
+  ]
+  & description ?~ "Sample template"
+  & parameters ?~
+  [ parameter "KeyName" "AWS::EC2::KeyPair::KeyName"
+    & description ?~ "Name of an existing EC2 KeyPair to enable SSH access to the instance"
+    & constraintDescription ?~ "Must be the name of an existing EC2 KeyPair."
+  ]
+```
+
+```json
+{
+  "Description": "Sample template",
+  "Parameters": {
+    "KeyName": {
+      "Description": "Name of an existing EC2 KeyPair to enable SSH access to the instance",
+      "ConstraintDescription": "Must be the name of an existing EC2 KeyPair.",
+      "Type": "AWS::EC2::KeyPair::KeyName"
+    }
+  },
+  "Resources": {
+    "EC2Instance": {
+      "DeletionPolicy": "Retain",
+      "Type": "AWS::EC2::Instance",
+      "Properties": {
+        "KeyName": {
+          "Ref": "KeyName"
+        },
+        "ImageId": "ami-22111148"
+      }
+    }
+  }
+}
+```
+
+Please see the [examples](examples/) directory for more in-depth examples.
+
+## Value Types
+
+CloudFormation resource parameters can be literals (strings, integers, etc),
+references to another resource or a Parameter, or the result of some function
+call. We encapsulate all of these possibilities in the `Val a` type.
+
+We recommend using the `OverloadedStrings` extension to reduce the number of
+`Literal`s you have to use.
+
+Note that CloudFormation represents numbers and bools in JSON as strings, so we
+had to some types called `Integer'` and `Bool'` to override the `aeson`
+instances. In a future version we plan on using our own JSON encoder/decoder to
+get around this.
+
+## Lenses
+
+Almost every CloudFormation resource has a handful of required arguments, and
+many more optional arguments. Each resource is represented as a record type
+with optional arguments wrapped in `Maybe`. Each resource also comes with a
+constructor that accepts required resource parameters as arguments. This allows
+the user to succinctly specify the resource parameters they actually use
+without adding too much noise to their code.
+
+To specify optional arguments, we recommend using the lens operators `&` and
+`?~`. In the example above, the `ec2Instance` function takes the AMI as an
+argument, since it is required by the `EC2Instance` resource type. Then, the
+optional EC2 key name is specified using the `&` and `?~` lens operators.
+
+This approach is very similar to the approach taken by the `amazonka` library.
+See this
+[blog post](http://brendanhay.nz/amazonka-comprehensive-haskell-aws-client#smart-constructors)
+for an explanation.
+
+## Auto-generation
+
+All of the resources and resource properties are auto-generated from JSON files
+and are placed in `library-gen/`. The `gen/` directory contains the
+auto-generator code and the JSON model files. We include the `library-gen/`
+directory in git so the build process is simplified. To build `library-gen`
+from scratch and then build all of `stratosphere`, just run the very short
+`build.sh` script. You can pass stack args to the script too, so run
+`./build.sh --fast` to build the library without optimization. This is useful
+for development.
+
+In the future, it would be great to not have to include the auto-generated code
+in git.
+
+Also, there is a file called `scraper.py` that scrapes a given CloudFormation
+resource documentation page to produce the JSON model. It isn't perfect, but it
+helps a lot.
+
+## Contributing
+
+Feel free to raise any issues, or even just make suggestions, by filing a
+Github issue.
+
+## Future Work
+
+The library is usable in its current state and it is already much more
+enjoyable to work with than writing JSON templates by hand, but there are of
+course a few possible future improvements:
+
+* Not all resources implemented. Adding resources is very easy though. Just
+  request them and I will implement them :)
+* Implement basic checker for things like undefined Refs and duplicate field
+  names. This stuff would be too unwieldy to do in types, and performing a
+  checking pass over a template should be pretty straightforward.
+* Use a custom JSON encoder so the templates look a little more idiomatic. We
+  also create a lot of empty whitespace and newlines using aeson-pretty. There
+  are limits on the size of CloudFormation templates, and we want readable
+  output without hitting the limits. Also, we have some newtypes that just
+  exist to override aeson instances, and we could get rid of those.
+* Use a custom JSON decoder with useful error messages. Although we don't use
+  them, we have implemented FromJSON instances for everything. Theoretically,
+  stratosphere could be used as a checker/linter for existing JSON
+  CloudFormation templates.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,4 @@
+import qualified Distribution.Simple
+
+main :: IO ()
+main = Distribution.Simple.defaultMain
diff --git a/examples/ec2-with-eip.hs b/examples/ec2-with-eip.hs
new file mode 100644
--- /dev/null
+++ b/examples/ec2-with-eip.hs
@@ -0,0 +1,89 @@
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | This is a translated version of an example from the CloudFormation docs at
+-- https://s3.amazonaws.com/cloudformation-templates-us-east-1/EIP_With_Association.template.
+-- The difference is the mappings are removed because they don't add anything
+-- to the exposition of stratosphere.
+
+module Main where
+
+import Control.Lens
+import qualified Data.ByteString.Lazy.Char8 as B
+
+import Stratosphere
+
+main :: IO ()
+main = B.putStrLn $ encodeTemplate myTemplate
+
+myTemplate :: Template
+myTemplate =
+  template
+  [ resource "EC2Instance" (
+      EC2InstanceProperties $
+      ec2Instance
+      "ami-22111148"
+      & eciInstanceType ?~ toRef instanceTypeParam
+      & eciKeyName ?~ toRef keyParam
+      & eciUserData ?~ Base64 (Join "" ["IPAddress=", toRef sshParam])
+      & eciSecurityGroups ?~ [Ref "InstanceSecuritygroup"]
+      )
+    & deletionPolicy ?~ Retain
+  , resource "InstanceSecurityGroup" $
+    SecurityGroupProperties $
+    securityGroup
+    "Enable SSH Access"
+    & sgSecurityGroupIngress ?~ [
+      securityGroupIngressRule
+      "tcp"
+      & sgirFromPort ?~ Literal 22
+      & sgirToPort ?~ Literal 22
+      & sgirCidrIp ?~ Ref "SSHLocation"
+      ]
+  , resource "IPAddress" (EIPProperties eip)
+  , resource "IPAssoc" $
+    EIPAssociationProperties $
+    eipAssociation
+    & eipaInstanceId ?~ Ref "EC2Instance"
+    & eipaEIP ?~ Ref "IPAddress"
+  ]
+  & description ?~ "See https://s3.amazonaws.com/cloudformation-templates-us-east-1/EIP_With_Association.template"
+  & formatVersion ?~ "2010-09-09"
+  & parameters ?~
+  [ instanceTypeParam
+  , keyParam
+  , sshParam
+  ]
+  & outputs ?~
+  [ output "InstanceId"
+    (Ref "EC2Instance")
+    & description ?~ "InstanceId of the newly created EC2 instance"
+  , output "InstanceIPAddress"
+    (Ref "IPAddress")
+    & description ?~ "IP address of the newly created EC2 instance"
+  ]
+
+instanceTypeParam :: Parameter
+instanceTypeParam =
+  parameter "InstanceType" "String"
+  & description ?~ "WebServer EC2 instance type"
+  & default' ?~ "t2.small"
+  & allowedValues ?~ [ "t1.micro", "t2.small" ]
+  & constraintDescription ?~ "must be a valid EC2 instance type."
+
+keyParam :: Parameter
+keyParam =
+  parameter "KeyName" "AWS::EC2::KeyPair::KeyName"
+  & description ?~ "Name of an existing EC2 KeyPair to enable SSH access to the instances"
+  & constraintDescription ?~ "must be the name of an existing EC2 KeyPair."
+
+sshParam :: Parameter
+sshParam =
+  parameter "SSHLocation" "String"
+  & description ?~ "The IP address range that can be used to SSH to the EC2 instances"
+  & minLength ?~ 9
+  & maxLength ?~ 18
+  & default' ?~ "0.0.0.0/0"
+  & allowedValues ?~ [ "t1.micro", "t2.small" ]
+  & allowedPattern ?~ "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
+  & constraintDescription ?~ "must be a valid IP CIDR range of the form x.x.x.x/x."
diff --git a/examples/rds-master-replica.hs b/examples/rds-master-replica.hs
new file mode 100644
--- /dev/null
+++ b/examples/rds-master-replica.hs
@@ -0,0 +1,91 @@
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | This example creates a Postgres RDS master and slave with a parameter
+-- group. Also note the DeletionPolicy of Retain, which will keep the resource
+-- alive if you delete the stack.
+
+module Main where
+
+import Control.Lens
+import Data.Aeson (object)
+import qualified Data.ByteString.Lazy.Char8 as B
+
+import Stratosphere
+
+main :: IO ()
+main = B.putStrLn $ encodeTemplate dbTemplate
+
+dbTemplate :: Template
+dbTemplate =
+  template
+  [ rdsParamGroup & deletionPolicy ?~ Retain
+  , rdsMaster & deletionPolicy ?~ Retain
+  , rdsReplica & deletionPolicy ?~ Retain
+  ]
+  & description ?~ "Stack for and RDS master and replica"
+  & parameters ?~
+  [ parameter "RdsMasterPassword" "String"
+  , parameter "RdsSubnetGroup" "String"
+  , parameter "VpcId" "String"
+  ]
+
+rdsMaster :: Resource
+rdsMaster =
+  resource "RDSMaster" $
+  DBInstanceProperties $
+  dbInstance
+  "db.t2.micro"
+  & dbiDBInstanceIdentifier ?~ Literal "db-master"
+  & dbiStorageType ?~ "gp2"
+  & dbiAllocatedStorage ?~ "20"
+  & dbiDBParameterGroupName ?~ toRef rdsParamGroup
+  & dbiEngine ?~ "postgres"
+  & dbiEngineVersion ?~ "9.3.10"
+  & dbiMasterUsername ?~ "postgres"
+  & dbiMasterUserPassword ?~ Ref "RdsMasterPassword"
+  & dbiDBName ?~ "the_database"
+  & dbiPreferredMaintenanceWindow ?~ "Sun:01:00-Sun:02:00"
+  & dbiBackupRetentionPeriod ?~ "30"
+  & dbiPreferredBackupWindow ?~ "08:00-09:00"
+  & dbiPort ?~ "5432"
+  & dbiBackupRetentionPeriod ?~ "2"
+  & dbiTags ?~
+  [ resourceTag "Role" "rds-master"
+  ]
+
+rdsReplica :: Resource
+rdsReplica =
+  resource "RDSReplica" $
+  DBInstanceProperties $
+  dbInstance
+  "db.t2.micro"
+  & dbiDBInstanceIdentifier ?~ Literal "db-standby"
+  & dbiSourceDBInstanceIdentifier ?~ toRef rdsMaster
+  & dbiStorageType ?~ "gp2"
+  & dbiTags ?~
+  [ resourceTag "Role" "rds-standby"
+  ]
+
+rdsParamGroup :: Resource
+rdsParamGroup =
+  resource "RDSParamGroup" $
+  DBParameterGroupProperties $
+  dbParameterGroup
+  "Parameter group for RDS instances"
+  "postgres9.3"
+  & dbpgParameters ?~
+    object
+    [ ("checkpoint_segments", "32")
+    , ("effective_cache_size", "5584716")
+    , ("hot_standby_feedback", "1")
+    , ("log_connections", "1")
+    , ("log_disconnections", "1")
+    , ("log_min_duration_statement", "0")
+    , ("maintenance_work_mem", "2000000")
+    , ("max_connections", "100")
+    , ("max_standby_archive_delay", "3600000")
+    , ("max_standby_streaming_delay", "3600000")
+    , ("wal_buffers", "2000")
+    , ("work_mem", "400000")
+    ]
diff --git a/library-gen/Stratosphere/ResourceProperties/AccessLoggingPolicy.hs b/library-gen/Stratosphere/ResourceProperties/AccessLoggingPolicy.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/AccessLoggingPolicy.hs
@@ -0,0 +1,65 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AccessLoggingPolicy property describes where and how access logs are
+-- stored for the AWS::ElasticLoadBalancing::LoadBalancer resource.
+
+module Stratosphere.ResourceProperties.AccessLoggingPolicy where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for AccessLoggingPolicy. See
+-- 'accessLoggingPolicy' for a more convenient constructor.
+data AccessLoggingPolicy =
+  AccessLoggingPolicy
+  { _accessLoggingPolicyEmitInterval :: Maybe (Val Integer')
+  , _accessLoggingPolicyEnabled :: Val Bool'
+  , _accessLoggingPolicyS3BucketName :: Val Text
+  , _accessLoggingPolicyS3BucketPrefix :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON AccessLoggingPolicy where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 20, omitNothingFields = True }
+
+instance FromJSON AccessLoggingPolicy where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 20, omitNothingFields = True }
+
+-- | Constructor for 'AccessLoggingPolicy' containing required fields as
+-- arguments.
+accessLoggingPolicy
+  :: Val Bool' -- ^ 'alpEnabled'
+  -> Val Text -- ^ 'alpS3BucketName'
+  -> AccessLoggingPolicy
+accessLoggingPolicy enabledarg s3BucketNamearg =
+  AccessLoggingPolicy
+  { _accessLoggingPolicyEmitInterval = Nothing
+  , _accessLoggingPolicyEnabled = enabledarg
+  , _accessLoggingPolicyS3BucketName = s3BucketNamearg
+  , _accessLoggingPolicyS3BucketPrefix = Nothing
+  }
+
+-- | The interval for publishing access logs in minutes. You can specify an
+-- interval of either 5 minutes or 60 minutes.
+alpEmitInterval :: Lens' AccessLoggingPolicy (Maybe (Val Integer'))
+alpEmitInterval = lens _accessLoggingPolicyEmitInterval (\s a -> s { _accessLoggingPolicyEmitInterval = a })
+
+-- | Whether logging is enabled for the load balancer.
+alpEnabled :: Lens' AccessLoggingPolicy (Val Bool')
+alpEnabled = lens _accessLoggingPolicyEnabled (\s a -> s { _accessLoggingPolicyEnabled = a })
+
+-- | The name of an Amazon S3 bucket where access log files are stored.
+alpS3BucketName :: Lens' AccessLoggingPolicy (Val Text)
+alpS3BucketName = lens _accessLoggingPolicyS3BucketName (\s a -> s { _accessLoggingPolicyS3BucketName = a })
+
+-- | A prefix for the all log object keys, such as my-load-balancer-logs/prod.
+-- If you store log files from multiple sources in a single bucket, you can
+-- use a prefix to distinguish each log file and its source.
+alpS3BucketPrefix :: Lens' AccessLoggingPolicy (Maybe (Val Text))
+alpS3BucketPrefix = lens _accessLoggingPolicyS3BucketPrefix (\s a -> s { _accessLoggingPolicyS3BucketPrefix = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/AliasTarget.hs b/library-gen/Stratosphere/ResourceProperties/AliasTarget.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/AliasTarget.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | AliasTarget is a property of the AWS::Route53::RecordSet resource. For
+-- more information about alias resource record sets, see Creating Alias
+-- Resource Record Sets in the Amazon Route 53 Developer Guide.
+
+module Stratosphere.ResourceProperties.AliasTarget where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for AliasTarget. See 'aliasTarget' for a more
+-- convenient constructor.
+data AliasTarget =
+  AliasTarget
+  { _aliasTargetDNSName :: Val Text
+  , _aliasTargetEvaluateTargetHealth :: Maybe (Val Bool')
+  , _aliasTargetHostedZoneId :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON AliasTarget where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+instance FromJSON AliasTarget where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+-- | Constructor for 'AliasTarget' containing required fields as arguments.
+aliasTarget
+  :: Val Text -- ^ 'atDNSName'
+  -> Val Text -- ^ 'atHostedZoneId'
+  -> AliasTarget
+aliasTarget dNSNamearg hostedZoneIdarg =
+  AliasTarget
+  { _aliasTargetDNSName = dNSNamearg
+  , _aliasTargetEvaluateTargetHealth = Nothing
+  , _aliasTargetHostedZoneId = hostedZoneIdarg
+  }
+
+-- | The DNS name of the load balancer, the domain name of the CloudFront
+-- distribution, the website endpoint of the Amazon S3 bucket, or another
+-- record set in the same hosted zone that is the target of the alias. Type:
+-- String
+atDNSName :: Lens' AliasTarget (Val Text)
+atDNSName = lens _aliasTargetDNSName (\s a -> s { _aliasTargetDNSName = a })
+
+-- | Whether Amazon Route 53 checks the health of the resource record sets in
+-- the alias target when responding to DNS queries. For more information about
+-- using this property, see EvaluateTargetHealth in the Amazon Route 53 API
+-- Reference. Type: Boolean
+atEvaluateTargetHealth :: Lens' AliasTarget (Maybe (Val Bool'))
+atEvaluateTargetHealth = lens _aliasTargetEvaluateTargetHealth (\s a -> s { _aliasTargetEvaluateTargetHealth = a })
+
+-- | The hosted zone ID. For load balancers, use the canonical hosted zone ID
+-- of the load balancer. For Amazon S3, use the hosted zone ID for your
+-- bucket's website endpoint. For CloudFront, use Z2FDTNDATAQYW2. For
+-- examples, see Example: Creating Alias Resource Record Sets in the Amazon
+-- Route 53 API Reference. Type: String
+atHostedZoneId :: Lens' AliasTarget (Val Text)
+atHostedZoneId = lens _aliasTargetHostedZoneId (\s a -> s { _aliasTargetHostedZoneId = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/AppCookieStickinessPolicy.hs b/library-gen/Stratosphere/ResourceProperties/AppCookieStickinessPolicy.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/AppCookieStickinessPolicy.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AppCookieStickinessPolicy type is an embedded property of the
+-- AWS::ElasticLoadBalancing::LoadBalancer type.
+
+module Stratosphere.ResourceProperties.AppCookieStickinessPolicy where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for AppCookieStickinessPolicy. See
+-- 'appCookieStickinessPolicy' for a more convenient constructor.
+data AppCookieStickinessPolicy =
+  AppCookieStickinessPolicy
+  { _appCookieStickinessPolicyCookieName :: Val Text
+  , _appCookieStickinessPolicyPolicyName :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON AppCookieStickinessPolicy where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 26, omitNothingFields = True }
+
+instance FromJSON AppCookieStickinessPolicy where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 26, omitNothingFields = True }
+
+-- | Constructor for 'AppCookieStickinessPolicy' containing required fields as
+-- arguments.
+appCookieStickinessPolicy
+  :: Val Text -- ^ 'acspCookieName'
+  -> Val Text -- ^ 'acspPolicyName'
+  -> AppCookieStickinessPolicy
+appCookieStickinessPolicy cookieNamearg policyNamearg =
+  AppCookieStickinessPolicy
+  { _appCookieStickinessPolicyCookieName = cookieNamearg
+  , _appCookieStickinessPolicyPolicyName = policyNamearg
+  }
+
+-- | Name of the application cookie used for stickiness.
+acspCookieName :: Lens' AppCookieStickinessPolicy (Val Text)
+acspCookieName = lens _appCookieStickinessPolicyCookieName (\s a -> s { _appCookieStickinessPolicyCookieName = a })
+
+-- | The name of the policy being created. The name must be unique within the
+-- set of policies for this Load Balancer. Note To associate this policy with
+-- a listener, include the policy name in the listener's PolicyNames property.
+acspPolicyName :: Lens' AppCookieStickinessPolicy (Val Text)
+acspPolicyName = lens _appCookieStickinessPolicyPolicyName (\s a -> s { _appCookieStickinessPolicyPolicyName = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/ConnectionDrainingPolicy.hs b/library-gen/Stratosphere/ResourceProperties/ConnectionDrainingPolicy.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/ConnectionDrainingPolicy.hs
@@ -0,0 +1,58 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The ConnectionDrainingPolicy property describes how deregistered or
+-- unhealthy instances handle in-flight requests for the
+-- AWS::ElasticLoadBalancing::LoadBalancer resource. Connection draining
+-- ensures that the load balancer completes serving all in-flight requests
+-- made to a registered instance when the instance is deregistered or becomes
+-- unhealthy. Without connection draining, the load balancer closes
+-- connections to deregistered or unhealthy instances, and any in-flight
+-- requests are not completed. For more information about connection draining
+-- and default values, see Enable or Disable Connection Draining for Your Load
+-- Balancer in the Elastic Load Balancing Developer Guide.
+
+module Stratosphere.ResourceProperties.ConnectionDrainingPolicy where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for ConnectionDrainingPolicy. See
+-- 'connectionDrainingPolicy' for a more convenient constructor.
+data ConnectionDrainingPolicy =
+  ConnectionDrainingPolicy
+  { _connectionDrainingPolicyEnabled :: Val Bool'
+  , _connectionDrainingPolicyTimeout :: Maybe (Val Integer')
+  } deriving (Show, Generic)
+
+instance ToJSON ConnectionDrainingPolicy where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 25, omitNothingFields = True }
+
+instance FromJSON ConnectionDrainingPolicy where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 25, omitNothingFields = True }
+
+-- | Constructor for 'ConnectionDrainingPolicy' containing required fields as
+-- arguments.
+connectionDrainingPolicy
+  :: Val Bool' -- ^ 'cdpEnabled'
+  -> ConnectionDrainingPolicy
+connectionDrainingPolicy enabledarg =
+  ConnectionDrainingPolicy
+  { _connectionDrainingPolicyEnabled = enabledarg
+  , _connectionDrainingPolicyTimeout = Nothing
+  }
+
+-- | Whether or not connection draining is enabled for the load balancer.
+cdpEnabled :: Lens' ConnectionDrainingPolicy (Val Bool')
+cdpEnabled = lens _connectionDrainingPolicyEnabled (\s a -> s { _connectionDrainingPolicyEnabled = a })
+
+-- | The time in seconds after the load balancer closes all connections to a
+-- deregistered or unhealthy instance.
+cdpTimeout :: Lens' ConnectionDrainingPolicy (Maybe (Val Integer'))
+cdpTimeout = lens _connectionDrainingPolicyTimeout (\s a -> s { _connectionDrainingPolicyTimeout = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/ConnectionSettings.hs b/library-gen/Stratosphere/ResourceProperties/ConnectionSettings.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/ConnectionSettings.hs
@@ -0,0 +1,48 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | ConnectionSettings is a property of the
+-- AWS::ElasticLoadBalancing::LoadBalancer resource that describes how long
+-- the front-end and back-end connections of your load balancer can remain
+-- idle. For more information, see Configure Idle Connection Timeout in the
+-- Elastic Load Balancing Developer Guide.
+
+module Stratosphere.ResourceProperties.ConnectionSettings where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for ConnectionSettings. See
+-- 'connectionSettings' for a more convenient constructor.
+data ConnectionSettings =
+  ConnectionSettings
+  { _connectionSettingsIdleTimeout :: Val Integer'
+  } deriving (Show, Generic)
+
+instance ToJSON ConnectionSettings where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 19, omitNothingFields = True }
+
+instance FromJSON ConnectionSettings where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 19, omitNothingFields = True }
+
+-- | Constructor for 'ConnectionSettings' containing required fields as
+-- arguments.
+connectionSettings
+  :: Val Integer' -- ^ 'csIdleTimeout'
+  -> ConnectionSettings
+connectionSettings idleTimeoutarg =
+  ConnectionSettings
+  { _connectionSettingsIdleTimeout = idleTimeoutarg
+  }
+
+-- | The time (in seconds) that a connection to the load balancer can remain
+-- idle, which means no data is sent over the connection. After the specified
+-- time, the load balancer closes the connection.
+csIdleTimeout :: Lens' ConnectionSettings (Val Integer')
+csIdleTimeout = lens _connectionSettingsIdleTimeout (\s a -> s { _connectionSettingsIdleTimeout = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/EBSBlockDevice.hs b/library-gen/Stratosphere/ResourceProperties/EBSBlockDevice.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/EBSBlockDevice.hs
@@ -0,0 +1,83 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The Amazon Elastic Block Store block device type is an embedded property
+-- of the Amazon EC2 Block Device Mapping Property property.
+
+module Stratosphere.ResourceProperties.EBSBlockDevice where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for EBSBlockDevice. See 'ebsBlockDevice' for a
+-- more convenient constructor.
+data EBSBlockDevice =
+  EBSBlockDevice
+  { _eBSBlockDeviceDeleteOnTermination :: Maybe (Val Bool')
+  , _eBSBlockDeviceEncrypted :: Maybe (Val Bool')
+  , _eBSBlockDeviceIops :: Maybe (Val Integer')
+  , _eBSBlockDeviceSnapshotId :: Maybe (Val Text)
+  , _eBSBlockDeviceVolumeSize :: Maybe (Val Text)
+  , _eBSBlockDeviceVolumeType :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON EBSBlockDevice where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 15, omitNothingFields = True }
+
+instance FromJSON EBSBlockDevice where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 15, omitNothingFields = True }
+
+-- | Constructor for 'EBSBlockDevice' containing required fields as arguments.
+ebsBlockDevice
+  :: EBSBlockDevice
+ebsBlockDevice  =
+  EBSBlockDevice
+  { _eBSBlockDeviceDeleteOnTermination = Nothing
+  , _eBSBlockDeviceEncrypted = Nothing
+  , _eBSBlockDeviceIops = Nothing
+  , _eBSBlockDeviceSnapshotId = Nothing
+  , _eBSBlockDeviceVolumeSize = Nothing
+  , _eBSBlockDeviceVolumeType = Nothing
+  }
+
+-- | Determines whether to delete the volume on instance termination. The
+-- default value is true.
+ebsbdDeleteOnTermination :: Lens' EBSBlockDevice (Maybe (Val Bool'))
+ebsbdDeleteOnTermination = lens _eBSBlockDeviceDeleteOnTermination (\s a -> s { _eBSBlockDeviceDeleteOnTermination = a })
+
+-- | Indicates whether the volume is encrypted. Encrypted Amazon EBS volumes
+-- can only be attached to instance types that support Amazon EBS encryption.
+-- Volumes that are created from encrypted snapshots are automatically
+-- encrypted. You cannot create an encrypted volume from an unencrypted
+-- snapshot or vice versa. If your AMI uses encrypted volumes, you can only
+-- launch the AMI on supported instance types. For more information, see
+-- Amazon EBS encryption in the Amazon EC2 User Guide for Linux Instances.
+ebsbdEncrypted :: Lens' EBSBlockDevice (Maybe (Val Bool'))
+ebsbdEncrypted = lens _eBSBlockDeviceEncrypted (\s a -> s { _eBSBlockDeviceEncrypted = a })
+
+-- | The number of I/O operations per second (IOPS) that the volume supports.
+-- This can be an integer from 100 - 2000.
+ebsbdIops :: Lens' EBSBlockDevice (Maybe (Val Integer'))
+ebsbdIops = lens _eBSBlockDeviceIops (\s a -> s { _eBSBlockDeviceIops = a })
+
+-- | The snapshot ID of the volume to use to create a block device.
+ebsbdSnapshotId :: Lens' EBSBlockDevice (Maybe (Val Text))
+ebsbdSnapshotId = lens _eBSBlockDeviceSnapshotId (\s a -> s { _eBSBlockDeviceSnapshotId = a })
+
+-- | The volume size, in gibibytes (GiB). This can be a number from 1 – 1024.
+-- If the volume type is io1, the minimum value is 10.
+ebsbdVolumeSize :: Lens' EBSBlockDevice (Maybe (Val Text))
+ebsbdVolumeSize = lens _eBSBlockDeviceVolumeSize (\s a -> s { _eBSBlockDeviceVolumeSize = a })
+
+-- | The volume type. You can specify standard, io1, or gp2. If you set the
+-- type to io1, you must also set the Iops property. For more information
+-- about these values and the default value, see CreateVolume in the Amazon
+-- EC2 API Reference.
+ebsbdVolumeType :: Lens' EBSBlockDevice (Maybe (Val Text))
+ebsbdVolumeType = lens _eBSBlockDeviceVolumeType (\s a -> s { _eBSBlockDeviceVolumeType = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/EC2BlockDeviceMapping.hs b/library-gen/Stratosphere/ResourceProperties/EC2BlockDeviceMapping.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/EC2BlockDeviceMapping.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The Amazon EC2 block device mapping property is an embedded property of
+-- the AWS::EC2::Instance resource. For block device mappings for an Auto
+-- Scaling launch configuration, see AutoScaling Block Device Mapping.
+
+module Stratosphere.ResourceProperties.EC2BlockDeviceMapping where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.EBSBlockDevice
+
+-- | Full data type definition for EC2BlockDeviceMapping. See
+-- 'ec2BlockDeviceMapping' for a more convenient constructor.
+data EC2BlockDeviceMapping =
+  EC2BlockDeviceMapping
+  { _eC2BlockDeviceMappingDeviceName :: Val Text
+  , _eC2BlockDeviceMappingEbs :: Maybe EBSBlockDevice
+  , _eC2BlockDeviceMappingNoDevice :: Maybe ()
+  , _eC2BlockDeviceMappingVirtualName :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON EC2BlockDeviceMapping where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 22, omitNothingFields = True }
+
+instance FromJSON EC2BlockDeviceMapping where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 22, omitNothingFields = True }
+
+-- | Constructor for 'EC2BlockDeviceMapping' containing required fields as
+-- arguments.
+ec2BlockDeviceMapping
+  :: Val Text -- ^ 'ecbdmDeviceName'
+  -> EC2BlockDeviceMapping
+ec2BlockDeviceMapping deviceNamearg =
+  EC2BlockDeviceMapping
+  { _eC2BlockDeviceMappingDeviceName = deviceNamearg
+  , _eC2BlockDeviceMappingEbs = Nothing
+  , _eC2BlockDeviceMappingNoDevice = Nothing
+  , _eC2BlockDeviceMappingVirtualName = Nothing
+  }
+
+-- | The name of the device within Amazon EC2.
+ecbdmDeviceName :: Lens' EC2BlockDeviceMapping (Val Text)
+ecbdmDeviceName = lens _eC2BlockDeviceMappingDeviceName (\s a -> s { _eC2BlockDeviceMappingDeviceName = a })
+
+-- |
+ecbdmEbs :: Lens' EC2BlockDeviceMapping (Maybe EBSBlockDevice)
+ecbdmEbs = lens _eC2BlockDeviceMappingEbs (\s a -> s { _eC2BlockDeviceMappingEbs = a })
+
+-- | This property can be used to unmap a defined device.
+ecbdmNoDevice :: Lens' EC2BlockDeviceMapping (Maybe ())
+ecbdmNoDevice = lens _eC2BlockDeviceMappingNoDevice (\s a -> s { _eC2BlockDeviceMappingNoDevice = a })
+
+-- | The name of the virtual device. The name must be in the form ephemeralX
+-- where X is a number starting from zero (0); for example, ephemeral0.
+ecbdmVirtualName :: Lens' EC2BlockDeviceMapping (Maybe (Val Text))
+ecbdmVirtualName = lens _eC2BlockDeviceMappingVirtualName (\s a -> s { _eC2BlockDeviceMappingVirtualName = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/EC2MountPoint.hs b/library-gen/Stratosphere/ResourceProperties/EC2MountPoint.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/EC2MountPoint.hs
@@ -0,0 +1,50 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The EC2 MountPoint property is an embedded property of the
+-- AWS::EC2::Instance type.
+
+module Stratosphere.ResourceProperties.EC2MountPoint where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for EC2MountPoint. See 'ec2MountPoint' for a
+-- more convenient constructor.
+data EC2MountPoint =
+  EC2MountPoint
+  { _eC2MountPointDevice :: Val Text
+  , _eC2MountPointVolumeId :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON EC2MountPoint where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 14, omitNothingFields = True }
+
+instance FromJSON EC2MountPoint where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 14, omitNothingFields = True }
+
+-- | Constructor for 'EC2MountPoint' containing required fields as arguments.
+ec2MountPoint
+  :: Val Text -- ^ 'ecmpDevice'
+  -> Val Text -- ^ 'ecmpVolumeId'
+  -> EC2MountPoint
+ec2MountPoint devicearg volumeIdarg =
+  EC2MountPoint
+  { _eC2MountPointDevice = devicearg
+  , _eC2MountPointVolumeId = volumeIdarg
+  }
+
+-- | How the device is exposed to the instance (such as /dev/sdh, or xvdh).
+ecmpDevice :: Lens' EC2MountPoint (Val Text)
+ecmpDevice = lens _eC2MountPointDevice (\s a -> s { _eC2MountPointDevice = a })
+
+-- | The ID of the Amazon EBS volume. The volume and instance must be within
+-- the same Availability Zone and the instance must be running.
+ecmpVolumeId :: Lens' EC2MountPoint (Val Text)
+ecmpVolumeId = lens _eC2MountPointVolumeId (\s a -> s { _eC2MountPointVolumeId = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/EC2SsmAssociationParameters.hs b/library-gen/Stratosphere/ResourceProperties/EC2SsmAssociationParameters.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/EC2SsmAssociationParameters.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | AssociationParameters is a property of the Amazon EC2 Instance
+-- SsmAssociations property that specifies input parameter values for an
+-- Amazon EC2 Simple Systems Manager (SSM) document.
+
+module Stratosphere.ResourceProperties.EC2SsmAssociationParameters where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for EC2SsmAssociationParameters. See
+-- 'ec2SsmAssociationParameters' for a more convenient constructor.
+data EC2SsmAssociationParameters =
+  EC2SsmAssociationParameters
+  { _eC2SsmAssociationParametersKey :: Val Text
+  , _eC2SsmAssociationParametersValue :: [Val Text]
+  } deriving (Show, Generic)
+
+instance ToJSON EC2SsmAssociationParameters where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 28, omitNothingFields = True }
+
+instance FromJSON EC2SsmAssociationParameters where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 28, omitNothingFields = True }
+
+-- | Constructor for 'EC2SsmAssociationParameters' containing required fields
+-- as arguments.
+ec2SsmAssociationParameters
+  :: Val Text -- ^ 'ecsapKey'
+  -> [Val Text] -- ^ 'ecsapValue'
+  -> EC2SsmAssociationParameters
+ec2SsmAssociationParameters keyarg valuearg =
+  EC2SsmAssociationParameters
+  { _eC2SsmAssociationParametersKey = keyarg
+  , _eC2SsmAssociationParametersValue = valuearg
+  }
+
+-- | The name of an input parameter that is in the associated SSM document.
+ecsapKey :: Lens' EC2SsmAssociationParameters (Val Text)
+ecsapKey = lens _eC2SsmAssociationParametersKey (\s a -> s { _eC2SsmAssociationParametersKey = a })
+
+-- | The value of an input parameter.
+ecsapValue :: Lens' EC2SsmAssociationParameters [Val Text]
+ecsapValue = lens _eC2SsmAssociationParametersValue (\s a -> s { _eC2SsmAssociationParametersValue = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/EC2SsmAssociations.hs b/library-gen/Stratosphere/ResourceProperties/EC2SsmAssociations.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/EC2SsmAssociations.hs
@@ -0,0 +1,50 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | SsmAssociations is a property of the AWS::EC2::Instance resource that
+-- specifies the Amazon EC2 Simple Systems Manager (SSM) document and
+-- parameter values to associate with an instance.
+
+module Stratosphere.ResourceProperties.EC2SsmAssociations where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.EC2SsmAssociationParameters
+
+-- | Full data type definition for EC2SsmAssociations. See
+-- 'ec2SsmAssociations' for a more convenient constructor.
+data EC2SsmAssociations =
+  EC2SsmAssociations
+  { _eC2SsmAssociationsAssociationParameters :: Maybe [EC2SsmAssociationParameters]
+  , _eC2SsmAssociationsDocumentName :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON EC2SsmAssociations where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 19, omitNothingFields = True }
+
+instance FromJSON EC2SsmAssociations where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 19, omitNothingFields = True }
+
+-- | Constructor for 'EC2SsmAssociations' containing required fields as
+-- arguments.
+ec2SsmAssociations
+  :: Val Text -- ^ 'ecsaDocumentName'
+  -> EC2SsmAssociations
+ec2SsmAssociations documentNamearg =
+  EC2SsmAssociations
+  { _eC2SsmAssociationsAssociationParameters = Nothing
+  , _eC2SsmAssociationsDocumentName = documentNamearg
+  }
+
+-- | The input parameter values to use with the associated SSM document.
+ecsaAssociationParameters :: Lens' EC2SsmAssociations (Maybe [EC2SsmAssociationParameters])
+ecsaAssociationParameters = lens _eC2SsmAssociationsAssociationParameters (\s a -> s { _eC2SsmAssociationsAssociationParameters = a })
+
+-- | The name of an SSM document to associate with the instance.
+ecsaDocumentName :: Lens' EC2SsmAssociations (Val Text)
+ecsaDocumentName = lens _eC2SsmAssociationsDocumentName (\s a -> s { _eC2SsmAssociationsDocumentName = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/ELBPolicy.hs b/library-gen/Stratosphere/ResourceProperties/ELBPolicy.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/ELBPolicy.hs
@@ -0,0 +1,74 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The ElasticLoadBalancing policy type is an embedded property of the
+-- AWS::ElasticLoadBalancing::LoadBalancer resource. You associate policies
+-- with a listener by referencing a policy's name in the listener's
+-- PolicyNames property.
+
+module Stratosphere.ResourceProperties.ELBPolicy where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for ELBPolicy. See 'elbPolicy' for a more
+-- convenient constructor.
+data ELBPolicy =
+  ELBPolicy
+  { _eLBPolicyAttributes :: Object
+  , _eLBPolicyInstancePorts :: Maybe [Val Text]
+  , _eLBPolicyLoadBalancerPorts :: Maybe [Val Text]
+  , _eLBPolicyPolicyName :: Val Text
+  , _eLBPolicyPolicyType :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON ELBPolicy where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 10, omitNothingFields = True }
+
+instance FromJSON ELBPolicy where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 10, omitNothingFields = True }
+
+-- | Constructor for 'ELBPolicy' containing required fields as arguments.
+elbPolicy
+  :: Object -- ^ 'elbpAttributes'
+  -> Val Text -- ^ 'elbpPolicyName'
+  -> Val Text -- ^ 'elbpPolicyType'
+  -> ELBPolicy
+elbPolicy attributesarg policyNamearg policyTypearg =
+  ELBPolicy
+  { _eLBPolicyAttributes = attributesarg
+  , _eLBPolicyInstancePorts = Nothing
+  , _eLBPolicyLoadBalancerPorts = Nothing
+  , _eLBPolicyPolicyName = policyNamearg
+  , _eLBPolicyPolicyType = policyTypearg
+  }
+
+-- | A list of arbitrary attributes for this policy. If you don't need to
+-- specify any policy attributes, specify an empty list ([]).
+elbpAttributes :: Lens' ELBPolicy Object
+elbpAttributes = lens _eLBPolicyAttributes (\s a -> s { _eLBPolicyAttributes = a })
+
+-- | A list of instance ports for the policy. These are the ports associated
+-- with the back-end server.
+elbpInstancePorts :: Lens' ELBPolicy (Maybe [Val Text])
+elbpInstancePorts = lens _eLBPolicyInstancePorts (\s a -> s { _eLBPolicyInstancePorts = a })
+
+-- | A list of external load balancer ports for the policy.
+elbpLoadBalancerPorts :: Lens' ELBPolicy (Maybe [Val Text])
+elbpLoadBalancerPorts = lens _eLBPolicyLoadBalancerPorts (\s a -> s { _eLBPolicyLoadBalancerPorts = a })
+
+-- | A name for this policy that is unique to the load balancer.
+elbpPolicyName :: Lens' ELBPolicy (Val Text)
+elbpPolicyName = lens _eLBPolicyPolicyName (\s a -> s { _eLBPolicyPolicyName = a })
+
+-- | The name of the policy type for this policy. This must be one of the
+-- types reported by the Elastic Load Balancing
+-- DescribeLoadBalancerPolicyTypes action.
+elbpPolicyType :: Lens' ELBPolicy (Val Text)
+elbpPolicyType = lens _eLBPolicyPolicyType (\s a -> s { _eLBPolicyPolicyType = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/HealthCheck.hs b/library-gen/Stratosphere/ResourceProperties/HealthCheck.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/HealthCheck.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The ElasticLoadBalancing HealthCheck is an embedded property of the
+-- AWS::ElasticLoadBalancing::LoadBalancer type.
+
+module Stratosphere.ResourceProperties.HealthCheck where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for HealthCheck. See 'healthCheck' for a more
+-- convenient constructor.
+data HealthCheck =
+  HealthCheck
+  { _healthCheckHealthyThreshold :: Val Text
+  , _healthCheckInterval :: Val Text
+  , _healthCheckTarget :: Val Text
+  , _healthCheckTimeout :: Val Text
+  , _healthCheckUnhealthyThreshold :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON HealthCheck where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+instance FromJSON HealthCheck where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+-- | Constructor for 'HealthCheck' containing required fields as arguments.
+healthCheck
+  :: Val Text -- ^ 'hcHealthyThreshold'
+  -> Val Text -- ^ 'hcInterval'
+  -> Val Text -- ^ 'hcTarget'
+  -> Val Text -- ^ 'hcTimeout'
+  -> Val Text -- ^ 'hcUnhealthyThreshold'
+  -> HealthCheck
+healthCheck healthyThresholdarg intervalarg targetarg timeoutarg unhealthyThresholdarg =
+  HealthCheck
+  { _healthCheckHealthyThreshold = healthyThresholdarg
+  , _healthCheckInterval = intervalarg
+  , _healthCheckTarget = targetarg
+  , _healthCheckTimeout = timeoutarg
+  , _healthCheckUnhealthyThreshold = unhealthyThresholdarg
+  }
+
+-- | Specifies the number of consecutive health probe successes required
+-- before moving the instance to the Healthy state.
+hcHealthyThreshold :: Lens' HealthCheck (Val Text)
+hcHealthyThreshold = lens _healthCheckHealthyThreshold (\s a -> s { _healthCheckHealthyThreshold = a })
+
+-- | Specifies the approximate interval, in seconds, between health checks of
+-- an individual instance.
+hcInterval :: Lens' HealthCheck (Val Text)
+hcInterval = lens _healthCheckInterval (\s a -> s { _healthCheckInterval = a })
+
+-- | Specifies the instance's protocol and port to check. The protocol can be
+-- TCP, HTTP, HTTPS, or SSL. The range of valid ports is 1 through 65535.
+hcTarget :: Lens' HealthCheck (Val Text)
+hcTarget = lens _healthCheckTarget (\s a -> s { _healthCheckTarget = a })
+
+-- | Specifies the amount of time, in seconds, during which no response means
+-- a failed health probe. This value must be less than the value for Interval.
+hcTimeout :: Lens' HealthCheck (Val Text)
+hcTimeout = lens _healthCheckTimeout (\s a -> s { _healthCheckTimeout = a })
+
+-- | Specifies the number of consecutive health probe failures required before
+-- moving the instance to the Unhealthy state.
+hcUnhealthyThreshold :: Lens' HealthCheck (Val Text)
+hcUnhealthyThreshold = lens _healthCheckUnhealthyThreshold (\s a -> s { _healthCheckUnhealthyThreshold = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/IAMPolicies.hs b/library-gen/Stratosphere/ResourceProperties/IAMPolicies.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/IAMPolicies.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Policies is a property of the AWS::IAM::Role, AWS::IAM::Group, and
+-- AWS::IAM::User resources. The Policies property describes what actions are
+-- allowed on what resources. For more information about IAM policies, see
+-- Overview of Policies in IAM User Guide.
+
+module Stratosphere.ResourceProperties.IAMPolicies where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for IAMPolicies. See 'iamPolicies' for a more
+-- convenient constructor.
+data IAMPolicies =
+  IAMPolicies
+  { _iAMPoliciesPolicyDocument :: Object
+  , _iAMPoliciesPolicyName :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON IAMPolicies where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+instance FromJSON IAMPolicies where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+-- | Constructor for 'IAMPolicies' containing required fields as arguments.
+iamPolicies
+  :: Object -- ^ 'iampPolicyDocument'
+  -> Val Text -- ^ 'iampPolicyName'
+  -> IAMPolicies
+iamPolicies policyDocumentarg policyNamearg =
+  IAMPolicies
+  { _iAMPoliciesPolicyDocument = policyDocumentarg
+  , _iAMPoliciesPolicyName = policyNamearg
+  }
+
+-- | A policy document that describes what actions are allowed on which
+-- resources.
+iampPolicyDocument :: Lens' IAMPolicies Object
+iampPolicyDocument = lens _iAMPoliciesPolicyDocument (\s a -> s { _iAMPoliciesPolicyDocument = a })
+
+-- | The name of the policy.
+iampPolicyName :: Lens' IAMPolicies (Val Text)
+iampPolicyName = lens _iAMPoliciesPolicyName (\s a -> s { _iAMPoliciesPolicyName = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/LBCookieStickinessPolicy.hs b/library-gen/Stratosphere/ResourceProperties/LBCookieStickinessPolicy.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/LBCookieStickinessPolicy.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The LBCookieStickinessPolicy type is an embedded property of the
+-- AWS::ElasticLoadBalancing::LoadBalancer type.
+
+module Stratosphere.ResourceProperties.LBCookieStickinessPolicy where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for LBCookieStickinessPolicy. See
+-- 'lbCookieStickinessPolicy' for a more convenient constructor.
+data LBCookieStickinessPolicy =
+  LBCookieStickinessPolicy
+  { _lBCookieStickinessPolicyCookieExpirationPeriod :: Maybe (Val Text)
+  , _lBCookieStickinessPolicyPolicyName :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON LBCookieStickinessPolicy where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 25, omitNothingFields = True }
+
+instance FromJSON LBCookieStickinessPolicy where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 25, omitNothingFields = True }
+
+-- | Constructor for 'LBCookieStickinessPolicy' containing required fields as
+-- arguments.
+lbCookieStickinessPolicy
+  :: Val Text -- ^ 'lbcspPolicyName'
+  -> LBCookieStickinessPolicy
+lbCookieStickinessPolicy policyNamearg =
+  LBCookieStickinessPolicy
+  { _lBCookieStickinessPolicyCookieExpirationPeriod = Nothing
+  , _lBCookieStickinessPolicyPolicyName = policyNamearg
+  }
+
+-- | The time period, in seconds, after which the cookie should be considered
+-- stale. If this parameter isn't specified, the sticky session will last for
+-- the duration of the browser session.
+lbcspCookieExpirationPeriod :: Lens' LBCookieStickinessPolicy (Maybe (Val Text))
+lbcspCookieExpirationPeriod = lens _lBCookieStickinessPolicyCookieExpirationPeriod (\s a -> s { _lBCookieStickinessPolicyCookieExpirationPeriod = a })
+
+-- | The name of the policy being created. The name must be unique within the
+-- set of policies for this load balancer. Note To associate this policy with
+-- a listener, include the policy name in the listener's PolicyNames property.
+lbcspPolicyName :: Lens' LBCookieStickinessPolicy (Val Text)
+lbcspPolicyName = lens _lBCookieStickinessPolicyPolicyName (\s a -> s { _lBCookieStickinessPolicyPolicyName = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/ListenerProperty.hs b/library-gen/Stratosphere/ResourceProperties/ListenerProperty.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/ListenerProperty.hs
@@ -0,0 +1,84 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The Listener property is an embedded property of the
+-- AWS::ElasticLoadBalancing::LoadBalancer type.
+
+module Stratosphere.ResourceProperties.ListenerProperty where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for ListenerProperty. See 'listenerProperty'
+-- for a more convenient constructor.
+data ListenerProperty =
+  ListenerProperty
+  { _listenerPropertyInstancePort :: Val Text
+  , _listenerPropertyInstanceProtocol :: Maybe (Val Text)
+  , _listenerPropertyLoadBalancerPort :: Val Text
+  , _listenerPropertyPolicyNames :: Maybe [Val Text]
+  , _listenerPropertyProtocol :: Val Text
+  , _listenerPropertySSLCertificateId :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON ListenerProperty where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 17, omitNothingFields = True }
+
+instance FromJSON ListenerProperty where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 17, omitNothingFields = True }
+
+-- | Constructor for 'ListenerProperty' containing required fields as
+-- arguments.
+listenerProperty
+  :: Val Text -- ^ 'lpInstancePort'
+  -> Val Text -- ^ 'lpLoadBalancerPort'
+  -> Val Text -- ^ 'lpProtocol'
+  -> ListenerProperty
+listenerProperty instancePortarg loadBalancerPortarg protocolarg =
+  ListenerProperty
+  { _listenerPropertyInstancePort = instancePortarg
+  , _listenerPropertyInstanceProtocol = Nothing
+  , _listenerPropertyLoadBalancerPort = loadBalancerPortarg
+  , _listenerPropertyPolicyNames = Nothing
+  , _listenerPropertyProtocol = protocolarg
+  , _listenerPropertySSLCertificateId = Nothing
+  }
+
+-- | Specifies the TCP port on which the instance server is listening. This
+-- property cannot be modified for the life of the load balancer.
+lpInstancePort :: Lens' ListenerProperty (Val Text)
+lpInstancePort = lens _listenerPropertyInstancePort (\s a -> s { _listenerPropertyInstancePort = a })
+
+-- | Specifies the protocol to use for routing traffic to back-end
+-- instances—HTTP, HTTPS, TCP, or SSL. This property cannot be modified for
+-- the life of the load balancer.
+lpInstanceProtocol :: Lens' ListenerProperty (Maybe (Val Text))
+lpInstanceProtocol = lens _listenerPropertyInstanceProtocol (\s a -> s { _listenerPropertyInstanceProtocol = a })
+
+-- | Specifies the external load balancer port number. This property cannot be
+-- modified for the life of the load balancer.
+lpLoadBalancerPort :: Lens' ListenerProperty (Val Text)
+lpLoadBalancerPort = lens _listenerPropertyLoadBalancerPort (\s a -> s { _listenerPropertyLoadBalancerPort = a })
+
+-- | A list of ElasticLoadBalancing policy names to associate with the
+-- listener.
+lpPolicyNames :: Lens' ListenerProperty (Maybe [Val Text])
+lpPolicyNames = lens _listenerPropertyPolicyNames (\s a -> s { _listenerPropertyPolicyNames = a })
+
+-- | Specifies the load balancer transport protocol to use for routing — HTTP,
+-- HTTPS, TCP or SSL. This property cannot be modified for the life of the
+-- load balancer.
+lpProtocol :: Lens' ListenerProperty (Val Text)
+lpProtocol = lens _listenerPropertyProtocol (\s a -> s { _listenerPropertyProtocol = a })
+
+-- | The ARN of the SSL certificate to use. For more information about SSL
+-- certificates, see Managing Server Certificates in the AWS Identity and
+-- Access Management documentation.
+lpSSLCertificateId :: Lens' ListenerProperty (Maybe (Val Text))
+lpSSLCertificateId = lens _listenerPropertySSLCertificateId (\s a -> s { _listenerPropertySSLCertificateId = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/NetworkInterface.hs b/library-gen/Stratosphere/ResourceProperties/NetworkInterface.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/NetworkInterface.hs
@@ -0,0 +1,117 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+
+
+module Stratosphere.ResourceProperties.NetworkInterface where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.PrivateIpAddressSpecification
+
+-- | Full data type definition for NetworkInterface. See 'networkInterface'
+-- for a more convenient constructor.
+data NetworkInterface =
+  NetworkInterface
+  { _networkInterfaceAssociatePublicIpAddress :: Maybe (Val Bool')
+  , _networkInterfaceDeleteOnTermination :: Maybe (Val Bool')
+  , _networkInterfaceDescription :: Maybe (Val Text)
+  , _networkInterfaceDeviceIndex :: Val Text
+  , _networkInterfaceGroupSet :: Maybe [Val Text]
+  , _networkInterfaceNetworkInterfaceId :: Maybe (Val Text)
+  , _networkInterfacePrivateIpAddress :: Maybe (Val Text)
+  , _networkInterfacePrivateIpAddresses :: Maybe [PrivateIpAddressSpecification]
+  , _networkInterfaceSecondaryPrivateIpAddressCount :: Maybe (Val Integer')
+  , _networkInterfaceSubnetId :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON NetworkInterface where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 17, omitNothingFields = True }
+
+instance FromJSON NetworkInterface where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 17, omitNothingFields = True }
+
+-- | Constructor for 'NetworkInterface' containing required fields as
+-- arguments.
+networkInterface
+  :: Val Text -- ^ 'niDeviceIndex'
+  -> NetworkInterface
+networkInterface deviceIndexarg =
+  NetworkInterface
+  { _networkInterfaceAssociatePublicIpAddress = Nothing
+  , _networkInterfaceDeleteOnTermination = Nothing
+  , _networkInterfaceDescription = Nothing
+  , _networkInterfaceDeviceIndex = deviceIndexarg
+  , _networkInterfaceGroupSet = Nothing
+  , _networkInterfaceNetworkInterfaceId = Nothing
+  , _networkInterfacePrivateIpAddress = Nothing
+  , _networkInterfacePrivateIpAddresses = Nothing
+  , _networkInterfaceSecondaryPrivateIpAddressCount = Nothing
+  , _networkInterfaceSubnetId = Nothing
+  }
+
+-- | Indicates whether the network interface receives a public IP address. You
+-- can associate a public IP address with a network interface only if it has a
+-- device index of eth0 and if it is a new network interface (not an existing
+-- one). In other words, if you specify true, don't specify a network
+-- interface ID. For more information, see Amazon EC2 Instance IP Addressing.
+niAssociatePublicIpAddress :: Lens' NetworkInterface (Maybe (Val Bool'))
+niAssociatePublicIpAddress = lens _networkInterfaceAssociatePublicIpAddress (\s a -> s { _networkInterfaceAssociatePublicIpAddress = a })
+
+-- | Whether to delete the network interface when the instance terminates.
+niDeleteOnTermination :: Lens' NetworkInterface (Maybe (Val Bool'))
+niDeleteOnTermination = lens _networkInterfaceDeleteOnTermination (\s a -> s { _networkInterfaceDeleteOnTermination = a })
+
+-- | The description of this network interface.
+niDescription :: Lens' NetworkInterface (Maybe (Val Text))
+niDescription = lens _networkInterfaceDescription (\s a -> s { _networkInterfaceDescription = a })
+
+-- | The network interface's position in the attachment order.
+niDeviceIndex :: Lens' NetworkInterface (Val Text)
+niDeviceIndex = lens _networkInterfaceDeviceIndex (\s a -> s { _networkInterfaceDeviceIndex = a })
+
+-- | A list of security group IDs associated with this network interface.
+niGroupSet :: Lens' NetworkInterface (Maybe [Val Text])
+niGroupSet = lens _networkInterfaceGroupSet (\s a -> s { _networkInterfaceGroupSet = a })
+
+-- | An existing network interface ID.
+niNetworkInterfaceId :: Lens' NetworkInterface (Maybe (Val Text))
+niNetworkInterfaceId = lens _networkInterfaceNetworkInterfaceId (\s a -> s { _networkInterfaceNetworkInterfaceId = a })
+
+-- | Assigns a single private IP address to the network interface, which is
+-- used as the primary private IP address. If you want to specify multiple
+-- private IP address, use the PrivateIpAddresses property.
+niPrivateIpAddress :: Lens' NetworkInterface (Maybe (Val Text))
+niPrivateIpAddress = lens _networkInterfacePrivateIpAddress (\s a -> s { _networkInterfacePrivateIpAddress = a })
+
+-- | Assigns a list of private IP addresses to the network interface. You can
+-- specify a primary private IP address by setting the value of the Primary
+-- property to true in the PrivateIpAddressSpecification property. If you want
+-- Amazon EC2 to automatically assign private IP addresses, use the
+-- SecondaryPrivateIpCount property and do not specify this property. For
+-- information about the maximum number of private IP addresses, see Private
+-- IP Addresses Per ENI Per Instance Type in the Amazon EC2 User Guide for
+-- Linux Instances.
+niPrivateIpAddresses :: Lens' NetworkInterface (Maybe [PrivateIpAddressSpecification])
+niPrivateIpAddresses = lens _networkInterfacePrivateIpAddresses (\s a -> s { _networkInterfacePrivateIpAddresses = a })
+
+-- | The number of secondary private IP addresses that Amazon EC2 auto assigns
+-- to the network interface. Amazon EC2 uses the value of the PrivateIpAddress
+-- property as the primary private IP address. If you don't specify that
+-- property, Amazon EC2 auto assigns both the primary and secondary private IP
+-- addresses. If you want to specify your own list of private IP addresses,
+-- use the PrivateIpAddresses property and do not specify this property. For
+-- information about the maximum number of private IP addresses, see Private
+-- IP Addresses Per ENI Per Instance Type in the Amazon EC2 User Guide for
+-- Linux Instances.
+niSecondaryPrivateIpAddressCount :: Lens' NetworkInterface (Maybe (Val Integer'))
+niSecondaryPrivateIpAddressCount = lens _networkInterfaceSecondaryPrivateIpAddressCount (\s a -> s { _networkInterfaceSecondaryPrivateIpAddressCount = a })
+
+-- | The ID of the subnet to associate with the network interface.
+niSubnetId :: Lens' NetworkInterface (Maybe (Val Text))
+niSubnetId = lens _networkInterfaceSubnetId (\s a -> s { _networkInterfaceSubnetId = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/PrivateIpAddressSpecification.hs b/library-gen/Stratosphere/ResourceProperties/PrivateIpAddressSpecification.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/PrivateIpAddressSpecification.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+
+
+module Stratosphere.ResourceProperties.PrivateIpAddressSpecification where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for PrivateIpAddressSpecification. See
+-- 'privateIpAddressSpecification' for a more convenient constructor.
+data PrivateIpAddressSpecification =
+  PrivateIpAddressSpecification
+  { _privateIpAddressSpecificationPrivateIpAddress :: Val Text
+  , _privateIpAddressSpecificationPrimary :: Val Bool'
+  } deriving (Show, Generic)
+
+instance ToJSON PrivateIpAddressSpecification where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 30, omitNothingFields = True }
+
+instance FromJSON PrivateIpAddressSpecification where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 30, omitNothingFields = True }
+
+-- | Constructor for 'PrivateIpAddressSpecification' containing required
+-- fields as arguments.
+privateIpAddressSpecification
+  :: Val Text -- ^ 'piasPrivateIpAddress'
+  -> Val Bool' -- ^ 'piasPrimary'
+  -> PrivateIpAddressSpecification
+privateIpAddressSpecification privateIpAddressarg primaryarg =
+  PrivateIpAddressSpecification
+  { _privateIpAddressSpecificationPrivateIpAddress = privateIpAddressarg
+  , _privateIpAddressSpecificationPrimary = primaryarg
+  }
+
+-- | The private IP address of the network interface.
+piasPrivateIpAddress :: Lens' PrivateIpAddressSpecification (Val Text)
+piasPrivateIpAddress = lens _privateIpAddressSpecificationPrivateIpAddress (\s a -> s { _privateIpAddressSpecificationPrivateIpAddress = a })
+
+-- | Sets the private IP address as the primary private address. You can set
+-- only one primary private IP address. If you don't specify a primary private
+-- IP address, Amazon EC2 automatically assigns a primary private IP address.
+piasPrimary :: Lens' PrivateIpAddressSpecification (Val Bool')
+piasPrimary = lens _privateIpAddressSpecificationPrimary (\s a -> s { _privateIpAddressSpecificationPrimary = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/RDSSecurityGroupRule.hs b/library-gen/Stratosphere/ResourceProperties/RDSSecurityGroupRule.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/RDSSecurityGroupRule.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The Amazon RDS security group rule is an embedded property of the
+-- AWS::RDS::DBSecurityGroup type.
+
+module Stratosphere.ResourceProperties.RDSSecurityGroupRule where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for RDSSecurityGroupRule. See
+-- 'rdsSecurityGroupRule' for a more convenient constructor.
+data RDSSecurityGroupRule =
+  RDSSecurityGroupRule
+  { _rDSSecurityGroupRuleCIDRIP :: Maybe (Val Text)
+  , _rDSSecurityGroupRuleEC2SecurityGroupId :: Maybe (Val Text)
+  , _rDSSecurityGroupRuleEC2SecurityGroupName :: Maybe (Val Text)
+  , _rDSSecurityGroupRuleEC2SecurityGroupOwnerId :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON RDSSecurityGroupRule where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 21, omitNothingFields = True }
+
+instance FromJSON RDSSecurityGroupRule where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 21, omitNothingFields = True }
+
+-- | Constructor for 'RDSSecurityGroupRule' containing required fields as
+-- arguments.
+rdsSecurityGroupRule
+  :: RDSSecurityGroupRule
+rdsSecurityGroupRule  =
+  RDSSecurityGroupRule
+  { _rDSSecurityGroupRuleCIDRIP = Nothing
+  , _rDSSecurityGroupRuleEC2SecurityGroupId = Nothing
+  , _rDSSecurityGroupRuleEC2SecurityGroupName = Nothing
+  , _rDSSecurityGroupRuleEC2SecurityGroupOwnerId = Nothing
+  }
+
+-- | The IP range to authorize. For an overview of CIDR ranges, go to the
+-- Wikipedia Tutorial. Type: String
+rdssgrCIDRIP :: Lens' RDSSecurityGroupRule (Maybe (Val Text))
+rdssgrCIDRIP = lens _rDSSecurityGroupRuleCIDRIP (\s a -> s { _rDSSecurityGroupRuleCIDRIP = a })
+
+-- | Id of the VPC or EC2 Security Group to authorize. For VPC DB Security
+-- Groups, use EC2SecurityGroupId. For EC2 Security Groups, use
+-- EC2SecurityGroupOwnerId and either EC2SecurityGroupName or
+-- EC2SecurityGroupId. Type: String
+rdssgrEC2SecurityGroupId :: Lens' RDSSecurityGroupRule (Maybe (Val Text))
+rdssgrEC2SecurityGroupId = lens _rDSSecurityGroupRuleEC2SecurityGroupId (\s a -> s { _rDSSecurityGroupRuleEC2SecurityGroupId = a })
+
+-- | Name of the EC2 Security Group to authorize. For VPC DB Security Groups,
+-- use EC2SecurityGroupId. For EC2 Security Groups, use
+-- EC2SecurityGroupOwnerId and either EC2SecurityGroupName or
+-- EC2SecurityGroupId. Type: String
+rdssgrEC2SecurityGroupName :: Lens' RDSSecurityGroupRule (Maybe (Val Text))
+rdssgrEC2SecurityGroupName = lens _rDSSecurityGroupRuleEC2SecurityGroupName (\s a -> s { _rDSSecurityGroupRuleEC2SecurityGroupName = a })
+
+-- | AWS Account Number of the owner of the EC2 Security Group specified in
+-- the EC2SecurityGroupName parameter. The AWS Access Key ID is not an
+-- acceptable value. For VPC DB Security Groups, use EC2SecurityGroupId. For
+-- EC2 Security Groups, use EC2SecurityGroupOwnerId and either
+-- EC2SecurityGroupName or EC2SecurityGroupId. Type: String
+rdssgrEC2SecurityGroupOwnerId :: Lens' RDSSecurityGroupRule (Maybe (Val Text))
+rdssgrEC2SecurityGroupOwnerId = lens _rDSSecurityGroupRuleEC2SecurityGroupOwnerId (\s a -> s { _rDSSecurityGroupRuleEC2SecurityGroupOwnerId = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/RecordSetGeoLocation.hs b/library-gen/Stratosphere/ResourceProperties/RecordSetGeoLocation.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/RecordSetGeoLocation.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The GeoLocation property is part of the AWS::Route53::RecordSet resource
+-- that describes how Amazon Route 53 responds to DNS queries based on the
+-- geographic location of the query.
+
+module Stratosphere.ResourceProperties.RecordSetGeoLocation where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for RecordSetGeoLocation. See
+-- 'recordSetGeoLocation' for a more convenient constructor.
+data RecordSetGeoLocation =
+  RecordSetGeoLocation
+  { _recordSetGeoLocationContinentCode :: Maybe (Val Text)
+  , _recordSetGeoLocationCountryCode :: Maybe (Val Text)
+  , _recordSetGeoLocationSubdivisionCode :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON RecordSetGeoLocation where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 21, omitNothingFields = True }
+
+instance FromJSON RecordSetGeoLocation where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 21, omitNothingFields = True }
+
+-- | Constructor for 'RecordSetGeoLocation' containing required fields as
+-- arguments.
+recordSetGeoLocation
+  :: RecordSetGeoLocation
+recordSetGeoLocation  =
+  RecordSetGeoLocation
+  { _recordSetGeoLocationContinentCode = Nothing
+  , _recordSetGeoLocationCountryCode = Nothing
+  , _recordSetGeoLocationSubdivisionCode = Nothing
+  }
+
+-- | All DNS queries from the continent that you specified are routed to this
+-- resource record set. If you specify this property, omit the CountryCode and
+-- SubdivisionCode properties. For valid values, see the ContinentCode element
+-- in the Amazon Route 53 API Reference. Type: String
+rsglContinentCode :: Lens' RecordSetGeoLocation (Maybe (Val Text))
+rsglContinentCode = lens _recordSetGeoLocationContinentCode (\s a -> s { _recordSetGeoLocationContinentCode = a })
+
+-- | All DNS queries from the country that you specified are routed to this
+-- resource record set. If you specify this property, omit the ContinentCode
+-- property. For valid values, see the CountryCode element in the Amazon Route
+-- 53 API Reference. Type: String
+rsglCountryCode :: Lens' RecordSetGeoLocation (Maybe (Val Text))
+rsglCountryCode = lens _recordSetGeoLocationCountryCode (\s a -> s { _recordSetGeoLocationCountryCode = a })
+
+-- | If you specified US for the country code, you can specify a state in the
+-- United States. All DNS queries from the state that you specified are routed
+-- to this resource record set. If you specify this property, you must specify
+-- US for the CountryCode and omit the ContinentCode property. For valid
+-- values, see the SubdivisionCode element in the Amazon Route 53 API
+-- Reference. Type: String
+rsglSubdivisionCode :: Lens' RecordSetGeoLocation (Maybe (Val Text))
+rsglSubdivisionCode = lens _recordSetGeoLocationSubdivisionCode (\s a -> s { _recordSetGeoLocationSubdivisionCode = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/ResourceTag.hs b/library-gen/Stratosphere/ResourceProperties/ResourceTag.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/ResourceTag.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | You can use the AWS CloudFormation Resource Tags property to apply tags
+-- to resources, which can help you identify and categorize those resources.
+-- You can tag only resources for which AWS CloudFormation supports tagging.
+-- For information about which resources you can tag with AWS CloudFormation,
+-- see the individual resources in AWS Resource Types Reference. In addition
+-- to any tags you define, AWS CloudFormation automatically creates the
+-- following stack-level tags with the prefix aws:: All stack-level tags,
+-- including automatically created tags, are propagated to resources that AWS
+-- CloudFormation supports. Currently, tags are not propagated to Amazon EBS
+-- volumes that are created from block device mappings.
+
+module Stratosphere.ResourceProperties.ResourceTag where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for ResourceTag. See 'resourceTag' for a more
+-- convenient constructor.
+data ResourceTag =
+  ResourceTag
+  { _resourceTagKey :: Val Text
+  , _resourceTagValue :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON ResourceTag where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+instance FromJSON ResourceTag where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+-- | Constructor for 'ResourceTag' containing required fields as arguments.
+resourceTag
+  :: Val Text -- ^ 'rtKey'
+  -> Val Text -- ^ 'rtValue'
+  -> ResourceTag
+resourceTag keyarg valuearg =
+  ResourceTag
+  { _resourceTagKey = keyarg
+  , _resourceTagValue = valuearg
+  }
+
+-- | The key name of the tag. You can specify a value that is 1 to 128 Unicode
+-- characters in length and cannot be prefixed with aws:. You can use any of
+-- the following characters: the set of Unicode letters, digits, whitespace,
+-- _, ., /, =, +, and -.
+rtKey :: Lens' ResourceTag (Val Text)
+rtKey = lens _resourceTagKey (\s a -> s { _resourceTagKey = a })
+
+-- | The value for the tag. You can specify a value that is 1 to 128 Unicode
+-- characters in length and cannot be prefixed with aws:. You can use any of
+-- the following characters: the set of Unicode letters, digits, whitespace,
+-- _, ., /, =, +, and -.
+rtValue :: Lens' ResourceTag (Val Text)
+rtValue = lens _resourceTagValue (\s a -> s { _resourceTagValue = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/SecurityGroupEgressRule.hs b/library-gen/Stratosphere/ResourceProperties/SecurityGroupEgressRule.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/SecurityGroupEgressRule.hs
@@ -0,0 +1,72 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The EC2 Security Group Rule is an embedded property of the
+-- AWS::EC2::SecurityGroup type.
+
+module Stratosphere.ResourceProperties.SecurityGroupEgressRule where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for SecurityGroupEgressRule. See
+-- 'securityGroupEgressRule' for a more convenient constructor.
+data SecurityGroupEgressRule =
+  SecurityGroupEgressRule
+  { _securityGroupEgressRuleCidrIp :: Maybe (Val Text)
+  , _securityGroupEgressRuleDestinationSecurityGroupId :: Maybe (Val Text)
+  , _securityGroupEgressRuleFromPort :: Maybe (Val Integer')
+  , _securityGroupEgressRuleIpProtocol :: Val Text
+  , _securityGroupEgressRuleToPort :: Maybe (Val Integer')
+  } deriving (Show, Generic)
+
+instance ToJSON SecurityGroupEgressRule where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 24, omitNothingFields = True }
+
+instance FromJSON SecurityGroupEgressRule where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 24, omitNothingFields = True }
+
+-- | Constructor for 'SecurityGroupEgressRule' containing required fields as
+-- arguments.
+securityGroupEgressRule
+  :: Val Text -- ^ 'sgerIpProtocol'
+  -> SecurityGroupEgressRule
+securityGroupEgressRule ipProtocolarg =
+  SecurityGroupEgressRule
+  { _securityGroupEgressRuleCidrIp = Nothing
+  , _securityGroupEgressRuleDestinationSecurityGroupId = Nothing
+  , _securityGroupEgressRuleFromPort = Nothing
+  , _securityGroupEgressRuleIpProtocol = ipProtocolarg
+  , _securityGroupEgressRuleToPort = Nothing
+  }
+
+-- | Specifies a CIDR range.
+sgerCidrIp :: Lens' SecurityGroupEgressRule (Maybe (Val Text))
+sgerCidrIp = lens _securityGroupEgressRuleCidrIp (\s a -> s { _securityGroupEgressRuleCidrIp = a })
+
+-- | Specifies the GroupId of the destination Amazon VPC security group. Type:
+-- String
+sgerDestinationSecurityGroupId :: Lens' SecurityGroupEgressRule (Maybe (Val Text))
+sgerDestinationSecurityGroupId = lens _securityGroupEgressRuleDestinationSecurityGroupId (\s a -> s { _securityGroupEgressRuleDestinationSecurityGroupId = a })
+
+-- | The start of port range for the TCP and UDP protocols, or an ICMP type
+-- number. An ICMP type number of -1 indicates a wildcard (i.e., any ICMP type
+-- number).
+sgerFromPort :: Lens' SecurityGroupEgressRule (Maybe (Val Integer'))
+sgerFromPort = lens _securityGroupEgressRuleFromPort (\s a -> s { _securityGroupEgressRuleFromPort = a })
+
+-- | An IP protocol name or number. For valid values, go to the IpProtocol
+-- parameter in AuthorizeSecurityGroupIngress
+sgerIpProtocol :: Lens' SecurityGroupEgressRule (Val Text)
+sgerIpProtocol = lens _securityGroupEgressRuleIpProtocol (\s a -> s { _securityGroupEgressRuleIpProtocol = a })
+
+-- | The end of port range for the TCP and UDP protocols, or an ICMP code. An
+-- ICMP code of -1 indicates a wildcard (i.e., any ICMP code).
+sgerToPort :: Lens' SecurityGroupEgressRule (Maybe (Val Integer'))
+sgerToPort = lens _securityGroupEgressRuleToPort (\s a -> s { _securityGroupEgressRuleToPort = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/SecurityGroupIngressRule.hs b/library-gen/Stratosphere/ResourceProperties/SecurityGroupIngressRule.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/SecurityGroupIngressRule.hs
@@ -0,0 +1,89 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The EC2 Security Group Rule is an embedded property of the
+-- AWS::EC2::SecurityGroup type.
+
+module Stratosphere.ResourceProperties.SecurityGroupIngressRule where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for SecurityGroupIngressRule. See
+-- 'securityGroupIngressRule' for a more convenient constructor.
+data SecurityGroupIngressRule =
+  SecurityGroupIngressRule
+  { _securityGroupIngressRuleCidrIp :: Maybe (Val Text)
+  , _securityGroupIngressRuleFromPort :: Maybe (Val Integer')
+  , _securityGroupIngressRuleIpProtocol :: Val Text
+  , _securityGroupIngressRuleSourceSecurityGroupId :: Maybe (Val Text)
+  , _securityGroupIngressRuleSourceSecurityGroupName :: Maybe (Val Text)
+  , _securityGroupIngressRuleSourceSecurityGroupOwnerId :: Maybe (Val Text)
+  , _securityGroupIngressRuleToPort :: Maybe (Val Integer')
+  } deriving (Show, Generic)
+
+instance ToJSON SecurityGroupIngressRule where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 25, omitNothingFields = True }
+
+instance FromJSON SecurityGroupIngressRule where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 25, omitNothingFields = True }
+
+-- | Constructor for 'SecurityGroupIngressRule' containing required fields as
+-- arguments.
+securityGroupIngressRule
+  :: Val Text -- ^ 'sgirIpProtocol'
+  -> SecurityGroupIngressRule
+securityGroupIngressRule ipProtocolarg =
+  SecurityGroupIngressRule
+  { _securityGroupIngressRuleCidrIp = Nothing
+  , _securityGroupIngressRuleFromPort = Nothing
+  , _securityGroupIngressRuleIpProtocol = ipProtocolarg
+  , _securityGroupIngressRuleSourceSecurityGroupId = Nothing
+  , _securityGroupIngressRuleSourceSecurityGroupName = Nothing
+  , _securityGroupIngressRuleSourceSecurityGroupOwnerId = Nothing
+  , _securityGroupIngressRuleToPort = Nothing
+  }
+
+-- | Specifies a CIDR range.
+sgirCidrIp :: Lens' SecurityGroupIngressRule (Maybe (Val Text))
+sgirCidrIp = lens _securityGroupIngressRuleCidrIp (\s a -> s { _securityGroupIngressRuleCidrIp = a })
+
+-- | The start of port range for the TCP and UDP protocols, or an ICMP type
+-- number. An ICMP type number of -1 indicates a wildcard (i.e., any ICMP type
+-- number). Type: Integer
+sgirFromPort :: Lens' SecurityGroupIngressRule (Maybe (Val Integer'))
+sgirFromPort = lens _securityGroupIngressRuleFromPort (\s a -> s { _securityGroupIngressRuleFromPort = a })
+
+-- | An IP protocol name or number. For valid values, go to the IpProtocol
+-- parameter in AuthorizeSecurityGroupIngress
+sgirIpProtocol :: Lens' SecurityGroupIngressRule (Val Text)
+sgirIpProtocol = lens _securityGroupIngressRuleIpProtocol (\s a -> s { _securityGroupIngressRuleIpProtocol = a })
+
+-- | For VPC security groups only. Specifies the ID of the Amazon EC2 Security
+-- Group to allow access. You can use the Ref intrinsic function to refer to
+-- the logical ID of a security group defined in the same template.
+sgirSourceSecurityGroupId :: Lens' SecurityGroupIngressRule (Maybe (Val Text))
+sgirSourceSecurityGroupId = lens _securityGroupIngressRuleSourceSecurityGroupId (\s a -> s { _securityGroupIngressRuleSourceSecurityGroupId = a })
+
+-- | For non-VPC security groups only. Specifies the name of the Amazon EC2
+-- Security Group to use for access. You can use the Ref intrinsic function to
+-- refer to the logical name of a security group that is defined in the same
+-- template.
+sgirSourceSecurityGroupName :: Lens' SecurityGroupIngressRule (Maybe (Val Text))
+sgirSourceSecurityGroupName = lens _securityGroupIngressRuleSourceSecurityGroupName (\s a -> s { _securityGroupIngressRuleSourceSecurityGroupName = a })
+
+-- | Specifies the AWS Account ID of the owner of the Amazon EC2 Security
+-- Group that is specified in the SourceSecurityGroupName property.
+sgirSourceSecurityGroupOwnerId :: Lens' SecurityGroupIngressRule (Maybe (Val Text))
+sgirSourceSecurityGroupOwnerId = lens _securityGroupIngressRuleSourceSecurityGroupOwnerId (\s a -> s { _securityGroupIngressRuleSourceSecurityGroupOwnerId = a })
+
+-- | The end of port range for the TCP and UDP protocols, or an ICMP code. An
+-- ICMP code of -1 indicates a wildcard (i.e., any ICMP code).
+sgirToPort :: Lens' SecurityGroupIngressRule (Maybe (Val Integer'))
+sgirToPort = lens _securityGroupIngressRuleToPort (\s a -> s { _securityGroupIngressRuleToPort = a })
diff --git a/library-gen/Stratosphere/ResourceProperties/UserLoginProfile.hs b/library-gen/Stratosphere/ResourceProperties/UserLoginProfile.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/ResourceProperties/UserLoginProfile.hs
@@ -0,0 +1,50 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | LoginProfile is a property of the AWS::IAM::User resource that creates a
+-- login profile for users so that they can access the AWS Management Console.
+
+module Stratosphere.ResourceProperties.UserLoginProfile where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for UserLoginProfile. See 'userLoginProfile'
+-- for a more convenient constructor.
+data UserLoginProfile =
+  UserLoginProfile
+  { _userLoginProfilePassword :: Val Text
+  , _userLoginProfilePasswordResetRequired :: Maybe (Val Bool')
+  } deriving (Show, Generic)
+
+instance ToJSON UserLoginProfile where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 17, omitNothingFields = True }
+
+instance FromJSON UserLoginProfile where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 17, omitNothingFields = True }
+
+-- | Constructor for 'UserLoginProfile' containing required fields as
+-- arguments.
+userLoginProfile
+  :: Val Text -- ^ 'ulpPassword'
+  -> UserLoginProfile
+userLoginProfile passwordarg =
+  UserLoginProfile
+  { _userLoginProfilePassword = passwordarg
+  , _userLoginProfilePasswordResetRequired = Nothing
+  }
+
+-- | The password for the user.
+ulpPassword :: Lens' UserLoginProfile (Val Text)
+ulpPassword = lens _userLoginProfilePassword (\s a -> s { _userLoginProfilePassword = a })
+
+-- | Specifies whether the user is required to set a new password the next
+-- time the user logs in to the AWS Management Console.
+ulpPasswordResetRequired :: Lens' UserLoginProfile (Maybe (Val Bool'))
+ulpPasswordResetRequired = lens _userLoginProfilePasswordResetRequired (\s a -> s { _userLoginProfilePasswordResetRequired = a })
diff --git a/library-gen/Stratosphere/Resources.hs b/library-gen/Stratosphere/Resources.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources.hs
@@ -0,0 +1,300 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+
+-- | See:
+-- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html
+--
+-- The required Resources section declare the AWS resources that you want as
+-- part of your stack, such as an Amazon EC2 instance or an Amazon S3 bucket.
+-- You must declare each resource separately; however, you can specify multiple
+-- resources of the same type. If you declare multiple resources, separate them
+-- with commas.
+
+module Stratosphere.Resources
+     ( module X
+     , Resource (..)
+     , resource
+     , properties
+     , deletionPolicy
+     , ResourceProperties (..)
+     , DeletionPolicy (..)
+     , Resources (..)
+     ) where
+
+import Control.Lens hiding ((.=))
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Maybe (catMaybes)
+import qualified Data.Text as T
+import GHC.Exts (IsList(..))
+import GHC.Generics (Generic)
+
+import Stratosphere.Resources.DBSecurityGroupIngress as X
+import Stratosphere.Resources.Subnet as X
+import Stratosphere.Resources.DBInstance as X
+import Stratosphere.Resources.IAMRole as X
+import Stratosphere.Resources.Group as X
+import Stratosphere.Resources.DBSubnetGroup as X
+import Stratosphere.Resources.SecurityGroup as X
+import Stratosphere.Resources.DBParameterGroup as X
+import Stratosphere.Resources.Policy as X
+import Stratosphere.Resources.EC2Instance as X
+import Stratosphere.Resources.RouteTable as X
+import Stratosphere.Resources.EIPAssociation as X
+import Stratosphere.Resources.InternetGateway as X
+import Stratosphere.Resources.InstanceProfile as X
+import Stratosphere.Resources.VPCGatewayAttachment as X
+import Stratosphere.Resources.EIP as X
+import Stratosphere.Resources.User as X
+import Stratosphere.Resources.DBSecurityGroup as X
+import Stratosphere.Resources.SubnetRouteTableAssociation as X
+import Stratosphere.Resources.RecordSetGroup as X
+import Stratosphere.Resources.Stack as X
+import Stratosphere.Resources.ManagedPolicy as X
+import Stratosphere.Resources.VPC as X
+import Stratosphere.Resources.AccessKey as X
+import Stratosphere.Resources.LoadBalancer as X
+import Stratosphere.Resources.Volume as X
+import Stratosphere.Resources.UserToGroupAddition as X
+import Stratosphere.Resources.VPCEndpoint as X
+import Stratosphere.Resources.RecordSet as X
+import Stratosphere.Resources.Route as X
+import Stratosphere.Resources.NatGateway as X
+import Stratosphere.Resources.VolumeAttachment as X
+
+import Stratosphere.ResourceProperties.ConnectionDrainingPolicy as X
+import Stratosphere.ResourceProperties.HealthCheck as X
+import Stratosphere.ResourceProperties.EC2SsmAssociationParameters as X
+import Stratosphere.ResourceProperties.ELBPolicy as X
+import Stratosphere.ResourceProperties.LBCookieStickinessPolicy as X
+import Stratosphere.ResourceProperties.AliasTarget as X
+import Stratosphere.ResourceProperties.NetworkInterface as X
+import Stratosphere.ResourceProperties.SecurityGroupEgressRule as X
+import Stratosphere.ResourceProperties.EC2BlockDeviceMapping as X
+import Stratosphere.ResourceProperties.RecordSetGeoLocation as X
+import Stratosphere.ResourceProperties.PrivateIpAddressSpecification as X
+import Stratosphere.ResourceProperties.IAMPolicies as X
+import Stratosphere.ResourceProperties.ListenerProperty as X
+import Stratosphere.ResourceProperties.EC2SsmAssociations as X
+import Stratosphere.ResourceProperties.ResourceTag as X
+import Stratosphere.ResourceProperties.EC2MountPoint as X
+import Stratosphere.ResourceProperties.SecurityGroupIngressRule as X
+import Stratosphere.ResourceProperties.RDSSecurityGroupRule as X
+import Stratosphere.ResourceProperties.EBSBlockDevice as X
+import Stratosphere.ResourceProperties.AccessLoggingPolicy as X
+import Stratosphere.ResourceProperties.AppCookieStickinessPolicy as X
+import Stratosphere.ResourceProperties.ConnectionSettings as X
+import Stratosphere.ResourceProperties.UserLoginProfile as X
+
+import Stratosphere.Helpers
+import Stratosphere.Values
+
+data ResourceProperties
+  = DBSecurityGroupIngressProperties DBSecurityGroupIngress
+  | SubnetProperties Subnet
+  | DBInstanceProperties DBInstance
+  | IAMRoleProperties IAMRole
+  | GroupProperties Group
+  | DBSubnetGroupProperties DBSubnetGroup
+  | SecurityGroupProperties SecurityGroup
+  | DBParameterGroupProperties DBParameterGroup
+  | PolicyProperties Policy
+  | EC2InstanceProperties EC2Instance
+  | RouteTableProperties RouteTable
+  | EIPAssociationProperties EIPAssociation
+  | InternetGatewayProperties InternetGateway
+  | InstanceProfileProperties InstanceProfile
+  | VPCGatewayAttachmentProperties VPCGatewayAttachment
+  | EIPProperties EIP
+  | UserProperties User
+  | DBSecurityGroupProperties DBSecurityGroup
+  | SubnetRouteTableAssociationProperties SubnetRouteTableAssociation
+  | RecordSetGroupProperties RecordSetGroup
+  | StackProperties Stack
+  | ManagedPolicyProperties ManagedPolicy
+  | VPCProperties VPC
+  | AccessKeyProperties AccessKey
+  | LoadBalancerProperties LoadBalancer
+  | VolumeProperties Volume
+  | UserToGroupAdditionProperties UserToGroupAddition
+  | VPCEndpointProperties VPCEndpoint
+  | RecordSetProperties RecordSet
+  | RouteProperties Route
+  | NatGatewayProperties NatGateway
+  | VolumeAttachmentProperties VolumeAttachment
+
+  deriving (Show)
+
+data DeletionPolicy
+  = Delete
+  | Retain
+  | Snapshot
+  deriving (Show, Generic)
+
+instance ToJSON DeletionPolicy where
+instance FromJSON DeletionPolicy where
+
+data Resource =
+  Resource
+  { resourceName :: T.Text
+  , resourceProperties :: ResourceProperties
+  , resourceDeletionPolicy :: Maybe DeletionPolicy
+  } deriving (Show)
+
+instance ToRef Resource b where
+  toRef r = Ref (resourceName r)
+
+-- | Convenient constructor for 'Resource' with required arguments.
+resource
+  :: T.Text -- ^ Logical name
+  -> ResourceProperties
+  -> Resource
+resource rn rp =
+  Resource
+  { resourceName = rn
+  , resourceProperties = rp
+  , resourceDeletionPolicy = Nothing
+  }
+
+$(makeFields ''Resource)
+
+resourceToJSON :: Resource -> Value
+resourceToJSON (Resource _ props dp) =
+    object $ resourcePropertiesJSON props ++ catMaybes
+    [ maybeField "DeletionPolicy" dp ]
+
+resourcePropertiesJSON :: ResourceProperties -> [Pair]
+resourcePropertiesJSON (DBSecurityGroupIngressProperties x) =
+  [ "Type" .= ("AWS::RDS::DBSecurityGroupIngress" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (SubnetProperties x) =
+  [ "Type" .= ("AWS::EC2::Subnet" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (DBInstanceProperties x) =
+  [ "Type" .= ("AWS::RDS::DBInstance" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (IAMRoleProperties x) =
+  [ "Type" .= ("AWS::IAM::Role" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (GroupProperties x) =
+  [ "Type" .= ("AWS::IAM::Group" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (DBSubnetGroupProperties x) =
+  [ "Type" .= ("AWS::RDS::DBSubnetGroup" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (SecurityGroupProperties x) =
+  [ "Type" .= ("AWS::EC2::SecurityGroup" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (DBParameterGroupProperties x) =
+  [ "Type" .= ("AWS::RDS::DBParameterGroup" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (PolicyProperties x) =
+  [ "Type" .= ("AWS::IAM::Policy" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (EC2InstanceProperties x) =
+  [ "Type" .= ("AWS::EC2::Instance" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (RouteTableProperties x) =
+  [ "Type" .= ("AWS::EC2::RouteTable" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (EIPAssociationProperties x) =
+  [ "Type" .= ("AWS::EC2::EIPAssociation" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (InternetGatewayProperties x) =
+  [ "Type" .= ("AWS::EC2::InternetGateway" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (InstanceProfileProperties x) =
+  [ "Type" .= ("AWS::IAM::InstanceProfile" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (VPCGatewayAttachmentProperties x) =
+  [ "Type" .= ("AWS::EC2::VPCGatewayAttachment" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (EIPProperties x) =
+  [ "Type" .= ("AWS::EC2::EIP" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (UserProperties x) =
+  [ "Type" .= ("AWS::IAM::User" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (DBSecurityGroupProperties x) =
+  [ "Type" .= ("AWS::RDS::DBSecurityGroup" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (SubnetRouteTableAssociationProperties x) =
+  [ "Type" .= ("AWS::EC2::SubnetRouteTableAssociation" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (RecordSetGroupProperties x) =
+  [ "Type" .= ("AWS::Route53::RecordSetGroup" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (StackProperties x) =
+  [ "Type" .= ("AWS::CloudFormation::Stack" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (ManagedPolicyProperties x) =
+  [ "Type" .= ("AWS::IAM::ManagedPolicy" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (VPCProperties x) =
+  [ "Type" .= ("AWS::EC2::VPC" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (AccessKeyProperties x) =
+  [ "Type" .= ("AWS::IAM::AccessKey" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (LoadBalancerProperties x) =
+  [ "Type" .= ("AWS::ElasticLoadBalancing::LoadBalancer" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (VolumeProperties x) =
+  [ "Type" .= ("AWS::EC2::Volume" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (UserToGroupAdditionProperties x) =
+  [ "Type" .= ("AWS::IAM::UserToGroupAddition" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (VPCEndpointProperties x) =
+  [ "Type" .= ("AWS::EC2::VPCEndpoint" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (RecordSetProperties x) =
+  [ "Type" .= ("AWS::Route53::RecordSet" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (RouteProperties x) =
+  [ "Type" .= ("AWS::EC2::Route" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (NatGatewayProperties x) =
+  [ "Type" .= ("AWS::EC2::NatGateway" :: String), "Properties" .= toJSON x]
+resourcePropertiesJSON (VolumeAttachmentProperties x) =
+  [ "Type" .= ("AWS::EC2::VolumeAttachment" :: String), "Properties" .= toJSON x]
+
+
+resourceFromJSON :: T.Text -> Object -> Parser Resource
+resourceFromJSON n o =
+    do type' <- o .: "Type" :: Parser String
+       props <- case type' of
+         "AWS::RDS::DBSecurityGroupIngress" -> DBSecurityGroupIngressProperties <$> (o .: "Properties")
+         "AWS::EC2::Subnet" -> SubnetProperties <$> (o .: "Properties")
+         "AWS::RDS::DBInstance" -> DBInstanceProperties <$> (o .: "Properties")
+         "AWS::IAM::Role" -> IAMRoleProperties <$> (o .: "Properties")
+         "AWS::IAM::Group" -> GroupProperties <$> (o .: "Properties")
+         "AWS::RDS::DBSubnetGroup" -> DBSubnetGroupProperties <$> (o .: "Properties")
+         "AWS::EC2::SecurityGroup" -> SecurityGroupProperties <$> (o .: "Properties")
+         "AWS::RDS::DBParameterGroup" -> DBParameterGroupProperties <$> (o .: "Properties")
+         "AWS::IAM::Policy" -> PolicyProperties <$> (o .: "Properties")
+         "AWS::EC2::Instance" -> EC2InstanceProperties <$> (o .: "Properties")
+         "AWS::EC2::RouteTable" -> RouteTableProperties <$> (o .: "Properties")
+         "AWS::EC2::EIPAssociation" -> EIPAssociationProperties <$> (o .: "Properties")
+         "AWS::EC2::InternetGateway" -> InternetGatewayProperties <$> (o .: "Properties")
+         "AWS::IAM::InstanceProfile" -> InstanceProfileProperties <$> (o .: "Properties")
+         "AWS::EC2::VPCGatewayAttachment" -> VPCGatewayAttachmentProperties <$> (o .: "Properties")
+         "AWS::EC2::EIP" -> EIPProperties <$> (o .: "Properties")
+         "AWS::IAM::User" -> UserProperties <$> (o .: "Properties")
+         "AWS::RDS::DBSecurityGroup" -> DBSecurityGroupProperties <$> (o .: "Properties")
+         "AWS::EC2::SubnetRouteTableAssociation" -> SubnetRouteTableAssociationProperties <$> (o .: "Properties")
+         "AWS::Route53::RecordSetGroup" -> RecordSetGroupProperties <$> (o .: "Properties")
+         "AWS::CloudFormation::Stack" -> StackProperties <$> (o .: "Properties")
+         "AWS::IAM::ManagedPolicy" -> ManagedPolicyProperties <$> (o .: "Properties")
+         "AWS::EC2::VPC" -> VPCProperties <$> (o .: "Properties")
+         "AWS::IAM::AccessKey" -> AccessKeyProperties <$> (o .: "Properties")
+         "AWS::ElasticLoadBalancing::LoadBalancer" -> LoadBalancerProperties <$> (o .: "Properties")
+         "AWS::EC2::Volume" -> VolumeProperties <$> (o .: "Properties")
+         "AWS::IAM::UserToGroupAddition" -> UserToGroupAdditionProperties <$> (o .: "Properties")
+         "AWS::EC2::VPCEndpoint" -> VPCEndpointProperties <$> (o .: "Properties")
+         "AWS::Route53::RecordSet" -> RecordSetProperties <$> (o .: "Properties")
+         "AWS::EC2::Route" -> RouteProperties <$> (o .: "Properties")
+         "AWS::EC2::NatGateway" -> NatGatewayProperties <$> (o .: "Properties")
+         "AWS::EC2::VolumeAttachment" -> VolumeAttachmentProperties <$> (o .: "Properties")
+
+         _ -> fail $ "Unknown resource type: " ++ type'
+       dp <- o .:? "DeletionPolicy"
+       return $ Resource n props dp
+
+-- | Wrapper around a list of 'Resources's to we can modify the aeson
+-- instances.
+newtype Resources = Resources { unResources :: [Resource] }
+                  deriving (Show, Monoid)
+
+instance IsList Resources where
+  type Item Resources = Resource
+  fromList = Resources
+  toList = unResources
+
+instance NamedItem Resource where
+  itemName = resourceName
+  nameToJSON = resourceToJSON
+  nameParseJSON = resourceFromJSON
+
+instance ToJSON Resources where
+  toJSON = namedItemToJSON . unResources
+
+instance FromJSON Resources where
+  parseJSON v = Resources <$> namedItemFromJSON v
diff --git a/library-gen/Stratosphere/Resources/AccessKey.hs b/library-gen/Stratosphere/Resources/AccessKey.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/AccessKey.hs
@@ -0,0 +1,60 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::IAM::AccessKey resource type generates a secret access key and
+-- assigns it to an IAM user or AWS account. This type supports updates. For
+-- more information about updating stacks, see AWS CloudFormation Stacks
+-- Updates.
+
+module Stratosphere.Resources.AccessKey where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for AccessKey. See 'accessKey' for a more
+-- convenient constructor.
+data AccessKey =
+  AccessKey
+  { _accessKeySerial :: Maybe (Val Integer')
+  , _accessKeyStatus :: Maybe (Val Text)
+  , _accessKeyUserName :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON AccessKey where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 10, omitNothingFields = True }
+
+instance FromJSON AccessKey where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 10, omitNothingFields = True }
+
+-- | Constructor for 'AccessKey' containing required fields as arguments.
+accessKey
+  :: Val Text -- ^ 'akUserName'
+  -> AccessKey
+accessKey userNamearg =
+  AccessKey
+  { _accessKeySerial = Nothing
+  , _accessKeyStatus = Nothing
+  , _accessKeyUserName = userNamearg
+  }
+
+-- | This value is specific to AWS CloudFormation and can only be incremented.
+-- Incrementing this value notifies AWS CloudFormation that you want to rotate
+-- your access key. When you update your stack, AWS CloudFormation will
+-- replace the existing access key with a new key.
+akSerial :: Lens' AccessKey (Maybe (Val Integer'))
+akSerial = lens _accessKeySerial (\s a -> s { _accessKeySerial = a })
+
+-- | The status of the access key. By default, AWS CloudFormation sets this
+-- property value to Active.
+akStatus :: Lens' AccessKey (Maybe (Val Text))
+akStatus = lens _accessKeyStatus (\s a -> s { _accessKeyStatus = a })
+
+-- | The name of the user that the new key will belong to.
+akUserName :: Lens' AccessKey (Val Text)
+akUserName = lens _accessKeyUserName (\s a -> s { _accessKeyUserName = a })
diff --git a/library-gen/Stratosphere/Resources/DBInstance.hs b/library-gen/Stratosphere/Resources/DBInstance.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/DBInstance.hs
@@ -0,0 +1,383 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::RDS::DBInstance type creates an Amazon RDS database instance.
+-- For detailed information about configuring RDS DB instances, see
+-- CreateDBInstance.
+
+module Stratosphere.Resources.DBInstance where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.ResourceTag
+
+-- | Full data type definition for DBInstance. See 'dbInstance' for a more
+-- convenient constructor.
+data DBInstance =
+  DBInstance
+  { _dBInstanceAllocatedStorage :: Maybe (Val Text)
+  , _dBInstanceAllowMajorVersionUpgrade :: Maybe (Val Bool')
+  , _dBInstanceAutoMinorVersionUpgrade :: Maybe (Val Bool')
+  , _dBInstanceAvailabilityZone :: Maybe (Val Text)
+  , _dBInstanceBackupRetentionPeriod :: Maybe (Val Text)
+  , _dBInstanceCharacterSetName :: Maybe (Val Text)
+  , _dBInstanceDBClusterIdentifier :: Maybe (Val Text)
+  , _dBInstanceDBInstanceClass :: Val Text
+  , _dBInstanceDBInstanceIdentifier :: Maybe (Val Text)
+  , _dBInstanceDBName :: Maybe (Val Text)
+  , _dBInstanceDBParameterGroupName :: Maybe (Val Text)
+  , _dBInstanceDBSecurityGroups :: Maybe [Val Text]
+  , _dBInstanceDBSnapshotIdentifier :: Maybe (Val Text)
+  , _dBInstanceDBSubnetGroupName :: Maybe (Val Text)
+  , _dBInstanceEngine :: Maybe (Val Text)
+  , _dBInstanceEngineVersion :: Maybe (Val Text)
+  , _dBInstanceIops :: Maybe (Val Integer')
+  , _dBInstanceKmsKeyId :: Maybe (Val Text)
+  , _dBInstanceLicenseModel :: Maybe (Val Text)
+  , _dBInstanceMasterUsername :: Maybe (Val Text)
+  , _dBInstanceMasterUserPassword :: Maybe (Val Text)
+  , _dBInstanceMultiAZ :: Maybe (Val Bool')
+  , _dBInstanceOptionGroupName :: Maybe (Val Text)
+  , _dBInstancePort :: Maybe (Val Text)
+  , _dBInstancePreferredBackupWindow :: Maybe (Val Text)
+  , _dBInstancePreferredMaintenanceWindow :: Maybe (Val Text)
+  , _dBInstancePubliclyAccessible :: Maybe (Val Bool')
+  , _dBInstanceSourceDBInstanceIdentifier :: Maybe (Val Text)
+  , _dBInstanceStorageEncrypted :: Maybe (Val Bool')
+  , _dBInstanceStorageType :: Maybe (Val Text)
+  , _dBInstanceTags :: Maybe [ResourceTag]
+  , _dBInstanceVPCSecurityGroups :: Maybe [Val Text]
+  } deriving (Show, Generic)
+
+instance ToJSON DBInstance where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 11, omitNothingFields = True }
+
+instance FromJSON DBInstance where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 11, omitNothingFields = True }
+
+-- | Constructor for 'DBInstance' containing required fields as arguments.
+dbInstance
+  :: Val Text -- ^ 'dbiDBInstanceClass'
+  -> DBInstance
+dbInstance dBInstanceClassarg =
+  DBInstance
+  { _dBInstanceAllocatedStorage = Nothing
+  , _dBInstanceAllowMajorVersionUpgrade = Nothing
+  , _dBInstanceAutoMinorVersionUpgrade = Nothing
+  , _dBInstanceAvailabilityZone = Nothing
+  , _dBInstanceBackupRetentionPeriod = Nothing
+  , _dBInstanceCharacterSetName = Nothing
+  , _dBInstanceDBClusterIdentifier = Nothing
+  , _dBInstanceDBInstanceClass = dBInstanceClassarg
+  , _dBInstanceDBInstanceIdentifier = Nothing
+  , _dBInstanceDBName = Nothing
+  , _dBInstanceDBParameterGroupName = Nothing
+  , _dBInstanceDBSecurityGroups = Nothing
+  , _dBInstanceDBSnapshotIdentifier = Nothing
+  , _dBInstanceDBSubnetGroupName = Nothing
+  , _dBInstanceEngine = Nothing
+  , _dBInstanceEngineVersion = Nothing
+  , _dBInstanceIops = Nothing
+  , _dBInstanceKmsKeyId = Nothing
+  , _dBInstanceLicenseModel = Nothing
+  , _dBInstanceMasterUsername = Nothing
+  , _dBInstanceMasterUserPassword = Nothing
+  , _dBInstanceMultiAZ = Nothing
+  , _dBInstanceOptionGroupName = Nothing
+  , _dBInstancePort = Nothing
+  , _dBInstancePreferredBackupWindow = Nothing
+  , _dBInstancePreferredMaintenanceWindow = Nothing
+  , _dBInstancePubliclyAccessible = Nothing
+  , _dBInstanceSourceDBInstanceIdentifier = Nothing
+  , _dBInstanceStorageEncrypted = Nothing
+  , _dBInstanceStorageType = Nothing
+  , _dBInstanceTags = Nothing
+  , _dBInstanceVPCSecurityGroups = Nothing
+  }
+
+-- | The allocated storage size specified in gigabytes (GB). If any value is
+-- used in the Iops parameter, AllocatedStorage must be at least 100 GB, which
+-- corresponds to the minimum Iops value of 1000. If Iops is increased (in
+-- 1000 IOPS increments), then AllocatedStorage must also be increased (in 100
+-- GB increments) correspondingly.
+dbiAllocatedStorage :: Lens' DBInstance (Maybe (Val Text))
+dbiAllocatedStorage = lens _dBInstanceAllocatedStorage (\s a -> s { _dBInstanceAllocatedStorage = a })
+
+-- | Indicates whether major version upgrades are allowed. Changing this
+-- parameter does not result in an outage, and the change is applied
+-- asynchronously as soon as possible. Constraints: This parameter must be set
+-- to true when you specify an EngineVersion that differs from the DB
+-- instance's current major version.
+dbiAllowMajorVersionUpgrade :: Lens' DBInstance (Maybe (Val Bool'))
+dbiAllowMajorVersionUpgrade = lens _dBInstanceAllowMajorVersionUpgrade (\s a -> s { _dBInstanceAllowMajorVersionUpgrade = a })
+
+-- | Indicates that minor engine upgrades will be applied automatically to the
+-- DB instance during the maintenance window. The default value is true.
+dbiAutoMinorVersionUpgrade :: Lens' DBInstance (Maybe (Val Bool'))
+dbiAutoMinorVersionUpgrade = lens _dBInstanceAutoMinorVersionUpgrade (\s a -> s { _dBInstanceAutoMinorVersionUpgrade = a })
+
+-- | The name of the Availability Zone where the DB instance is located. You
+-- cannot set the AvailabilityZone parameter if the MultiAZ parameter is set
+-- to true.
+dbiAvailabilityZone :: Lens' DBInstance (Maybe (Val Text))
+dbiAvailabilityZone = lens _dBInstanceAvailabilityZone (\s a -> s { _dBInstanceAvailabilityZone = a })
+
+-- | The number of days for which automatic DB snapshots are retained.
+-- Important If this DB instance is deleted or replaced during an update, all
+-- automated snapshots are deleted. However, manual DB snapshot are retained.
+dbiBackupRetentionPeriod :: Lens' DBInstance (Maybe (Val Text))
+dbiBackupRetentionPeriod = lens _dBInstanceBackupRetentionPeriod (\s a -> s { _dBInstanceBackupRetentionPeriod = a })
+
+-- | For supported engines, specifies the character set to associate with the
+-- database instance. For more information, see Appendix: Oracle Character
+-- Sets Supported in Amazon RDS in the Amazon Relational Database Service User
+-- Guide. If you specify the DBSnapshotIdentifier or
+-- SourceDBInstanceIdentifier property, do not specify this property. The
+-- value is inherited from the snapshot or source database instance.
+dbiCharacterSetName :: Lens' DBInstance (Maybe (Val Text))
+dbiCharacterSetName = lens _dBInstanceCharacterSetName (\s a -> s { _dBInstanceCharacterSetName = a })
+
+-- | The identifier of an existing DB cluster that this instance will be
+-- associated with. If you specify this property, specify aurora for the
+-- Engine property and do not specify any of the following properties:
+-- AllocatedStorage, CharacterSetName, DBSecurityGroups,
+-- SourceDBInstanceIdentifier, and StorageType. Amazon RDS assigns the first
+-- DB instance in the cluster as the primary and additional DB instances as
+-- replicas.
+dbiDBClusterIdentifier :: Lens' DBInstance (Maybe (Val Text))
+dbiDBClusterIdentifier = lens _dBInstanceDBClusterIdentifier (\s a -> s { _dBInstanceDBClusterIdentifier = a })
+
+-- | The name of the compute and memory capacity class of the DB instance.
+dbiDBInstanceClass :: Lens' DBInstance (Val Text)
+dbiDBInstanceClass = lens _dBInstanceDBInstanceClass (\s a -> s { _dBInstanceDBInstanceClass = a })
+
+-- | A name for the DB instance. If you specify a name, AWS CloudFormation
+-- converts it to lower case. If you don't specify a name, AWS CloudFormation
+-- generates a unique physical ID and uses that ID for the DB instance. For
+-- more information, see Name Type. Important If you specify a name, you
+-- cannot do updates that require this resource to be replaced. You can still
+-- do updates that require no or some interruption. If you must replace the
+-- resource, specify a new name.
+dbiDBInstanceIdentifier :: Lens' DBInstance (Maybe (Val Text))
+dbiDBInstanceIdentifier = lens _dBInstanceDBInstanceIdentifier (\s a -> s { _dBInstanceDBInstanceIdentifier = a })
+
+-- | The name of the initial database of this instance that was provided at
+-- create time, if one was specified. This same name is returned for the life
+-- of the DB instance. Note If you restore from a snapshot, do specify this
+-- property for the MySQL or MariaDB engines.
+dbiDBName :: Lens' DBInstance (Maybe (Val Text))
+dbiDBName = lens _dBInstanceDBName (\s a -> s { _dBInstanceDBName = a })
+
+-- | The name of an existing DB parameter group or a reference to an
+-- AWS::RDS::DBParameterGroup resource created in the template.
+dbiDBParameterGroupName :: Lens' DBInstance (Maybe (Val Text))
+dbiDBParameterGroupName = lens _dBInstanceDBParameterGroupName (\s a -> s { _dBInstanceDBParameterGroupName = a })
+
+-- | A list of the DB security groups to assign to the Amazon RDS instance.
+-- The list can include both the name of existing DB security groups or
+-- references to AWS::RDS::DBSecurityGroup resources created in the template.
+-- If you set DBSecurityGroups, you must not set VPCSecurityGroups, and
+-- vice-versa.
+dbiDBSecurityGroups :: Lens' DBInstance (Maybe [Val Text])
+dbiDBSecurityGroups = lens _dBInstanceDBSecurityGroups (\s a -> s { _dBInstanceDBSecurityGroups = a })
+
+-- | The identifier for the DB snapshot to restore from. By specifying this
+-- property, you can create a DB instance from the specified DB snapshot. If
+-- the DBSnapshotIdentifier property is an empty string or the
+-- AWS::RDS::DBInstance declaration has no DBSnapshotIdentifier property, the
+-- database is created as a new database. If the property contains a value
+-- (other than empty string), AWS CloudFormation creates a database from the
+-- specified snapshot. If a snapshot with the specified name does not exist,
+-- the database creation fails and the stack rolls back. Some DB instance
+-- properties are not valid when you restore from a snapshot, such as the
+-- MasterUsername and MasterUserPassword properties. For information about the
+-- properties that you can specify, see the RestoreDBInstanceFromDBSnapshot
+-- action in the Amazon Relational Database Service API Reference.
+dbiDBSnapshotIdentifier :: Lens' DBInstance (Maybe (Val Text))
+dbiDBSnapshotIdentifier = lens _dBInstanceDBSnapshotIdentifier (\s a -> s { _dBInstanceDBSnapshotIdentifier = a })
+
+-- | A DB subnet group to associate with the DB instance. If there is no DB
+-- subnet group, then it is a non-VPC DB instance. For more information about
+-- using Amazon RDS in a VPC, go to Using Amazon RDS with Amazon Virtual
+-- Private Cloud (VPC) in the Amazon Relational Database Service Developer
+-- Guide.
+dbiDBSubnetGroupName :: Lens' DBInstance (Maybe (Val Text))
+dbiDBSubnetGroupName = lens _dBInstanceDBSubnetGroupName (\s a -> s { _dBInstanceDBSubnetGroupName = a })
+
+-- | The name of the database engine that the DB instance uses. This property
+-- is optional when you specify the DBSnapshotIdentifier property to create DB
+-- instances. For valid values, see the Engine parameter of the
+-- CreateDBInstance action in the Amazon Relational Database Service API
+-- Reference.
+dbiEngine :: Lens' DBInstance (Maybe (Val Text))
+dbiEngine = lens _dBInstanceEngine (\s a -> s { _dBInstanceEngine = a })
+
+-- | The version number of the database engine to use.
+dbiEngineVersion :: Lens' DBInstance (Maybe (Val Text))
+dbiEngineVersion = lens _dBInstanceEngineVersion (\s a -> s { _dBInstanceEngineVersion = a })
+
+-- | The number of I/O operations per second (IOPS) that the database
+-- provisions. The value must be equal to or greater than 1000. If you specify
+-- this property, you must follow the range of allowed ratios of your
+-- requested IOPS rate to the amount of storage that you allocate (IOPS to
+-- allocated storage). For example, you can provision an Oracle database
+-- instance with 1000 IOPS and 200 GB of storage (a ratio of 5:1) or specify
+-- 2000 IOPS with 200 GB of storage (a ratio of 10:1). For more information,
+-- see Amazon RDS Provisioned IOPS Storage to Improve Performance in the
+-- Amazon Relational Database Service User Guide.
+dbiIops :: Lens' DBInstance (Maybe (Val Integer'))
+dbiIops = lens _dBInstanceIops (\s a -> s { _dBInstanceIops = a })
+
+-- | The Amazon Resource Name (ARN) of the AWS Key Management Service master
+-- key that is used to encrypt the database instance, such as
+-- arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123-456a-a12b-a123b4cd56ef.
+-- If you enable the StorageEncrypted property but don't specify this
+-- property, the default master key is used. If you specify this property, you
+-- must set the StorageEncrypted property to true. If you specify the
+-- DBSnapshotIdentifier or SourceDBInstanceIdentifier property, do not specify
+-- this property. The value is inherited from the snapshot or source database
+-- instance. Note Currently, if you specify DBSecurityGroups, this property is
+-- ignored. If you want to specify a security group and this property, you
+-- must use a VPC security group. For more information about Amazon RDS and
+-- VPC, see Using Amazon RDS with Amazon VPC in the Amazon Relational Database
+-- Service User Guide.
+dbiKmsKeyId :: Lens' DBInstance (Maybe (Val Text))
+dbiKmsKeyId = lens _dBInstanceKmsKeyId (\s a -> s { _dBInstanceKmsKeyId = a })
+
+-- | The license model information for the DB instance.
+dbiLicenseModel :: Lens' DBInstance (Maybe (Val Text))
+dbiLicenseModel = lens _dBInstanceLicenseModel (\s a -> s { _dBInstanceLicenseModel = a })
+
+-- | The master user name for the database instance. This property is optional
+-- when you specify the DBSnapshotIdentifier or the DBClusterIdentifier
+-- property to create DB instances. Note If you specify the
+-- SourceDBInstanceIdentifier or DBSnapshotIdentifier property, do not specify
+-- this property. The value is inherited from the source database instance or
+-- snapshot.
+dbiMasterUsername :: Lens' DBInstance (Maybe (Val Text))
+dbiMasterUsername = lens _dBInstanceMasterUsername (\s a -> s { _dBInstanceMasterUsername = a })
+
+-- | The master password for the database instance. This property is optional
+-- when you specify the DBSnapshotIdentifier or the DBClusterIdentifier
+-- property to create DB instances. Note If you specify the
+-- SourceDBInstanceIdentifier property, do not specify this property. The
+-- value is inherited from the source database instance.
+dbiMasterUserPassword :: Lens' DBInstance (Maybe (Val Text))
+dbiMasterUserPassword = lens _dBInstanceMasterUserPassword (\s a -> s { _dBInstanceMasterUserPassword = a })
+
+-- | Specifies if the database instance is a multiple Availability Zone
+-- deployment. You cannot set the AvailabilityZone parameter if the MultiAZ
+-- parameter is set to true. Note Do not specify this property if you want a
+-- Multi-AZ deployment for a SQL Server database instance. Use the mirroring
+-- option in an option group to set Multi-AZ for a SQL Server database
+-- instance.
+dbiMultiAZ :: Lens' DBInstance (Maybe (Val Bool'))
+dbiMultiAZ = lens _dBInstanceMultiAZ (\s a -> s { _dBInstanceMultiAZ = a })
+
+-- | An option group that this database instance is associated with.
+dbiOptionGroupName :: Lens' DBInstance (Maybe (Val Text))
+dbiOptionGroupName = lens _dBInstanceOptionGroupName (\s a -> s { _dBInstanceOptionGroupName = a })
+
+-- | The port for the instance.
+dbiPort :: Lens' DBInstance (Maybe (Val Text))
+dbiPort = lens _dBInstancePort (\s a -> s { _dBInstancePort = a })
+
+-- | The daily time range during which automated backups are created if
+-- automated backups are enabled, as determined by the BackupRetentionPeriod.
+dbiPreferredBackupWindow :: Lens' DBInstance (Maybe (Val Text))
+dbiPreferredBackupWindow = lens _dBInstancePreferredBackupWindow (\s a -> s { _dBInstancePreferredBackupWindow = a })
+
+-- | The weekly time range (in UTC) during which system maintenance can occur.
+dbiPreferredMaintenanceWindow :: Lens' DBInstance (Maybe (Val Text))
+dbiPreferredMaintenanceWindow = lens _dBInstancePreferredMaintenanceWindow (\s a -> s { _dBInstancePreferredMaintenanceWindow = a })
+
+-- | Indicates whether the database instance is an Internet-facing instance.
+-- If you specify true, an instance is created with a publicly resolvable DNS
+-- name, which resolves to a public IP address. If you specify false, an
+-- internal instance is created with a DNS name that resolves to a private IP
+-- address. The default behavior value depends on your VPC setup and the
+-- database subnet group. For more information, see the PubliclyAccessible
+-- parameter in CreateDBInstance in the Amazon Relational Database Service API
+-- Reference. If this resource has a public IP address and is also in a VPC
+-- that is defined in the same template, you must use the DependsOn attribute
+-- to declare a dependency on the VPC-gateway attachment. For more
+-- information, see DependsOn Attribute. Note Currently, if you specify
+-- DBSecurityGroups, this property is ignored. If you want to specify a
+-- security group and this property, you must use a VPC security group. For
+-- more information about Amazon RDS and VPC, see Using Amazon RDS with Amazon
+-- VPC in the Amazon Relational Database Service User Guide.
+dbiPubliclyAccessible :: Lens' DBInstance (Maybe (Val Bool'))
+dbiPubliclyAccessible = lens _dBInstancePubliclyAccessible (\s a -> s { _dBInstancePubliclyAccessible = a })
+
+-- | If you want to create a read replica DB instance, specify the ID of the
+-- source database instance. Each database instance can have a certain number
+-- of read replicas. For more information, see Working with Read Replicas in
+-- the Amazon Relational Database Service Developer Guide. The
+-- SourceDBInstanceIdentifier property determines whether a database instance
+-- is a read replica. If you remove the SourceDBInstanceIdentifier property
+-- from your current template and then update your stack, the read replica is
+-- deleted and a new database instance (not a read replica) is created.
+-- Important Read replicas do not support deletion policies. Any deletion
+-- policy that's associated with a read replica is ignored. If you specify
+-- SourceDBInstanceIdentifier, do not set the MultiAZ property to true and do
+-- not specify the DBSnapshotIdentifier property. You cannot deploy read
+-- replicas in multiple Availability Zones, and you cannot create a read
+-- replica from a snapshot. Do not set the BackupRetentionPeriod, DBName,
+-- MasterUsername, MasterUserPassword, and PreferredBackupWindow properties.
+-- The database attributes are inherited from the source database instance,
+-- and backups are disabled for read replicas. If the source DB instance is in
+-- a different region than the read replica, specify a valid DB instance ARN.
+-- For more information, see Constructing a Amazon RDS Amazon Resource Name
+-- (ARN) in the Amazon Relational Database Service User Guide. For DB
+-- instances in an Amazon Aurora clusters, do not specify this property.
+-- Amazon RDS assigns automatically assigns a writer and reader DB instances.
+dbiSourceDBInstanceIdentifier :: Lens' DBInstance (Maybe (Val Text))
+dbiSourceDBInstanceIdentifier = lens _dBInstanceSourceDBInstanceIdentifier (\s a -> s { _dBInstanceSourceDBInstanceIdentifier = a })
+
+-- | Indicates whether the database instance is encrypted. If you specify the
+-- DBClusterIdentifier, DBSnapshotIdentifier, or SourceDBInstanceIdentifier
+-- property, do not specify this property. The value is inherited from the
+-- cluster, snapshot, or source database instance. Note Currently, if you
+-- specify DBSecurityGroups, this property is ignored. If you want to specify
+-- a security group and this property, you must use a VPC security group. For
+-- more information about Amazon RDS and VPC, see Using Amazon RDS with Amazon
+-- VPC in the Amazon Relational Database Service User Guide.
+dbiStorageEncrypted :: Lens' DBInstance (Maybe (Val Bool'))
+dbiStorageEncrypted = lens _dBInstanceStorageEncrypted (\s a -> s { _dBInstanceStorageEncrypted = a })
+
+-- | The storage type associated with this database instance. For the default
+-- and valid values, see the StorageType parameter of the CreateDBInstance
+-- action in the Amazon Relational Database Service API Reference. Note
+-- Currently, if you specify DBSecurityGroups, this property is ignored. If
+-- you want to specify a security group and this property, you must use a VPC
+-- security group. For more information about Amazon RDS and VPC, see Using
+-- Amazon RDS with Amazon VPC in the Amazon Relational Database Service User
+-- Guide.
+dbiStorageType :: Lens' DBInstance (Maybe (Val Text))
+dbiStorageType = lens _dBInstanceStorageType (\s a -> s { _dBInstanceStorageType = a })
+
+-- | An arbitrary set of tags (key–value pairs) for this database instance.
+dbiTags :: Lens' DBInstance (Maybe [ResourceTag])
+dbiTags = lens _dBInstanceTags (\s a -> s { _dBInstanceTags = a })
+
+-- | A list of the VPC security groups to assign to the Amazon RDS instance.
+-- The list can include both the physical IDs of existing VPC security groups
+-- or references to AWS::EC2::SecurityGroup resources created in the template.
+-- If you set VPCSecurityGroups, you must not set DBSecurityGroups, and
+-- vice-versa. Important You can migrate a database instance in your stack
+-- from an RDS DB security group to a VPC security group, but you should keep
+-- the following points in mind: You cannot revert to using an RDS security
+-- group once you have established a VPC security group membership. When you
+-- migrate your DB instance to VPC security groups, if your stack update rolls
+-- back because of another failure in the database instance update, or because
+-- of an update failure in another AWS CloudFormation resource, the rollback
+-- will fail because it cannot revert to an RDS security group. To avoid this
+-- situation, only migrate your DB instance to using VPC security groups when
+-- that is the only change in your stack template.
+dbiVPCSecurityGroups :: Lens' DBInstance (Maybe [Val Text])
+dbiVPCSecurityGroups = lens _dBInstanceVPCSecurityGroups (\s a -> s { _dBInstanceVPCSecurityGroups = a })
diff --git a/library-gen/Stratosphere/Resources/DBParameterGroup.hs b/library-gen/Stratosphere/Resources/DBParameterGroup.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/DBParameterGroup.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Creates a custom parameter group for an RDS database family. For more
+-- information about RDS parameter groups, see Working with DB Parameter
+-- Groups in the Amazon Relational Database Service User Guide. This type can
+-- be declared in a template and referenced in the DBParameterGroupName
+-- parameter of AWS::RDS::DBInstance.
+
+module Stratosphere.Resources.DBParameterGroup where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.ResourceTag
+
+-- | Full data type definition for DBParameterGroup. See 'dbParameterGroup'
+-- for a more convenient constructor.
+data DBParameterGroup =
+  DBParameterGroup
+  { _dBParameterGroupDescription :: Val Text
+  , _dBParameterGroupFamily :: Val Text
+  , _dBParameterGroupParameters :: Maybe Value
+  , _dBParameterGroupTags :: Maybe [ResourceTag]
+  } deriving (Show, Generic)
+
+instance ToJSON DBParameterGroup where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 17, omitNothingFields = True }
+
+instance FromJSON DBParameterGroup where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 17, omitNothingFields = True }
+
+-- | Constructor for 'DBParameterGroup' containing required fields as
+-- arguments.
+dbParameterGroup
+  :: Val Text -- ^ 'dbpgDescription'
+  -> Val Text -- ^ 'dbpgFamily'
+  -> DBParameterGroup
+dbParameterGroup descriptionarg familyarg =
+  DBParameterGroup
+  { _dBParameterGroupDescription = descriptionarg
+  , _dBParameterGroupFamily = familyarg
+  , _dBParameterGroupParameters = Nothing
+  , _dBParameterGroupTags = Nothing
+  }
+
+-- | A friendly description of the RDS parameter group. For example, "My
+-- Parameter Group".
+dbpgDescription :: Lens' DBParameterGroup (Val Text)
+dbpgDescription = lens _dBParameterGroupDescription (\s a -> s { _dBParameterGroupDescription = a })
+
+-- | The database family of this RDS parameter group. For example, "MySQL5.1".
+dbpgFamily :: Lens' DBParameterGroup (Val Text)
+dbpgFamily = lens _dBParameterGroupFamily (\s a -> s { _dBParameterGroupFamily = a })
+
+-- | The parameters to set for this RDS parameter group. Changes to dynamic
+-- parameters are applied immediately. Changes to static parameters require a
+-- reboot without failover to the DB instance that is associated with the
+-- parameter group before the change can take effect.
+dbpgParameters :: Lens' DBParameterGroup (Maybe Value)
+dbpgParameters = lens _dBParameterGroupParameters (\s a -> s { _dBParameterGroupParameters = a })
+
+-- | The tags that you want to attach to the RDS parameter group.
+dbpgTags :: Lens' DBParameterGroup (Maybe [ResourceTag])
+dbpgTags = lens _dBParameterGroupTags (\s a -> s { _dBParameterGroupTags = a })
diff --git a/library-gen/Stratosphere/Resources/DBSecurityGroup.hs b/library-gen/Stratosphere/Resources/DBSecurityGroup.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/DBSecurityGroup.hs
@@ -0,0 +1,70 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::RDS::DBSecurityGroup type is used to create or update an Amazon
+-- RDS DB Security Group. For more information about DB Security Groups, see
+-- Working with DB Security Groups in the Amazon Relational Database Service
+-- Developer Guide. For details on the settings for DB security groups, see
+-- CreateDBSecurityGroup. When you specify an AWS::RDS::DBSecurityGroup as an
+-- argument to the Ref function, AWS CloudFormation returns the value of the
+-- DBSecurityGroupName.
+
+module Stratosphere.Resources.DBSecurityGroup where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.ResourceTag
+import Stratosphere.ResourceProperties.RDSSecurityGroupRule
+
+-- | Full data type definition for DBSecurityGroup. See 'dbSecurityGroup' for
+-- a more convenient constructor.
+data DBSecurityGroup =
+  DBSecurityGroup
+  { _dBSecurityGroupEC2VpcId :: Maybe (Val Text)
+  , _dBSecurityGroupDBSecurityGroupIngress :: [RDSSecurityGroupRule]
+  , _dBSecurityGroupGroupDescription :: Val Text
+  , _dBSecurityGroupResourceTags :: Maybe [ResourceTag]
+  } deriving (Show, Generic)
+
+instance ToJSON DBSecurityGroup where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 16, omitNothingFields = True }
+
+instance FromJSON DBSecurityGroup where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 16, omitNothingFields = True }
+
+-- | Constructor for 'DBSecurityGroup' containing required fields as
+-- arguments.
+dbSecurityGroup
+  :: [RDSSecurityGroupRule] -- ^ 'dbsgDBSecurityGroupIngress'
+  -> Val Text -- ^ 'dbsgGroupDescription'
+  -> DBSecurityGroup
+dbSecurityGroup dBSecurityGroupIngressarg groupDescriptionarg =
+  DBSecurityGroup
+  { _dBSecurityGroupEC2VpcId = Nothing
+  , _dBSecurityGroupDBSecurityGroupIngress = dBSecurityGroupIngressarg
+  , _dBSecurityGroupGroupDescription = groupDescriptionarg
+  , _dBSecurityGroupResourceTags = Nothing
+  }
+
+-- | The Id of VPC. Indicates which VPC this DB Security Group should belong
+-- to. Type: String
+dbsgEC2VpcId :: Lens' DBSecurityGroup (Maybe (Val Text))
+dbsgEC2VpcId = lens _dBSecurityGroupEC2VpcId (\s a -> s { _dBSecurityGroupEC2VpcId = a })
+
+-- | Network ingress authorization for an Amazon EC2 security group or an IP
+-- address range. Type: List of RDS Security Group Rules.
+dbsgDBSecurityGroupIngress :: Lens' DBSecurityGroup [RDSSecurityGroupRule]
+dbsgDBSecurityGroupIngress = lens _dBSecurityGroupDBSecurityGroupIngress (\s a -> s { _dBSecurityGroupDBSecurityGroupIngress = a })
+
+-- | Description of the security group. Type: String
+dbsgGroupDescription :: Lens' DBSecurityGroup (Val Text)
+dbsgGroupDescription = lens _dBSecurityGroupGroupDescription (\s a -> s { _dBSecurityGroupGroupDescription = a })
+
+-- | The tags that you want to attach to the Amazon RDS DB security group.
+dbsgResourceTags :: Lens' DBSecurityGroup (Maybe [ResourceTag])
+dbsgResourceTags = lens _dBSecurityGroupResourceTags (\s a -> s { _dBSecurityGroupResourceTags = a })
diff --git a/library-gen/Stratosphere/Resources/DBSecurityGroupIngress.hs b/library-gen/Stratosphere/Resources/DBSecurityGroupIngress.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/DBSecurityGroupIngress.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::RDS::DBSecurityGroupIngress type enables ingress to a
+-- DBSecurityGroup using one of two forms of authorization. First, EC2 or VPC
+-- security groups can be added to the DBSecurityGroup if the application
+-- using the database is running on EC2 or VPC instances. Second, IP ranges
+-- are available if the application accessing your database is running on the
+-- Internet. For more information about DB security groups, see Working with
+-- DB security groups This type supports updates. For more information about
+-- updating stacks, see AWS CloudFormation Stacks Updates. For details about
+-- the settings for DB security group ingress, see
+-- AuthorizeDBSecurityGroupIngress.
+
+module Stratosphere.Resources.DBSecurityGroupIngress where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for DBSecurityGroupIngress. See
+-- 'dbSecurityGroupIngress' for a more convenient constructor.
+data DBSecurityGroupIngress =
+  DBSecurityGroupIngress
+  { _dBSecurityGroupIngressCIDRIP :: Maybe (Val Text)
+  , _dBSecurityGroupIngressDBSecurityGroupName :: Val Text
+  , _dBSecurityGroupIngressEC2SecurityGroupId :: Maybe (Val Text)
+  , _dBSecurityGroupIngressEC2SecurityGroupName :: Maybe (Val Text)
+  , _dBSecurityGroupIngressEC2SecurityGroupOwnerId :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON DBSecurityGroupIngress where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 23, omitNothingFields = True }
+
+instance FromJSON DBSecurityGroupIngress where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 23, omitNothingFields = True }
+
+-- | Constructor for 'DBSecurityGroupIngress' containing required fields as
+-- arguments.
+dbSecurityGroupIngress
+  :: Val Text -- ^ 'dbsgiDBSecurityGroupName'
+  -> DBSecurityGroupIngress
+dbSecurityGroupIngress dBSecurityGroupNamearg =
+  DBSecurityGroupIngress
+  { _dBSecurityGroupIngressCIDRIP = Nothing
+  , _dBSecurityGroupIngressDBSecurityGroupName = dBSecurityGroupNamearg
+  , _dBSecurityGroupIngressEC2SecurityGroupId = Nothing
+  , _dBSecurityGroupIngressEC2SecurityGroupName = Nothing
+  , _dBSecurityGroupIngressEC2SecurityGroupOwnerId = Nothing
+  }
+
+-- | The IP range to authorize. For an overview of CIDR ranges, go to the
+-- Wikipedia Tutorial. Type: String Update requires: No interruption
+dbsgiCIDRIP :: Lens' DBSecurityGroupIngress (Maybe (Val Text))
+dbsgiCIDRIP = lens _dBSecurityGroupIngressCIDRIP (\s a -> s { _dBSecurityGroupIngressCIDRIP = a })
+
+-- | The name (ARN) of the AWS::RDS::DBSecurityGroup to which this ingress
+-- will be added. Type: String
+dbsgiDBSecurityGroupName :: Lens' DBSecurityGroupIngress (Val Text)
+dbsgiDBSecurityGroupName = lens _dBSecurityGroupIngressDBSecurityGroupName (\s a -> s { _dBSecurityGroupIngressDBSecurityGroupName = a })
+
+-- | The ID of the VPC or EC2 security group to authorize. For VPC DB security
+-- groups, use EC2SecurityGroupId. For EC2 security groups, use
+-- EC2SecurityGroupOwnerId and either EC2SecurityGroupName or
+-- EC2SecurityGroupId. Type: String
+dbsgiEC2SecurityGroupId :: Lens' DBSecurityGroupIngress (Maybe (Val Text))
+dbsgiEC2SecurityGroupId = lens _dBSecurityGroupIngressEC2SecurityGroupId (\s a -> s { _dBSecurityGroupIngressEC2SecurityGroupId = a })
+
+-- | The name of the EC2 security group to authorize. For VPC DB security
+-- groups, use EC2SecurityGroupId. For EC2 security groups, use
+-- EC2SecurityGroupOwnerId and either EC2SecurityGroupName or
+-- EC2SecurityGroupId. Type: String
+dbsgiEC2SecurityGroupName :: Lens' DBSecurityGroupIngress (Maybe (Val Text))
+dbsgiEC2SecurityGroupName = lens _dBSecurityGroupIngressEC2SecurityGroupName (\s a -> s { _dBSecurityGroupIngressEC2SecurityGroupName = a })
+
+-- | The AWS Account Number of the owner of the EC2 security group specified
+-- in the EC2SecurityGroupName parameter. The AWS Access Key ID is not an
+-- acceptable value. For VPC DB security groups, use EC2SecurityGroupId. For
+-- EC2 security groups, use EC2SecurityGroupOwnerId and either
+-- EC2SecurityGroupName or EC2SecurityGroupId. Type: String
+dbsgiEC2SecurityGroupOwnerId :: Lens' DBSecurityGroupIngress (Maybe (Val Text))
+dbsgiEC2SecurityGroupOwnerId = lens _dBSecurityGroupIngressEC2SecurityGroupOwnerId (\s a -> s { _dBSecurityGroupIngressEC2SecurityGroupOwnerId = a })
diff --git a/library-gen/Stratosphere/Resources/DBSubnetGroup.hs b/library-gen/Stratosphere/Resources/DBSubnetGroup.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/DBSubnetGroup.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::RDS::DBSubnetGroup type creates an RDS database subnet group.
+-- Subnet groups must contain at least two subnet in two different
+-- Availability Zones in the same region.
+
+module Stratosphere.Resources.DBSubnetGroup where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.ResourceTag
+
+-- | Full data type definition for DBSubnetGroup. See 'dbSubnetGroup' for a
+-- more convenient constructor.
+data DBSubnetGroup =
+  DBSubnetGroup
+  { _dBSubnetGroupDBSubnetGroupDescription :: Val Text
+  , _dBSubnetGroupSubnetIds :: [Val Text]
+  , _dBSubnetGroupTags :: Maybe [ResourceTag]
+  } deriving (Show, Generic)
+
+instance ToJSON DBSubnetGroup where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 14, omitNothingFields = True }
+
+instance FromJSON DBSubnetGroup where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 14, omitNothingFields = True }
+
+-- | Constructor for 'DBSubnetGroup' containing required fields as arguments.
+dbSubnetGroup
+  :: Val Text -- ^ 'dbsgDBSubnetGroupDescription'
+  -> [Val Text] -- ^ 'dbsgSubnetIds'
+  -> DBSubnetGroup
+dbSubnetGroup dBSubnetGroupDescriptionarg subnetIdsarg =
+  DBSubnetGroup
+  { _dBSubnetGroupDBSubnetGroupDescription = dBSubnetGroupDescriptionarg
+  , _dBSubnetGroupSubnetIds = subnetIdsarg
+  , _dBSubnetGroupTags = Nothing
+  }
+
+-- | The description for the DB Subnet Group.
+dbsgDBSubnetGroupDescription :: Lens' DBSubnetGroup (Val Text)
+dbsgDBSubnetGroupDescription = lens _dBSubnetGroupDBSubnetGroupDescription (\s a -> s { _dBSubnetGroupDBSubnetGroupDescription = a })
+
+-- | The EC2 Subnet IDs for the DB Subnet Group.
+dbsgSubnetIds :: Lens' DBSubnetGroup [Val Text]
+dbsgSubnetIds = lens _dBSubnetGroupSubnetIds (\s a -> s { _dBSubnetGroupSubnetIds = a })
+
+-- | The tags that you want to attach to the RDS database subnet group.
+dbsgTags :: Lens' DBSubnetGroup (Maybe [ResourceTag])
+dbsgTags = lens _dBSubnetGroupTags (\s a -> s { _dBSubnetGroupTags = a })
diff --git a/library-gen/Stratosphere/Resources/EC2Instance.hs b/library-gen/Stratosphere/Resources/EC2Instance.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/EC2Instance.hs
@@ -0,0 +1,253 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::EC2::Instance type creates an Amazon EC2 instance. If an Elastic
+-- IP address is attached to your instance, AWS CloudFormation reattaches the
+-- Elastic IP address after it updates the instance. For more information
+-- about updating stacks, see AWS CloudFormation Stacks Updates.
+
+module Stratosphere.Resources.EC2Instance where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.EC2BlockDeviceMapping
+import Stratosphere.ResourceProperties.NetworkInterface
+import Stratosphere.ResourceProperties.EC2SsmAssociations
+import Stratosphere.ResourceProperties.ResourceTag
+import Stratosphere.ResourceProperties.EC2MountPoint
+
+-- | Full data type definition for EC2Instance. See 'ec2Instance' for a more
+-- convenient constructor.
+data EC2Instance =
+  EC2Instance
+  { _eC2InstanceAvailabilityZone :: Maybe (Val Text)
+  , _eC2InstanceBlockDeviceMappings :: Maybe [EC2BlockDeviceMapping]
+  , _eC2InstanceDisableApiTermination :: Maybe (Val Bool')
+  , _eC2InstanceEbsOptimized :: Maybe (Val Bool')
+  , _eC2InstanceIamInstanceProfile :: Maybe (Val Text)
+  , _eC2InstanceImageId :: Val Text
+  , _eC2InstanceInstanceInitiatedShutdownBehavior :: Maybe (Val Text)
+  , _eC2InstanceInstanceType :: Maybe (Val Text)
+  , _eC2InstanceKernelId :: Maybe (Val Text)
+  , _eC2InstanceKeyName :: Maybe (Val Text)
+  , _eC2InstanceMonitoring :: Maybe (Val Bool')
+  , _eC2InstanceNetworkInterfaces :: Maybe [NetworkInterface]
+  , _eC2InstancePlacementGroupName :: Maybe (Val Text)
+  , _eC2InstancePrivateIpAddress :: Maybe (Val Text)
+  , _eC2InstanceRamdiskId :: Maybe (Val Text)
+  , _eC2InstanceSecurityGroupIds :: Maybe [Val Text]
+  , _eC2InstanceSecurityGroups :: Maybe [Val Text]
+  , _eC2InstanceSourceDestCheck :: Maybe (Val Bool')
+  , _eC2InstanceSsmAssociations :: Maybe [EC2SsmAssociations]
+  , _eC2InstanceSubnetId :: Maybe (Val Text)
+  , _eC2InstanceTags :: Maybe [ResourceTag]
+  , _eC2InstanceTenancy :: Maybe (Val Text)
+  , _eC2InstanceUserData :: Maybe (Val Text)
+  , _eC2InstanceVolumes :: Maybe [EC2MountPoint]
+  , _eC2InstanceAdditionalInfo :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON EC2Instance where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+instance FromJSON EC2Instance where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+-- | Constructor for 'EC2Instance' containing required fields as arguments.
+ec2Instance
+  :: Val Text -- ^ 'eciImageId'
+  -> EC2Instance
+ec2Instance imageIdarg =
+  EC2Instance
+  { _eC2InstanceAvailabilityZone = Nothing
+  , _eC2InstanceBlockDeviceMappings = Nothing
+  , _eC2InstanceDisableApiTermination = Nothing
+  , _eC2InstanceEbsOptimized = Nothing
+  , _eC2InstanceIamInstanceProfile = Nothing
+  , _eC2InstanceImageId = imageIdarg
+  , _eC2InstanceInstanceInitiatedShutdownBehavior = Nothing
+  , _eC2InstanceInstanceType = Nothing
+  , _eC2InstanceKernelId = Nothing
+  , _eC2InstanceKeyName = Nothing
+  , _eC2InstanceMonitoring = Nothing
+  , _eC2InstanceNetworkInterfaces = Nothing
+  , _eC2InstancePlacementGroupName = Nothing
+  , _eC2InstancePrivateIpAddress = Nothing
+  , _eC2InstanceRamdiskId = Nothing
+  , _eC2InstanceSecurityGroupIds = Nothing
+  , _eC2InstanceSecurityGroups = Nothing
+  , _eC2InstanceSourceDestCheck = Nothing
+  , _eC2InstanceSsmAssociations = Nothing
+  , _eC2InstanceSubnetId = Nothing
+  , _eC2InstanceTags = Nothing
+  , _eC2InstanceTenancy = Nothing
+  , _eC2InstanceUserData = Nothing
+  , _eC2InstanceVolumes = Nothing
+  , _eC2InstanceAdditionalInfo = Nothing
+  }
+
+-- | Specifies the name of the Availability Zone in which the instance is
+-- located. For more information about AWS regions and Availability Zones, see
+-- Regions and Availability Zones in the Amazon EC2 User Guide.
+eciAvailabilityZone :: Lens' EC2Instance (Maybe (Val Text))
+eciAvailabilityZone = lens _eC2InstanceAvailabilityZone (\s a -> s { _eC2InstanceAvailabilityZone = a })
+
+-- | Defines a set of Amazon Elastic Block Store block device mappings,
+-- ephemeral instance store block device mappings, or both. For more
+-- information, see Amazon Elastic Block Store or Amazon EC2 Instance Store in
+-- the Amazon EC2 User Guide for Linux Instances.
+eciBlockDeviceMappings :: Lens' EC2Instance (Maybe [EC2BlockDeviceMapping])
+eciBlockDeviceMappings = lens _eC2InstanceBlockDeviceMappings (\s a -> s { _eC2InstanceBlockDeviceMappings = a })
+
+-- | Specifies whether the instance can be terminated through the API.
+eciDisableApiTermination :: Lens' EC2Instance (Maybe (Val Bool'))
+eciDisableApiTermination = lens _eC2InstanceDisableApiTermination (\s a -> s { _eC2InstanceDisableApiTermination = a })
+
+-- | Specifies whether the instance is optimized for Amazon Elastic Block
+-- Store I/O. This optimization provides dedicated throughput to Amazon EBS
+-- and an optimized configuration stack to provide optimal EBS I/O
+-- performance. For more information about the instance types that can be
+-- launched as Amazon EBS optimized instances, see Amazon EBS-Optimized
+-- Instances in the Amazon Elastic Compute Cloud User Guide. Additional fees
+-- are incurred when using Amazon EBS-optimized instances.
+eciEbsOptimized :: Lens' EC2Instance (Maybe (Val Bool'))
+eciEbsOptimized = lens _eC2InstanceEbsOptimized (\s a -> s { _eC2InstanceEbsOptimized = a })
+
+-- | The physical ID (resource name) of an instance profile or a reference to
+-- an AWS::IAM::InstanceProfile resource. For more information about IAM
+-- roles, see Working with Roles in the AWS Identity and Access Management
+-- User Guide.
+eciIamInstanceProfile :: Lens' EC2Instance (Maybe (Val Text))
+eciIamInstanceProfile = lens _eC2InstanceIamInstanceProfile (\s a -> s { _eC2InstanceIamInstanceProfile = a })
+
+-- | Provides the unique ID of the Amazon Machine Image (AMI) that was
+-- assigned during registration.
+eciImageId :: Lens' EC2Instance (Val Text)
+eciImageId = lens _eC2InstanceImageId (\s a -> s { _eC2InstanceImageId = a })
+
+-- | Indicates whether an instance stops or terminates when you shut down the
+-- instance from the instance's operating system shutdown command. You can
+-- specify stop or terminate. For more information, see the RunInstances
+-- command in the Amazon EC2 API Reference.
+eciInstanceInitiatedShutdownBehavior :: Lens' EC2Instance (Maybe (Val Text))
+eciInstanceInitiatedShutdownBehavior = lens _eC2InstanceInstanceInitiatedShutdownBehavior (\s a -> s { _eC2InstanceInstanceInitiatedShutdownBehavior = a })
+
+-- | The instance type, such as t2.micro. The default type is "m1.small". For
+-- a list of instance types, see Instance Families and Types.
+eciInstanceType :: Lens' EC2Instance (Maybe (Val Text))
+eciInstanceType = lens _eC2InstanceInstanceType (\s a -> s { _eC2InstanceInstanceType = a })
+
+-- | The kernel ID.
+eciKernelId :: Lens' EC2Instance (Maybe (Val Text))
+eciKernelId = lens _eC2InstanceKernelId (\s a -> s { _eC2InstanceKernelId = a })
+
+-- | Provides the name of the Amazon EC2 key pair.
+eciKeyName :: Lens' EC2Instance (Maybe (Val Text))
+eciKeyName = lens _eC2InstanceKeyName (\s a -> s { _eC2InstanceKeyName = a })
+
+-- | Specifies whether monitoring is enabled for the instance.
+eciMonitoring :: Lens' EC2Instance (Maybe (Val Bool'))
+eciMonitoring = lens _eC2InstanceMonitoring (\s a -> s { _eC2InstanceMonitoring = a })
+
+-- | A list of embedded objects that describe the network interfaces to
+-- associate with this instance. Note If this resource has a public IP address
+-- and is also in a VPC that is defined in the same template, you must use the
+-- DependsOn attribute to declare a dependency on the VPC-gateway attachment.
+-- For more information, see DependsOn Attribute.
+eciNetworkInterfaces :: Lens' EC2Instance (Maybe [NetworkInterface])
+eciNetworkInterfaces = lens _eC2InstanceNetworkInterfaces (\s a -> s { _eC2InstanceNetworkInterfaces = a })
+
+-- | The name of an existing placement group that you want to launch the
+-- instance into (for cluster instances).
+eciPlacementGroupName :: Lens' EC2Instance (Maybe (Val Text))
+eciPlacementGroupName = lens _eC2InstancePlacementGroupName (\s a -> s { _eC2InstancePlacementGroupName = a })
+
+-- | The private IP address for this instance. Important If you make an update
+-- to an instance that requires replacement, you must assign a new private IP
+-- address. During a replacement, AWS CloudFormation creates a new instance
+-- but doesn't delete the old instance until the stack has successfully
+-- updated. If the stack update fails, AWS CloudFormation uses the old
+-- instance in order to roll back the stack to the previous working state. The
+-- old and new instances cannot have the same private IP address. (Optional)
+-- If you're using Amazon VPC, you can use this parameter to assign the
+-- instance a specific available IP address from the subnet (for example,
+-- 10.0.0.25). By default, Amazon VPC selects an IP address from the subnet
+-- for the instance.
+eciPrivateIpAddress :: Lens' EC2Instance (Maybe (Val Text))
+eciPrivateIpAddress = lens _eC2InstancePrivateIpAddress (\s a -> s { _eC2InstancePrivateIpAddress = a })
+
+-- | The ID of the RAM disk to select. Some kernels require additional drivers
+-- at launch. Check the kernel requirements for information about whether you
+-- need to specify a RAM disk. To find kernel requirements, go to the AWS
+-- Resource Center and search for the kernel ID.
+eciRamdiskId :: Lens' EC2Instance (Maybe (Val Text))
+eciRamdiskId = lens _eC2InstanceRamdiskId (\s a -> s { _eC2InstanceRamdiskId = a })
+
+-- | A list that contains the security group IDs for VPC security groups to
+-- assign to the Amazon EC2 instance. If you specified the NetworkInterfaces
+-- property, do not specify this property.
+eciSecurityGroupIds :: Lens' EC2Instance (Maybe [Val Text])
+eciSecurityGroupIds = lens _eC2InstanceSecurityGroupIds (\s a -> s { _eC2InstanceSecurityGroupIds = a })
+
+-- | Valid only for Amazon EC2 security groups. A list that contains the
+-- Amazon EC2 security groups to assign to the Amazon EC2 instance. The list
+-- can contain both the name of existing Amazon EC2 security groups or
+-- references to AWS::EC2::SecurityGroup resources created in the template.
+eciSecurityGroups :: Lens' EC2Instance (Maybe [Val Text])
+eciSecurityGroups = lens _eC2InstanceSecurityGroups (\s a -> s { _eC2InstanceSecurityGroups = a })
+
+-- | Controls whether source/destination checking is enabled on the instance.
+-- Also determines if an instance in a VPC will perform network address
+-- translation (NAT). A value of "true" means that source/destination checking
+-- is enabled, and a value of "false" means that checking is disabled. For the
+-- instance to perform NAT, the value must be "false". For more information,
+-- see NAT Instances in the Amazon Virtual Private Cloud User Guide.
+eciSourceDestCheck :: Lens' EC2Instance (Maybe (Val Bool'))
+eciSourceDestCheck = lens _eC2InstanceSourceDestCheck (\s a -> s { _eC2InstanceSourceDestCheck = a })
+
+-- | The Amazon EC2 Simple Systems Manager (SSM) document and parameter values
+-- to associate with this instance. To use this property, you must specify an
+-- IAM role for the instance. For more information, see Prerequisites for
+-- Remotely Running Commands on EC2 Instances in the Amazon EC2 User Guide for
+-- Microsoft Windows Instances. Note You can currently associate only one
+-- document with an instance.
+eciSsmAssociations :: Lens' EC2Instance (Maybe [EC2SsmAssociations])
+eciSsmAssociations = lens _eC2InstanceSsmAssociations (\s a -> s { _eC2InstanceSsmAssociations = a })
+
+-- | If you're using Amazon VPC, this property specifies the ID of the subnet
+-- that you want to launch the instance into. If you specified the
+-- NetworkInterfaces property, do not specify this property.
+eciSubnetId :: Lens' EC2Instance (Maybe (Val Text))
+eciSubnetId = lens _eC2InstanceSubnetId (\s a -> s { _eC2InstanceSubnetId = a })
+
+-- | An arbitrary set of tags (key–value pairs) for this instance.
+eciTags :: Lens' EC2Instance (Maybe [ResourceTag])
+eciTags = lens _eC2InstanceTags (\s a -> s { _eC2InstanceTags = a })
+
+-- | The tenancy of the instance that you want to launch. This value can be
+-- either "default" or "dedicated". An instance that has a tenancy value of
+-- "dedicated" runs on single-tenant hardware and can be launched only into a
+-- VPC. For more information, see Using EC2 Dedicated Instances Within Your
+-- VPC in the Amazon VPC User Guide.
+eciTenancy :: Lens' EC2Instance (Maybe (Val Text))
+eciTenancy = lens _eC2InstanceTenancy (\s a -> s { _eC2InstanceTenancy = a })
+
+-- | Base64-encoded MIME user data that is made available to the instances.
+eciUserData :: Lens' EC2Instance (Maybe (Val Text))
+eciUserData = lens _eC2InstanceUserData (\s a -> s { _eC2InstanceUserData = a })
+
+-- | The Amazon EBS volumes to attach to the instance. Note Before detaching a
+-- volume, unmount any file systems on the device within your operating
+-- system. If you don't unmount the file system, a volume might get stuck in a
+-- busy state while detaching.
+eciVolumes :: Lens' EC2Instance (Maybe [EC2MountPoint])
+eciVolumes = lens _eC2InstanceVolumes (\s a -> s { _eC2InstanceVolumes = a })
+
+-- | Reserved.
+eciAdditionalInfo :: Lens' EC2Instance (Maybe (Val Text))
+eciAdditionalInfo = lens _eC2InstanceAdditionalInfo (\s a -> s { _eC2InstanceAdditionalInfo = a })
diff --git a/library-gen/Stratosphere/Resources/EIP.hs b/library-gen/Stratosphere/Resources/EIP.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/EIP.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::EC2::EIP resource allocates an Elastic IP (EIP) address and can,
+-- optionally, associate it with an Amazon EC2 instance.
+
+module Stratosphere.Resources.EIP where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for EIP. See 'eip' for a more convenient
+-- constructor.
+data EIP =
+  EIP
+  { _eIPInstanceId :: Maybe (Val Text)
+  , _eIPDomain :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON EIP where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 4, omitNothingFields = True }
+
+instance FromJSON EIP where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 4, omitNothingFields = True }
+
+-- | Constructor for 'EIP' containing required fields as arguments.
+eip
+  :: EIP
+eip  =
+  EIP
+  { _eIPInstanceId = Nothing
+  , _eIPDomain = Nothing
+  }
+
+-- | The Instance ID of the Amazon EC2 instance that you want to associate
+-- with this Elastic IP address.
+eipInstanceId :: Lens' EIP (Maybe (Val Text))
+eipInstanceId = lens _eIPInstanceId (\s a -> s { _eIPInstanceId = a })
+
+-- | Set to vpc to allocate the address to your Virtual Private Cloud (VPC).
+-- No other values are supported. Note If you define an Elastic IP address and
+-- associate it with a VPC that is defined in the same template, you must
+-- declare a dependency on the VPC-gateway attachment by using the DependsOn
+-- attribute on this resource. For more information, see DependsOn Attribute.
+-- For more information, see AllocateAddress in the Amazon EC2 API Reference.
+-- For more information about Elastic IP Addresses in VPC, go to IP Addressing
+-- in Your VPC in the Amazon VPC User Guide.
+eipDomain :: Lens' EIP (Maybe (Val Text))
+eipDomain = lens _eIPDomain (\s a -> s { _eIPDomain = a })
diff --git a/library-gen/Stratosphere/Resources/EIPAssociation.hs b/library-gen/Stratosphere/Resources/EIPAssociation.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/EIPAssociation.hs
@@ -0,0 +1,78 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::EC2::EIPAssociation resource type associates an Elastic IP
+-- address with an Amazon EC2 instance. The Elastic IP address can be an
+-- existing Elastic IP address or an Elastic IP address allocated through an
+-- AWS::EC2::EIP resource. This type supports updates. For more information
+-- about updating stacks, see AWS CloudFormation Stacks Updates.
+
+module Stratosphere.Resources.EIPAssociation where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for EIPAssociation. See 'eipAssociation' for a
+-- more convenient constructor.
+data EIPAssociation =
+  EIPAssociation
+  { _eIPAssociationAllocationId :: Maybe (Val Text)
+  , _eIPAssociationEIP :: Maybe (Val Text)
+  , _eIPAssociationInstanceId :: Maybe (Val Text)
+  , _eIPAssociationNetworkInterfaceId :: Maybe (Val Text)
+  , _eIPAssociationPrivateIpAddress :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON EIPAssociation where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 15, omitNothingFields = True }
+
+instance FromJSON EIPAssociation where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 15, omitNothingFields = True }
+
+-- | Constructor for 'EIPAssociation' containing required fields as arguments.
+eipAssociation
+  :: EIPAssociation
+eipAssociation  =
+  EIPAssociation
+  { _eIPAssociationAllocationId = Nothing
+  , _eIPAssociationEIP = Nothing
+  , _eIPAssociationInstanceId = Nothing
+  , _eIPAssociationNetworkInterfaceId = Nothing
+  , _eIPAssociationPrivateIpAddress = Nothing
+  }
+
+-- | Allocation ID for the VPC Elastic IP address you want to associate with
+-- an Amazon EC2 instance in your VPC.
+eipaAllocationId :: Lens' EIPAssociation (Maybe (Val Text))
+eipaAllocationId = lens _eIPAssociationAllocationId (\s a -> s { _eIPAssociationAllocationId = a })
+
+-- | Elastic IP address that you want to associate with the Amazon EC2
+-- instance specified by the InstanceId property. You can specify an existing
+-- Elastic IP address or a reference to an Elastic IP address allocated with a
+-- AWS::EC2::EIP resource.
+eipaEIP :: Lens' EIPAssociation (Maybe (Val Text))
+eipaEIP = lens _eIPAssociationEIP (\s a -> s { _eIPAssociationEIP = a })
+
+-- | Instance ID of the Amazon EC2 instance that you want to associate with
+-- the Elastic IP address specified by the EIP property.
+eipaInstanceId :: Lens' EIPAssociation (Maybe (Val Text))
+eipaInstanceId = lens _eIPAssociationInstanceId (\s a -> s { _eIPAssociationInstanceId = a })
+
+-- | The ID of the network interface to associate with the Elastic IP address
+-- (VPC only).
+eipaNetworkInterfaceId :: Lens' EIPAssociation (Maybe (Val Text))
+eipaNetworkInterfaceId = lens _eIPAssociationNetworkInterfaceId (\s a -> s { _eIPAssociationNetworkInterfaceId = a })
+
+-- | The private IP address that you want to associate with the Elastic IP
+-- address. The private IP address is restricted to the primary and secondary
+-- private IP addresses that are associated with the network interface. By
+-- default, the private IP address that is associated with the EIP is the
+-- primary private IP address of the network interface.
+eipaPrivateIpAddress :: Lens' EIPAssociation (Maybe (Val Text))
+eipaPrivateIpAddress = lens _eIPAssociationPrivateIpAddress (\s a -> s { _eIPAssociationPrivateIpAddress = a })
diff --git a/library-gen/Stratosphere/Resources/Group.hs b/library-gen/Stratosphere/Resources/Group.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/Group.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::IAM::Group type creates an Identity and Access Management (IAM)
+-- group. This type supports updates. For more information about updating
+-- stacks, see AWS CloudFormation Stacks Updates.
+
+module Stratosphere.Resources.Group where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.IAMPolicies
+
+-- | Full data type definition for Group. See 'group' for a more convenient
+-- constructor.
+data Group =
+  Group
+  { _groupManagedPolicyArns :: Maybe [Val Text]
+  , _groupPath :: Maybe (Val Text)
+  , _groupPolicies :: Maybe [IAMPolicies]
+  } deriving (Show, Generic)
+
+instance ToJSON Group where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 6, omitNothingFields = True }
+
+instance FromJSON Group where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 6, omitNothingFields = True }
+
+-- | Constructor for 'Group' containing required fields as arguments.
+group
+  :: Group
+group  =
+  Group
+  { _groupManagedPolicyArns = Nothing
+  , _groupPath = Nothing
+  , _groupPolicies = Nothing
+  }
+
+-- | One or more managed policy ARNs to attach to this group.
+gManagedPolicyArns :: Lens' Group (Maybe [Val Text])
+gManagedPolicyArns = lens _groupManagedPolicyArns (\s a -> s { _groupManagedPolicyArns = a })
+
+-- | The path to the group. For more information about paths, see Identifiers
+-- for IAM Entities in Using IAM.
+gPath :: Lens' Group (Maybe (Val Text))
+gPath = lens _groupPath (\s a -> s { _groupPath = a })
+
+-- | The policies to associate with this group. For information about
+-- policies, see Overview of Policies in Using IAM.
+gPolicies :: Lens' Group (Maybe [IAMPolicies])
+gPolicies = lens _groupPolicies (\s a -> s { _groupPolicies = a })
diff --git a/library-gen/Stratosphere/Resources/IAMRole.hs b/library-gen/Stratosphere/Resources/IAMRole.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/IAMRole.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Creates an AWS Identity and Access Management (IAM) role. An IAM role can
+-- be used to enable applications running on an Amazon EC2 instance to
+-- securely access your AWS resources. For more information about IAM roles,
+-- see Working with Roles in the AWS Identity and Access Management User
+-- Guide.
+
+module Stratosphere.Resources.IAMRole where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.IAMPolicies
+
+-- | Full data type definition for IAMRole. See 'iamRole' for a more
+-- convenient constructor.
+data IAMRole =
+  IAMRole
+  { _iAMRoleAssumeRolePolicyDocument :: Object
+  , _iAMRoleManagedPolicyArns :: Maybe [Val Text]
+  , _iAMRolePath :: Maybe (Val Text)
+  , _iAMRolePolicies :: Maybe [IAMPolicies]
+  } deriving (Show, Generic)
+
+instance ToJSON IAMRole where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 8, omitNothingFields = True }
+
+instance FromJSON IAMRole where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 8, omitNothingFields = True }
+
+-- | Constructor for 'IAMRole' containing required fields as arguments.
+iamRole
+  :: Object -- ^ 'iamrAssumeRolePolicyDocument'
+  -> IAMRole
+iamRole assumeRolePolicyDocumentarg =
+  IAMRole
+  { _iAMRoleAssumeRolePolicyDocument = assumeRolePolicyDocumentarg
+  , _iAMRoleManagedPolicyArns = Nothing
+  , _iAMRolePath = Nothing
+  , _iAMRolePolicies = Nothing
+  }
+
+-- | The IAM assume role policy that is associated with this role.
+iamrAssumeRolePolicyDocument :: Lens' IAMRole Object
+iamrAssumeRolePolicyDocument = lens _iAMRoleAssumeRolePolicyDocument (\s a -> s { _iAMRoleAssumeRolePolicyDocument = a })
+
+-- | One or more managed policy ARNs to attach to this role.
+iamrManagedPolicyArns :: Lens' IAMRole (Maybe [Val Text])
+iamrManagedPolicyArns = lens _iAMRoleManagedPolicyArns (\s a -> s { _iAMRoleManagedPolicyArns = a })
+
+-- | The path associated with this role. For information about IAM paths, see
+-- Friendly Names and Paths in IAM User Guide.
+iamrPath :: Lens' IAMRole (Maybe (Val Text))
+iamrPath = lens _iAMRolePath (\s a -> s { _iAMRolePath = a })
+
+-- | The policies to associate with this role. Policies can also be specified
+-- externally. For sample templates that demonstrates both embedded and
+-- external policies, see Template Examples. If you specify multiple polices,
+-- specify unique values for the policy name. If you don't, updates to the IAM
+-- role will fail. Note If an external policy (such as AWS::IAM::Policy or
+-- AWS::IAM::ManagedPolicy) has a Ref to a role and if a resource (such as
+-- AWS::ECS::Service) also has a Ref to the same role, add a DependsOn
+-- attribute to the resource so that the resource depends on the external
+-- policy. This dependency ensures that the role's policy is available
+-- throughout the resource's lifecycle. For example, when you delete a stack
+-- with an AWS::ECS::Service resource, the DependsOn attribute ensures that
+-- the AWS::ECS::Service resource can complete its deletion before its role's
+-- policy is deleted.
+iamrPolicies :: Lens' IAMRole (Maybe [IAMPolicies])
+iamrPolicies = lens _iAMRolePolicies (\s a -> s { _iAMRolePolicies = a })
diff --git a/library-gen/Stratosphere/Resources/InstanceProfile.hs b/library-gen/Stratosphere/Resources/InstanceProfile.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/InstanceProfile.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Creates an AWS Identity and Access Management (IAM) Instance Profile that
+-- can be used with IAM Roles for EC2 Instances. For more information about
+-- IAM roles, see Working with Roles in the AWS Identity and Access Management
+-- User Guide.
+
+module Stratosphere.Resources.InstanceProfile where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for InstanceProfile. See 'instanceProfile' for
+-- a more convenient constructor.
+data InstanceProfile =
+  InstanceProfile
+  { _instanceProfilePath :: Val Text
+  , _instanceProfileRoles :: [Val Text]
+  } deriving (Show, Generic)
+
+instance ToJSON InstanceProfile where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 16, omitNothingFields = True }
+
+instance FromJSON InstanceProfile where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 16, omitNothingFields = True }
+
+-- | Constructor for 'InstanceProfile' containing required fields as
+-- arguments.
+instanceProfile
+  :: Val Text -- ^ 'ipPath'
+  -> [Val Text] -- ^ 'ipRoles'
+  -> InstanceProfile
+instanceProfile patharg rolesarg =
+  InstanceProfile
+  { _instanceProfilePath = patharg
+  , _instanceProfileRoles = rolesarg
+  }
+
+-- | The path associated with this IAM instance profile. For information about
+-- IAM paths, see Friendly Names and Paths in the AWS Identity and Access
+-- Management User Guide.
+ipPath :: Lens' InstanceProfile (Val Text)
+ipPath = lens _instanceProfilePath (\s a -> s { _instanceProfilePath = a })
+
+-- | The roles associated with this IAM instance profile.
+ipRoles :: Lens' InstanceProfile [Val Text]
+ipRoles = lens _instanceProfileRoles (\s a -> s { _instanceProfileRoles = a })
diff --git a/library-gen/Stratosphere/Resources/InternetGateway.hs b/library-gen/Stratosphere/Resources/InternetGateway.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/InternetGateway.hs
@@ -0,0 +1,42 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Creates a new Internet gateway in your AWS account. After creating the
+-- Internet gateway, you then attach it to a VPC.
+
+module Stratosphere.Resources.InternetGateway where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.ResourceTag
+
+-- | Full data type definition for InternetGateway. See 'internetGateway' for
+-- a more convenient constructor.
+data InternetGateway =
+  InternetGateway
+  { _internetGatewayTags :: Maybe [ResourceTag]
+  } deriving (Show, Generic)
+
+instance ToJSON InternetGateway where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 16, omitNothingFields = True }
+
+instance FromJSON InternetGateway where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 16, omitNothingFields = True }
+
+-- | Constructor for 'InternetGateway' containing required fields as
+-- arguments.
+internetGateway
+  :: InternetGateway
+internetGateway  =
+  InternetGateway
+  { _internetGatewayTags = Nothing
+  }
+
+-- | An arbitrary set of tags (key–value pairs) for this resource.
+igTags :: Lens' InternetGateway (Maybe [ResourceTag])
+igTags = lens _internetGatewayTags (\s a -> s { _internetGatewayTags = a })
diff --git a/library-gen/Stratosphere/Resources/LoadBalancer.hs b/library-gen/Stratosphere/Resources/LoadBalancer.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/LoadBalancer.hs
@@ -0,0 +1,176 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::ElasticLoadBalancing::LoadBalancer type creates a LoadBalancer.
+
+module Stratosphere.Resources.LoadBalancer where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.AccessLoggingPolicy
+import Stratosphere.ResourceProperties.AppCookieStickinessPolicy
+import Stratosphere.ResourceProperties.ConnectionDrainingPolicy
+import Stratosphere.ResourceProperties.ConnectionSettings
+import Stratosphere.ResourceProperties.HealthCheck
+import Stratosphere.ResourceProperties.LBCookieStickinessPolicy
+import Stratosphere.ResourceProperties.ListenerProperty
+import Stratosphere.ResourceProperties.ELBPolicy
+import Stratosphere.ResourceProperties.ResourceTag
+
+-- | Full data type definition for LoadBalancer. See 'loadBalancer' for a more
+-- convenient constructor.
+data LoadBalancer =
+  LoadBalancer
+  { _loadBalancerAccessLoggingPolicy :: Maybe AccessLoggingPolicy
+  , _loadBalancerAppCookieStickinessPolicy :: Maybe [AppCookieStickinessPolicy]
+  , _loadBalancerAvailabilityZones :: Maybe [Val Text]
+  , _loadBalancerConnectionDrainingPolicy :: Maybe ConnectionDrainingPolicy
+  , _loadBalancerConnectionSettings :: Maybe ConnectionSettings
+  , _loadBalancerCrossZone :: Maybe (Val Bool')
+  , _loadBalancerHealthCheck :: Maybe HealthCheck
+  , _loadBalancerInstances :: Maybe [Val Text]
+  , _loadBalancerLBCookieStickinessPolicy :: Maybe [LBCookieStickinessPolicy]
+  , _loadBalancerLoadBalancerName :: Maybe (Val Text)
+  , _loadBalancerListeners :: [ListenerProperty]
+  , _loadBalancerPolicies :: Maybe [ELBPolicy]
+  , _loadBalancerScheme :: Maybe (Val Text)
+  , _loadBalancerSecurityGroups :: Maybe [Val Text]
+  , _loadBalancerSubnets :: Maybe [Val Text]
+  , _loadBalancerTags :: Maybe [ResourceTag]
+  } deriving (Show, Generic)
+
+instance ToJSON LoadBalancer where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 13, omitNothingFields = True }
+
+instance FromJSON LoadBalancer where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 13, omitNothingFields = True }
+
+-- | Constructor for 'LoadBalancer' containing required fields as arguments.
+loadBalancer
+  :: [ListenerProperty] -- ^ 'lbListeners'
+  -> LoadBalancer
+loadBalancer listenersarg =
+  LoadBalancer
+  { _loadBalancerAccessLoggingPolicy = Nothing
+  , _loadBalancerAppCookieStickinessPolicy = Nothing
+  , _loadBalancerAvailabilityZones = Nothing
+  , _loadBalancerConnectionDrainingPolicy = Nothing
+  , _loadBalancerConnectionSettings = Nothing
+  , _loadBalancerCrossZone = Nothing
+  , _loadBalancerHealthCheck = Nothing
+  , _loadBalancerInstances = Nothing
+  , _loadBalancerLBCookieStickinessPolicy = Nothing
+  , _loadBalancerLoadBalancerName = Nothing
+  , _loadBalancerListeners = listenersarg
+  , _loadBalancerPolicies = Nothing
+  , _loadBalancerScheme = Nothing
+  , _loadBalancerSecurityGroups = Nothing
+  , _loadBalancerSubnets = Nothing
+  , _loadBalancerTags = Nothing
+  }
+
+-- | Captures detailed information for all requests made to your load
+-- balancer, such as the time a request was received, client’s IP address,
+-- latencies, request path, and server responses.
+lbAccessLoggingPolicy :: Lens' LoadBalancer (Maybe AccessLoggingPolicy)
+lbAccessLoggingPolicy = lens _loadBalancerAccessLoggingPolicy (\s a -> s { _loadBalancerAccessLoggingPolicy = a })
+
+-- | Generates one or more stickiness policies with sticky session lifetimes
+-- that follow that of an application-generated cookie. These policies can be
+-- associated only with HTTP/HTTPS listeners.
+lbAppCookieStickinessPolicy :: Lens' LoadBalancer (Maybe [AppCookieStickinessPolicy])
+lbAppCookieStickinessPolicy = lens _loadBalancerAppCookieStickinessPolicy (\s a -> s { _loadBalancerAppCookieStickinessPolicy = a })
+
+-- | The Availability Zones in which to create the load balancer. You can
+-- specify the AvailabilityZones or Subnets property, but not both. Note For
+-- load balancers that are in a VPC, specify the Subnets property.
+lbAvailabilityZones :: Lens' LoadBalancer (Maybe [Val Text])
+lbAvailabilityZones = lens _loadBalancerAvailabilityZones (\s a -> s { _loadBalancerAvailabilityZones = a })
+
+-- | Whether deregistered or unhealthy instances can complete all in-flight
+-- requests.
+lbConnectionDrainingPolicy :: Lens' LoadBalancer (Maybe ConnectionDrainingPolicy)
+lbConnectionDrainingPolicy = lens _loadBalancerConnectionDrainingPolicy (\s a -> s { _loadBalancerConnectionDrainingPolicy = a })
+
+-- | Specifies how long front-end and back-end connections of your load
+-- balancer can remain idle.
+lbConnectionSettings :: Lens' LoadBalancer (Maybe ConnectionSettings)
+lbConnectionSettings = lens _loadBalancerConnectionSettings (\s a -> s { _loadBalancerConnectionSettings = a })
+
+-- | Whether cross-zone load balancing is enabled for the load balancer. With
+-- cross-zone load balancing, your load balancer nodes route traffic to the
+-- back-end instances across all Availability Zones. By default the CrossZone
+-- property is false.
+lbCrossZone :: Lens' LoadBalancer (Maybe (Val Bool'))
+lbCrossZone = lens _loadBalancerCrossZone (\s a -> s { _loadBalancerCrossZone = a })
+
+-- | Application health check for the instances.
+lbHealthCheck :: Lens' LoadBalancer (Maybe HealthCheck)
+lbHealthCheck = lens _loadBalancerHealthCheck (\s a -> s { _loadBalancerHealthCheck = a })
+
+-- | A list of EC2 instance IDs for the load balancer.
+lbInstances :: Lens' LoadBalancer (Maybe [Val Text])
+lbInstances = lens _loadBalancerInstances (\s a -> s { _loadBalancerInstances = a })
+
+-- | Generates a stickiness policy with sticky session lifetimes controlled by
+-- the lifetime of the browser (user-agent), or by a specified expiration
+-- period. This policy can be associated only with HTTP/HTTPS listeners.
+lbLBCookieStickinessPolicy :: Lens' LoadBalancer (Maybe [LBCookieStickinessPolicy])
+lbLBCookieStickinessPolicy = lens _loadBalancerLBCookieStickinessPolicy (\s a -> s { _loadBalancerLBCookieStickinessPolicy = a })
+
+-- | A name for the load balancer. If you don't specify a name, AWS
+-- CloudFormation generates a unique physical ID and uses that ID for the load
+-- balancer. The name must be unique within your set of load balancers. For
+-- more information, see Name Type. Important If you specify a name, you
+-- cannot do updates that require this resource to be replaced. You can still
+-- do updates that require no or some interruption. If you must replace the
+-- resource, specify a new name.
+lbLoadBalancerName :: Lens' LoadBalancer (Maybe (Val Text))
+lbLoadBalancerName = lens _loadBalancerLoadBalancerName (\s a -> s { _loadBalancerLoadBalancerName = a })
+
+-- | One or more listeners for this load balancer. Each listener must be
+-- registered for a specific port, and you cannot have more than one listener
+-- for a given port. Important If you update the property values for a
+-- listener specified by the Listeners property, AWS CloudFormation will
+-- delete the existing listener and create a new one with the updated
+-- properties. During the time that AWS CloudFormation is performing this
+-- action, clients will not be able to connect to the load balancer.
+lbListeners :: Lens' LoadBalancer [ListenerProperty]
+lbListeners = lens _loadBalancerListeners (\s a -> s { _loadBalancerListeners = a })
+
+-- | A list of elastic load balancing policies to apply to this elastic load
+-- balancer.
+lbPolicies :: Lens' LoadBalancer (Maybe [ELBPolicy])
+lbPolicies = lens _loadBalancerPolicies (\s a -> s { _loadBalancerPolicies = a })
+
+-- | For load balancers attached to an Amazon VPC, this parameter can be used
+-- to specify the type of load balancer to use. Specify internal to create an
+-- internal load balancer with a DNS name that resolves to private IP
+-- addresses or internet-facing to create a load balancer with a publicly
+-- resolvable DNS name, which resolves to public IP addresses. Note If you
+-- specify internal, you must specify subnets to associate with the load
+-- balancer, not Availability Zones.
+lbScheme :: Lens' LoadBalancer (Maybe (Val Text))
+lbScheme = lens _loadBalancerScheme (\s a -> s { _loadBalancerScheme = a })
+
+-- |
+lbSecurityGroups :: Lens' LoadBalancer (Maybe [Val Text])
+lbSecurityGroups = lens _loadBalancerSecurityGroups (\s a -> s { _loadBalancerSecurityGroups = a })
+
+-- | A list of subnet IDs in your virtual private cloud (VPC) to attach to
+-- your load balancer. Do not specify multiple subnets that are in the same
+-- Availability Zone. You can specify the AvailabilityZones or Subnets
+-- property, but not both. For more information about using Elastic Load
+-- Balancing in a VPC, see How Do I Use Elastic Load Balancing in Amazon VPC
+-- in the Elastic Load Balancing Developer Guide.
+lbSubnets :: Lens' LoadBalancer (Maybe [Val Text])
+lbSubnets = lens _loadBalancerSubnets (\s a -> s { _loadBalancerSubnets = a })
+
+-- | An arbitrary set of tags (key-value pairs) for this load balancer.
+lbTags :: Lens' LoadBalancer (Maybe [ResourceTag])
+lbTags = lens _loadBalancerTags (\s a -> s { _loadBalancerTags = a })
diff --git a/library-gen/Stratosphere/Resources/ManagedPolicy.hs b/library-gen/Stratosphere/Resources/ManagedPolicy.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/ManagedPolicy.hs
@@ -0,0 +1,86 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | AWS::IAM::ManagedPolicy creates an AWS Identity and Access Management
+-- (IAM) managed policy for your AWS account that you can use to apply
+-- permissions to IAM users, groups, and roles. For more information about
+-- managed policies, see Managed Policies and Inline Policies in the IAM User
+-- Guide guide.
+
+module Stratosphere.Resources.ManagedPolicy where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for ManagedPolicy. See 'managedPolicy' for a
+-- more convenient constructor.
+data ManagedPolicy =
+  ManagedPolicy
+  { _managedPolicyDescription :: Maybe (Val Text)
+  , _managedPolicyGroups :: Maybe [Val Text]
+  , _managedPolicyPath :: Maybe (Val Text)
+  , _managedPolicyPolicyDocument :: Object
+  , _managedPolicyRoles :: Maybe [Val Text]
+  , _managedPolicyUsers :: Maybe [Val Text]
+  } deriving (Show, Generic)
+
+instance ToJSON ManagedPolicy where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 14, omitNothingFields = True }
+
+instance FromJSON ManagedPolicy where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 14, omitNothingFields = True }
+
+-- | Constructor for 'ManagedPolicy' containing required fields as arguments.
+managedPolicy
+  :: Object -- ^ 'mpPolicyDocument'
+  -> ManagedPolicy
+managedPolicy policyDocumentarg =
+  ManagedPolicy
+  { _managedPolicyDescription = Nothing
+  , _managedPolicyGroups = Nothing
+  , _managedPolicyPath = Nothing
+  , _managedPolicyPolicyDocument = policyDocumentarg
+  , _managedPolicyRoles = Nothing
+  , _managedPolicyUsers = Nothing
+  }
+
+-- | A description of the policy. For example, you can describe the
+-- permissions that are defined in the policy.
+mpDescription :: Lens' ManagedPolicy (Maybe (Val Text))
+mpDescription = lens _managedPolicyDescription (\s a -> s { _managedPolicyDescription = a })
+
+-- | The names of groups to attach to this policy.
+mpGroups :: Lens' ManagedPolicy (Maybe [Val Text])
+mpGroups = lens _managedPolicyGroups (\s a -> s { _managedPolicyGroups = a })
+
+-- | The path for the policy. By default, the path is /. For more information,
+-- see IAM Identifiers in the IAM User Guide guide.
+mpPath :: Lens' ManagedPolicy (Maybe (Val Text))
+mpPath = lens _managedPolicyPath (\s a -> s { _managedPolicyPath = a })
+
+-- | Policies that define the permissions for this managed policy. For more
+-- information about policy syntax, see IAM Policy Elements Reference in IAM
+-- User Guide.
+mpPolicyDocument :: Lens' ManagedPolicy Object
+mpPolicyDocument = lens _managedPolicyPolicyDocument (\s a -> s { _managedPolicyPolicyDocument = a })
+
+-- | The names of roles to attach to this policy. Note If a policy has a Ref
+-- to a role and if a resource (such as AWS::ECS::Service) also has a Ref to
+-- the same role, add a DependsOn attribute to the resource so that the
+-- resource depends on the policy. This dependency ensures that the role's
+-- policy is available throughout the resource's lifecycle. For example, when
+-- you delete a stack with an AWS::ECS::Service resource, the DependsOn
+-- attribute ensures that the AWS::ECS::Service resource can complete its
+-- deletion before its role's policy is deleted.
+mpRoles :: Lens' ManagedPolicy (Maybe [Val Text])
+mpRoles = lens _managedPolicyRoles (\s a -> s { _managedPolicyRoles = a })
+
+-- | The names of users to attach to this policy.
+mpUsers :: Lens' ManagedPolicy (Maybe [Val Text])
+mpUsers = lens _managedPolicyUsers (\s a -> s { _managedPolicyUsers = a })
diff --git a/library-gen/Stratosphere/Resources/NatGateway.hs b/library-gen/Stratosphere/Resources/NatGateway.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/NatGateway.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::EC2::NatGateway resource creates a network address translation
+-- (NAT) gateway in the specified public subnet. Use a NAT gateway to allow
+-- instances in a private subnet to connect to the Internet or to other AWS
+-- services, but prevent the Internet from initiating a connection with those
+-- instances. For more information and a sample architectural diagram, see NAT
+-- Gateways in the Amazon VPC User Guide.
+
+module Stratosphere.Resources.NatGateway where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for NatGateway. See 'natGateway' for a more
+-- convenient constructor.
+data NatGateway =
+  NatGateway
+  { _natGatewayAllocationId :: Val Text
+  , _natGatewaySubnetId :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON NatGateway where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 11, omitNothingFields = True }
+
+instance FromJSON NatGateway where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 11, omitNothingFields = True }
+
+-- | Constructor for 'NatGateway' containing required fields as arguments.
+natGateway
+  :: Val Text -- ^ 'ngAllocationId'
+  -> Val Text -- ^ 'ngSubnetId'
+  -> NatGateway
+natGateway allocationIdarg subnetIdarg =
+  NatGateway
+  { _natGatewayAllocationId = allocationIdarg
+  , _natGatewaySubnetId = subnetIdarg
+  }
+
+-- | The allocation ID of an Elastic IP address to associate with the NAT
+-- gateway. If the Elastic IP address is associated with another resource, you
+-- must first disassociate it.
+ngAllocationId :: Lens' NatGateway (Val Text)
+ngAllocationId = lens _natGatewayAllocationId (\s a -> s { _natGatewayAllocationId = a })
+
+-- | The public subnet in which to create the NAT gateway.
+ngSubnetId :: Lens' NatGateway (Val Text)
+ngSubnetId = lens _natGatewaySubnetId (\s a -> s { _natGatewaySubnetId = a })
diff --git a/library-gen/Stratosphere/Resources/Policy.hs b/library-gen/Stratosphere/Resources/Policy.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/Policy.hs
@@ -0,0 +1,78 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::IAM::Policy resource associates an IAM policy with IAM users,
+-- roles, or groups. For more information about IAM policies, see Overview of
+-- IAM Policies in the IAM User Guide guide.
+
+module Stratosphere.Resources.Policy where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for Policy. See 'policy' for a more convenient
+-- constructor.
+data Policy =
+  Policy
+  { _policyGroups :: Maybe [Val Text]
+  , _policyPolicyDocument :: Object
+  , _policyPolicyName :: Val Text
+  , _policyRoles :: Maybe [Val Text]
+  , _policyUsers :: Maybe [Val Text]
+  } deriving (Show, Generic)
+
+instance ToJSON Policy where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 7, omitNothingFields = True }
+
+instance FromJSON Policy where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 7, omitNothingFields = True }
+
+-- | Constructor for 'Policy' containing required fields as arguments.
+policy
+  :: Object -- ^ 'pPolicyDocument'
+  -> Val Text -- ^ 'pPolicyName'
+  -> Policy
+policy policyDocumentarg policyNamearg =
+  Policy
+  { _policyGroups = Nothing
+  , _policyPolicyDocument = policyDocumentarg
+  , _policyPolicyName = policyNamearg
+  , _policyRoles = Nothing
+  , _policyUsers = Nothing
+  }
+
+-- | The names of groups to which you want to add the policy.
+pGroups :: Lens' Policy (Maybe [Val Text])
+pGroups = lens _policyGroups (\s a -> s { _policyGroups = a })
+
+-- | A policy document that contains permissions to add to the specified users
+-- or groups.
+pPolicyDocument :: Lens' Policy Object
+pPolicyDocument = lens _policyPolicyDocument (\s a -> s { _policyPolicyDocument = a })
+
+-- | The name of the policy. If you specify multiple policies for an entity,
+-- specify unique names. For example, if you specify a list of policies for an
+-- IAM role, each policy must have a unique name.
+pPolicyName :: Lens' Policy (Val Text)
+pPolicyName = lens _policyPolicyName (\s a -> s { _policyPolicyName = a })
+
+-- | The names of AWS::IAM::Roles to attach to this policy. Note If a policy
+-- has a Ref to a role and if a resource (such as AWS::ECS::Service) also has
+-- a Ref to the same role, add a DependsOn attribute to the resource so that
+-- the resource depends on the policy. This dependency ensures that the role's
+-- policy is available throughout the resource's lifecycle. For example, when
+-- you delete a stack with an AWS::ECS::Service resource, the DependsOn
+-- attribute ensures that the AWS::ECS::Service resource can complete its
+-- deletion before its role's policy is deleted.
+pRoles :: Lens' Policy (Maybe [Val Text])
+pRoles = lens _policyRoles (\s a -> s { _policyRoles = a })
+
+-- | The names of users for whom you want to add the policy.
+pUsers :: Lens' Policy (Maybe [Val Text])
+pUsers = lens _policyUsers (\s a -> s { _policyUsers = a })
diff --git a/library-gen/Stratosphere/Resources/RecordSet.hs b/library-gen/Stratosphere/Resources/RecordSet.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/RecordSet.hs
@@ -0,0 +1,182 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::Route53::RecordSet type can be used as a standalone resource or
+-- as an embedded property in the AWS::Route53::RecordSetGroup type. Note that
+-- some AWS::Route53::RecordSet properties are valid only when used within
+-- AWS::Route53::RecordSetGroup. For more information about constraints and
+-- values for each property, see POST CreateHostedZone for hosted zones and
+-- POST ChangeResourceRecordSet for resource record sets.
+
+module Stratosphere.Resources.RecordSet where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.AliasTarget
+import Stratosphere.ResourceProperties.RecordSetGeoLocation
+
+-- | Full data type definition for RecordSet. See 'recordSet' for a more
+-- convenient constructor.
+data RecordSet =
+  RecordSet
+  { _recordSetAliasTarget :: Maybe AliasTarget
+  , _recordSetComment :: Maybe (Val Text)
+  , _recordSetFailover :: Maybe (Val Text)
+  , _recordSetGeoLocation :: Maybe [RecordSetGeoLocation]
+  , _recordSetHealthCheckId :: Maybe (Val Text)
+  , _recordSetHostedZoneId :: Maybe (Val Text)
+  , _recordSetHostedZoneName :: Maybe (Val Text)
+  , _recordSetName :: Val Text
+  , _recordSetRegion :: Maybe (Val Text)
+  , _recordSetResourceRecords :: Maybe [Val Text]
+  , _recordSetSetIdentifier :: Maybe (Val Text)
+  , _recordSetTTL :: Maybe (Val Text)
+  , _recordSetType :: Val Text
+  , _recordSetWeight :: Maybe (Val Integer')
+  } deriving (Show, Generic)
+
+instance ToJSON RecordSet where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 10, omitNothingFields = True }
+
+instance FromJSON RecordSet where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 10, omitNothingFields = True }
+
+-- | Constructor for 'RecordSet' containing required fields as arguments.
+recordSet
+  :: Val Text -- ^ 'rsName'
+  -> Val Text -- ^ 'rsType'
+  -> RecordSet
+recordSet namearg typearg =
+  RecordSet
+  { _recordSetAliasTarget = Nothing
+  , _recordSetComment = Nothing
+  , _recordSetFailover = Nothing
+  , _recordSetGeoLocation = Nothing
+  , _recordSetHealthCheckId = Nothing
+  , _recordSetHostedZoneId = Nothing
+  , _recordSetHostedZoneName = Nothing
+  , _recordSetName = namearg
+  , _recordSetRegion = Nothing
+  , _recordSetResourceRecords = Nothing
+  , _recordSetSetIdentifier = Nothing
+  , _recordSetTTL = Nothing
+  , _recordSetType = typearg
+  , _recordSetWeight = Nothing
+  }
+
+-- | Alias resource record sets only: Information about the domain to which
+-- you are redirecting traffic. If you specify this property, do not specify
+-- the TTL property. The alias uses a TTL value from the alias target record.
+-- For more information about alias resource record sets, see Creating Alias
+-- Resource Record Sets in the Amazon Route 53 Developer Guide and POST
+-- ChangeResourceRecordSets in the Amazon Route 53 API reference.
+rsAliasTarget :: Lens' RecordSet (Maybe AliasTarget)
+rsAliasTarget = lens _recordSetAliasTarget (\s a -> s { _recordSetAliasTarget = a })
+
+-- | Any comments that you want to include about the hosted zone. Important If
+-- the record set is part of a record set group, this property isn't valid.
+-- Don't specify this property.
+rsComment :: Lens' RecordSet (Maybe (Val Text))
+rsComment = lens _recordSetComment (\s a -> s { _recordSetComment = a })
+
+-- | Designates the record set as a PRIMARY or SECONDARY failover record set.
+-- When you have more than one resource performing the same function, you can
+-- configure Amazon Route 53 to check the health of your resources and use
+-- only health resources to respond to DNS queries. You cannot create
+-- nonfailover resource record sets that have the same Name and Type property
+-- values as failover resource record sets. For more information, see the
+-- Failover element in the Amazon Route 53 API Reference. If you specify this
+-- property, you must specify the SetIdentifier property.
+rsFailover :: Lens' RecordSet (Maybe (Val Text))
+rsFailover = lens _recordSetFailover (\s a -> s { _recordSetFailover = a })
+
+-- | Describes how Amazon Route 53 responds to DNS queries based on the
+-- geographic origin of the query.
+rsGeoLocation :: Lens' RecordSet (Maybe [RecordSetGeoLocation])
+rsGeoLocation = lens _recordSetGeoLocation (\s a -> s { _recordSetGeoLocation = a })
+
+-- | The health check ID that you want to apply to this record set. Amazon
+-- Route 53 returns this resource record set in response to a DNS query only
+-- while record set is healthy.
+rsHealthCheckId :: Lens' RecordSet (Maybe (Val Text))
+rsHealthCheckId = lens _recordSetHealthCheckId (\s a -> s { _recordSetHealthCheckId = a })
+
+-- | The ID of the hosted zone.
+rsHostedZoneId :: Lens' RecordSet (Maybe (Val Text))
+rsHostedZoneId = lens _recordSetHostedZoneId (\s a -> s { _recordSetHostedZoneId = a })
+
+-- | The name of the domain for the hosted zone where you want to add the
+-- record set. When you create a stack using an AWS::Route53::RecordSet that
+-- specifies HostedZoneName, AWS CloudFormation attempts to find a hosted zone
+-- whose name matches the HostedZoneName. If AWS CloudFormation cannot find a
+-- hosted zone with a matching domain name, or if there is more than one
+-- hosted zone with the specified domain name, AWS CloudFormation will not
+-- create the stack. If you have multiple hosted zones with the same domain
+-- name, you must explicitly specify the hosted zone using HostedZoneId.
+rsHostedZoneName :: Lens' RecordSet (Maybe (Val Text))
+rsHostedZoneName = lens _recordSetHostedZoneName (\s a -> s { _recordSetHostedZoneName = a })
+
+-- | The name of the domain. You must specify a fully qualified domain name
+-- that ends with a period as the last label indication. If you omit the final
+-- period, AWS CloudFormation adds it.
+rsName :: Lens' RecordSet (Val Text)
+rsName = lens _recordSetName (\s a -> s { _recordSetName = a })
+
+-- | Latency resource record sets only: The Amazon EC2 region where the
+-- resource that is specified in this resource record set resides. The
+-- resource typically is an AWS resource, for example, Amazon EC2 instance or
+-- an Elastic Load Balancing load balancer, and is referred to by an IP
+-- address or a DNS domain name, depending on the record type. When Amazon
+-- Route 53 receives a DNS query for a domain name and type for which you have
+-- created latency resource record sets, Amazon Route 53 selects the latency
+-- resource record set that has the lowest latency between the end user and
+-- the associated Amazon EC2 region. Amazon Route 53 then returns the value
+-- that is associated with the selected resource record set. The following
+-- restrictions must be followed: You can only specify one resource record per
+-- latency resource record set. You can only create one latency resource
+-- record set for each Amazon EC2 region. You are not required to create
+-- latency resource record sets for all Amazon EC2 regions. Amazon Route 53
+-- will choose the region with the best latency from among the regions for
+-- which you create latency resource record sets. You cannot create both
+-- weighted and latency resource record sets that have the same values for the
+-- Name and Type elements. To see a list of regions by service, see Regions
+-- and Endpoints in the AWS General Reference.
+rsRegion :: Lens' RecordSet (Maybe (Val Text))
+rsRegion = lens _recordSetRegion (\s a -> s { _recordSetRegion = a })
+
+-- | List of resource records to add. Each record should be in the format
+-- appropriate for the record type specified by the Type property. For
+-- information about different record types and their record formats, see
+-- Appendix: Domain Name Format in the Amazon Route 53 Developer Guide.
+rsResourceRecords :: Lens' RecordSet (Maybe [Val Text])
+rsResourceRecords = lens _recordSetResourceRecords (\s a -> s { _recordSetResourceRecords = a })
+
+-- | A unique identifier that differentiates among multiple resource record
+-- sets that have the same combination of DNS name and type.
+rsSetIdentifier :: Lens' RecordSet (Maybe (Val Text))
+rsSetIdentifier = lens _recordSetSetIdentifier (\s a -> s { _recordSetSetIdentifier = a })
+
+-- | The resource record cache time to live (TTL), in seconds. If you specify
+-- this property, do not specify the AliasTarget property. For alias target
+-- records, the alias uses a TTL value from the target. If you specify this
+-- property, you must specify the ResourceRecords property.
+rsTTL :: Lens' RecordSet (Maybe (Val Text))
+rsTTL = lens _recordSetTTL (\s a -> s { _recordSetTTL = a })
+
+-- | The type of records to add.
+rsType :: Lens' RecordSet (Val Text)
+rsType = lens _recordSetType (\s a -> s { _recordSetType = a })
+
+-- | Weighted resource record sets only: Among resource record sets that have
+-- the same combination of DNS name and type, a value that determines what
+-- portion of traffic for the current resource record set is routed to the
+-- associated location. For more information about weighted resource record
+-- sets, see Setting Up Weighted Resource Record Sets in the Amazon Route 53
+-- Developer Guide.
+rsWeight :: Lens' RecordSet (Maybe (Val Integer'))
+rsWeight = lens _recordSetWeight (\s a -> s { _recordSetWeight = a })
diff --git a/library-gen/Stratosphere/Resources/RecordSetGroup.hs b/library-gen/Stratosphere/Resources/RecordSetGroup.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/RecordSetGroup.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::Route53::RecordSetGroup resource creates record sets for a
+-- hosted zone. For more information about constraints and values for each
+-- property, see POST CreateHostedZone for hosted zones and POST
+-- ChangeResourceRecordSet for resource record sets.
+
+module Stratosphere.Resources.RecordSetGroup where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.Resources.RecordSet
+
+-- | Full data type definition for RecordSetGroup. See 'recordSetGroup' for a
+-- more convenient constructor.
+data RecordSetGroup =
+  RecordSetGroup
+  { _recordSetGroupComment :: Maybe (Val Text)
+  , _recordSetGroupHostedZoneId :: Maybe (Val Text)
+  , _recordSetGroupHostedZoneName :: Maybe (Val Text)
+  , _recordSetGroupRecordSets :: [RecordSet]
+  } deriving (Show, Generic)
+
+instance ToJSON RecordSetGroup where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 15, omitNothingFields = True }
+
+instance FromJSON RecordSetGroup where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 15, omitNothingFields = True }
+
+-- | Constructor for 'RecordSetGroup' containing required fields as arguments.
+recordSetGroup
+  :: [RecordSet] -- ^ 'rsgRecordSets'
+  -> RecordSetGroup
+recordSetGroup recordSetsarg =
+  RecordSetGroup
+  { _recordSetGroupComment = Nothing
+  , _recordSetGroupHostedZoneId = Nothing
+  , _recordSetGroupHostedZoneName = Nothing
+  , _recordSetGroupRecordSets = recordSetsarg
+  }
+
+-- | Any comments you want to include about the hosted zone.
+rsgComment :: Lens' RecordSetGroup (Maybe (Val Text))
+rsgComment = lens _recordSetGroupComment (\s a -> s { _recordSetGroupComment = a })
+
+-- | The ID of the hosted zone.
+rsgHostedZoneId :: Lens' RecordSetGroup (Maybe (Val Text))
+rsgHostedZoneId = lens _recordSetGroupHostedZoneId (\s a -> s { _recordSetGroupHostedZoneId = a })
+
+-- | The name of the domain for the hosted zone where you want to add the
+-- record set. When you create a stack using an AWS::Route53::RecordSet that
+-- specifies HostedZoneName, AWS CloudFormation attempts to find a hosted zone
+-- whose name matches the HostedZoneName. If AWS CloudFormation cannot find a
+-- hosted zone with a matching domain name, or if there is more than one
+-- hosted zone with the specified domain name, AWS CloudFormation will not
+-- create the stack. If you have multiple hosted zones with the same domain
+-- name, you must explicitly specify the hosted zone using HostedZoneId.
+rsgHostedZoneName :: Lens' RecordSetGroup (Maybe (Val Text))
+rsgHostedZoneName = lens _recordSetGroupHostedZoneName (\s a -> s { _recordSetGroupHostedZoneName = a })
+
+-- | List of resource record sets to add.
+rsgRecordSets :: Lens' RecordSetGroup [RecordSet]
+rsgRecordSets = lens _recordSetGroupRecordSets (\s a -> s { _recordSetGroupRecordSets = a })
diff --git a/library-gen/Stratosphere/Resources/Route.hs b/library-gen/Stratosphere/Resources/Route.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/Route.hs
@@ -0,0 +1,77 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Creates a new route in a route table within a VPC. The route's target can
+-- be either a gateway attached to the VPC or a NAT instance in the VPC.
+
+module Stratosphere.Resources.Route where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for Route. See 'route' for a more convenient
+-- constructor.
+data Route =
+  Route
+  { _routeDestinationCidrBlock :: Val Text
+  , _routeGatewayId :: Maybe (Val Text)
+  , _routeInstanceId :: Maybe (Val Text)
+  , _routeNatGatewayId :: Maybe (Val Text)
+  , _routeNetworkInterfaceId :: Maybe (Val Text)
+  , _routeRouteTableId :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON Route where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 6, omitNothingFields = True }
+
+instance FromJSON Route where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 6, omitNothingFields = True }
+
+-- | Constructor for 'Route' containing required fields as arguments.
+route
+  :: Val Text -- ^ 'rDestinationCidrBlock'
+  -> Val Text -- ^ 'rRouteTableId'
+  -> Route
+route destinationCidrBlockarg routeTableIdarg =
+  Route
+  { _routeDestinationCidrBlock = destinationCidrBlockarg
+  , _routeGatewayId = Nothing
+  , _routeInstanceId = Nothing
+  , _routeNatGatewayId = Nothing
+  , _routeNetworkInterfaceId = Nothing
+  , _routeRouteTableId = routeTableIdarg
+  }
+
+-- | The CIDR address block used for the destination match. For example,
+-- 0.0.0.0/0. Routing decisions are based on the most specific match.
+rDestinationCidrBlock :: Lens' Route (Val Text)
+rDestinationCidrBlock = lens _routeDestinationCidrBlock (\s a -> s { _routeDestinationCidrBlock = a })
+
+-- | The ID of an Internet gateway or virtual private gateway that is attached
+-- to your VPC. For example: igw-eaad4883. For route entries that specify a
+-- gateway, you must specify a dependency on the gateway attachment resource.
+-- For more information, see DependsOn Attribute.
+rGatewayId :: Lens' Route (Maybe (Val Text))
+rGatewayId = lens _routeGatewayId (\s a -> s { _routeGatewayId = a })
+
+-- | The ID of a NAT instance in your VPC. For example, i-1a2b3c4d.
+rInstanceId :: Lens' Route (Maybe (Val Text))
+rInstanceId = lens _routeInstanceId (\s a -> s { _routeInstanceId = a })
+
+-- | The ID of a NAT gateway. For example, nat-0a12bc456789de0fg.
+rNatGatewayId :: Lens' Route (Maybe (Val Text))
+rNatGatewayId = lens _routeNatGatewayId (\s a -> s { _routeNatGatewayId = a })
+
+-- | Allows the routing of network interface IDs.
+rNetworkInterfaceId :: Lens' Route (Maybe (Val Text))
+rNetworkInterfaceId = lens _routeNetworkInterfaceId (\s a -> s { _routeNetworkInterfaceId = a })
+
+-- | The ID of the route table where the route will be added.
+rRouteTableId :: Lens' Route (Val Text)
+rRouteTableId = lens _routeRouteTableId (\s a -> s { _routeRouteTableId = a })
diff --git a/library-gen/Stratosphere/Resources/RouteTable.hs b/library-gen/Stratosphere/Resources/RouteTable.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/RouteTable.hs
@@ -0,0 +1,49 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Creates a new route table within a VPC. After you create a new route
+-- table, you can add routes and associate the table with a subnet.
+
+module Stratosphere.Resources.RouteTable where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.ResourceTag
+
+-- | Full data type definition for RouteTable. See 'routeTable' for a more
+-- convenient constructor.
+data RouteTable =
+  RouteTable
+  { _routeTableVpcId :: Val Text
+  , _routeTableTags :: Maybe [ResourceTag]
+  } deriving (Show, Generic)
+
+instance ToJSON RouteTable where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 11, omitNothingFields = True }
+
+instance FromJSON RouteTable where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 11, omitNothingFields = True }
+
+-- | Constructor for 'RouteTable' containing required fields as arguments.
+routeTable
+  :: Val Text -- ^ 'rtVpcId'
+  -> RouteTable
+routeTable vpcIdarg =
+  RouteTable
+  { _routeTableVpcId = vpcIdarg
+  , _routeTableTags = Nothing
+  }
+
+-- | The ID of the VPC where the route table will be created. Example:
+-- vpc-11ad4878
+rtVpcId :: Lens' RouteTable (Val Text)
+rtVpcId = lens _routeTableVpcId (\s a -> s { _routeTableVpcId = a })
+
+-- | An arbitrary set of tags (key–value pairs) for this route table.
+rtTags :: Lens' RouteTable (Maybe [ResourceTag])
+rtTags = lens _routeTableTags (\s a -> s { _routeTableTags = a })
diff --git a/library-gen/Stratosphere/Resources/SecurityGroup.hs b/library-gen/Stratosphere/Resources/SecurityGroup.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/SecurityGroup.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Creates an Amazon EC2 security group. To create a VPC security group, use
+-- the VpcId property. This type supports updates. For more information about
+-- updating stacks, see AWS CloudFormation Stacks Updates.
+
+module Stratosphere.Resources.SecurityGroup where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.SecurityGroupEgressRule
+import Stratosphere.ResourceProperties.SecurityGroupIngressRule
+import Stratosphere.ResourceProperties.ResourceTag
+
+-- | Full data type definition for SecurityGroup. See 'securityGroup' for a
+-- more convenient constructor.
+data SecurityGroup =
+  SecurityGroup
+  { _securityGroupGroupDescription :: Val Text
+  , _securityGroupSecurityGroupEgress :: Maybe [SecurityGroupEgressRule]
+  , _securityGroupSecurityGroupIngress :: Maybe [SecurityGroupIngressRule]
+  , _securityGroupTags :: Maybe [ResourceTag]
+  , _securityGroupVpcId :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON SecurityGroup where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 14, omitNothingFields = True }
+
+instance FromJSON SecurityGroup where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 14, omitNothingFields = True }
+
+-- | Constructor for 'SecurityGroup' containing required fields as arguments.
+securityGroup
+  :: Val Text -- ^ 'sgGroupDescription'
+  -> SecurityGroup
+securityGroup groupDescriptionarg =
+  SecurityGroup
+  { _securityGroupGroupDescription = groupDescriptionarg
+  , _securityGroupSecurityGroupEgress = Nothing
+  , _securityGroupSecurityGroupIngress = Nothing
+  , _securityGroupTags = Nothing
+  , _securityGroupVpcId = Nothing
+  }
+
+-- | Description of the security group.
+sgGroupDescription :: Lens' SecurityGroup (Val Text)
+sgGroupDescription = lens _securityGroupGroupDescription (\s a -> s { _securityGroupGroupDescription = a })
+
+-- | A list of Amazon EC2 security group egress rules.
+sgSecurityGroupEgress :: Lens' SecurityGroup (Maybe [SecurityGroupEgressRule])
+sgSecurityGroupEgress = lens _securityGroupSecurityGroupEgress (\s a -> s { _securityGroupSecurityGroupEgress = a })
+
+-- | A list of Amazon EC2 security group ingress rules.
+sgSecurityGroupIngress :: Lens' SecurityGroup (Maybe [SecurityGroupIngressRule])
+sgSecurityGroupIngress = lens _securityGroupSecurityGroupIngress (\s a -> s { _securityGroupSecurityGroupIngress = a })
+
+-- | The tags that you want to attach to the resource.
+sgTags :: Lens' SecurityGroup (Maybe [ResourceTag])
+sgTags = lens _securityGroupTags (\s a -> s { _securityGroupTags = a })
+
+-- | The physical ID of the VPC. Can be obtained by using a reference to an
+-- AWS::EC2::VPC, such as: { "Ref" : "myVPC" }. For more information about
+-- using the Ref function, see Ref.
+sgVpcId :: Lens' SecurityGroup (Maybe (Val Text))
+sgVpcId = lens _securityGroupVpcId (\s a -> s { _securityGroupVpcId = a })
diff --git a/library-gen/Stratosphere/Resources/Stack.hs b/library-gen/Stratosphere/Resources/Stack.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/Stack.hs
@@ -0,0 +1,89 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::CloudFormation::Stack type nests a stack as a resource in a
+-- top-level template. You can add output values from a nested stack within
+-- the containing template. You use the GetAtt function with the nested
+-- stack's logical name and the name of the output value in the nested stack
+-- in the format Outputs.NestedStackOutputName. When you apply template
+-- changes to update a top-level stack, AWS CloudFormation updates the
+-- top-level stack and initiates an update to its nested stacks. AWS
+-- CloudFormation updates the resources of modified nested stacks, but does
+-- not update the resources of unmodified nested stacks. For more information,
+-- see AWS CloudFormation Stacks Updates.
+
+module Stratosphere.Resources.Stack where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.ResourceTag
+import Stratosphere.Parameters
+
+-- | Full data type definition for Stack. See 'stack' for a more convenient
+-- constructor.
+data Stack =
+  Stack
+  { _stackNotificationARNs :: Maybe [Val Text]
+  , _stackParameters :: Maybe Parameters
+  , _stackResourceTags :: Maybe [ResourceTag]
+  , _stackTemplateURL :: Val Text
+  , _stackTimeoutInMinutes :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON Stack where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 6, omitNothingFields = True }
+
+instance FromJSON Stack where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 6, omitNothingFields = True }
+
+-- | Constructor for 'Stack' containing required fields as arguments.
+stack
+  :: Val Text -- ^ 'sTemplateURL'
+  -> Stack
+stack templateURLarg =
+  Stack
+  { _stackNotificationARNs = Nothing
+  , _stackParameters = Nothing
+  , _stackResourceTags = Nothing
+  , _stackTemplateURL = templateURLarg
+  , _stackTimeoutInMinutes = Nothing
+  }
+
+-- | A list of existing Amazon SNS topics where notifications about stack
+-- events are sent.
+sNotificationARNs :: Lens' Stack (Maybe [Val Text])
+sNotificationARNs = lens _stackNotificationARNs (\s a -> s { _stackNotificationARNs = a })
+
+-- | The set of parameters passed to AWS CloudFormation when this nested stack
+-- is created. Note If you use the ref function to pass a parameter value to a
+-- nested stack, comma-delimited list parameters must be of type String. In
+-- other words, you cannot pass values that are of type CommaDelimitedList to
+-- nested stacks.
+sParameters :: Lens' Stack (Maybe Parameters)
+sParameters = lens _stackParameters (\s a -> s { _stackParameters = a })
+
+-- | An arbitrary set of tags (key–value pairs) to describe this stack.
+sResourceTags :: Lens' Stack (Maybe [ResourceTag])
+sResourceTags = lens _stackResourceTags (\s a -> s { _stackResourceTags = a })
+
+-- | The URL of a template that specifies the stack that you want to create as
+-- a resource. The template must be stored on an Amazon S3 bucket, so the URL
+-- must have the form: https://s3.amazonaws.com/.../TemplateName.template
+sTemplateURL :: Lens' Stack (Val Text)
+sTemplateURL = lens _stackTemplateURL (\s a -> s { _stackTemplateURL = a })
+
+-- | The length of time, in minutes, that AWS CloudFormation waits for the
+-- nested stack to reach the CREATE_COMPLETE state. The default is no timeout.
+-- When AWS CloudFormation detects that the nested stack has reached the
+-- CREATE_COMPLETE state, it marks the nested stack resource as
+-- CREATE_COMPLETE in the parent stack and resumes creating the parent stack.
+-- If the timeout period expires before the nested stack reaches
+-- CREATE_COMPLETE, AWS CloudFormation marks the nested stack as failed and
+-- rolls back both the nested stack and parent stack.
+sTimeoutInMinutes :: Lens' Stack (Maybe (Val Text))
+sTimeoutInMinutes = lens _stackTimeoutInMinutes (\s a -> s { _stackTimeoutInMinutes = a })
diff --git a/library-gen/Stratosphere/Resources/Subnet.hs b/library-gen/Stratosphere/Resources/Subnet.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/Subnet.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Creates a subnet in an existing VPC.
+
+module Stratosphere.Resources.Subnet where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.ResourceTag
+
+-- | Full data type definition for Subnet. See 'subnet' for a more convenient
+-- constructor.
+data Subnet =
+  Subnet
+  { _subnetAvailabilityZone :: Maybe (Val Text)
+  , _subnetCidrBlock :: Val Text
+  , _subnetMapPublicIpOnLaunch :: Maybe (Val Bool')
+  , _subnetTags :: Maybe [ResourceTag]
+  , _subnetVpcId :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON Subnet where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 7, omitNothingFields = True }
+
+instance FromJSON Subnet where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 7, omitNothingFields = True }
+
+-- | Constructor for 'Subnet' containing required fields as arguments.
+subnet
+  :: Val Text -- ^ 'sCidrBlock'
+  -> Val Text -- ^ 'sVpcId'
+  -> Subnet
+subnet cidrBlockarg vpcIdarg =
+  Subnet
+  { _subnetAvailabilityZone = Nothing
+  , _subnetCidrBlock = cidrBlockarg
+  , _subnetMapPublicIpOnLaunch = Nothing
+  , _subnetTags = Nothing
+  , _subnetVpcId = vpcIdarg
+  }
+
+-- | The availability zone in which you want the subnet. Default: AWS selects
+-- a zone for you (recommended).
+sAvailabilityZone :: Lens' Subnet (Maybe (Val Text))
+sAvailabilityZone = lens _subnetAvailabilityZone (\s a -> s { _subnetAvailabilityZone = a })
+
+-- | The CIDR block that you want the subnet to cover (for example,
+-- "10.0.0.0/24").
+sCidrBlock :: Lens' Subnet (Val Text)
+sCidrBlock = lens _subnetCidrBlock (\s a -> s { _subnetCidrBlock = a })
+
+-- | Indicates whether instances that are launched in this subnet receive a
+-- public IP address. By default, the value is false.
+sMapPublicIpOnLaunch :: Lens' Subnet (Maybe (Val Bool'))
+sMapPublicIpOnLaunch = lens _subnetMapPublicIpOnLaunch (\s a -> s { _subnetMapPublicIpOnLaunch = a })
+
+-- | An arbitrary set of tags (key–value pairs) for this subnet.
+sTags :: Lens' Subnet (Maybe [ResourceTag])
+sTags = lens _subnetTags (\s a -> s { _subnetTags = a })
+
+-- | A Ref structure that contains the ID of the VPC on which you want to
+-- create the subnet. The VPC ID is provided as the value of the "Ref"
+-- property, as: { "Ref": "VPCID" }.
+sVpcId :: Lens' Subnet (Val Text)
+sVpcId = lens _subnetVpcId (\s a -> s { _subnetVpcId = a })
diff --git a/library-gen/Stratosphere/Resources/SubnetRouteTableAssociation.hs b/library-gen/Stratosphere/Resources/SubnetRouteTableAssociation.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/SubnetRouteTableAssociation.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Associates a subnet with a route table.
+
+module Stratosphere.Resources.SubnetRouteTableAssociation where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for SubnetRouteTableAssociation. See
+-- 'subnetRouteTableAssociation' for a more convenient constructor.
+data SubnetRouteTableAssociation =
+  SubnetRouteTableAssociation
+  { _subnetRouteTableAssociationRouteTableId :: Val Text
+  , _subnetRouteTableAssociationSubnetId :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON SubnetRouteTableAssociation where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 28, omitNothingFields = True }
+
+instance FromJSON SubnetRouteTableAssociation where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 28, omitNothingFields = True }
+
+-- | Constructor for 'SubnetRouteTableAssociation' containing required fields
+-- as arguments.
+subnetRouteTableAssociation
+  :: Val Text -- ^ 'srtaRouteTableId'
+  -> Val Text -- ^ 'srtaSubnetId'
+  -> SubnetRouteTableAssociation
+subnetRouteTableAssociation routeTableIdarg subnetIdarg =
+  SubnetRouteTableAssociation
+  { _subnetRouteTableAssociationRouteTableId = routeTableIdarg
+  , _subnetRouteTableAssociationSubnetId = subnetIdarg
+  }
+
+-- | The ID of the route table. This is commonly written as a reference to a
+-- route table declared elsewhere in the template. For example:
+srtaRouteTableId :: Lens' SubnetRouteTableAssociation (Val Text)
+srtaRouteTableId = lens _subnetRouteTableAssociationRouteTableId (\s a -> s { _subnetRouteTableAssociationRouteTableId = a })
+
+-- | The ID of the subnet. This is commonly written as a reference to a subnet
+-- declared elsewhere in the template. For example:
+srtaSubnetId :: Lens' SubnetRouteTableAssociation (Val Text)
+srtaSubnetId = lens _subnetRouteTableAssociationSubnetId (\s a -> s { _subnetRouteTableAssociationSubnetId = a })
diff --git a/library-gen/Stratosphere/Resources/User.hs b/library-gen/Stratosphere/Resources/User.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/User.hs
@@ -0,0 +1,70 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::IAM::User type creates a user.
+
+module Stratosphere.Resources.User where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.IAMPolicies
+import Stratosphere.ResourceProperties.UserLoginProfile
+
+-- | Full data type definition for User. See 'user' for a more convenient
+-- constructor.
+data User =
+  User
+  { _userGroups :: Maybe [Val Text]
+  , _userLoginProfile :: Maybe UserLoginProfile
+  , _userManagedPolicyArns :: Maybe [Val Text]
+  , _userPath :: Maybe (Val Text)
+  , _userPolicies :: Maybe [IAMPolicies]
+  } deriving (Show, Generic)
+
+instance ToJSON User where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 5, omitNothingFields = True }
+
+instance FromJSON User where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 5, omitNothingFields = True }
+
+-- | Constructor for 'User' containing required fields as arguments.
+user
+  :: User
+user  =
+  User
+  { _userGroups = Nothing
+  , _userLoginProfile = Nothing
+  , _userManagedPolicyArns = Nothing
+  , _userPath = Nothing
+  , _userPolicies = Nothing
+  }
+
+-- | A name of a group to which you want to add the user.
+uGroups :: Lens' User (Maybe [Val Text])
+uGroups = lens _userGroups (\s a -> s { _userGroups = a })
+
+-- | Creates a login profile so that the user can access the AWS Management
+-- Console.
+uLoginProfile :: Lens' User (Maybe UserLoginProfile)
+uLoginProfile = lens _userLoginProfile (\s a -> s { _userLoginProfile = a })
+
+-- | One or more managed policy ARNs to attach to this user.
+uManagedPolicyArns :: Lens' User (Maybe [Val Text])
+uManagedPolicyArns = lens _userManagedPolicyArns (\s a -> s { _userManagedPolicyArns = a })
+
+-- | The path for the user name. For more information about paths, see
+-- Identifiers for IAM Entities in Using AWS Identity and Access Management.
+uPath :: Lens' User (Maybe (Val Text))
+uPath = lens _userPath (\s a -> s { _userPath = a })
+
+-- | The policies to associate with this user. For information about policies,
+-- see Overview of Policies in [Using IAM]. Note If you specify multiple
+-- polices, specify unique values for the policy name. If you don't, updates
+-- to the IAM user will fail.
+uPolicies :: Lens' User (Maybe [IAMPolicies])
+uPolicies = lens _userPolicies (\s a -> s { _userPolicies = a })
diff --git a/library-gen/Stratosphere/Resources/UserToGroupAddition.hs b/library-gen/Stratosphere/Resources/UserToGroupAddition.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/UserToGroupAddition.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::IAM::UserToGroupAddition type adds AWS Identity and Access
+-- Management (IAM) users to a group. This type supports updates. For more
+-- information about updating stacks, see AWS CloudFormation Stacks Updates.
+
+module Stratosphere.Resources.UserToGroupAddition where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for UserToGroupAddition. See
+-- 'userToGroupAddition' for a more convenient constructor.
+data UserToGroupAddition =
+  UserToGroupAddition
+  { _userToGroupAdditionGroupName :: Val Text
+  , _userToGroupAdditionUsers :: [Val Text]
+  } deriving (Show, Generic)
+
+instance ToJSON UserToGroupAddition where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 20, omitNothingFields = True }
+
+instance FromJSON UserToGroupAddition where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 20, omitNothingFields = True }
+
+-- | Constructor for 'UserToGroupAddition' containing required fields as
+-- arguments.
+userToGroupAddition
+  :: Val Text -- ^ 'utgaGroupName'
+  -> [Val Text] -- ^ 'utgaUsers'
+  -> UserToGroupAddition
+userToGroupAddition groupNamearg usersarg =
+  UserToGroupAddition
+  { _userToGroupAdditionGroupName = groupNamearg
+  , _userToGroupAdditionUsers = usersarg
+  }
+
+-- | The name of group to add users to.
+utgaGroupName :: Lens' UserToGroupAddition (Val Text)
+utgaGroupName = lens _userToGroupAdditionGroupName (\s a -> s { _userToGroupAdditionGroupName = a })
+
+-- |
+utgaUsers :: Lens' UserToGroupAddition [Val Text]
+utgaUsers = lens _userToGroupAdditionUsers (\s a -> s { _userToGroupAdditionUsers = a })
diff --git a/library-gen/Stratosphere/Resources/VPC.hs b/library-gen/Stratosphere/Resources/VPC.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/VPC.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Creates a Virtual Private Cloud (VPC) with the CIDR block that you
+-- specify.
+
+module Stratosphere.Resources.VPC where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.ResourceTag
+
+-- | Full data type definition for VPC. See 'vpc' for a more convenient
+-- constructor.
+data VPC =
+  VPC
+  { _vPCCidrBlock :: Val Text
+  , _vPCEnableDnsSupport :: Maybe (Val Bool')
+  , _vPCEnableDnsHostnames :: Maybe (Val Bool')
+  , _vPCInstanceTenancy :: Maybe (Val Text)
+  , _vPCTags :: Maybe [ResourceTag]
+  } deriving (Show, Generic)
+
+instance ToJSON VPC where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 4, omitNothingFields = True }
+
+instance FromJSON VPC where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 4, omitNothingFields = True }
+
+-- | Constructor for 'VPC' containing required fields as arguments.
+vpc
+  :: Val Text -- ^ 'vpcCidrBlock'
+  -> VPC
+vpc cidrBlockarg =
+  VPC
+  { _vPCCidrBlock = cidrBlockarg
+  , _vPCEnableDnsSupport = Nothing
+  , _vPCEnableDnsHostnames = Nothing
+  , _vPCInstanceTenancy = Nothing
+  , _vPCTags = Nothing
+  }
+
+-- | The CIDR block you want the VPC to cover. For example: "10.0.0.0/16".
+vpcCidrBlock :: Lens' VPC (Val Text)
+vpcCidrBlock = lens _vPCCidrBlock (\s a -> s { _vPCCidrBlock = a })
+
+-- | Specifies whether DNS resolution is supported for the VPC. If this
+-- attribute is true, the Amazon DNS server resolves DNS hostnames for your
+-- instances to their corresponding IP addresses; otherwise, it does not. By
+-- default the value is set to true.
+vpcEnableDnsSupport :: Lens' VPC (Maybe (Val Bool'))
+vpcEnableDnsSupport = lens _vPCEnableDnsSupport (\s a -> s { _vPCEnableDnsSupport = a })
+
+-- | Specifies whether the instances launched in the VPC get DNS hostnames. If
+-- this attribute is true, instances in the VPC get DNS hostnames; otherwise,
+-- they do not. You can only set EnableDnsHostnames to true if you also set
+-- the EnableDnsSupport attribute to true. By default, the value is set to
+-- false.
+vpcEnableDnsHostnames :: Lens' VPC (Maybe (Val Bool'))
+vpcEnableDnsHostnames = lens _vPCEnableDnsHostnames (\s a -> s { _vPCEnableDnsHostnames = a })
+
+-- | The allowed tenancy of instances launched into the VPC. "default":
+-- Instances can be launched with any tenancy. "dedicated": Any instance
+-- launched into the VPC will automatically be dedicated, regardless of the
+-- tenancy option you specify when you launch the instance.
+vpcInstanceTenancy :: Lens' VPC (Maybe (Val Text))
+vpcInstanceTenancy = lens _vPCInstanceTenancy (\s a -> s { _vPCInstanceTenancy = a })
+
+-- | An arbitrary set of tags (key–value pairs) for this VPC.
+vpcTags :: Lens' VPC (Maybe [ResourceTag])
+vpcTags = lens _vPCTags (\s a -> s { _vPCTags = a })
diff --git a/library-gen/Stratosphere/Resources/VPCEndpoint.hs b/library-gen/Stratosphere/Resources/VPCEndpoint.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/VPCEndpoint.hs
@@ -0,0 +1,68 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::EC2::VPCEndpoint resource creates a VPC endpoint that you can
+-- use to establish a private connection between your VPC and another AWS
+-- service without requiring access over the Internet, a VPN connection, or
+-- AWS Direct Connect.
+
+module Stratosphere.Resources.VPCEndpoint where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for VPCEndpoint. See 'vpcEndpoint' for a more
+-- convenient constructor.
+data VPCEndpoint =
+  VPCEndpoint
+  { _vPCEndpointPolicyDocument :: Maybe Object
+  , _vPCEndpointRouteTableIds :: Maybe [Val Text]
+  , _vPCEndpointServiceName :: Val Text
+  , _vPCEndpointVpcId :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON VPCEndpoint where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+instance FromJSON VPCEndpoint where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 12, omitNothingFields = True }
+
+-- | Constructor for 'VPCEndpoint' containing required fields as arguments.
+vpcEndpoint
+  :: Val Text -- ^ 'vpceServiceName'
+  -> Val Text -- ^ 'vpceVpcId'
+  -> VPCEndpoint
+vpcEndpoint serviceNamearg vpcIdarg =
+  VPCEndpoint
+  { _vPCEndpointPolicyDocument = Nothing
+  , _vPCEndpointRouteTableIds = Nothing
+  , _vPCEndpointServiceName = serviceNamearg
+  , _vPCEndpointVpcId = vpcIdarg
+  }
+
+-- | A policy to attach to the endpoint that controls access to the service.
+-- The policy must be valid JSON. The default policy allows full access to the
+-- AWS service. For more information, see Controlling Access to Services in
+-- the Amazon VPC User Guide.
+vpcePolicyDocument :: Lens' VPCEndpoint (Maybe Object)
+vpcePolicyDocument = lens _vPCEndpointPolicyDocument (\s a -> s { _vPCEndpointPolicyDocument = a })
+
+-- | One or more route table IDs that are used by the VPC to reach the
+-- endpoint.
+vpceRouteTableIds :: Lens' VPCEndpoint (Maybe [Val Text])
+vpceRouteTableIds = lens _vPCEndpointRouteTableIds (\s a -> s { _vPCEndpointRouteTableIds = a })
+
+-- | The AWS service to which you want to establish a connection. Specify the
+-- service name in the form of com.amazonaws.region.service.
+vpceServiceName :: Lens' VPCEndpoint (Val Text)
+vpceServiceName = lens _vPCEndpointServiceName (\s a -> s { _vPCEndpointServiceName = a })
+
+-- | The ID of the VPC in which the endpoint is used.
+vpceVpcId :: Lens' VPCEndpoint (Val Text)
+vpceVpcId = lens _vPCEndpointVpcId (\s a -> s { _vPCEndpointVpcId = a })
diff --git a/library-gen/Stratosphere/Resources/VPCGatewayAttachment.hs b/library-gen/Stratosphere/Resources/VPCGatewayAttachment.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/VPCGatewayAttachment.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Attaches a gateway to a VPC.
+
+module Stratosphere.Resources.VPCGatewayAttachment where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for VPCGatewayAttachment. See
+-- 'vpcGatewayAttachment' for a more convenient constructor.
+data VPCGatewayAttachment =
+  VPCGatewayAttachment
+  { _vPCGatewayAttachmentInternetGatewayId :: Maybe (Val Text)
+  , _vPCGatewayAttachmentVpcId :: Val Text
+  , _vPCGatewayAttachmentVpnGatewayId :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON VPCGatewayAttachment where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 21, omitNothingFields = True }
+
+instance FromJSON VPCGatewayAttachment where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 21, omitNothingFields = True }
+
+-- | Constructor for 'VPCGatewayAttachment' containing required fields as
+-- arguments.
+vpcGatewayAttachment
+  :: Val Text -- ^ 'vpcgaVpcId'
+  -> VPCGatewayAttachment
+vpcGatewayAttachment vpcIdarg =
+  VPCGatewayAttachment
+  { _vPCGatewayAttachmentInternetGatewayId = Nothing
+  , _vPCGatewayAttachmentVpcId = vpcIdarg
+  , _vPCGatewayAttachmentVpnGatewayId = Nothing
+  }
+
+-- | The ID of the Internet gateway.
+vpcgaInternetGatewayId :: Lens' VPCGatewayAttachment (Maybe (Val Text))
+vpcgaInternetGatewayId = lens _vPCGatewayAttachmentInternetGatewayId (\s a -> s { _vPCGatewayAttachmentInternetGatewayId = a })
+
+-- | The ID of the VPC to associate with this gateway.
+vpcgaVpcId :: Lens' VPCGatewayAttachment (Val Text)
+vpcgaVpcId = lens _vPCGatewayAttachmentVpcId (\s a -> s { _vPCGatewayAttachmentVpcId = a })
+
+-- | The ID of the virtual private network (VPN) gateway to attach to the VPC.
+vpcgaVpnGatewayId :: Lens' VPCGatewayAttachment (Maybe (Val Text))
+vpcgaVpnGatewayId = lens _vPCGatewayAttachmentVpnGatewayId (\s a -> s { _vPCGatewayAttachmentVpnGatewayId = a })
diff --git a/library-gen/Stratosphere/Resources/Volume.hs b/library-gen/Stratosphere/Resources/Volume.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/Volume.hs
@@ -0,0 +1,121 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | The AWS::EC2::Volume type creates a new Amazon Elastic Block Store
+-- (Amazon EBS) volume. You can set a deletion policy for your volume to
+-- control how AWS CloudFormation handles the volume when the stack is
+-- deleted. For Amazon EBS volumes, you can choose to retain the volume, to
+-- delete the volume, or to create a snapshot of the volume. For more
+-- information, see DeletionPolicy Attribute.
+
+module Stratosphere.Resources.Volume where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+import Stratosphere.ResourceProperties.ResourceTag
+
+-- | Full data type definition for Volume. See 'volume' for a more convenient
+-- constructor.
+data Volume =
+  Volume
+  { _volumeAutoEnableIO :: Maybe (Val Bool')
+  , _volumeAvailabilityZone :: Val Text
+  , _volumeEncrypted :: Maybe (Val Bool')
+  , _volumeIops :: Maybe (Val Integer')
+  , _volumeKmsKeyId :: Maybe (Val Text)
+  , _volumeSize :: Maybe (Val Text)
+  , _volumeSnapshotId :: Maybe (Val Text)
+  , _volumeTags :: Maybe [ResourceTag]
+  , _volumeVolumeType :: Maybe (Val Text)
+  } deriving (Show, Generic)
+
+instance ToJSON Volume where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 7, omitNothingFields = True }
+
+instance FromJSON Volume where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 7, omitNothingFields = True }
+
+-- | Constructor for 'Volume' containing required fields as arguments.
+volume
+  :: Val Text -- ^ 'vAvailabilityZone'
+  -> Volume
+volume availabilityZonearg =
+  Volume
+  { _volumeAutoEnableIO = Nothing
+  , _volumeAvailabilityZone = availabilityZonearg
+  , _volumeEncrypted = Nothing
+  , _volumeIops = Nothing
+  , _volumeKmsKeyId = Nothing
+  , _volumeSize = Nothing
+  , _volumeSnapshotId = Nothing
+  , _volumeTags = Nothing
+  , _volumeVolumeType = Nothing
+  }
+
+-- | Indicates whether the volume is auto-enabled for I/O operations. By
+-- default, Amazon EBS disables I/O to the volume from attached EC2 instances
+-- when it determines that a volume's data is potentially inconsistent. If the
+-- consistency of the volume is not a concern, and you prefer that the volume
+-- be made available immediately if it's impaired, you can configure the
+-- volume to automatically enable I/O. For more information, see Working with
+-- the AutoEnableIO Volume Attribute in the Amazon EC2 User Guide for Linux
+-- Instances.
+vAutoEnableIO :: Lens' Volume (Maybe (Val Bool'))
+vAutoEnableIO = lens _volumeAutoEnableIO (\s a -> s { _volumeAutoEnableIO = a })
+
+-- | The Availability Zone in which to create the new volume.
+vAvailabilityZone :: Lens' Volume (Val Text)
+vAvailabilityZone = lens _volumeAvailabilityZone (\s a -> s { _volumeAvailabilityZone = a })
+
+-- | Indicates whether the volume is encrypted. Encrypted Amazon EBS volumes
+-- can only be attached to instance types that support Amazon EBS encryption.
+-- Volumes that are created from encrypted snapshots are automatically
+-- encrypted. You cannot create an encrypted volume from an unencrypted
+-- snapshot or vice versa. If your AMI uses encrypted volumes, you can only
+-- launch the AMI on supported instance types. For more information, see
+-- Amazon EBS encryption in the Amazon EC2 User Guide for Linux Instances.
+vEncrypted :: Lens' Volume (Maybe (Val Bool'))
+vEncrypted = lens _volumeEncrypted (\s a -> s { _volumeEncrypted = a })
+
+-- | The number of I/O operations per second (IOPS) that the volume supports.
+-- For more information about the valid sizes for each volume type, see the
+-- Iops parameter for the CreateVolume action in the Amazon EC2 API Reference.
+vIops :: Lens' Volume (Maybe (Val Integer'))
+vIops = lens _volumeIops (\s a -> s { _volumeIops = a })
+
+-- | The Amazon Resource Name (ARN) of the AWS Key Management Service master
+-- key that is used to create the encrypted volume, such as
+-- arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123-456a-a12b-a123b4cd56ef.
+-- If you create an encrypted volume and don't specify this property, the
+-- default master key is used.
+vKmsKeyId :: Lens' Volume (Maybe (Val Text))
+vKmsKeyId = lens _volumeKmsKeyId (\s a -> s { _volumeKmsKeyId = a })
+
+-- | The size of the volume, in gibibytes (GiBs). For more information about
+-- the valid sizes for each volume type, see the Size parameter for the
+-- CreateVolume action in the Amazon EC2 API Reference. If you specify the
+-- SnapshotId property, specify a size that is equal to or greater than the
+-- snapshot size. If you don't specify a size, Amazon EC2 will use the size of
+-- the snapshot as the volume size.
+vSize :: Lens' Volume (Maybe (Val Text))
+vSize = lens _volumeSize (\s a -> s { _volumeSize = a })
+
+-- | The snapshot from which to create the new volume.
+vSnapshotId :: Lens' Volume (Maybe (Val Text))
+vSnapshotId = lens _volumeSnapshotId (\s a -> s { _volumeSnapshotId = a })
+
+-- | An arbitrary set of tags (key–value pairs) for this volume.
+vTags :: Lens' Volume (Maybe [ResourceTag])
+vTags = lens _volumeTags (\s a -> s { _volumeTags = a })
+
+-- | The volume type. You can specify standard, io1, or gp2. If you set the
+-- type to io1, you must also set the Iops property. For more information
+-- about these values and the default value, see the VolumeType parameter for
+-- the CreateVolume action in the Amazon EC2 API Reference.
+vVolumeType :: Lens' Volume (Maybe (Val Text))
+vVolumeType = lens _volumeVolumeType (\s a -> s { _volumeVolumeType = a })
diff --git a/library-gen/Stratosphere/Resources/VolumeAttachment.hs b/library-gen/Stratosphere/Resources/VolumeAttachment.hs
new file mode 100644
--- /dev/null
+++ b/library-gen/Stratosphere/Resources/VolumeAttachment.hs
@@ -0,0 +1,62 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Attaches an Amazon EBS volume to a running instance and exposes it to the
+-- instance with the specified device name.
+
+module Stratosphere.Resources.VolumeAttachment where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Types
+import Data.Text
+import GHC.Generics
+
+import Stratosphere.Values
+
+
+-- | Full data type definition for VolumeAttachment. See 'volumeAttachment'
+-- for a more convenient constructor.
+data VolumeAttachment =
+  VolumeAttachment
+  { _volumeAttachmentDevice :: Val Text
+  , _volumeAttachmentInstanceId :: Val Text
+  , _volumeAttachmentVolumeId :: Val Text
+  } deriving (Show, Generic)
+
+instance ToJSON VolumeAttachment where
+  toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 17, omitNothingFields = True }
+
+instance FromJSON VolumeAttachment where
+  parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 17, omitNothingFields = True }
+
+-- | Constructor for 'VolumeAttachment' containing required fields as
+-- arguments.
+volumeAttachment
+  :: Val Text -- ^ 'vaDevice'
+  -> Val Text -- ^ 'vaInstanceId'
+  -> Val Text -- ^ 'vaVolumeId'
+  -> VolumeAttachment
+volumeAttachment devicearg instanceIdarg volumeIdarg =
+  VolumeAttachment
+  { _volumeAttachmentDevice = devicearg
+  , _volumeAttachmentInstanceId = instanceIdarg
+  , _volumeAttachmentVolumeId = volumeIdarg
+  }
+
+-- | How the device is exposed to the instance (e.g., /dev/sdh, or xvdh).
+vaDevice :: Lens' VolumeAttachment (Val Text)
+vaDevice = lens _volumeAttachmentDevice (\s a -> s { _volumeAttachmentDevice = a })
+
+-- | The ID of the instance to which the volume attaches. This value can be a
+-- reference to an AWS::EC2::Instance resource, or it can be the physical ID
+-- of an existing EC2 instance.
+vaInstanceId :: Lens' VolumeAttachment (Val Text)
+vaInstanceId = lens _volumeAttachmentInstanceId (\s a -> s { _volumeAttachmentInstanceId = a })
+
+-- | The ID of the Amazon EBS volume. The volume and instance must be within
+-- the same Availability Zone. This value can be a reference to an
+-- AWS::EC2::Volume resource, or it can be the volume ID of an existing Amazon
+-- EBS volume.
+vaVolumeId :: Lens' VolumeAttachment (Val Text)
+vaVolumeId = lens _volumeAttachmentVolumeId (\s a -> s { _volumeAttachmentVolumeId = a })
diff --git a/library/Stratosphere.hs b/library/Stratosphere.hs
new file mode 100644
--- /dev/null
+++ b/library/Stratosphere.hs
@@ -0,0 +1,81 @@
+-- | This is a library for creating AWS CloudFormation templates.
+--
+-- CloudFormation is a system that creates AWS resources from declarative
+-- templates. One common criticism of CloudFormation is its use of JSON as the
+-- template specification language. Once you have a large number of templates,
+-- possibly including cross-references among themselves, raw JSON templates
+-- become unwieldy, and it becomes harder to confidently modify them.
+-- Stratosphere alleviates this issue by providing an Embedded Domain Specific
+-- Language (EDSL) to construct templates.
+
+module Stratosphere
+       (
+         -- * Introduction
+         -- $intro
+
+         -- * Usage
+         -- $usage
+
+         module Stratosphere.Outputs
+       , module Stratosphere.Parameters
+       , module Stratosphere.Resources
+       , module Stratosphere.Template
+       , module Stratosphere.Values
+       , module Control.Lens
+       ) where
+
+import Control.Lens
+import Stratosphere.Outputs
+import Stratosphere.Parameters
+import Stratosphere.Resources
+import Stratosphere.Template
+import Stratosphere.Values
+
+{-# ANN module "HLint: ignore Use import/export shortcut" #-}
+
+
+-- $intro
+--
+-- The core datatype of stratosphere is the 'Template', which corresponds to a
+-- single CloudFormation template document. Users construct a template in a
+-- type-safe way using simple data types. The following example creates a
+-- template containing a single EC2 instance with a key pair passed in as a
+-- parameter:
+--
+-- @
+-- instanceTemplate :: Template
+-- instanceTemplate =
+--   template
+--   [ resource "EC2Instance" (
+--     EC2InstanceProperties $
+--     ec2Instance
+--     "ami-22111148"
+--     & eciKeyName ?~ (Ref "KeyName")
+--     )
+--     & deletionPolicy ?~ Retain
+--   ]
+--   & description ?~ "Sample template"
+--   & parameters ?~
+--   [ parameter \"KeyName\" \"AWS::EC2::KeyPair::KeyName\"
+--     & description ?~ "Name of an existing EC2 KeyPair to enable SSH access to the instance"
+--     & constraintDescription ?~ "Must be the name of an existing EC2 KeyPair."
+--   ]
+-- @
+
+-- $usage
+--
+-- The types in stratosphere attempt to map exactly to CloudFormation template
+-- components. For example, a template requires a set of 'Resources', and
+-- optionally accepts a Description, 'Parameters', etc. For each component of a
+-- template, there is usually a set of required arguments, and a (usually
+-- large) number of optional arguments. Each record type has a corresponding
+-- constructor function that has the required parameters as arguments.
+--
+-- For example, since a 'Template' requires a set of Resources, the 'template'
+-- constructor has 'Resources' as an argument. Then, you can fill in the
+-- 'Maybe' parameters using lenses like '&' and '?~'.
+--
+-- Once a 'Template' is created, you can either use Aeson's encode function, or
+-- use our 'encodeTemplate' function (based on aeson-pretty) to produce a JSON
+-- ByteString. From there, you can use your favorite tool to interact with
+-- CloudFormation using the template.
diff --git a/library/Stratosphere/Helpers.hs b/library/Stratosphere/Helpers.hs
new file mode 100644
--- /dev/null
+++ b/library/Stratosphere/Helpers.hs
@@ -0,0 +1,67 @@
+module Stratosphere.Helpers
+       ( maybeField
+       , prefixNamer
+       , prefixFieldRules
+       , modTemplateJSONField
+       , NamedItem (..)
+       , namedItemToJSON
+       , namedItemFromJSON
+       ) where
+
+import Control.Lens (set)
+import Control.Lens.TH
+import Data.Aeson
+import Data.Aeson.Types (Parser)
+import Data.Char (isUpper, toLower)
+import qualified Data.HashMap.Strict as HM
+import Data.List (stripPrefix)
+import Data.Maybe (maybeToList)
+import qualified Data.Text as T
+import Language.Haskell.TH
+
+-- | Might create an aeson pair from a Maybe value.
+maybeField :: ToJSON a => T.Text -> Maybe a -> Maybe (T.Text, Value)
+maybeField field = fmap ((field .=) . toJSON)
+
+-- | Similar to `camelCaseNamer`, except we specify the prefix exactly. We use
+-- this because camelCaseNamer is terrible with names that start in all caps,
+-- like EC2. We would like to start the field names with "ec2...", but
+-- camelCaseNamer wants "eC2...".
+prefixNamer :: String -> Name -> [Name] -> Name -> [DefName]
+prefixNamer prefix _ _ field = maybeToList $
+  do
+    fieldPart <- stripPrefix prefix (nameBase field)
+    method    <- computeMethod fieldPart
+    let cls = "Has" ++ fieldPart
+    return (MethodName (mkName cls) (mkName method))
+    where computeMethod (x:xs) | isUpper x = Just (toLower x : xs)
+          computeMethod _                  = Nothing
+
+-- | See `prefixNamer`
+prefixFieldRules :: String -> LensRules
+prefixFieldRules prefix = set lensField (prefixNamer prefix) defaultFieldRules
+
+-- | Used for the JSON instances in Template. It is put here because it must be
+-- in a separate module.
+modTemplateJSONField :: String -> String
+modTemplateJSONField "templateFormatVersion" = "AWSTemplateFormatVersion"
+modTemplateJSONField s = drop 8 s
+
+
+-- | This class defines items with names in them. It is used to extract the
+-- name from JSON fields so we can get an Object with the names as keys instead
+-- of just an array.
+class NamedItem a where
+  itemName :: a -> T.Text
+  nameToJSON :: a -> Value
+  nameParseJSON :: T.Text -> Object -> Parser a
+
+namedItemToJSON :: (NamedItem a) => [a] -> Value
+namedItemToJSON xs =
+    object $ fmap (\x -> itemName x .= nameToJSON x) xs
+
+namedItemFromJSON :: (NamedItem a) => Value -> Parser [a]
+namedItemFromJSON v = do
+    objs <- parseJSON v :: Parser (HM.HashMap T.Text Value)
+    sequence [withObject "NamedItem" (nameParseJSON n) obj |
+              (n, obj) <- HM.toList objs]
diff --git a/library/Stratosphere/Outputs.hs b/library/Stratosphere/Outputs.hs
new file mode 100644
--- /dev/null
+++ b/library/Stratosphere/Outputs.hs
@@ -0,0 +1,103 @@
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+
+-- | See:
+-- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html
+--
+-- The optional Outputs section declares output values that you want to view
+-- from the AWS CloudFormation console or that you want to return in response
+-- to describe stack calls. For example, you can output the Amazon S3 bucket
+-- name for a stack so that you can easily find it.
+
+module Stratosphere.Outputs
+       ( Output (..)
+       , output
+       , Outputs (..)
+       , name
+       , description
+       , value
+       ) where
+
+import Control.Lens hiding ((.=))
+import Data.Aeson
+import Data.Aeson.Types (Parser)
+import Data.Maybe (catMaybes)
+import qualified Data.Text as T
+import GHC.Exts (IsList(..))
+
+import Stratosphere.Helpers
+import Stratosphere.Parameters
+import Stratosphere.Values
+
+-- | See 'output' for a convenient constructor.
+data Output =
+  Output
+  { outputName :: T.Text
+    -- ^ An identifier for this output. The logical ID must be alphanumeric
+    -- (A-Za-z0-9) and unique within the template.
+  , outputDescription :: Maybe T.Text
+    -- ^ A String type up to 4K in length describing the output value.
+  , outputValue :: Val T.Text
+    -- ^ The value of the property that is returned by the aws cloudformation
+    -- describe-stacks command. The value of an output can be literals,
+    -- parameter references, pseudo parameters, a mapping value, and intrinsic
+    -- functions.
+  } deriving (Show)
+
+$(makeFields ''Output)
+
+instance ToRef Output b where
+  toRef o = Ref (outputName o)
+
+-- | Constructor for 'Output'
+output
+  :: T.Text -- ^ Name
+  -> Val T.Text -- ^ Value
+  -> Output
+output oname oval =
+  Output
+  { outputName = oname
+  , outputDescription = Nothing
+  , outputValue = oval
+  }
+
+outputToJSON :: Output -> Value
+outputToJSON Output {..} =
+  object $ catMaybes
+  [ Just ("Value" .= outputValue)
+  , maybeField "Description" outputDescription
+  ]
+
+outputFromJSON :: T.Text -> Object -> Parser Output
+outputFromJSON n o =
+  Output n
+  <$> o .:? "Description"
+  <*> o .:  "Value"
+
+-- | Wrapper around a list of 'Output's to we can modify the aeson instances.
+newtype Outputs = Outputs { unOutputs :: [Output] }
+                deriving (Show, Monoid)
+
+instance IsList Outputs where
+  type Item Outputs = Output
+  fromList = Outputs
+  toList = unOutputs
+
+instance NamedItem Output where
+  itemName = outputName
+  nameToJSON = outputToJSON
+  nameParseJSON = outputFromJSON
+
+instance ToJSON Outputs where
+  toJSON = namedItemToJSON . unOutputs
+
+instance FromJSON Outputs where
+  parseJSON v = Outputs <$> namedItemFromJSON v
diff --git a/library/Stratosphere/Parameters.hs b/library/Stratosphere/Parameters.hs
new file mode 100644
--- /dev/null
+++ b/library/Stratosphere/Parameters.hs
@@ -0,0 +1,146 @@
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+
+-- | See:
+-- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html
+--
+-- You can use the optional Parameters section to pass values into your
+-- template when you create a stack. With parameters, you can create templates
+-- that are customized each time you create a stack. Each parameter must
+-- contain a value when you create a stack. You can specify a default value to
+-- make the parameter optional. For more information about creating stacks, see
+-- Working with Stacks.
+
+module Stratosphere.Parameters where
+
+import Control.Lens hiding ((.=))
+import Data.Aeson
+import Data.Aeson.Types (Parser)
+import Data.Maybe (catMaybes)
+import qualified Data.Text as T
+import GHC.Exts (IsList(..))
+
+import Stratosphere.Helpers
+import Stratosphere.Values
+
+data Parameter =
+  Parameter
+  { parameterName :: T.Text
+  , parameterType' :: T.Text
+    -- ^ The data type for the parameter.
+  , parameterDefault' :: Maybe Value
+    -- ^ A value of the appropriate type for the template to use if no value is
+    -- specified when a stack is created. If you define constraints for the
+    -- parameter, you must specify a value that adheres to those constraints.
+  , parameterNoEcho :: Maybe Bool'
+    -- ^ Whether to mask the parameter value whenever anyone makes a call that
+    -- describes the stack. If you set the value to true, the parameter value
+    -- is masked with asterisks (*****).
+  , parameterAllowedValues :: Maybe Array
+    -- ^ An array containing the list of values allowed for the parameter.
+  , parameterAllowedPattern :: Maybe T.Text
+    -- ^ A regular expression that represents the patterns you want to allow
+    -- for String types.
+  , parameterMaxLength :: Maybe Integer'
+    -- ^ An integer value that determines the largest number of characters you
+    -- want to allow for String types.
+  , parameterMinLength :: Maybe Integer'
+    -- ^ An integer value that determines the smallest number of characters you
+    -- want to allow for String types.
+  , parameterMaxValue :: Maybe Integer'
+    -- ^ A numeric value that determines the largest numeric value you want to
+    -- allow for Number types.
+  , parameterMinValue :: Maybe Integer'
+    -- ^ A numeric value that determines the smallest numeric value you want to
+    -- allow for Number types.
+  , parameterDescription :: Maybe T.Text
+    -- ^ A string of up to 4000 characters that describes the parameter.
+  , parameterConstraintDescription :: Maybe T.Text
+    -- ^ A string that explains the constraint when the constraint is violated.
+  } deriving (Show, Eq)
+
+$(makeFields ''Parameter)
+
+instance ToRef Parameter b where
+  toRef p = Ref (parameterName p)
+
+parameterToJSON :: Parameter -> Value
+parameterToJSON Parameter {..} =
+  object $ catMaybes
+  [ Just ("Type" .= parameterType')
+  , maybeField "Default" parameterDefault'
+  , maybeField "NoEcho" parameterNoEcho
+  , maybeField "AllowedValues" parameterAllowedValues
+  , maybeField "AllowedPattern" parameterAllowedPattern
+  , maybeField "MaxLength" parameterMaxLength
+  , maybeField "MinLength" parameterMinLength
+  , maybeField "MaxValue" parameterMaxValue
+  , maybeField "MinValue" parameterMinValue
+  , maybeField "Description" parameterDescription
+  , maybeField "ConstraintDescription" parameterConstraintDescription
+  ]
+
+parameterFromJSON :: T.Text -> Object -> Parser Parameter
+parameterFromJSON n o =
+  Parameter n
+  <$> o .:  "Type"
+  <*> o .:? "Default"
+  <*> o .:? "NoEcho"
+  <*> o .:? "AllowedValues"
+  <*> o .:? "AllowedPattern"
+  <*> o .:? "MaxLength"
+  <*> o .:? "MinLength"
+  <*> o .:? "MaxValue"
+  <*> o .:? "MinValue"
+  <*> o .:? "Description"
+  <*> o .:? "ConstraintDescription"
+
+-- | Constructor for 'Parameter' with required arguments.
+parameter
+  :: T.Text -- ^ Name
+  -> T.Text -- ^ Type
+  -> Parameter
+parameter pname ptype =
+  Parameter
+  { parameterName = pname
+  , parameterType' = ptype
+  , parameterDefault' = Nothing
+  , parameterNoEcho = Nothing
+  , parameterAllowedValues = Nothing
+  , parameterAllowedPattern = Nothing
+  , parameterMaxLength = Nothing
+  , parameterMinLength = Nothing
+  , parameterMaxValue = Nothing
+  , parameterMinValue = Nothing
+  , parameterDescription = Nothing
+  , parameterConstraintDescription = Nothing
+  }
+
+-- | Wrapper around a list of 'Parameters's to we can modify the aeson
+-- instances.
+newtype Parameters = Parameters { unParameters :: [Parameter] }
+                   deriving (Show, Eq, Monoid)
+
+instance IsList Parameters where
+  type Item Parameters = Parameter
+  fromList = Parameters
+  toList = unParameters
+
+instance NamedItem Parameter where
+  itemName = parameterName
+  nameToJSON = parameterToJSON
+  nameParseJSON = parameterFromJSON
+
+instance ToJSON Parameters where
+  toJSON = namedItemToJSON . unParameters
+
+instance FromJSON Parameters where
+  parseJSON v = Parameters <$> namedItemFromJSON v
diff --git a/library/Stratosphere/Template.hs b/library/Stratosphere/Template.hs
new file mode 100644
--- /dev/null
+++ b/library/Stratosphere/Template.hs
@@ -0,0 +1,113 @@
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+-- | See:
+-- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html
+
+module Stratosphere.Template
+       ( Template (..)
+       , template
+       , encodeTemplate
+
+       -- Template lenses
+       , formatVersion
+       , description
+       , metadata
+       , parameters
+       , mappings
+       , conditions
+       , resources
+       , outputs
+       ) where
+
+import Control.Lens
+import Data.Aeson
+import Data.Aeson.Encode.Pretty
+import Data.Aeson.TH
+import qualified Data.ByteString.Lazy as BS
+import qualified Data.HashMap.Strict as HM
+import qualified Data.Text as T
+
+import Stratosphere.Helpers (modTemplateJSONField)
+import Stratosphere.Outputs
+import Stratosphere.Parameters
+import Stratosphere.Resources
+
+type Mapping = HM.HashMap T.Text Object
+
+data Template =
+  Template
+  { templateFormatVersion :: Maybe T.Text
+    -- ^ Specifies the AWS CloudFormation template version that the template
+    -- conforms to. The template format version is not the same as the API or
+    -- WSDL version. The template format version can change independently of
+    -- the API and WSDL versions.
+  , templateDescription :: Maybe T.Text
+    -- ^ A text string that describes the template. This section must always
+    -- follow the template format version section.
+  , templateMetadata :: Maybe Object
+    -- ^ JSON objects that provide additional information about the template.
+  , templateParameters :: Maybe Parameters
+    -- ^ Specifies values that you can pass in to your template at runtime
+    -- (when you create or update a stack). You can refer to parameters in the
+    -- Resources and Outputs sections of the template.
+  , templateMappings :: Maybe (HM.HashMap T.Text Mapping)
+    -- ^ A mapping of keys and associated values that you can use to specify
+    -- conditional parameter values, similar to a lookup table. You can match a
+    -- key to a corresponding value by using the Fn::FindInMap intrinsic
+    -- function in the Resources and Outputs section.
+  , templateConditions :: Maybe Object
+    -- ^ Defines conditions that control whether certain resources are created
+    -- or whether certain resource properties are assigned a value during stack
+    -- creation or update. For example, you could conditionally create a
+    -- resource that depends on whether the stack is for a production or test
+    -- environment.
+  , templateResources :: Resources
+    -- ^ Specifies the stack resources and their properties, such as an Amazon
+    -- Elastic Compute Cloud instance or an Amazon Simple Storage Service
+    -- bucket. You can refer to resources in the Resources and Outputs sections
+    -- of the template.
+  , templateOutputs :: Maybe Outputs
+    -- ^ Describes the values that are returned whenever you view your stack's
+    -- properties. For example, you can declare an output for an Amazon S3
+    -- bucket name and then call the aws cloudformation describe-stacks AWS CLI
+    -- command to view the name.
+  } deriving (Show)
+
+
+$(deriveJSON defaultOptions { fieldLabelModifier = modTemplateJSONField
+                            , omitNothingFields = True } ''Template)
+$(makeFields ''Template)
+
+-- | Convenient constructor for 'Template' with required arguments.
+template :: Resources -> Template
+template res =
+  Template
+  { templateFormatVersion = Nothing
+  , templateDescription = Nothing
+  , templateMetadata = Nothing
+  , templateParameters = Nothing
+  , templateMappings = Nothing
+  , templateConditions = Nothing
+  , templateResources = res
+  , templateOutputs = Nothing
+  }
+
+-- | Pretty print a template using aeson-pretty.
+encodeTemplate :: Template -> BS.ByteString
+encodeTemplate = encodePretty' defConfig { confIndent = 2, confCompare = comp }
+  where comp = keyOrder [ "AWSTemplateFormatVersion"
+                        , "Description"
+                        , "Metadata"
+                        , "Parameters"
+                        , "Mappings"
+                        , "Conditions"
+                        , "Resources"
+                        , "Outputs"
+                        ]
diff --git a/library/Stratosphere/Values.hs b/library/Stratosphere/Values.hs
new file mode 100644
--- /dev/null
+++ b/library/Stratosphere/Values.hs
@@ -0,0 +1,122 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE StandaloneDeriving #-}
+
+module Stratosphere.Values
+       ( Val (..)
+       , Integer' (..)
+       , Bool' (..)
+       , ToRef (..)
+       ) where
+
+import Data.Aeson
+import qualified Data.HashMap.Strict as HM
+import Data.String (IsString (..))
+import qualified Data.Text as T
+import Text.Read (readMaybe)
+import GHC.Exts (fromList)
+
+-- GADTs are cool, but I couldn't get this to work with FromJSON
+-- data Val a where
+--   Literal :: a -> Val a
+--   Ref :: T.Text -> Val a
+--   If :: T.Text -> Val a -> Val a -> Val a
+--   And :: Val Bool -> Val Bool -> Val Bool
+--   Equals :: (Show a, ToJSON a) => Val a -> Val a -> Val Bool
+--   Or :: Val Bool -> Val Bool -> Val Bool
+
+-- | This type is a wrapper around any values in a template. A value can be a
+-- 'Literal', a 'Ref', or an intrinsic function. See:
+-- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html
+data Val a
+ = Literal a
+ | Ref T.Text
+ | If T.Text (Val a) (Val a)
+ | And (Val Bool') (Val Bool')
+ | Equals (Val Bool') (Val Bool')
+ | Or (Val Bool') (Val Bool')
+ | GetAtt T.Text T.Text
+ | Base64 (Val a)
+ | Join T.Text [Val a]
+ | Select Integer' (Val a)
+ | GetAZs (Val a)
+
+deriving instance (Show a) => Show (Val a)
+
+instance (IsString a) => IsString (Val a) where
+  fromString s = Literal (fromString s)
+
+instance (ToJSON a) => ToJSON (Val a) where
+  toJSON (Literal v) = toJSON v
+  toJSON (Ref r) = object [("Ref", toJSON r)]
+  toJSON (If i x y) = mkFunc "Fn::If" [toJSON i, toJSON x, toJSON y]
+  toJSON (And x y) = mkFunc "Fn::And" [toJSON x, toJSON y]
+  toJSON (Equals x y) = mkFunc "Fn::Equals" [toJSON x, toJSON y]
+  toJSON (Or x y) = mkFunc "Fn::Or" [toJSON x, toJSON y]
+  toJSON (GetAtt x y) = mkFunc "Fn::GetAtt" [toJSON x, toJSON y]
+  toJSON (Base64 v) = object [("Fn::Base64", toJSON v)]
+  toJSON (Join d vs) = mkFunc "Fn::Join" [toJSON d, toJSON vs]
+  toJSON (Select i vs) = mkFunc "Fn::Select" [toJSON i, toJSON vs]
+  toJSON (GetAZs r) = object [("Fn::GetAZs", toJSON r)]
+
+mkFunc :: T.Text -> [Value] -> Value
+mkFunc name args = object [(name, Array $ fromList args)]
+
+instance (FromJSON a) => FromJSON (Val a) where
+  parseJSON (Object o) =
+    case HM.toList o of
+      [] -> fail "Empty object as Val"
+      [("Ref", o')] -> Ref <$> parseJSON o'
+      [("Fn::If", o')] -> (\(i, x, y) -> If i x y) <$> parseJSON o'
+      [("Fn::And", o')] -> uncurry And <$> parseJSON o'
+      [("Fn::Equals", o')] -> uncurry Equals <$> parseJSON o'
+      [("Fn::Or", o')] -> uncurry Or <$> parseJSON o'
+      [("Fn::GetAtt", o')] -> uncurry GetAtt <$> parseJSON o'
+      [("Fn::Base64", o')] -> Base64 <$> parseJSON o'
+      [("Fn::Join", o')] -> uncurry Join <$> parseJSON o'
+      [("Fn::Select", o')] -> uncurry Select <$> parseJSON o'
+      [("Fn::GetAZs", o')] -> GetAZs <$> parseJSON o'
+      [(n, o')] -> Literal <$> parseJSON (object [(n, o')])
+      os -> Literal <$> parseJSON (object os)
+  parseJSON v = Literal <$> parseJSON v
+
+
+-- | We need to wrap integers so we can override the Aeson type-classes. This
+-- is necessary because CloudFront made the silly decision to represent numbers
+-- as JSON strings.
+newtype Integer' = Integer' { unInteger' :: Integer }
+                 deriving (Show, Eq, Num)
+
+instance ToJSON Integer' where
+  toJSON (Integer' i) = toJSON $ show i
+
+instance FromJSON Integer' where
+  parseJSON v = Integer' <$> do
+    numString <- parseJSON v
+    case readMaybe (numString :: String) of
+      Nothing -> fail "Can't read number from string"
+      (Just n) -> return n
+
+-- | We need to wrap Bools for the same reason we need to wrap Ints.
+data Bool'
+  = False'
+  | True'
+  deriving (Show, Bounded, Enum, Eq, Ord)
+
+instance ToJSON Bool' where
+  toJSON True' = "true"
+  toJSON False' = "false"
+
+instance FromJSON Bool' where
+  parseJSON v = do
+    string <- parseJSON v
+    case string of
+      "true" -> return True'
+      "false" -> return False'
+      _ -> fail $ "Unknown bool string " ++ string
+
+-- | Class used to create a 'Ref' from another type.
+class ToRef a b where
+  toRef :: a -> Val b
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
--- /dev/null
+++ b/stack.yaml
@@ -0,0 +1,4 @@
+resolver: nightly-2016-04-05
+packages:
+  - '.'
+extra-deps: []
diff --git a/stratosphere.cabal b/stratosphere.cabal
new file mode 100644
--- /dev/null
+++ b/stratosphere.cabal
@@ -0,0 +1,196 @@
+-- This file has been generated from package.yaml by hpack version 0.12.0.
+--
+-- see: https://github.com/sol/hpack
+
+name:           stratosphere
+version:        0.1.0
+synopsis:       EDSL for AWS CloudFormation
+description:    EDSL for AWS CloudFormation
+category:       AWS, Cloud
+stability:      experimental
+homepage:       https://github.com/frontrowed/stratosphere#readme
+bug-reports:    https://github.com/frontrowed/stratosphere/issues
+maintainer:     David Reaver
+license:        MIT
+license-file:   LICENSE.md
+build-type:     Simple
+cabal-version:  >= 1.10
+
+extra-source-files:
+    CHANGELOG.md
+    README.md
+    stack.yaml
+
+source-repository head
+  type: git
+  location: https://github.com/frontrowed/stratosphere
+
+library
+  hs-source-dirs:
+      library
+    , library-gen
+  ghc-options: -Wall
+  build-depends:
+      base >= 4.8 && < 5
+    , aeson >= 0.11
+    , aeson-pretty >= 0.7
+    , bytestring
+    , ede
+    , lens >= 4.5
+    , system-fileio
+    , system-filepath
+    , template-haskell >= 2.0
+    , text >= 1.1
+    , unordered-containers >= 0.2
+  exposed-modules:
+      Stratosphere
+      Stratosphere.Helpers
+      Stratosphere.Outputs
+      Stratosphere.Parameters
+      Stratosphere.Template
+      Stratosphere.Values
+      Stratosphere.ResourceProperties.AccessLoggingPolicy
+      Stratosphere.ResourceProperties.AliasTarget
+      Stratosphere.ResourceProperties.AppCookieStickinessPolicy
+      Stratosphere.ResourceProperties.ConnectionDrainingPolicy
+      Stratosphere.ResourceProperties.ConnectionSettings
+      Stratosphere.ResourceProperties.EBSBlockDevice
+      Stratosphere.ResourceProperties.EC2BlockDeviceMapping
+      Stratosphere.ResourceProperties.EC2MountPoint
+      Stratosphere.ResourceProperties.EC2SsmAssociationParameters
+      Stratosphere.ResourceProperties.EC2SsmAssociations
+      Stratosphere.ResourceProperties.ELBPolicy
+      Stratosphere.ResourceProperties.HealthCheck
+      Stratosphere.ResourceProperties.IAMPolicies
+      Stratosphere.ResourceProperties.LBCookieStickinessPolicy
+      Stratosphere.ResourceProperties.ListenerProperty
+      Stratosphere.ResourceProperties.NetworkInterface
+      Stratosphere.ResourceProperties.PrivateIpAddressSpecification
+      Stratosphere.ResourceProperties.RDSSecurityGroupRule
+      Stratosphere.ResourceProperties.RecordSetGeoLocation
+      Stratosphere.ResourceProperties.ResourceTag
+      Stratosphere.ResourceProperties.SecurityGroupEgressRule
+      Stratosphere.ResourceProperties.SecurityGroupIngressRule
+      Stratosphere.ResourceProperties.UserLoginProfile
+      Stratosphere.Resources
+      Stratosphere.Resources.AccessKey
+      Stratosphere.Resources.DBInstance
+      Stratosphere.Resources.DBParameterGroup
+      Stratosphere.Resources.DBSecurityGroup
+      Stratosphere.Resources.DBSecurityGroupIngress
+      Stratosphere.Resources.DBSubnetGroup
+      Stratosphere.Resources.EC2Instance
+      Stratosphere.Resources.EIP
+      Stratosphere.Resources.EIPAssociation
+      Stratosphere.Resources.Group
+      Stratosphere.Resources.IAMRole
+      Stratosphere.Resources.InstanceProfile
+      Stratosphere.Resources.InternetGateway
+      Stratosphere.Resources.LoadBalancer
+      Stratosphere.Resources.ManagedPolicy
+      Stratosphere.Resources.NatGateway
+      Stratosphere.Resources.Policy
+      Stratosphere.Resources.RecordSet
+      Stratosphere.Resources.RecordSetGroup
+      Stratosphere.Resources.Route
+      Stratosphere.Resources.RouteTable
+      Stratosphere.Resources.SecurityGroup
+      Stratosphere.Resources.Stack
+      Stratosphere.Resources.Subnet
+      Stratosphere.Resources.SubnetRouteTableAssociation
+      Stratosphere.Resources.User
+      Stratosphere.Resources.UserToGroupAddition
+      Stratosphere.Resources.Volume
+      Stratosphere.Resources.VolumeAttachment
+      Stratosphere.Resources.VPC
+      Stratosphere.Resources.VPCEndpoint
+      Stratosphere.Resources.VPCGatewayAttachment
+  default-language: Haskell2010
+
+executable ec2-with-eip
+  main-is: ec2-with-eip.hs
+  hs-source-dirs:
+      examples
+  ghc-options: -Wall
+  build-depends:
+      base >= 4.8 && < 5
+    , aeson >= 0.11
+    , aeson-pretty >= 0.7
+    , bytestring
+    , ede
+    , lens >= 4.5
+    , system-fileio
+    , system-filepath
+    , template-haskell >= 2.0
+    , text >= 1.1
+    , unordered-containers >= 0.2
+    , stratosphere
+  default-language: Haskell2010
+
+executable rds-master-replica
+  main-is: rds-master-replica.hs
+  hs-source-dirs:
+      examples
+  ghc-options: -Wall
+  build-depends:
+      base >= 4.8 && < 5
+    , aeson >= 0.11
+    , aeson-pretty >= 0.7
+    , bytestring
+    , ede
+    , lens >= 4.5
+    , system-fileio
+    , system-filepath
+    , template-haskell >= 2.0
+    , text >= 1.1
+    , unordered-containers >= 0.2
+    , stratosphere
+  default-language: Haskell2010
+
+test-suite style
+  type: exitcode-stdio-1.0
+  main-is: HLint.hs
+  hs-source-dirs:
+      tests
+  build-depends:
+      base >= 4.8 && < 5
+    , aeson >= 0.11
+    , aeson-pretty >= 0.7
+    , bytestring
+    , ede
+    , lens >= 4.5
+    , system-fileio
+    , system-filepath
+    , template-haskell >= 2.0
+    , text >= 1.1
+    , unordered-containers >= 0.2
+    , base
+    , hlint
+  other-modules:
+      Main
+  default-language: Haskell2010
+
+test-suite tasty
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  hs-source-dirs:
+      tests
+  build-depends:
+      base >= 4.8 && < 5
+    , aeson >= 0.11
+    , aeson-pretty >= 0.7
+    , bytestring
+    , ede
+    , lens >= 4.5
+    , system-fileio
+    , system-filepath
+    , template-haskell >= 2.0
+    , text >= 1.1
+    , unordered-containers >= 0.2
+    , base
+    , stratosphere
+    , tasty
+    , tasty-hspec
+  other-modules:
+      HLint
+  default-language: Haskell2010
diff --git a/tests/HLint.hs b/tests/HLint.hs
new file mode 100644
--- /dev/null
+++ b/tests/HLint.hs
@@ -0,0 +1,16 @@
+module Main (main) where
+
+import Language.Haskell.HLint (hlint)
+import System.Exit (exitFailure, exitSuccess)
+
+arguments :: [String]
+arguments =
+    [ "library"
+    , "tests"
+    , "gen"
+    ]
+
+main :: IO ()
+main = do
+    hints <- hlint arguments
+    if null hints then exitSuccess else exitFailure
diff --git a/tests/Main.hs b/tests/Main.hs
new file mode 100644
--- /dev/null
+++ b/tests/Main.hs
@@ -0,0 +1,12 @@
+import qualified Test.Tasty
+import Test.Tasty.Hspec
+
+main :: IO ()
+main = do
+    test <- testSpec "stratosphere" spec
+    Test.Tasty.defaultMain test
+
+spec :: Spec
+spec = parallel $
+    it "is trivially true" $
+        True `shouldBe` True
