stack_master 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +208 -0
  7. data/Rakefile +11 -0
  8. data/apply_demo.gif +0 -0
  9. data/bin/stack_master +16 -0
  10. data/example/simple/Gemfile +3 -0
  11. data/example/simple/parameters/myapp_vpc.yml +1 -0
  12. data/example/simple/parameters/myapp_web.yml +2 -0
  13. data/example/simple/stack_master.yml +13 -0
  14. data/example/simple/templates/myapp_vpc.rb +39 -0
  15. data/example/simple/templates/myapp_web.rb +16 -0
  16. data/features/apply.feature +241 -0
  17. data/features/delete.feature +43 -0
  18. data/features/diff.feature +191 -0
  19. data/features/events.feature +38 -0
  20. data/features/init.feature +6 -0
  21. data/features/outputs.feature +49 -0
  22. data/features/region_aliases.feature +66 -0
  23. data/features/resources.feature +45 -0
  24. data/features/stack_defaults.feature +88 -0
  25. data/features/status.feature +124 -0
  26. data/features/step_definitions/stack_steps.rb +50 -0
  27. data/features/support/env.rb +14 -0
  28. data/lib/stack_master.rb +81 -0
  29. data/lib/stack_master/aws_driver/cloud_formation.rb +56 -0
  30. data/lib/stack_master/cli.rb +164 -0
  31. data/lib/stack_master/command.rb +13 -0
  32. data/lib/stack_master/commands/apply.rb +104 -0
  33. data/lib/stack_master/commands/delete.rb +53 -0
  34. data/lib/stack_master/commands/diff.rb +31 -0
  35. data/lib/stack_master/commands/events.rb +39 -0
  36. data/lib/stack_master/commands/init.rb +109 -0
  37. data/lib/stack_master/commands/list_stacks.rb +16 -0
  38. data/lib/stack_master/commands/outputs.rb +27 -0
  39. data/lib/stack_master/commands/resources.rb +33 -0
  40. data/lib/stack_master/commands/status.rb +47 -0
  41. data/lib/stack_master/commands/validate.rb +17 -0
  42. data/lib/stack_master/config.rb +86 -0
  43. data/lib/stack_master/ctrl_c.rb +4 -0
  44. data/lib/stack_master/parameter_loader.rb +17 -0
  45. data/lib/stack_master/parameter_resolver.rb +45 -0
  46. data/lib/stack_master/parameter_resolvers/secret.rb +42 -0
  47. data/lib/stack_master/parameter_resolvers/security_group.rb +20 -0
  48. data/lib/stack_master/parameter_resolvers/sns_topic_name.rb +29 -0
  49. data/lib/stack_master/parameter_resolvers/stack_output.rb +53 -0
  50. data/lib/stack_master/prompter.rb +14 -0
  51. data/lib/stack_master/security_group_finder.rb +29 -0
  52. data/lib/stack_master/sns_topic_finder.rb +27 -0
  53. data/lib/stack_master/stack.rb +96 -0
  54. data/lib/stack_master/stack_definition.rb +49 -0
  55. data/lib/stack_master/stack_differ.rb +80 -0
  56. data/lib/stack_master/stack_events/fetcher.rb +45 -0
  57. data/lib/stack_master/stack_events/presenter.rb +27 -0
  58. data/lib/stack_master/stack_events/streamer.rb +55 -0
  59. data/lib/stack_master/stack_states.rb +34 -0
  60. data/lib/stack_master/template_compiler.rb +21 -0
  61. data/lib/stack_master/test_driver/cloud_formation.rb +139 -0
  62. data/lib/stack_master/testing.rb +7 -0
  63. data/lib/stack_master/utils.rb +31 -0
  64. data/lib/stack_master/validator.rb +25 -0
  65. data/lib/stack_master/version.rb +3 -0
  66. data/logo.png +0 -0
  67. data/script/buildkite/bundle.sh +5 -0
  68. data/script/buildkite/clean.sh +3 -0
  69. data/script/buildkite_rspec.sh +27 -0
  70. data/spec/fixtures/parameters/myapp_vpc.yml +1 -0
  71. data/spec/fixtures/stack_master.yml +35 -0
  72. data/spec/fixtures/templates/myapp_vpc.json +1 -0
  73. data/spec/spec_helper.rb +99 -0
  74. data/spec/stack_master/commands/apply_spec.rb +92 -0
  75. data/spec/stack_master/commands/delete_spec.rb +40 -0
  76. data/spec/stack_master/commands/init_spec.rb +17 -0
  77. data/spec/stack_master/commands/status_spec.rb +38 -0
  78. data/spec/stack_master/commands/validate_spec.rb +26 -0
  79. data/spec/stack_master/config_spec.rb +81 -0
  80. data/spec/stack_master/parameter_loader_spec.rb +81 -0
  81. data/spec/stack_master/parameter_resolver_spec.rb +58 -0
  82. data/spec/stack_master/parameter_resolvers/secret_spec.rb +66 -0
  83. data/spec/stack_master/parameter_resolvers/security_group_spec.rb +17 -0
  84. data/spec/stack_master/parameter_resolvers/sns_topic_name_spec.rb +43 -0
  85. data/spec/stack_master/parameter_resolvers/stack_output_spec.rb +77 -0
  86. data/spec/stack_master/security_group_finder_spec.rb +49 -0
  87. data/spec/stack_master/sns_topic_finder_spec.rb +25 -0
  88. data/spec/stack_master/stack_definition_spec.rb +37 -0
  89. data/spec/stack_master/stack_differ_spec.rb +34 -0
  90. data/spec/stack_master/stack_events/fetcher_spec.rb +65 -0
  91. data/spec/stack_master/stack_events/presenter_spec.rb +18 -0
  92. data/spec/stack_master/stack_events/streamer_spec.rb +33 -0
  93. data/spec/stack_master/stack_spec.rb +157 -0
  94. data/spec/stack_master/template_compiler_spec.rb +48 -0
  95. data/spec/stack_master/test_driver/cloud_formation_spec.rb +24 -0
  96. data/spec/stack_master/utils_spec.rb +30 -0
  97. data/spec/stack_master/validator_spec.rb +38 -0
  98. data/stack_master.gemspec +38 -0
  99. data/stacktemplates/parameter_region.yml +3 -0
  100. data/stacktemplates/parameter_stack_name.yml +3 -0
  101. data/stacktemplates/stack.json.erb +20 -0
  102. data/stacktemplates/stack_master.yml.erb +6 -0
  103. metadata +427 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: be7dbbbfb5ac18598037c53174655253fef33f73
