{"id":15403411,"url":"https://github.com/mbj/stratosphere-mbj","last_synced_at":"2025-09-11T01:34:55.673Z","repository":{"id":66234543,"uuid":"488618512","full_name":"mbj/stratosphere-mbj","owner":"mbj","description":null,"archived":false,"fork":false,"pushed_at":"2022-05-04T14:19:06.000Z","size":5583,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"add/aeson-2-support-redux","last_synced_at":"2025-07-14T11:45:40.810Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mbj.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-04T14:18:53.000Z","updated_at":"2022-05-04T14:20:35.000Z","dependencies_parsed_at":"2023-02-24T01:01:17.609Z","dependency_job_id":null,"html_url":"https://github.com/mbj/stratosphere-mbj","commit_stats":{"total_commits":448,"total_committers":12,"mean_commits":"37.333333333333336","dds":0.1316964285714286,"last_synced_commit":"59b6c8216e54b7014118f1dd06d124d1506805aa"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mbj/stratosphere-mbj","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbj%2Fstratosphere-mbj","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbj%2Fstratosphere-mbj/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbj%2Fstratosphere-mbj/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbj%2Fstratosphere-mbj/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mbj","download_url":"https://codeload.github.com/mbj/stratosphere-mbj/tar.gz/refs/heads/add/aeson-2-support-redux","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbj%2Fstratosphere-mbj/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274561142,"owners_count":25308254,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-10T02:00:12.551Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T16:08:25.888Z","updated_at":"2025-09-11T01:34:55.634Z","avatar_url":"https://github.com/mbj.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Stratosphere: AWS CloudFormation in Haskell\n\n[![Circle CI](https://circleci.com/gh/freckle/stratosphere.svg?style=svg)](https://circleci.com/gh/freckle/stratosphere)\n\nAWS CloudFormation is a system that provisions and updates Amazon Web Services\n(AWS) resources based on declarative templates. Common criticisms of\nCloudFormation include the use of JSON as the template language and limited\nerror-checking, often only available in the form of run-time errors and stack\nrollbacks. By wrapping templates in Haskell, we are able to easily construct\nthem and help ensure correctness.\n\nThe goals of stratosphere are to:\n* Build a Haskell EDSL to specify CloudFormation templates. Since it is\n  embedded in Haskell, it is type-checked and generally much easier to work\n  with than raw JSON.\n* Have a simple checking/linting system outside of the types that can find\n  common errors in templates.\n* Be able to also read valid CloudFormation JSON templates so they can be\n  type-checked. This also gives us free integration tests by using the huge\n  amount of example templates available in the AWS docs.\n\n## Example\n\nHere is an example of a `Template` that creates an EC2 instance, along with the\nJSON output:\n\n```haskell\n{-# LANGUAGE OverloadedLists #-}\n{-# LANGUAGE OverloadedStrings #-}\n\nmodule Main where\n\nimport qualified Data.ByteString.Lazy.Char8 as B\nimport Stratosphere\n\nmain :: IO ()\nmain = B.putStrLn $ encodeTemplate instanceTemplate\n\ninstanceTemplate :: Template\ninstanceTemplate =\n  template\n  [ resource \"EC2Instance\" (\n    EC2InstanceProperties $\n    ec2Instance\n    \u0026 eciImageId ?~ \"ami-22111148\"\n    \u0026 eciKeyName ?~ (Ref \"KeyName\")\n    )\n    \u0026 resourceDeletionPolicy ?~ Retain\n  ]\n  \u0026 templateDescription ?~ \"Sample template\"\n  \u0026 templateParameters ?~\n  [ parameter \"KeyName\" \"AWS::EC2::KeyPair::KeyName\"\n    \u0026 parameterDescription ?~ \"Name of an existing EC2 KeyPair to enable SSH access to the instance\"\n    \u0026 parameterConstraintDescription ?~ \"Must be the name of an existing EC2 KeyPair.\"\n  ]\n```\n\n```json\n{\n  \"Description\": \"Sample template\",\n  \"Parameters\": {\n    \"KeyName\": {\n      \"Description\": \"Name of an existing EC2 KeyPair to enable SSH access to the instance\",\n      \"ConstraintDescription\": \"Must be the name of an existing EC2 KeyPair.\",\n      \"Type\": \"AWS::EC2::KeyPair::KeyName\"\n    }\n  },\n  \"Resources\": {\n    \"EC2Instance\": {\n      \"DeletionPolicy\": \"Retain\",\n      \"Type\": \"AWS::EC2::Instance\",\n      \"Properties\": {\n        \"KeyName\": {\n          \"Ref\": \"KeyName\"\n        },\n        \"ImageId\": \"ami-22111148\"\n      }\n    }\n  }\n}\n```\n\nPlease see the [examples](examples/) directory for more in-depth examples.\n\n## Value Types\n\nCloudFormation resource parameters can be literals (strings, integers, etc),\nreferences to another resource or a Parameter, or the result of some function\ncall. We encapsulate all of these possibilities in the `Val a` type.\n\nWe recommend using the `OverloadedStrings` extension to reduce the number of\n`Literal`s you have to use.\n\n## Lenses\n\nAlmost every CloudFormation resource has a handful of required arguments, and\nmany more optional arguments. Each resource is represented as a record type\nwith optional arguments wrapped in `Maybe`. Each resource also comes with a\nconstructor that accepts required resource parameters as arguments. This allows\nthe user to succinctly specify the resource parameters they actually use\nwithout adding too much noise to their code.\n\nTo specify optional arguments, we recommend using the lens operators `\u0026` and\n`?~`. In the example above, the optional EC2 key name is specified using the \n`\u0026` and `?~` lens operators.\n\nThis approach is very similar to the approach taken by the `amazonka` library.\nSee this\n[blog post](http://brendanhay.nz/amazonka-comprehensive-haskell-aws-client#smart-constructors)\nfor an explanation.\n\n## Auto-generation\n\nAll of the resources and resource properties are auto-generated from\na\n[JSON schema file](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html) and\nare placed in `library-gen/`. The `gen/` directory contains the auto-generator\ncode and the JSON model file. We include the `library-gen/` directory in git so\nthe build process is simplified. To build `library-gen` from scratch and then\nbuild all of `stratosphere`, just run the very short `build.sh` script. You can\npass stack args to the script too, so run `./build.sh --fast` to build the\nlibrary without optimization. This is useful for development.\n\nIn the future, it would be great to not have to include the auto-generated code\nin git.\n\n## Contributing\n\nFeel free to raise any issues, or even just make suggestions, by filing a\nGithub issue.\n\n## Future Work\n\n* Implement basic checker for things like undefined Refs and duplicate field\n  names. This stuff would be too unwieldy to do in types, and performing a\n  checking pass over a template should be pretty straightforward.\n* Use a custom JSON encoder so the templates look a little more idiomatic. We\n  also create a lot of empty whitespace and newlines using aeson-pretty. There\n  are limits on the size of CloudFormation templates, and we want readable\n  output without hitting the limits. Also, we have some newtypes that just\n  exist to override aeson instances, and we could get rid of those.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmbj%2Fstratosphere-mbj","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmbj%2Fstratosphere-mbj","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmbj%2Fstratosphere-mbj/lists"}