{"id":13602617,"url":"https://github.com/envato/stack_master","last_synced_at":"2026-02-02T05:31:40.743Z","repository":{"id":44782924,"uuid":"44935321","full_name":"envato/stack_master","owner":"envato","description":"The missing CloudFormation tool","archived":false,"fork":false,"pushed_at":"2025-01-12T23:39:05.000Z","size":1796,"stargazers_count":292,"open_issues_count":26,"forks_count":46,"subscribers_count":90,"default_branch":"master","last_synced_at":"2025-04-12T21:22:45.904Z","etag":null,"topics":["aws","aws-cloudformation","cloudformation"],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/envato.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2015-10-25T23:40:28.000Z","updated_at":"2025-03-26T05:44:35.000Z","dependencies_parsed_at":"2024-01-02T21:57:51.200Z","dependency_job_id":"f41df799-0f2d-4c4f-a5bf-3389479afcb0","html_url":"https://github.com/envato/stack_master","commit_stats":{"total_commits":1072,"total_committers":40,"mean_commits":26.8,"dds":0.6940298507462687,"last_synced_commit":"36b3fe8ef9d96989d64e3bf615e407053c413025"},"previous_names":[],"tags_count":86,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/envato%2Fstack_master","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/envato%2Fstack_master/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/envato%2Fstack_master/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/envato%2Fstack_master/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/envato","download_url":"https://codeload.github.com/envato/stack_master/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253830789,"owners_count":21970999,"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","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":["aws","aws-cloudformation","cloudformation"],"created_at":"2024-08-01T18:01:31.798Z","updated_at":"2026-02-02T05:31:40.736Z","avatar_url":"https://github.com/envato.png","language":"Ruby","readme":"![StackMaster](/logo.png?raw=true)\n\n[![License MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/envato/stack_master/blob/master/LICENSE.md)\n[![Gem Version](https://badge.fury.io/rb/stack_master.svg)](https://badge.fury.io/rb/stack_master)\n[![Build Status](https://github.com/envato/stack_master/actions/workflows/test.yml/badge.svg)](https://github.com/envato/stack_master/actions/workflows/test.yml)\n\nStackMaster is a CLI tool to manage [CloudFormation](https://aws.amazon.com/cloudformation/) stacks, with the following features:\n\n- Synchronous visibility into stack updates. See exactly what is changing and\n  what will happen before agreeing to apply a change.\n- Dynamic parameter resolvers.\n- Template compiler support for YAML and [SparkleFormation](http://www.sparkleformation.io).\n\nStack updates can cause a lot of damage if applied blindly. StackMaster helps\nwith this by providing the operator with as much information about the proposed\nchange as possible before asking for confirmation to continue. That information\nincludes:\n\n- Template body and parameter diffs.\n- [Change\n  sets](https://aws.amazon.com/blogs/aws/new-change-sets-for-aws-cloudformation/)\nare displayed for review.\n- Once the diffs \u0026 change set have been reviewed, the change can be applied and\n  stack events monitored.\n- Stack events will be displayed until an end state is reached.\n\nStack parameters can be dynamically resolved at runtime using one of the\nbuilt in parameter resolvers. Parameters can be sourced from other stacks\noutputs, or by querying various AWS APIs to get resource ARNs, etc.\n\n## Installation\n\n### System-wide\n\n```shell\ngem install stack_master\n\n# if you want linting capabilities:\npip install cfn-lint\n```\n\n### Bundler\n\n- `pip install cfn-lint` if you need lint functionality\n- Add `gem 'stack_master'` to your Gemfile.\n- Run `bundle install`\n- Run `bundle exec stack_master init` to generate a directory structure and stack_master.yml file\n\n## Configuration\n\nStacks are defined inside a `stack_master.yml` YAML file. When running\n`stack_master`, it is assumed that this file will exist in the current working\ndirectory, or that the file is passed in with `--config\n/path/to/stack_master.yml`.  Here's an example configuration file:\n\n```yaml\nregion_aliases:\n  production: us-east-1\n  staging: ap-southeast-2\nstack_defaults:\n  tags:\n    application: my-awesome-app\n  role_arn: service_role_arn\nregion_defaults:\n  us-east-1:\n    tags:\n      environment: production\n    notification_arns:\n      - test_arn\n  ap-southeast-2:\n    tags:\n      environment: staging\nstacks:\n  production:\n    myapp-vpc:\n      template: myapp_vpc.rb\n      tags:\n        purpose: front-end\n    myapp-db:\n      template: myapp_db.rb\n      stack_policy_file: db_stack_policy.json\n      tags:\n        purpose: back-end\n    myapp-web:\n      template: myapp_web.rb\n      tags:\n        purpose: front-end\n  staging:\n    myapp-vpc:\n      template: myapp_vpc.rb\n      allowed_accounts: '123456789'\n      tags:\n        purpose: front-end\n    myapp-db:\n      template: myapp_db.rb\n      allowed_accounts:\n        - '1234567890'\n        - '9876543210'\n      tags:\n        purpose: back-end\n    myapp-web:\n      template: myapp_web.rb\n      tags:\n        purpose: front-end\n  eu-central-1:\n    myapp-vpc:\n      template: myapp_vpc.rb\n      tags:\n        purpose: vpc\n```\n\n## S3\n\nStackMaster can optionally use S3 to store the templates before creating a stack.\nThis requires you to configure an S3 bucket in stack_master.yml:\n\n```yaml\nstack_defaults:\n  s3:\n    bucket: my_bucket_name\n    prefix: cfn_templates/my-awesome-app\n    region: us-west-2\n```\n\nAdditional files can be configured to be uploaded to S3 alongside the templates:\n\n```yaml\nstacks:\n  production:\n    myapp-vpc:\n      template: myapp_vpc.rb\n      files:\n        - userdata.sh\n```\n\n## Directories\n\n- `templates` - CloudFormation, SparkleFormation or CfnDsl templates.\n- `parameters` - Parameters as YAML files.\n- `secrets` - encrypted secret files.\n- `policies` - Stack policy JSON files.\n\n## Templates\n\nStackMaster supports CloudFormation templates in plain JSON or YAML. Any `.yml` or `.yaml` file will be processed as\nYAML, while any `.json` file will be processed as JSON. Additionally, YAML files can be pre-processed using ERB and\ncompile-time parameters.\n\n### Ruby DSLs\nBy default, any template ending with `.rb` will be processed as a [SparkleFormation](https://github.com/sparkleformation/sparkle_formation)\ntemplate. However, if you want to use [CfnDsl](https://github.com/stevenjack/cfndsl) templates you can add\nthe following lines to your `stack_master.yml`.\n\n```\ntemplate_compilers:\n  rb: cfndsl\n```\n\n## Parameters\n\nBy default, parameters are loaded from multiple YAML files, merged from the\nfollowing lookup paths from bottom to top:\n\n- parameters/[stack_name].yaml\n- parameters/[stack_name].yml\n- parameters/[region]/[stack_name].yaml\n- parameters/[region]/[stack_name].yml\n- parameters/[region_alias]/[stack_name].yaml\n- parameters/[region_alias]/[stack_name].yml\n\nA simple parameter file could look like this:\n\n```yaml\nkey_name: myapp-us-east-1\n```\n\nAlternatively, a `parameter_files` array can be defined to explicitly list\nparameter files that will be loaded. If `parameter_files` are defined, the\nautomatic search locations will not be used.\n\n```yaml\nparameters_dir: parameters # the default\nstacks:\n  us-east-1:\n    my-app:\n      parameter_files:\n        - my-app.yml # parameters/my-app.yml\n```\n\nParameters can also be defined inline with stack definitions:\n\n```yaml\nstacks:\n  us-east-1:\n    my-app:\n      parameters:\n        VpcId:\n          stack_output: my-vpc/VpcId\n```\n\n### Compile Time Parameters\n\nCompile time parameters can be defined in a stack's parameters file, using the key `compile_time_parameters`. Keys in\nparameter files are automatically converted to camel case.\n\nAs an example:\n\n```yaml\n# parameters/some_stack.yml\nvpc_cidr: 10.0.0.0/16\ncompile_time_parameters:\n  subnet_cidrs:\n    - 10.0.0.0/28\n    - 10.0.2.0/28\n```\n\n#### SparkleFormation\n\nCompile time parameters can be used for [SparkleFormation](http://www.sparkleformation.io) templates. It conforms and\nallows you to use the [Compile Time Parameters](http://www.sparkleformation.io/docs/sparkle_formation/compile-time-parameters.html) feature.\n\n#### CloudFormation YAML ERB\n\nCompile time parameters can be used to pre-process YAML CloudFormation templates. An example template:\n\n```yaml\n# templates/some_stack_template.yml.erb\nParameters:\n  VpcCidr:\n    Type: String\nResources:\n  Vpc:\n    Type: AWS::EC2::VPC\n    Properties:\n      CidrBlock: !Ref VpcCidr\n  # Given the two subnet_cidrs parameters, this creates two resources:\n  # SubnetPrivate0 with a CidrBlock of 10.0.0.0/28, and\n  # SubnetPrivate1 with a CidrBlock of 10.0.2.0/28\n  \u003c% params[\"SubnetCidrs\"].each_with_index do |cidr, index| %\u003e\n  SubnetPrivate\u003c%= index %\u003e:\n    Type: AWS::EC2::Subnet\n    Properties:\n      VpcId: !Ref Vpc\n      AvailabilityZone: ap-southeast-2\n      CidrBlock: \u003c%= cidr %\u003e\n  \u003c% end %\u003e\n```\n\n## Parameter Resolvers\n\nParameter values can be sourced dynamically using parameter resolvers.\n\nOne benefit of using parameter resolvers instead of hard coding values like VPC\nIDs and resource ARNs is that the same configuration works cross\nregion/account, even though the resolved values will be different.\n\n### Cross-account parameter resolving\n\nOne way to resolve parameter values from different accounts to the one StackMaster runs in, is to\nassume a role in another account with the relevant IAM permissions to execute successfully.\n\nThis is supported in StackMaster by specifying the `role` and `account` properties for the\nparameter resolver in the stack's parameters file.\n\nAll parameter resolvers are supported.\n\n```yaml\nvpc_peering_id:\n  role: cross-account-parameter-resolver\n  account: 1234567890\n  stack_output: vpc-peering-stack-in-other-account/peering_name\n\nan_array_param:\n  role: cross-account-parameter-resolver\n  account: 1234567890\n  stack_outputs:\n    - stack-in-account1/output\n    - stack-in-account1/another_output\n\nanother_array_param:\n  - role: cross-account-parameter-resolver\n    account: 1234567890\n    stack_output: stack-in-account1/output\n  - role: cross-account-parameter-resolver\n    account: 0987654321\n    stack_output: stack-in-account2/output\n\nmy_secret:\n  role: cross-account-parameter-resolver\n  account: 1234567890\n  parameter_store: ssm_parameter_name\n```\n\nAn example of use case where cross-account parameter resolving is particularly useful is when\nsetting up VPC peering where you need the VPC ID of the peer. Without the ability to assume\na role in another account, the only option was to hard code the peer's VPC ID.\n\n### Stack Output\n\nThe stack output parameter resolver looks up outputs from other stacks in the\nsame or different region. The expected format is `[(region|region-alias):]stack-name/(OutputName|output_name)`.\n\n```yaml\nvpc_id:\n  # Output from a stack in the same region\n  stack_output: my-vpc-stack/VpcId\n\nbucket_name:\n  # Output from a stack in a different region\n  stack_output: us-east-1:init-bucket/bucket_name\n\nzone_name:\n  # Output from a stack in a different region using its alias\n  stack_output: global:hosted-zone/ZoneName\n```\n\nThis is the most used parameter resolver because it enables stacks to be split\nup into their separated concerns (VPC, web, database etc) with outputs feeding\ninto parameters of dependent stacks.\n\n### Secret\n\nNote: The GPG parameter resolver has been extracted into a dedicated gem. Please install and\nfollow the instructions for the [stack_master-gpg_parameter_resolver] gem.\n\n[stack_master-gpg_parameter_resolver]: https://github.com/envato/stack_master-gpg_parameter_resolver\n\n### Parameter Store\n\nAn alternative to the secrets store, uses the AWS SSM Parameter store to protect\nsecrets.   Expects a parameter of either `String` or `SecureString` type to be present in the\nsame region as the stack. You can store the parameter using a command like this\n\n`aws ssm put-parameter --region \u003cregion\u003e --name \u003cparameter name\u003e --value \u003csecret\u003e --type (String|SecureString)`\n\nWhen doing so make sure you don't accidentally store the secret in your `.bash_history` and\nyou will likely want to set the parameter to NoEcho in your template.\n\n```yaml\ndb_password:\n  parameter_store: ssm_parameter_name\n```\n\n### 1Password Lookup\nAn alternative to the secrets store is accessing 1password secrets using the 1password cli (`op`).\nYou declare a 1password lookup with the following parameters in your parameters file:\n\n```yaml\n# parameters/database.yml\ndatabase_password:\n  one_password:\n    title: production database\n    vault: Shared\n    type: password\n```\n\n1password stores the name of the secret in the `title`. You can pass the `vault` you expect the secret to be in.\nCurrently we support two types of secrets, `password`s and `secureNote`s. All values must be declared, there are no defaults.\n\nFor more information on 1password cli please see [here](https://support.1password.com/command-line-getting-started/)\n\n### EJSON Store\n\n[ejson](https://github.com/Shopify/ejson) is a tool to manage asymmetrically encrypted values in JSON format.\nThis allows you to keep secrets securely in git/Github and gives anyone the ability the capability to add new\nsecrets without requiring access to the private key. [ejson_wrapper](https://github.com/envato/ejson_wrapper)\nencrypts the underlying EJSON private key with KMS and stores it in the ejson file as `_private_key_enc`. Each\ntime an ejson secret is required, the underlying EJSON private key is first decrypted before passing it onto\nejson to decrypt the file.\n\nFirst, generate an ejson file with ejson_wrapper, specifying the KMS key ID to be used:\n\n```shell\ngem install ejson_wrapper\nejson_wrapper generate --region us-east-1 --kms-key-id [key_id] --file secrets/production.ejson\n```\n\nThen, add the `ejson_file` argument to your stack in stack_master.yml:\n\n```yaml\nstacks:\n  us-east-1:\n    my_app:\n      template: my_app.json\n      ejson_file: production.ejson\n```\n\nfinally refer to the secret key in the parameter file, i.e. parameters/my_app.yml:\n\n```yaml\nmy_param:\n  ejson: \"my_secret\"\n```\n\nAdditional configuration options:\n\n- `ejson_file_region` The AWS region to attempt to decrypt private key with\n- `ejson_file_kms` Default: true. Set to false to use ejson without KMS.\n\n### Security Group\n\nLooks up a security group by name and returns the ARN.\n\n```yaml\nssh_sg:\n  security_group: SSHSecurityGroup\n```\n\n### Security Groups\n\nAn array of security group names can also be provided.\n```yaml\nssh_sg:\n  security_groups:\n    - SSHSecurityGroup\n    - WebAccessSecurityGroup\n```\n\n### AWS IIC/SSO Group IDs\n\nLooks up AWS Identity Center group name in the configured Identity Store and returns the ID suitable for use in AWS IIC assignments.\nIt is likely that account and role will need to be specified to do the lookup, the region specification is optional it defaults to stack region.\n\n```yaml\nGroupId:\n  sso_group_id: '[region:]identity-store-id/SSO Group Name'\n```\n\ne.g.\n```yaml\nGroupIdNotInStackRegion:\n  sso_group_id: 'us-east-1:d-123456df8:Okta-App-AWS-FooBar'\nGroupIdInStackRegion:\n  sso_group_id: 'd-123456df8:Okta-App-AWS-FooBar'\n```\n\n### SNS Topic\n\nLooks up an SNS topic by name and returns the ARN.\n\n```yaml\nnotification_topic:\n  sns_topic_name: PagerDuty\n```\n\n### Latest AMI by Tag\n\nLooks up the latest AMI ID by a given set of tags.\n\n```yaml\nweb_ami:\n  latest_ami_by_tags: role=web,application=myapp\n```\n\nNote that the corresponding array resolver is named `latest_amis_by_tags`.\n\n### Latest AMI by attribute\n\nLooks up the latest AMI ID by a given set of attributes. By default it will only return AMIs from the account the stack is created in, but you can specify the account ID or [certain keywords mentioned in the aws documentation](http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-DescribeImages.html)\n\nThis selects the latest wily hvm AMI from Ubuntu (using the account id):\n\n```yaml\nbastion_ami:\n  latest_ami:\n    owners: 099720109477\n    filters:\n      name: ubuntu/images/hvm/ubuntu-wily-15.10-amd64-server-*\n```\n\nA set of possible attributes is available in the [AWS documentation](https://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Client.html#describe_images-instance_method).\n\nAny value can be an array of possible matches.\n\n### Latest Container from Repository\n\nLooks up the a Container Image from an ECR repository. By default this will return the latest container in a repository.\nIf `tag` is specified we return the sha digest of the image with this tag.\nThis avoids the issue where CloudFormation won't update a Task Definition if we use a tag such as `latest`, because it only updates resources if a parameter has changed.\nThis allows us to tag an image and deploy the latest version of that image via CloudFormation and avoids versioning our tags and having to store the metadata about the latest tag version somewhere.\n\nReturns the docker repository URI, i.e. `aws_account_id.dkr.ecr.region.amazonaws.com/container@sha256:digest`\n\n```yaml\ncontainer_image_id:\n  latest_container:\n    repository_name: nginx # Required. The name of the repository\n    registry_id: \"012345678910\" # The AWS Account ID the repository is located in. Defaults to the current account's default registry. Must be in quotes.\n    region: us-east-1 # Defaults to the region the stack is located in\n    tag: production # By default we'll find the latest image pushed to the repository. If tag is specified we return the sha digest of the image with this tag\n```\n\n### Environment Variable\n\nLookup an environment variable:\n\n```yaml\ndb_username:\n  env: DB_USERNAME\n```\n\n### ACM Certificates\n\nFind an ACM certificate by domain name:\n\n```yaml\ncert:\n  acm_certificate: www.example.com\n```\n\n### Custom parameter resolvers\n\nNew parameter resolvers can be created in a separate gem.\n\nTo create a resolver named my_resolver:\n  * Create a new gem using your favorite tool\n  * The gem structure must contain the following path:\n```\nlib/stack_master/parameter_resolvers/my_resolver.rb\n```\n  * That file needs to contain a class named `StackMaster::ParameterResolvers::MyResolver`\n    that implements a `resolve` method and an initializer taking 2 parameters :\n```ruby\nmodule StackMaster\n  module ParameterResolvers\n    class MyResolver \u003c Resolver\n      array_resolver # Also create a MyResolvers resolver to handle arrays\n\n      def initialize(config, stack_definition)\n        @config = config\n        @stack_definition = stack_definition\n      end\n\n      def resolve(value)\n        value\n      end\n    end\n  end\nend\n```\n  * Note that the filename and classname are both derived from the resolver name\n    passed in the parameter file. In our case, the parameters YAML would look like:\n```yaml\nvpc_id:\n  my_resolver: dummy_value\n```\n\n## Resolver Arrays\n\nMost resolvers support taking an array of values that will each be resolved.\nUnless stated otherwise in the documentation, the array version of the\nresolver will be named with the [pluralized](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-pluralize)\nname of the original resolver.\n\nWhen creating a new resolver, one can automatically create the array resolver by adding a `array_resolver` statement\nin the class definition, with an optional class name if different from the default one.\n```ruby\nmodule StackMaster\n  module ParameterResolvers\n    class MyResolver \u003c Resolver\n      array_resolver class_name: 'MyCustomArrayResolver'\n      ...\n    end\n  end\nend\n```\nIn that example, using the array resolver would look like:\n```yaml\nmy_parameter:\n  my_custom_array_resolver:\n    - value1\n    - value2\n```\n\nArray parameter values can include nested parameter resolvers.\n\nFor example, given the following parameter definition:\n```yaml\nmy_parameter:\n  - stack_output: my-stack/output # value resolves to 'value1'\n  - value2\n```\nThe parameter value will resolve to:\n```yaml\nmy_parameter: 'value1,value2'\n```\n\n## ERB Template Files in SparkleFormation templates\n\nAn extension to SparkleFormation is the `user_data_file!` method, which evaluates templates in `templates/user_data/[file_name]`. Most of the usual SparkleFormation methods are available in user data templates. Example:\n\n```\n# templates/user_data/app.erb\nREGION=\u003c%= region! %\u003e\nROLE=\u003c%= role %\u003e\n```\n\nAnd used like this in SparkleFormation templates:\n\n```ruby\n# templates/app.rb\n  user_data user_data_file!('app.erb', role: :worker)\n```\n\nYou can also use the `joined_file!` method which evaluates templates in `templates/config/[file_name]`. It is similar to `user_data_file!` but doesn't do base64 encoding. Example:\n\n```\n# templates/config/someconfig.conf.erb\nmy_variable=\u003c%= ref!(:foo) %\u003e\nmy_other_variable=\u003c%= account_id! %\u003e\n```\n\n```ruby\n# templates/ecs_task.rb\ncontainer_definitions array!(\n  -\u003e {\n    command array!(\n      \"-e\",\n      joined_file!('someconfig.conf.erb')\n    )\n    ...\n  }\n)\n```\n\n## Compiler Options \u0026 Alternate Template Directories\n\nStackMaster allows you to separate your stack definitions and parameters from your templates by way of a `template_dir` key in your stack_master.yml.\nYou can also pass compiler-specific options to the template compiler to further customize SparkleFormation or CfnDsl's behavior.  Combining the 2 lets you move your SFN templates away from your stack definitions.  For example, if your project is laid out as:\n\n```\nproject-root\n|-- envs\n  |-- env-1\n    |-- stack_master.yml\n  |-- env-2\n    |-- stack_master.yml\n|-- sparkle\n  |-- templates\n    |-- my-stack.rb\n```\n\nYour env-1/stack_master.yml files can reference common templates by setting:\n\n```yaml\ntemplate_dir: ../../sparkle/templates\nstack_defaults:\n  compiler_options:\n    sparkle_path: ../../sparkle\n\nstacks:\n  us-east-1:\n    my-stack:\n      template: my-stack.rb\n```\n\n### Loading SparklePacks\n\n[SparklePacks](http://www.sparkleformation.io/docs/sparkle_formation/sparkle-packs.html) can be pre-loaded using compiler options. This requires the name of a rubygem to `require` followed by the name of the SparklePack, which is usually the same name as the Gem.\n\n```yaml\nstacks:\n  us-east-1:\n    my-stack:\n      template: my-stack-with-dynamic.rb\n      compiler_options:\n        sparkle_packs:\n          - vpc-sparkle-pack\n```\n\nThe template can then simply load a dynamic from the sparkle pack like so:\n\n```ruby\nSparkleFormation.new(:my_stack_with_dynamic) do\n   dynamic!(:sparkle_pack_dynamic)\nend\n```\n\nNote though that if a dynamic with the same name exists in your `templates/dynamics/` directory it will get loaded since it has higher precedence.\n\nTemplates can be also loaded from sparkle packs by defining `sparkle_pack_template`. The name corresponds to the registered symbol rather than specific name. That means for a sparkle pack containing:\n\n```ruby\nSparkleFormation.new(:template_name) do\n  ...\nend\n```\n\nwe can use stack defined as follows:\n\n```yaml\nstacks:\n  us-east-1:\n    my-stack:\n      template: template_name\n      compiler: sparkle_formation\n      compiler_options:\n        sparkle_packs:\n          - some-sparkle-pack\n        sparkle_pack_template: true\n```\n\n## Allowed accounts\n\nThe AWS account the command is executing in can be restricted to a specific list of allowed accounts. This is useful in reducing the possibility of applying non-production changes in a production account. Each stack definition can specify the `allowed_accounts` property with an array of AWS account IDs or aliases the stack is allowed to work with.\n\nThis is an opt-in feature which is enabled by specifying at least one account to allow.\n\nUnlike other stack defaults, the `allowed_accounts` property values specified in the stack definition override values specified in the stack defaults (i.e., other stack property values are merged together with those specified in the stack defaults). This allows specifying allowed accounts in the stack defaults (inherited by all stacks) and override them for specific stacks. See below example config for an example.\n\n```yaml\nstack_defaults:\n  allowed_accounts: '555555555'\nstacks:\n  us-east-1:\n    myapp-vpc: # only allow account 555555555 (inherited from the stack defaults)\n      template: myapp_vpc.rb\n      tags:\n        purpose: front-end\n    myapp-db:\n      template: myapp_db.rb\n      allowed_accounts: # only allow these accounts (overrides the stack defaults)\n        - '1234567890'\n        - my-account-alias\n      tags:\n        purpose: back-end\n    myapp-web:\n      template: myapp_web.rb\n      allowed_accounts: [] # allow all accounts (overrides the stack defaults)\n      tags:\n        purpose: front-end\n    myapp-redis:\n      template: myapp_redis.rb\n      allowed_accounts: '888888888' # only allow this account (overrides the stack defaults)\n      tags:\n        purpose: back-end\n```\n\nIn the cases where you want to bypass the account check, there is the StackMaster flag `--skip-account-check` that can be used.\n\n\n## Commands\n\n```bash\nstack_master help # Display up to date docs on the commands available\nstack_master init # Initialises a directory structure and stack_master.yml file\nstack_master list # Lists stack definitions\nstack_master apply [region-or-alias] [stack-name] # Create or update a stack\nstack_master apply [region-or-alias] [stack-name] [region-or-alias] [stack-name] # Create or update multiple stacks\nstack_master apply [region-or-alias] # Create or update stacks in the given region\nstack_master apply # Create or update all stacks\nstack_master --changed apply # Create or update all stacks that have changed\nstack_master --yes apply [region-or-alias] [stack-name] # Create or update a stack non-interactively (forcing yes)\nstack_master diff [region-or-alias] [stack-name] # Display a stack template and parameter diff\nstack_master drift [region-or-alias] [stack-name] # Detects and displays stack drift using the CloudFormation Drift API\nstack_master delete [region-or-alias] [stack-name] # Delete a stack\nstack_master events [region-or-alias] [stack-name] # Display events for a stack\nstack_master outputs [region-or-alias] [stack-name] # Display outputs for a stack\nstack_master resources [region-or-alias] [stack-name] # Display outputs for a stack\nstack_master status # Displays the status of each stack\nstack_master tidy # Find missing or extra templates or parameter files\nstack_master compile # Print the compiled version of a given stack\nstack_master validate # Validate a template\nstack_master lint # Check the stack definition locally using cfn-lint\nstack_master nag # Check the stack template with cfn_nag\n```\n\n## Applying updates - `stack_master apply`\n\nThe apply command does the following:\n\n- Compiles the proposed stack template and resolves parameters.\n- Fetches the current state of the stack from CloudFormation.\n- Displays a diff of the current stack and the proposed stack.\n- Creates a change set and displays the actions that CloudFormation will take\n  to perform the update (if the stack already exists).\n- Asks if the update should continue.\n- If yes, the API calls are made to update or create the stack.\n- Stack events are displayed until CloudFormation has finished applying the changes.\n\nDemo:\n\n![Apply Demo](/apply_demo.gif?raw=true)\n\n## Drift Detection - `stack_master drift`\n\n`stack_master drift us-east-1 mystack` uses the CloudFormation APIs to trigger drift detection and display resources\nthat have changed outside of the CloudFormation stack. This can happen if a resource has been updated via the console or\nCLI directly rather than via a stack update.\n\n## Diff - `stack_master diff`\n\n`stack_master diff us-east-1 mystack` displays whether the computed parameters or template differ to what was last\napplied in CloudFormation. This can happen if the template or computed parameters have changed in code and the change\nhasn't been applied to this stack.\n\n## License\n\nStackMaster uses the MIT license. See [LICENSE.txt](https://github.com/envato/stack_master/blob/master/LICENSE.txt) for details.\n\n## Contributing\n\n1. Fork it ( http://github.com/envato/stack_master/fork )\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n","funding_links":[],"categories":["aws","Ruby","Open Source Repos"],"sub_categories":["CloudFormation"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenvato%2Fstack_master","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenvato%2Fstack_master","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenvato%2Fstack_master/lists"}