4
+ data.tar.gz: e1b2cb9dd3846993f497dc51a606053fc7670907
5
+ SHA512:
6
+ metadata.gz: 5fea5f38e52302091b2ab880cb59ca68ad9e60547a8f09b7eceb52611aa23475b4c3131fa62b9074580264315f7a75c0796c9fe9bebb1fd535c63c11ebe7d130
7
+ data.tar.gz: 4442a6772b1a8efd992660b9ba720f73208935a1bb0f5760a5e4b2b8ea5d4a1c3675964f4f4c3288d968bf45d3c752c4b05fba49f8487894f995e8cfc4537dbb
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ /spec/examples.txt
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in stack_master.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Steve Hodgkiss
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,208 @@
1
+ ![StackMaster](/logo.png?raw=true)
2
+
3
+ StackMaster is a sure-footed way of creating, updating and keeping track of
4
+ Amazon (AWS) CloudFormation stacks.
5
+
6
+ - See the changes you are making to a stack before you apply them
7
+ - Connect stacks
8
+ - Keep secrets secret
9
+ - Customise stacks in different environments
10
+ - Apply descriptive labels to regions
11
+
12
+ StackMaster provides an easy command line interface to managing CloudFormation
13
+ stacks defined with templates specified in either the
14
+ [SparkleFormation](http://www.sparkleformation.io) DSL or standard JSON format.
15
+
16
+ ## Installation
17
+
18
+ System-wide: `gem install stack_master`
19
+
20
+ With bundler:
21
+
22
+ - Add `gem 'stack_master'` to your Gemfile.
23
+ - Run `bundle install`
24
+ - Run `bundle exec stack_master init` to generate a directory structure and stack_master.yml file
25
+
26
+ ## Configuration
27
+
28
+ Stacks are defined inside a `stack_master.yml` YAML file. When running
29
+ `stack_master`, it is assumed that this file will exist in the current working
30
+ directory, or that the file is passed in with `--config
31
+ /path/to/stack_master.yml`. Here's an example configuration file:
32
+
33
+ ```
34
+ region_aliases:
35
+ production: us-east-1
36
+ staging: ap-southeast-2
37
+ stack_defaults:
38
+ tags:
39
+ application: my-awesome-app
40
+ region_defaults:
41
+ us-east-1:
42
+ secret_file: production.yml.gpg
43
+ tags:
44
+ environment: production
45
+ notification_arns:
46
+ - test_arn
47
+ ap-southeast-2:
48
+ secret_file: staging.yml.gpg
49
+ tags:
50
+ environment: staging
51
+ stacks:
52
+ production:
53
+ myapp-vpc:
54
+ template: myapp_vpc.rb
55
+ myapp-db:
56
+ template: myapp_db.rb
57
+ stack_policy_file: db_stack_policy.json
58
+ myapp-web:
59
+ template: myapp_web.rb
60
+ staging:
61
+ myapp-vpc:
62
+ template: myapp_vpc.rb
63
+ myapp-db:
64
+ template: myapp_db.rb
65
+ myapp-web:
66
+ template: myapp_web.rb
67
+ eu-central-1:
68
+ myapp-vpc:
69
+ template: myapp_vpc.rb
70
+ ```
71
+
72
+ ## Directories
73
+
74
+ - `templates` - CloudFormation or SparkleFormation templates.
75
+ - `polices` - Stack policies.
76
+ - `parameters` - Parameters as YAML files.
77
+ - `secrets` - GPG encrypted secret files.
78
+
79
+ ## Parameters
80
+
81
+ Parameters are loaded from multiple YAML files, merged from the following lookup paths:
82
+
83
+ - parameters/[stack_name].yml
84
+ - parameters/[region]/[stack_name].yml
85
+ - parameters/[region_alias]/[stack_name].yml
86
+
87
+ A simple parameter file could look like this:
88
+
89
+ ```
90
+ key_name: myapp-us-east-1
91
+ ```
92
+
93
+ Keys in parameter files are automatically converted to camel case.
94
+
95
+ ## Parameter Resolvers
96
+
97
+ Parameter resolvers enable dynamic resolution of parameter values. A parameter
98
+ using a resolver will be a hash with one key where the key is the name of the
99
+ resolver.
100
+
101
+ One benefit of using resolvers instead of hard coding values like VPC ID's and
102
+ resource ARNs is that the same configuration works cross region, even though
103
+ the resolved values will be different.
104
+
105
+ ### Stack Output
106
+
107
+ The stack output parameter resolver looks up outputs from other stacks in the
108
+ same region. The expected format is `[stack-name]/[OutputName]`.
109
+
110
+ ```yaml
111
+ vpc_id:
112
+ stack_output: my-vpc-stack/VpcId
113
+ ```
114
+
115
+ ### Secret
116
+
117
+ The secret parameters resolver expects a `secret_file` to be defined in the
118
+ stack definition which is a GPG encrypted YAML file. Once decrypted and parsed,
119
+ the value provided to the secret resolver is used to lookup the associated key
120
+ in the secret file. A common use case for this is to store database passwords.
121
+
122
+ stack_master.yml:
123
+
124
+ ```yaml
125
+ stacks:
126
+ us-east-1:
127
+ my_app:
128
+ template: my_app.json
129
+ secret_file: production.yml.gpg
130
+ ```
131
+
132
+ secrets/production.yml.gpg, when decrypted:
133
+
134
+ ```yaml
135
+ db_password: my-password
136
+ ```
137
+
138
+ parameters/my_app.yml:
139
+
140
+ ```yaml
141
+ db_password:
142
+ secret: db_password
143
+ ```
144
+
145
+ ### Security Group
146
+
147
+ Looks up a security group by name and returns the ARN.
148
+
149
+ ```yaml
150
+ ssh_sg:
151
+ security_group: SSHSecurityGroup
152
+ ```
153
+
154
+ ### SNS Topic
155
+
156
+ Looks up an SNS topic by name and returns the ARN.
157
+
158
+ ```yaml
159
+ notification_topic:
160
+ sns_topic: PagerDuty
161
+ ```
162
+
163
+ ## Commands
164
+
165
+ ```bash
166
+ stack_master help # Display up to date docs on the commands available
167
+ stack_master init # Initialises a directory structure and stack_master.yml file
168
+ stack_master list # Lists stack definitions
169
+ stack_master apply [region-or-alias] [stack-name] # Create or update a stack
170
+ stack_master diff [region-or-alias] [stack-name] # Display a stack tempalte and parameter diff
171
+ stack_master delete [region-or-alias] [stack-name] # Delete a stack
172
+ stack_master events [region-or-alias] [stack-name] # Display events for a stack
173
+ stack_master outputs [region-or-alias] [stack-name] # Display outputs for a stack
174
+ stack_master resources [region-or-alias] [stack-name] # Display outputs for a stack
175
+ stack_master status # Displays the status of each stacks
176
+ ```
177
+
178
+ ## Applying updates
179
+
180
+ The apply command does the following:
181
+
182
+ - Builds the proposed stack json and resolves parameters.
183
+ - Fetches the current state of the stack from CloudFormation.
184
+ - Displays a diff of the current stack and the proposed stack.
185
+ - Asks if the update should continue.
186
+ - If yes, the API call is made to update or create the stack.
187
+ - Stack events are displayed until CloudFormation has finished applying the changes.
188
+
189
+ Demo:
190
+
191
+ ![Apply Demo](/apply_demo.gif?raw=true)
192
+
193
+ ## Maintainers
194
+
195
+ - [Steve Hodgkiss](https://github.com/stevehodgkiss)
196
+ - [Glen Stampoultzis](https://github.com/gstamp)
197
+
198
+ ## License
199
+
200
+ StackMaster uses the MIT license. See [LICENSE.txt](https://github.com/envato/stack_master/blob/master/LICENSE.txt) for details.
201
+
202
+ ## Contributing
203
+
204
+ 1. Fork it ( http://github.com/envato/stack_master/fork )
205
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
206
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
207
+ 4. Push to the branch (`git push origin my-new-feature`)
208
+ 5. Create new Pull Request
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require 'bundler/setup'
3
+
4
+ task :environment do
5
+ require 'stack_master'
6
+ end
7
+
8
+ task :console => :environment do
9
+ require 'pry'
10
+ binding.pry
11
+ end
Binary file
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'stack_master'
5
+
6
+ if ENV['STUB_AWS'] == 'true'
7
+ require 'stack_master/testing'
8
+ end
9
+
10
+ trap("SIGINT") { raise StackMaster::CtrlC }
11
+
12
+ begin
13
+ StackMaster::CLI.new(ARGV.dup).execute!
14
+ rescue StackMaster::CtrlC
15
+ StackMaster.stdout.puts "Exiting..."
16
+ end
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'stack_master', path: '../../'
@@ -0,0 +1 @@
1
+ vpc_az_1: ap-southeast-2a
@@ -0,0 +1,2 @@
1
+ VpcId:
2
+ stack_output: myapp-vpc/VpcId
@@ -0,0 +1,13 @@
1
+ stack_defaults:
2
+ tags:
3
+ application: my-awesome-app
4
+ region_defaults:
5
+ ap_southeast_2:
6
+ tags:
7
+ environment: production
8
+ stacks:
9
+ ap_southeast_2:
10
+ myapp_vpc:
11
+ template: myapp_vpc.rb
12
+ myapp_web:
13
+ template: myapp_web.rb
@@ -0,0 +1,39 @@
1
+ SparkleFormation.new(:myapp_vpc) do
2
+ description "A test VPC template"
3
+
4
+ resources.vpc do
5
+ type 'AWS::EC2::VPC'
6
+ properties do
7
+ cidr_block '10.200.0.0/16'
8
+ end
9
+ end
10
+
11
+ parameters.vpc_az_1 do
12
+ description 'VPC AZ 1'
13
+ type 'AWS::EC2::AvailabilityZone::Name'
14
+ end
15
+
16
+ resources.public_subnet do
17
+ type 'AWS::EC2::Subnet'
18
+ properties do
19
+ vpc_id ref!(:vpc)
20
+ cidr_block '10.200.1.0/24'
21
+ availability_zone ref!(:vpc_az_1)
22
+ tags _array(
23
+ { Key: 'Name', Value: 'PublicSubnet' },
24
+ { Key: 'network', Value: 'public' }
25
+ )
26
+ end
27
+ end
28
+
29
+ outputs do
30
+ vpc_id do
31
+ description 'VPC ID'
32
+ value ref!(:vpc)
33
+ end
34
+ public_subnet do
35
+ description 'Public subnet'
36
+ value ref!(:public_subnet)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ SparkleFormation.new(:myapp_web) do
2
+ description "Test web template"
3
+
4
+ parameters.vpc_id do
5
+ description 'VPC ID'
6
+ type 'String'
7
+ end
8
+
9
+ resources.web_sg do
10
+ type 'AWS::EC2::SecurityGroup'
11
+ properties do
12
+ group_description 'Security group for web instances'
13
+ vpc_id ref!(:vpc_id)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,241 @@
1
+ Feature: Apply command
2
+
3
+ Background:
4
+ Given a file named "stack_master.yml" with:
5
+ """
6
+ stacks:
7
+ us_east_1:
8
+ myapp_vpc:
9
+ template: myapp_vpc.rb
10
+ myapp_web:
11
+ template: myapp_web.rb
12
+ """
13
+ And a directory named "parameters"
14
+ And a file named "parameters/myapp_vpc.yml" with:
15
+ """
16
+ KeyName: my-key
17
+ """
18
+ And a directory named "templates"
19
+ And a file named "templates/myapp_vpc.rb" with:
20
+ """
21
+ SparkleFormation.new(:myapp_vpc) do
22
+ description "Test template"
23
+ set!('AWSTemplateFormatVersion', '2010-09-09')
24
+
25
+ parameters.key_name do
26
+ description 'Key name'
27
+ type 'String'
28
+ end
29
+
30
+ resources.vpc do
31
+ type 'AWS::EC2::VPC'
32
+ properties do
33
+ cidr_block '10.200.0.0/16'
34
+ end
35
+ end
36
+
37
+ outputs do
38
+ vpc_id do
39
+ description 'A VPC ID'
40
+ value ref!(:vpc)
41
+ end
42
+ end
43
+ end
44
+ """
45
+ And a file named "templates/myapp_web.rb" with:
46
+ """
47
+ SparkleFormation.new(:myapp_web) do
48
+ description "Test template"
49
+ set!('AWSTemplateFormatVersion', '2010-09-09')
50
+
51
+ parameters.vpc_id do
52
+ description 'VPC ID'
53
+ type 'AWS::EC2::VPC::Id'
54
+ end
55
+
56
+ resources.test_sg do
57
+ type 'AWS::EC2::SecurityGroup'
58
+ properties do
59
+ group_description 'Test SG'
60
+ vpc_id ref!(:vpc_id)
61
+ end
62
+ end
63
+ end
64
+ """
65
+ And I set the environment variables to:
66
+ | variable | value |
67
+ | STUB_AWS | true |
68
+
69
+ Scenario: Run apply and create a new stack
70
+ Given I set the environment variables to:
71
+ | variable | value |
72
+ | ANSWER | y |
73
+ And I stub the following stack events:
74
+ | stack_id | event_id | stack_name | logical_resource_id | resource_status | resource_type | timestamp |
75
+ | 1 | 1 | myapp-vpc | TestSg | CREATE_COMPLETE | AWS::EC2::SecurityGroup | 2020-10-29 00:00:00 |
76
+ | 1 | 1 | myapp-vpc | myapp-vpc | CREATE_COMPLETE | AWS::CloudFormation::Stack | 2020-10-29 00:00:00 |
77
+ When I run `stack_master apply us-east-1 myapp-vpc --trace` interactively
78
+ And the output should contain all of these lines:
79
+ | Stack diff: |
80
+ | + "Vpc": { |
81
+ | Parameters diff: |
82
+ | KeyName: my-key |
83
+ | 2020-10-29 00:00:00 +1100 myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE |
84
+ Then the exit status should be 0
85
+
86
+ Scenario: Run apply and don't create the stack
87
+ Given I set the environment variables to:
88
+ | variable | value |
89
+ | ANSWER | n |
90
+ When I run `stack_master apply us-east-1 myapp-vpc --trace` interactively
91
+ And the output should contain all of these lines:
92
+ | Stack diff: |
93
+ | + "Vpc": { |
94
+ | Parameters diff: |
95
+ | KeyName: my-key |
96
+ | aborted |
97
+ And the output should not contain all of these lines:
98
+ | 2020-10-29 00:00:00 +1100 myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE |
99
+ Then the exit status should be 0
100
+
101
+ Scenario: Run apply on an existing stack
102
+ Given I set the environment variables to:
103
+ | variable | value |
104
+ | ANSWER | y |
105
+ And I stub the following stack events:
106
+ | stack_id | event_id | stack_name | logical_resource_id | resource_status | resource_type | timestamp |
107
+ | 1 | 1 | myapp-vpc | TestSg | CREATE_COMPLETE | AWS::EC2::SecurityGroup | 2020-10-29 00:00:00 |
108
+ | 1 | 1 | myapp-vpc | myapp-vpc | CREATE_COMPLETE | AWS::CloudFormation::Stack | 2020-10-29 00:00:00 |
109
+ And I stub the following stacks:
110
+ | stack_id | stack_name | parameters | region |
111
+ | 1 | myapp-vpc | KeyName=my-key | us-east-1 |
112
+ And I stub a template for the stack "myapp-vpc":
113
+ """
114
+ {
115
+ "Description": "Test template",
116
+ "AWSTemplateFormatVersion": "2010-09-09",
117
+ "Parameters": {
118
+ "KeyName": {
119
+ "Description": "Key Name",
120
+ "Type": "String"
121
+ }
122
+ },
123
+ "Resources": {
124
+ "TestSg": {
125
+ "Type": "AWS::EC2::SecurityGroup",
126
+ "Properties": {
127
+ "GroupDescription": "Test SG",
128
+ "VpcId": {
129
+ "Ref": "VpcId"
130
+ }
131
+ }
132
+ },
133
+ "TestSg2": {
134
+ "Type": "AWS::EC2::SecurityGroup",
135
+ "Properties": {
136
+ "GroupDescription": "Test SG 2",
137
+ "VpcId": {
138
+ "Ref": "VpcId"
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ """
145
+ When I run `stack_master apply us-east-1 myapp-vpc --trace` interactively
146
+ And the output should contain all of these lines:
147
+ | Stack diff: |
148
+ | - "TestSg2": { |
149
+ | Parameters diff: No changes |
150
+ Then the exit status should be 0
151
+
152
+ Scenario: Create a stack using a stack output resolver
153
+ Given I set the environment variables to:
154
+ | variable | value |
155
+ | ANSWER | y |
156
+ And a file named "parameters/myapp_web.yml" with:
157
+ """
158
+ VpcId:
159
+ stack_output: myapp-vpc/VpcId
160
+ """
161
+ And I stub the following stack events:
162
+ | stack_id | event_id | stack_name | logical_resource_id | resource_status | resource_type | timestamp |
163
+ | 1 | 1 | myapp-web | TestSg | CREATE_COMPLETE | AWS::EC2::SecurityGroup | 2020-10-29 00:00:00 |
164
+ | 1 | 1 | myapp-web | myapp-web | CREATE_COMPLETE | AWS::CloudFormation::Stack | 2020-10-29 00:00:00 |
165
+ And I stub the following stacks:
166
+ | stack_id | stack_name | region | outputs |
167
+ | 1 | myapp-vpc | us-east-1 | VpcId=vpc-xxxxxx |
168
+ When I run `stack_master apply us-east-1 myapp-web --trace` interactively
169
+ And the output should contain all of these lines:
170
+ | Stack diff: |
171
+ | + "TestSg": { |
172
+ | Parameters diff: |
173
+ | VpcId: vpc-xxxxxx |
174
+ | 2020-10-29 00:00:00 +1100 myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE |
175
+ Then the exit status should be 0
176
+
177
+ Scenario: Create a stack with a notification ARN and a stack update policy
178
+ Given a file named "stack_master.yml" with:
179
+ """
180
+ stacks:
181
+ us_east_1:
182
+ myapp_vpc:
183
+ template: myapp_vpc.rb
184
+ notification_arns:
185
+ - test_arn
186
+ stack_policy_file: no_rds_replacement.json
187
+ """
188
+ And a file named "policies/no_rds_replacement.json" with:
189
+ """
190
+ {}
191
+ """
192
+ And I set the environment variables to:
193
+ | variable | value |
194
+ | ANSWER | y |
195
+ And I stub the following stack events:
196
+ | stack_id | event_id | stack_name | logical_resource_id | resource_status | resource_type | timestamp |
197
+ | 1 | 1 | myapp-vpc | TestSg | CREATE_COMPLETE | AWS::EC2::SecurityGroup | 2020-10-29 00:00:00 |
198
+ | 1 | 1 | myapp-vpc | myapp-vpc | CREATE_COMPLETE | AWS::CloudFormation::Stack | 2020-10-29 00:00:00 |
199
+ And I stub the following stacks:
200
+ | stack_id | stack_name | parameters | region |
201
+ | 1 | myapp-vpc | KeyName=my-key | us-east-1 |
202
+ And I stub a template for the stack "myapp-vpc":
203
+ """
204
+ {
205
+ "Description": "Test template",
206
+ "AWSTemplateFormatVersion": "2010-09-09",
207
+ "Parameters": {
208
+ "KeyName": {
209
+ "Description": "Key Name",
210
+ "Type": "String"
211
+ }
212
+ },
213
+ "Resources": {
214
+ "TestSg": {
215
+ "Type": "AWS::EC2::SecurityGroup",
216
+ "Properties": {
217
+ "GroupDescription": "Test SG",
218
+ "VpcId": {
219
+ "Ref": "VpcId"
220
+ }
221
+ }
222
+ },
223
+ "TestSg2": {
224
+ "Type": "AWS::EC2::SecurityGroup",
225
+ "Properties": {
226
+ "GroupDescription": "Test SG 2",
227
+ "VpcId": {
228
+ "Ref": "VpcId"
229
+ }
230
+ }
231
+ }
232
+ }
233
+ }
234
+ """
235
+ When I run `stack_master apply us-east-1 myapp-vpc --trace` interactively
236
+ Then the stack "myapp-vpc" should have a policy with the following:
237
+ """
238
+ {}
239
+ """
240
+ And the stack "myapp-vpc" should contain this notification ARN "test_arn"
241
+ Then the exit status should be 0