stack_master 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -0
- data/features/apply.feature +1 -1
- data/features/apply_with_s3.feature +106 -0
- data/features/step_definitions/stack_steps.rb +5 -0
- data/features/support/env.rb +1 -0
- data/lib/stack_master.rb +78 -58
- data/lib/stack_master/aws_driver/s3.rb +66 -0
- data/lib/stack_master/cli.rb +1 -0
- data/lib/stack_master/commands/apply.rb +52 -5
- data/lib/stack_master/commands/init.rb +2 -0
- data/lib/stack_master/commands/list_stacks.rb +2 -0
- data/lib/stack_master/commands/outputs.rb +2 -0
- data/lib/stack_master/commands/status.rb +3 -0
- data/lib/stack_master/parameter_resolver.rb +1 -1
- data/lib/stack_master/parameter_resolvers/secret.rb +2 -0
- data/lib/stack_master/stack.rb +20 -13
- data/lib/stack_master/stack_definition.rb +63 -13
- data/lib/stack_master/stack_differ.rb +2 -0
- data/lib/stack_master/stack_events/fetcher.rb +1 -1
- data/lib/stack_master/stack_events/presenter.rb +1 -1
- data/lib/stack_master/stack_events/streamer.rb +1 -1
- data/lib/stack_master/template_compiler.rb +3 -1
- data/lib/stack_master/template_compilers/cfndsl.rb +4 -2
- data/lib/stack_master/template_compilers/json.rb +4 -0
- data/lib/stack_master/template_compilers/sparkle_formation.rb +5 -0
- data/lib/stack_master/template_compilers/yaml.rb +4 -0
- data/lib/stack_master/test_driver/cloud_formation.rb +50 -36
- data/lib/stack_master/test_driver/s3.rb +34 -0
- data/lib/stack_master/testing.rb +1 -0
- data/lib/stack_master/utils.rb +19 -0
- data/lib/stack_master/version.rb +1 -1
- data/spec/fixtures/stack_master.yml +4 -1
- data/spec/stack_master/aws_driver/s3_spec.rb +130 -0
- data/spec/stack_master/commands/apply_spec.rb +26 -0
- data/spec/stack_master/config_spec.rb +8 -1
- data/spec/stack_master/parameter_resolver_spec.rb +5 -0
- data/spec/stack_master/sparkle_formation/user_data_file_spec.rb +2 -0
- data/spec/stack_master/stack_events/presenter_spec.rb +1 -1
- data/spec/stack_master/stack_spec.rb +23 -5
- data/spec/stack_master/template_compiler_spec.rb +1 -0
- data/spec/stack_master/template_compilers/cfndsl_spec.rb +2 -0
- data/spec/stack_master/test_driver/s3_spec.rb +17 -0
- data/stack_master.gemspec +0 -1
- metadata +10 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24f9543391ced08e41349c5cd75aaecacce6aab2
|
4
|
+
data.tar.gz: 0130dc01c3bfacea757155caf6896aef4daaebaf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95bf919587f2d04956c97ef82caa0f9d79747b2272e1c97075549950a5d5606dbf084cfba5ef65a4e61935a4d3c11fd13c06183f02e9305f55e8f98353ded7be
|
7
|
+
data.tar.gz: d5523800109d4f3ac1a5a04a4f2f3246ad51d2014b76234c2b35c54f18e39b24a8b7fe4e5b9696682d1b299f8bf5b969961b0d49355c54381d2cc247e7cde26d
|
data/README.md
CHANGED
@@ -95,6 +95,28 @@ stacks:
|
|
95
95
|
purpose: vpc
|
96
96
|
```
|
97
97
|
|
98
|
+
## S3
|
99
|
+
|
100
|
+
StackMaster can optionally use S3 to store the templates before creating a stack.
|
101
|
+
This requires to configure an S3 bucket in stack_master.yml:
|
102
|
+
|
103
|
+
```yaml
|
104
|
+
stack_defaults:
|
105
|
+
s3:
|
106
|
+
bucket: my_bucket_name
|
107
|
+
prefix: cfn_templates/my-awesome-app
|
108
|
+
region: us-west-2
|
109
|
+
```
|
110
|
+
|
111
|
+
Additional files can be configured to be uploaded to S3 alongside the templates:
|
112
|
+
```yaml
|
113
|
+
stacks:
|
114
|
+
production:
|
115
|
+
myapp-vpc:
|
116
|
+
template: myapp_vpc.rb
|
117
|
+
files:
|
118
|
+
- userdata.sh
|
119
|
+
```
|
98
120
|
## Directories
|
99
121
|
|
100
122
|
- `templates` - CloudFormation, SparkleFormation or CfnDsl templates.
|
data/features/apply.feature
CHANGED
@@ -90,7 +90,7 @@ Feature: Apply command
|
|
90
90
|
| Parameters diff: |
|
91
91
|
| KeyName: my-key |
|
92
92
|
| aborted |
|
93
|
-
And the output should not match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
93
|
+
And the output should not match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
94
94
|
Then the exit status should be 0
|
95
95
|
|
96
96
|
Scenario: Run apply with region only and create 2 stacks
|
@@ -0,0 +1,106 @@
|
|
1
|
+
Feature: Apply command
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a file named "stack_master.yml" with:
|
5
|
+
"""
|
6
|
+
stack_defaults:
|
7
|
+
s3:
|
8
|
+
bucket: my-bucket
|
9
|
+
region: us-east-1
|
10
|
+
prefix: cfn_templates/my-app
|
11
|
+
stacks:
|
12
|
+
us_east_1:
|
13
|
+
myapp_vpc:
|
14
|
+
template: myapp_vpc.rb
|
15
|
+
files:
|
16
|
+
- user_data.sh
|
17
|
+
"""
|
18
|
+
And a directory named "parameters"
|
19
|
+
And a file named "parameters/myapp_vpc.yml" with:
|
20
|
+
"""
|
21
|
+
KeyName: my-key
|
22
|
+
"""
|
23
|
+
And a file named "parameters/myapp_web.yml" with:
|
24
|
+
"""
|
25
|
+
VpcId: vpc-blah
|
26
|
+
"""
|
27
|
+
And a directory named "templates"
|
28
|
+
And a file named "files/user_data.sh" with:
|
29
|
+
"""
|
30
|
+
#!/bin/bash
|
31
|
+
echo "HI"
|
32
|
+
"""
|
33
|
+
And a file named "templates/myapp_vpc.rb" with:
|
34
|
+
"""
|
35
|
+
SparkleFormation.new(:myapp_vpc) do
|
36
|
+
description "Test template"
|
37
|
+
set!('AWSTemplateFormatVersion', '2010-09-09')
|
38
|
+
|
39
|
+
parameters.key_name do
|
40
|
+
description 'Key name'
|
41
|
+
type 'String'
|
42
|
+
end
|
43
|
+
|
44
|
+
resources.vpc do
|
45
|
+
type 'AWS::EC2::VPC'
|
46
|
+
properties do
|
47
|
+
cidr_block '10.200.0.0/16'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
outputs do
|
52
|
+
vpc_id do
|
53
|
+
description 'A VPC ID'
|
54
|
+
value ref!(:vpc)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
"""
|
59
|
+
|
60
|
+
Scenario: Run apply and create a new stack
|
61
|
+
Given I stub the following stack events:
|
62
|
+
| stack_id | event_id | stack_name | logical_resource_id | resource_status | resource_type | timestamp |
|
63
|
+
| 1 | 1 | myapp-vpc | TestSg | CREATE_COMPLETE | AWS::EC2::SecurityGroup | 2020-10-29 00:00:00 |
|
64
|
+
| 1 | 1 | myapp-vpc | myapp-vpc | CREATE_COMPLETE | AWS::CloudFormation::Stack | 2020-10-29 00:00:00 |
|
65
|
+
When I run `stack_master apply us-east-1 myapp-vpc --trace`
|
66
|
+
And the output should contain all of these lines:
|
67
|
+
| Stack diff: |
|
68
|
+
| + "Vpc": { |
|
69
|
+
| Parameters diff: |
|
70
|
+
| KeyName: my-key |
|
71
|
+
And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
72
|
+
And an S3 file in bucket "my-bucket" with key "cfn_templates/my-app/myapp_vpc.json" exists with content:
|
73
|
+
"""
|
74
|
+
{
|
75
|
+
"Description": "Test template",
|
76
|
+
"AWSTemplateFormatVersion": "2010-09-09",
|
77
|
+
"Parameters": {
|
78
|
+
"KeyName": {
|
79
|
+
"Description": "Key name",
|
80
|
+
"Type": "String"
|
81
|
+
}
|
82
|
+
},
|
83
|
+
"Resources": {
|
84
|
+
"Vpc": {
|
85
|
+
"Type": "AWS::EC2::VPC",
|
86
|
+
"Properties": {
|
87
|
+
"CidrBlock": "10.200.0.0/16"
|
88
|
+
}
|
89
|
+
}
|
90
|
+
},
|
91
|
+
"Outputs": {
|
92
|
+
"VpcId": {
|
93
|
+
"Description": "A VPC ID",
|
94
|
+
"Value": {
|
95
|
+
"Ref": "Vpc"
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
"""
|
101
|
+
And an S3 file in bucket "my-bucket" with key "cfn_templates/my-app/user_data.sh" exists with content:
|
102
|
+
"""
|
103
|
+
#!/bin/bash
|
104
|
+
echo "HI"
|
105
|
+
"""
|
106
|
+
Then the exit status should be 0
|
@@ -64,3 +64,8 @@ end
|
|
64
64
|
Given(/^I stub CloudFormation validate calls to fail validation with message "([^"]*)"$/) do |message|
|
65
65
|
allow(StackMaster.cloud_formation_driver).to receive(:validate_template).and_raise(Aws::CloudFormation::Errors::ValidationError.new('', message))
|
66
66
|
end
|
67
|
+
|
68
|
+
When(/^an S3 file in bucket "([^"]*)" with key "([^"]*)" exists with content:$/) do |bucket, key, body|
|
69
|
+
file = StackMaster.s3_driver.find_file(bucket: bucket, object_key: key)
|
70
|
+
expect(file).to eq body
|
71
|
+
end
|
data/features/support/env.rb
CHANGED
data/lib/stack_master.rb
CHANGED
@@ -1,69 +1,82 @@
|
|
1
1
|
require "commander"
|
2
2
|
require "yaml"
|
3
|
-
require "virtus"
|
4
3
|
require "aws-sdk"
|
5
|
-
require "diffy"
|
6
4
|
require "colorize"
|
7
|
-
require "table_print"
|
8
5
|
require 'active_support/core_ext/string'
|
9
|
-
require "erb"
|
10
|
-
require 'sparkle_formation'
|
11
|
-
require 'dotgpg'
|
12
|
-
require 'ruby-progressbar'
|
13
|
-
|
14
|
-
require "stack_master/ctrl_c"
|
15
|
-
require "stack_master/sparkle_formation/user_data_file"
|
16
|
-
require "stack_master/command"
|
17
|
-
require "stack_master/version"
|
18
|
-
require "stack_master/stack"
|
19
|
-
require "stack_master/prompter"
|
20
|
-
require "stack_master/aws_driver/cloud_formation"
|
21
|
-
require "stack_master/test_driver/cloud_formation"
|
22
|
-
require "stack_master/stack_events/fetcher"
|
23
|
-
require "stack_master/stack_events/presenter"
|
24
|
-
require "stack_master/stack_events/streamer"
|
25
|
-
require "stack_master/stack_states"
|
26
|
-
require "stack_master/stack_status"
|
27
|
-
require "stack_master/sns_topic_finder"
|
28
|
-
require "stack_master/security_group_finder"
|
29
|
-
require "stack_master/parameter_loader"
|
30
|
-
require "stack_master/parameter_resolver"
|
31
|
-
require "stack_master/resolver_array"
|
32
|
-
require "stack_master/parameter_resolvers/ami_finder"
|
33
|
-
require "stack_master/parameter_resolvers/stack_output"
|
34
|
-
require "stack_master/parameter_resolvers/secret"
|
35
|
-
require "stack_master/parameter_resolvers/sns_topic_name"
|
36
|
-
require "stack_master/parameter_resolvers/security_group"
|
37
|
-
require "stack_master/parameter_resolvers/latest_ami_by_tags"
|
38
|
-
require "stack_master/parameter_resolvers/latest_ami"
|
39
|
-
require "stack_master/utils"
|
40
|
-
require "stack_master/config"
|
41
|
-
require "stack_master/paged_response_accumulator"
|
42
|
-
require "stack_master/stack_definition"
|
43
|
-
require "stack_master/template_compiler"
|
44
|
-
require "stack_master/template_compilers/sparkle_formation"
|
45
|
-
require "stack_master/template_compilers/json"
|
46
|
-
require "stack_master/template_compilers/yaml"
|
47
|
-
require "stack_master/template_compilers/cfndsl"
|
48
|
-
require "stack_master/commands/terminal_helper"
|
49
|
-
require "stack_master/commands/apply"
|
50
|
-
require "stack_master/change_set"
|
51
|
-
require "stack_master/commands/events"
|
52
|
-
require "stack_master/commands/outputs"
|
53
|
-
require "stack_master/commands/init"
|
54
|
-
require "stack_master/commands/diff"
|
55
|
-
require "stack_master/commands/list_stacks"
|
56
|
-
require "stack_master/commands/validate"
|
57
|
-
require "stack_master/commands/resources"
|
58
|
-
require "stack_master/commands/delete"
|
59
|
-
require "stack_master/commands/status"
|
60
|
-
require "stack_master/stack_differ"
|
61
|
-
require "stack_master/validator"
|
62
|
-
require "stack_master/cli"
|
63
6
|
|
64
7
|
module StackMaster
|
65
8
|
extend self
|
66
9
|
|
10
|
+
autoload :Initializable, 'stack_master/utils/initializable'
|
11
|
+
autoload :ChangeSet, 'stack_master/change_set'
|
12
|
+
autoload :CLI, 'stack_master/cli'
|
13
|
+
autoload :CtrlC, 'stack_master/ctrl_c'
|
14
|
+
autoload :Command, 'stack_master/command'
|
15
|
+
autoload :Version, 'stack_master/version'
|
16
|
+
autoload :Stack, 'stack_master/stack'
|
17
|
+
autoload :Prompter, 'stack_master/prompter'
|
18
|
+
autoload :StackStates, 'stack_master/stack_states'
|
19
|
+
autoload :StackStatus, 'stack_master/stack_status'
|
20
|
+
autoload :SnsTopicFinder, 'stack_master/sns_topic_finder'
|
21
|
+
autoload :SecurityGroupFinder, 'stack_master/security_group_finder'
|
22
|
+
autoload :ParameterLoader, 'stack_master/parameter_loader'
|
23
|
+
autoload :ParameterResolver, 'stack_master/parameter_resolver'
|
24
|
+
autoload :ResolverArray, 'stack_master/resolver_array'
|
25
|
+
autoload :Resolver, 'stack_master/resolver_array'
|
26
|
+
autoload :Utils, 'stack_master/utils'
|
27
|
+
autoload :Config, 'stack_master/config'
|
28
|
+
autoload :PagedResponseAccumulator, 'stack_master/paged_response_accumulator'
|
29
|
+
autoload :StackDefinition, 'stack_master/stack_definition'
|
30
|
+
autoload :TemplateCompiler, 'stack_master/template_compiler'
|
31
|
+
|
32
|
+
autoload :StackDiffer, 'stack_master/stack_differ'
|
33
|
+
autoload :Validator, 'stack_master/validator'
|
34
|
+
|
35
|
+
require 'stack_master/template_compilers/sparkle_formation'
|
36
|
+
require 'stack_master/template_compilers/json'
|
37
|
+
require 'stack_master/template_compilers/yaml'
|
38
|
+
require 'stack_master/template_compilers/cfndsl'
|
39
|
+
|
40
|
+
module Commands
|
41
|
+
autoload :TerminalHelper, 'stack_master/commands/terminal_helper'
|
42
|
+
autoload :Apply, 'stack_master/commands/apply'
|
43
|
+
autoload :Events, 'stack_master/commands/events'
|
44
|
+
autoload :Outputs, 'stack_master/commands/outputs'
|
45
|
+
autoload :Init, 'stack_master/commands/init'
|
46
|
+
autoload :Diff, 'stack_master/commands/diff'
|
47
|
+
autoload :ListStacks, 'stack_master/commands/list_stacks'
|
48
|
+
autoload :Validate, 'stack_master/commands/validate'
|
49
|
+
autoload :Resources, 'stack_master/commands/resources'
|
50
|
+
autoload :Delete, 'stack_master/commands/delete'
|
51
|
+
autoload :Status, 'stack_master/commands/status'
|
52
|
+
end
|
53
|
+
|
54
|
+
module ParameterResolvers
|
55
|
+
autoload :AmiFinder, 'stack_master/parameter_resolvers/ami_finder'
|
56
|
+
autoload :StackOutput, 'stack_master/parameter_resolvers/stack_output'
|
57
|
+
autoload :Secret, 'stack_master/parameter_resolvers/secret'
|
58
|
+
autoload :SnsTopicName, 'stack_master/parameter_resolvers/sns_topic_name'
|
59
|
+
autoload :SecurityGroup, 'stack_master/parameter_resolvers/security_group'
|
60
|
+
autoload :LatestAmiByTags, 'stack_master/parameter_resolvers/latest_ami_by_tags'
|
61
|
+
autoload :LatestAmi, 'stack_master/parameter_resolvers/latest_ami'
|
62
|
+
end
|
63
|
+
|
64
|
+
module AwsDriver
|
65
|
+
autoload :CloudFormation, 'stack_master/aws_driver/cloud_formation'
|
66
|
+
autoload :S3, 'stack_master/aws_driver/s3'
|
67
|
+
end
|
68
|
+
|
69
|
+
module TestDriver
|
70
|
+
autoload :CloudFormation, 'stack_master/test_driver/cloud_formation'
|
71
|
+
autoload :S3, 'stack_master/test_driver/s3'
|
72
|
+
end
|
73
|
+
|
74
|
+
module StackEvents
|
75
|
+
autoload :Fetcher, 'stack_master/stack_events/fetcher'
|
76
|
+
autoload :Presenter, 'stack_master/stack_events/presenter'
|
77
|
+
autoload :Streamer, 'stack_master/stack_events/streamer'
|
78
|
+
end
|
79
|
+
|
67
80
|
def interactive?
|
68
81
|
!non_interactive?
|
69
82
|
end
|
@@ -106,6 +119,14 @@ module StackMaster
|
|
106
119
|
@cloud_formation_driver = value
|
107
120
|
end
|
108
121
|
|
122
|
+
def s3_driver
|
123
|
+
@s3_driver ||= AwsDriver::S3.new
|
124
|
+
end
|
125
|
+
|
126
|
+
def s3_driver=(value)
|
127
|
+
@s3_driver = value
|
128
|
+
end
|
129
|
+
|
109
130
|
def stdout
|
110
131
|
@stdout || $stdout
|
111
132
|
end
|
@@ -126,4 +147,3 @@ module StackMaster
|
|
126
147
|
@stderr = io
|
127
148
|
end
|
128
149
|
end
|
129
|
-
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
module AwsDriver
|
5
|
+
class S3ConfigurationError < StandardError; end
|
6
|
+
|
7
|
+
class S3
|
8
|
+
def set_region(region)
|
9
|
+
@region = region
|
10
|
+
@s3 = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def upload_files(bucket: nil, prefix: nil, region: nil, files: {})
|
14
|
+
raise StackMaster::AwsDriver::S3ConfigurationError, 'A bucket must be specified in order to use S3' unless bucket
|
15
|
+
|
16
|
+
return if files.empty?
|
17
|
+
|
18
|
+
s3 = new_s3_client(region: region)
|
19
|
+
|
20
|
+
current_objects = s3.list_objects(
|
21
|
+
prefix: prefix,
|
22
|
+
bucket: bucket
|
23
|
+
).map(&:contents).flatten.inject({}){|h,obj|
|
24
|
+
h.merge(obj.key => obj)
|
25
|
+
}
|
26
|
+
|
27
|
+
StackMaster.stdout.puts "Uploading files to S3:"
|
28
|
+
|
29
|
+
files.each do |template, file|
|
30
|
+
body = file.fetch(:body)
|
31
|
+
path = file.fetch(:path)
|
32
|
+
object_key = template.dup
|
33
|
+
object_key.prepend("#{prefix}/") if prefix
|
34
|
+
compiled_template_md5 = Digest::MD5.hexdigest(body).to_s
|
35
|
+
s3_md5 = current_objects[object_key] ? current_objects[object_key].etag.gsub("\"", '') : nil
|
36
|
+
|
37
|
+
next if compiled_template_md5 == s3_md5
|
38
|
+
s3_uri = "s3://#{bucket}/#{object_key}"
|
39
|
+
StackMaster.stdout.print "- #{File.basename(path)} => #{s3_uri} "
|
40
|
+
|
41
|
+
s3.put_object(
|
42
|
+
bucket: bucket,
|
43
|
+
key: object_key,
|
44
|
+
body: body,
|
45
|
+
metadata: { md5: compiled_template_md5 }
|
46
|
+
)
|
47
|
+
StackMaster.stdout.puts "done."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def url(bucket:, prefix:, region:, template:)
|
52
|
+
if region == 'us-east-1'
|
53
|
+
["https://s3.amazonaws.com", bucket, prefix, template].compact.join('/')
|
54
|
+
else
|
55
|
+
["https://s3-#{region}.amazonaws.com", bucket, prefix, template].compact.join('/')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def new_s3_client(region: nil)
|
62
|
+
Aws::S3::Client.new(region: region || @region)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/stack_master/cli.rb
CHANGED
@@ -4,10 +4,11 @@ module StackMaster
|
|
4
4
|
include Command
|
5
5
|
include Commander::UI
|
6
6
|
include StackMaster::Prompter
|
7
|
-
TEMPLATE_TOO_LARGE_ERROR_MESSAGE = 'The (space compressed) stack is larger than the limit set by AWS. See http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html'
|
7
|
+
TEMPLATE_TOO_LARGE_ERROR_MESSAGE = 'The (space compressed) stack is larger than the limit set by AWS. See http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html'.freeze
|
8
8
|
|
9
9
|
def initialize(config, stack_definition, options = {})
|
10
10
|
@config = config
|
11
|
+
@s3_config = stack_definition.s3
|
11
12
|
@stack_definition = stack_definition
|
12
13
|
@from_time = Time.now
|
13
14
|
end
|
@@ -26,6 +27,10 @@ module StackMaster
|
|
26
27
|
@cf ||= StackMaster.cloud_formation_driver
|
27
28
|
end
|
28
29
|
|
30
|
+
def s3
|
31
|
+
@s3 ||= StackMaster.s3_driver
|
32
|
+
end
|
33
|
+
|
29
34
|
def stack
|
30
35
|
@stack ||= Stack.find(region, stack_name)
|
31
36
|
end
|
@@ -38,6 +43,10 @@ module StackMaster
|
|
38
43
|
!stack.nil?
|
39
44
|
end
|
40
45
|
|
46
|
+
def use_s3?
|
47
|
+
!@s3_config.empty?
|
48
|
+
end
|
49
|
+
|
41
50
|
def diff_stacks
|
42
51
|
StackDiffer.new(proposed_stack, stack).output_diff
|
43
52
|
end
|
@@ -51,9 +60,10 @@ module StackMaster
|
|
51
60
|
end
|
52
61
|
|
53
62
|
def create_stack
|
54
|
-
unless ask?(
|
63
|
+
unless ask?('Create stack (y/n)? ')
|
55
64
|
failed!("Stack creation aborted")
|
56
65
|
end
|
66
|
+
upload_files
|
57
67
|
cf.create_stack(stack_options.merge(tags: proposed_stack.aws_tags))
|
58
68
|
end
|
59
69
|
|
@@ -73,17 +83,54 @@ module StackMaster
|
|
73
83
|
ChangeSet.delete(@change_set.id)
|
74
84
|
halt! "Stack update aborted"
|
75
85
|
end
|
86
|
+
upload_files
|
76
87
|
execute_change_set
|
77
88
|
end
|
78
89
|
|
90
|
+
def upload_files
|
91
|
+
return unless use_s3?
|
92
|
+
s3.upload_files(s3_options)
|
93
|
+
end
|
94
|
+
|
95
|
+
def template_method
|
96
|
+
use_s3? ? :template_url : :template_body
|
97
|
+
end
|
98
|
+
|
99
|
+
def template_value
|
100
|
+
if use_s3?
|
101
|
+
s3.url(bucket: @s3_config['bucket'], prefix: @s3_config['prefix'], region: @s3_config['region'], template: @stack_definition.s3_template_file_name)
|
102
|
+
else
|
103
|
+
proposed_stack.maybe_compressed_template_body
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def files_to_upload
|
108
|
+
return {} unless use_s3?
|
109
|
+
@stack_definition.s3_files.tap do |files|
|
110
|
+
files[@stack_definition.s3_template_file_name] = {
|
111
|
+
path: @stack_definition.template_file_path,
|
112
|
+
body: proposed_stack.maybe_compressed_template_body
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
79
117
|
def stack_options
|
80
118
|
{
|
81
119
|
stack_name: stack_name,
|
82
|
-
template_body: proposed_stack.maybe_compressed_template_body,
|
83
120
|
parameters: proposed_stack.aws_parameters,
|
84
121
|
capabilities: ['CAPABILITY_IAM'],
|
85
122
|
notification_arns: proposed_stack.notification_arns,
|
86
|
-
stack_policy_body: proposed_stack.stack_policy_body
|
123
|
+
stack_policy_body: proposed_stack.stack_policy_body,
|
124
|
+
template_method => template_value
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
def s3_options
|
129
|
+
{
|
130
|
+
bucket: @s3_config['bucket'],
|
131
|
+
prefix: @s3_config['prefix'],
|
132
|
+
region: @s3_config['region'],
|
133
|
+
files: files_to_upload
|
87
134
|
}
|
88
135
|
end
|
89
136
|
|
@@ -110,7 +157,7 @@ module StackMaster
|
|
110
157
|
end
|
111
158
|
|
112
159
|
def ensure_valid_template_body_size!
|
113
|
-
if proposed_stack.too_big?
|
160
|
+
if proposed_stack.too_big?(use_s3?)
|
114
161
|
failed! TEMPLATE_TOO_LARGE_ERROR_MESSAGE
|
115
162
|
end
|
116
163
|
end
|