aws-cft-tools 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.editorconfig +10 -0
- data/.gitignore +52 -0
- data/.rspec +2 -0
- data/.rubocop.yml +19 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/BEST-PRACTICES.md +136 -0
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +8 -0
- data/LICENSE +15 -0
- data/README.md +118 -0
- data/Rakefile +17 -0
- data/USAGE.adoc +404 -0
- data/aws-cft-tools.gemspec +53 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/code.json +24 -0
- data/exe/aws-cft +176 -0
- data/lib/aws-cft-tools.rb +3 -0
- data/lib/aws_cft_tools.rb +31 -0
- data/lib/aws_cft_tools/aws_enumerator.rb +55 -0
- data/lib/aws_cft_tools/change.rb +66 -0
- data/lib/aws_cft_tools/client.rb +84 -0
- data/lib/aws_cft_tools/client/base.rb +40 -0
- data/lib/aws_cft_tools/client/cft.rb +93 -0
- data/lib/aws_cft_tools/client/cft/changeset_management.rb +109 -0
- data/lib/aws_cft_tools/client/cft/stack_management.rb +85 -0
- data/lib/aws_cft_tools/client/ec2.rb +136 -0
- data/lib/aws_cft_tools/client/templates.rb +84 -0
- data/lib/aws_cft_tools/deletion_change.rb +43 -0
- data/lib/aws_cft_tools/dependency_tree.rb +109 -0
- data/lib/aws_cft_tools/dependency_tree/nodes.rb +71 -0
- data/lib/aws_cft_tools/dependency_tree/variables.rb +37 -0
- data/lib/aws_cft_tools/errors.rb +25 -0
- data/lib/aws_cft_tools/runbook.rb +166 -0
- data/lib/aws_cft_tools/runbook/report.rb +30 -0
- data/lib/aws_cft_tools/runbooks.rb +16 -0
- data/lib/aws_cft_tools/runbooks/common/changesets.rb +30 -0
- data/lib/aws_cft_tools/runbooks/common/templates.rb +38 -0
- data/lib/aws_cft_tools/runbooks/deploy.rb +107 -0
- data/lib/aws_cft_tools/runbooks/deploy/reporting.rb +50 -0
- data/lib/aws_cft_tools/runbooks/deploy/stacks.rb +109 -0
- data/lib/aws_cft_tools/runbooks/deploy/templates.rb +37 -0
- data/lib/aws_cft_tools/runbooks/deploy/threading.rb +37 -0
- data/lib/aws_cft_tools/runbooks/diff.rb +28 -0
- data/lib/aws_cft_tools/runbooks/diff/context.rb +86 -0
- data/lib/aws_cft_tools/runbooks/diff/context/reporting.rb +87 -0
- data/lib/aws_cft_tools/runbooks/hosts.rb +43 -0
- data/lib/aws_cft_tools/runbooks/images.rb +43 -0
- data/lib/aws_cft_tools/runbooks/init.rb +86 -0
- data/lib/aws_cft_tools/runbooks/retract.rb +69 -0
- data/lib/aws_cft_tools/runbooks/retract/templates.rb +44 -0
- data/lib/aws_cft_tools/runbooks/stacks.rb +43 -0
- data/lib/aws_cft_tools/stack.rb +83 -0
- data/lib/aws_cft_tools/template.rb +177 -0
- data/lib/aws_cft_tools/template/dsl_context.rb +14 -0
- data/lib/aws_cft_tools/template/file_system.rb +62 -0
- data/lib/aws_cft_tools/template/metadata.rb +144 -0
- data/lib/aws_cft_tools/template/properties.rb +129 -0
- data/lib/aws_cft_tools/template_set.rb +120 -0
- data/lib/aws_cft_tools/template_set/array_methods.rb +63 -0
- data/lib/aws_cft_tools/template_set/closure.rb +77 -0
- data/lib/aws_cft_tools/template_set/dependencies.rb +55 -0
- data/lib/aws_cft_tools/template_set/each_slice_state.rb +58 -0
- data/lib/aws_cft_tools/version.rb +8 -0
- data/rubycritic.reek +3 -0
- metadata +321 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AwsCftTools
|
4
|
+
module Runbooks
|
5
|
+
class Retract
|
6
|
+
##
|
7
|
+
# module with methods to manage ordering of templates
|
8
|
+
#
|
9
|
+
module Templates
|
10
|
+
require_relative '../common/templates'
|
11
|
+
|
12
|
+
include Common::Templates
|
13
|
+
|
14
|
+
##
|
15
|
+
# list the templates in-scope for this retraction
|
16
|
+
#
|
17
|
+
# @return [AwsCftTools::TemplateSet]
|
18
|
+
#
|
19
|
+
def templates
|
20
|
+
@templates ||= filtered_templates(client.templates)
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# List the templates that are available for deletion.
|
25
|
+
#
|
26
|
+
# Templates with known dependents that are not in the set will be removed. Note that this does
|
27
|
+
# not capture dependencies between environments.
|
28
|
+
#
|
29
|
+
# @return [AwsCftTools::TemplateSet]
|
30
|
+
def free_templates
|
31
|
+
set = AwsCftTools::TemplateSet.new(templates.in_folder_order(template_folder_order))
|
32
|
+
client.templates.closed_subset(set).reverse
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# @return [Array<String>]
|
37
|
+
#
|
38
|
+
def template_folder_order
|
39
|
+
options[:template_folder_priorities] || []
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AwsCftTools
|
4
|
+
module Runbooks
|
5
|
+
##
|
6
|
+
# Images - report on available AMIs
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# % aws-cli stacks # list all known stacks
|
10
|
+
# % aws-cli stacks -e QA # list all known stacks tagged for the QA environment
|
11
|
+
# % aws-cli stacks -e QA -r App # list all known stacks tagged for the QA environment and App role
|
12
|
+
#
|
13
|
+
class Stacks < Runbook::Report
|
14
|
+
###
|
15
|
+
# @return [Array<AwsCftTools::Stack>]
|
16
|
+
#
|
17
|
+
def items
|
18
|
+
client.stacks.sort_by(&method(:sort_key))
|
19
|
+
end
|
20
|
+
|
21
|
+
###
|
22
|
+
# @return [Array<String>]
|
23
|
+
#
|
24
|
+
def columns
|
25
|
+
environment_column + role_column + %w[filename created_at name state]
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def sort_key(stack)
|
31
|
+
stack.name
|
32
|
+
end
|
33
|
+
|
34
|
+
def environment_column
|
35
|
+
options[:environment] ? [] : ['environment']
|
36
|
+
end
|
37
|
+
|
38
|
+
def role_column
|
39
|
+
options[:role] ? [] : ['role']
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AwsCftTools
|
4
|
+
##
|
5
|
+
# Provides a unified interface for accessing information about deployed CloudFormation templates.
|
6
|
+
#
|
7
|
+
class Stack
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
def initialize(aws_stack, aws_client)
|
11
|
+
@aws_client = aws_client
|
12
|
+
@aws_stack = aws_stack
|
13
|
+
end
|
14
|
+
|
15
|
+
def_delegators :@aws_stack, :description
|
16
|
+
def_delegator :@aws_stack, :stack_name, :name
|
17
|
+
def_delegator :@aws_stack, :creation_time, :created_at
|
18
|
+
def_delegator :@aws_stack, :last_updated_time, :updated_at
|
19
|
+
def_delegator :@aws_stack, :stack_status, :state
|
20
|
+
def_delegator :@aws_stack, :stack_id, :id
|
21
|
+
|
22
|
+
###
|
23
|
+
# @return [String] the unparsed body of the template definition
|
24
|
+
#
|
25
|
+
def template_source
|
26
|
+
@template ||= begin
|
27
|
+
resp = @aws_client.get_template(stack_name: name,
|
28
|
+
template_stage: 'Original')
|
29
|
+
resp.template_body
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# @return [Hash] dictionary of tag names and values for the stack
|
35
|
+
#
|
36
|
+
def tags
|
37
|
+
@tags ||= @aws_stack.tags.each_with_object({}) { |tag, hash| hash[tag.key] = tag.value }
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# @return [Hash] mapping of output name with output definition
|
42
|
+
def outputs
|
43
|
+
@outputs ||= build_hashes(@aws_stack.outputs || [], &:output_key)
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# @return [Hash] mapping of parameter name to parameter definition
|
48
|
+
#
|
49
|
+
def parameters
|
50
|
+
@parameters ||= build_hashes(@aws_stack.parameters || [], &:parameter_key)
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# @return [String] the environment of the stack
|
55
|
+
#
|
56
|
+
def environment
|
57
|
+
tags['Environment']
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# @return [String] the role of the stack
|
62
|
+
#
|
63
|
+
def role
|
64
|
+
tags['Role']
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# @return [String] the filename of the stack's template source
|
69
|
+
#
|
70
|
+
def filename
|
71
|
+
@filename ||= begin
|
72
|
+
source = tags['Source']
|
73
|
+
source ? source.sub(%r{^/+}, '') : nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def build_hashes(source, &block)
|
80
|
+
source.map(&block).zip(source).to_h
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'erb'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
module AwsCftTools
|
8
|
+
##
|
9
|
+
# The AwsCftTools::Template class wraps a CloudFormation template source to provide support for various
|
10
|
+
# operations by the toolset.
|
11
|
+
#
|
12
|
+
# == CloudFormation Templates
|
13
|
+
#
|
14
|
+
# As much as possible, this tool uses CloudFormation templates as-is and makes as many inferences as
|
15
|
+
# reasonable. However, some things aren't captured in stock template information.
|
16
|
+
#
|
17
|
+
# @note Stacks should be removed ("retracted") from AWS before they are removed from the set of templates.
|
18
|
+
# Otherwise, they won't be considered in the set of available templates or stacks.
|
19
|
+
#
|
20
|
+
# @todo Fetch templates from deployed stacks and consider them in the dependency tree for removing or
|
21
|
+
# deploying templates in the repo. Flag stacks with no local source to not be updated on deployment.
|
22
|
+
#
|
23
|
+
# @todo Add ability to init to fetch templates from stacks and put them in files.
|
24
|
+
#
|
25
|
+
# === Allowed Environments
|
26
|
+
#
|
27
|
+
# The environments in which a template should be deployed is provided by the +AllowedValues+ key of the
|
28
|
+
# +Environment+ template parameter.
|
29
|
+
#
|
30
|
+
# @example Allowed Environments
|
31
|
+
# ---
|
32
|
+
# Parameters:
|
33
|
+
# Environment:
|
34
|
+
# AllowedValues:
|
35
|
+
# - QA
|
36
|
+
# - Staging
|
37
|
+
# - Production
|
38
|
+
#
|
39
|
+
# === Allowed Regions
|
40
|
+
#
|
41
|
+
# A template can be pinned to a particular region or set of regions by providing a list of values for
|
42
|
+
# the +Region+ key in the template metadata. If no such key is present, then the template can be
|
43
|
+
# deployed or otherwise used in all regions.
|
44
|
+
#
|
45
|
+
# @example Allowed Regions
|
46
|
+
# ---
|
47
|
+
# Metadata:
|
48
|
+
# Region:
|
49
|
+
# - us-east-1
|
50
|
+
# - us-west-1
|
51
|
+
#
|
52
|
+
# === Explicit Template Dependencies
|
53
|
+
#
|
54
|
+
# As much as possible, dependencies between templates are inferred based on exported and imported
|
55
|
+
# values. However, some templates might depend on another template in a way that isn't captured by
|
56
|
+
# these values. For those dependencies, the templates that should be run first can be listed under the
|
57
|
+
# +DependesOn.Templates+ metadata key.
|
58
|
+
#
|
59
|
+
# @example Explicit Template Dependency
|
60
|
+
# ---
|
61
|
+
# Metadata:
|
62
|
+
# DependsOn:
|
63
|
+
# Templates:
|
64
|
+
# - network/peering.yaml
|
65
|
+
#
|
66
|
+
# === Template Parameters
|
67
|
+
#
|
68
|
+
# Rather than require mappings in templates to hold environment-specific values, a template has a
|
69
|
+
# corresponding parameters file that holds the value for the stack parameter for each environment.
|
70
|
+
# This parameters file is in YAML format and passed through ERB before parsing, so it can incorporate
|
71
|
+
# environment variables and other logic into specifying parameter values.
|
72
|
+
#
|
73
|
+
class Template
|
74
|
+
attr_reader :filename
|
75
|
+
|
76
|
+
require_relative 'template/dsl_context'
|
77
|
+
require_relative 'template/file_system'
|
78
|
+
require_relative 'template/metadata'
|
79
|
+
require_relative 'template/properties'
|
80
|
+
|
81
|
+
include FileSystem
|
82
|
+
include Metadata
|
83
|
+
include Properties
|
84
|
+
|
85
|
+
##
|
86
|
+
# @param filename [String] path to template relative to the +template_dir+ path
|
87
|
+
# @param options [Hash] runbook options
|
88
|
+
# @option options [String] :environment environment in which parameters should be fetched
|
89
|
+
# @option options [String] :parameter_dir directory relative to the +root+ path in which parameter files
|
90
|
+
# are found
|
91
|
+
# @option options [Pathname] :root path to the root of the project
|
92
|
+
# @option options [String] :template_dir directory relative to the +root+ path in which template sources
|
93
|
+
# are found
|
94
|
+
#
|
95
|
+
def initialize(filename, options = {})
|
96
|
+
@options = options
|
97
|
+
@filename = filename
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# @return [Array<Hash>] template tags suitable for use in deploying a stack
|
102
|
+
#
|
103
|
+
def tags
|
104
|
+
[
|
105
|
+
{ key: 'Environment', value: @options[:environment] },
|
106
|
+
{ key: 'Source', value: ('/' + filename.to_s).gsub(%r{/+}, '/') }
|
107
|
+
] + role_tag
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# @return [Hash] parameters to provide to the AWS client to deploy the template
|
112
|
+
#
|
113
|
+
def stack_parameters
|
114
|
+
{
|
115
|
+
stack_name: name,
|
116
|
+
template_body: template_source_for_aws,
|
117
|
+
parameters: hash_to_param_list(parameters || {}),
|
118
|
+
tags: tags
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def role_tag
|
125
|
+
if role
|
126
|
+
[{ key: 'Role', value: role }]
|
127
|
+
else
|
128
|
+
[]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def hash_to_param_list(hash)
|
133
|
+
hash.map do |key, value|
|
134
|
+
{
|
135
|
+
parameter_key: key.to_s,
|
136
|
+
parameter_value: value_to_string(value),
|
137
|
+
use_previous_value: !value && value != false || value == ''
|
138
|
+
}
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def value_to_string(value)
|
143
|
+
case value
|
144
|
+
when false
|
145
|
+
'false'
|
146
|
+
when true
|
147
|
+
'true'
|
148
|
+
else
|
149
|
+
value ? value.to_s : value
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Looks through the template to find instances of +Fn::ImportValue+
|
155
|
+
#
|
156
|
+
def pull_imports(hash)
|
157
|
+
hash.flat_map do |key, value|
|
158
|
+
value ||= key
|
159
|
+
if %w[Fn::ImportValue ImportValue].include?(key)
|
160
|
+
pull_import(value)
|
161
|
+
elsif value.is_a?(Hash) || value.is_a?(Array)
|
162
|
+
pull_imports(value)
|
163
|
+
else
|
164
|
+
[]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def pull_import(value)
|
170
|
+
if value.is_a?(Hash)
|
171
|
+
[value['Fn::Sub'] || value['Sub'] || value]
|
172
|
+
else
|
173
|
+
[value]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AwsCftTools
|
4
|
+
class Template
|
5
|
+
##
|
6
|
+
# Utility module for evaluating ruby dsl templates.
|
7
|
+
#
|
8
|
+
module DSLContext
|
9
|
+
require 'cloudformation-ruby-dsl/cfntemplate'
|
10
|
+
require 'cloudformation-ruby-dsl/spotprice'
|
11
|
+
require 'cloudformation-ruby-dsl/table'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module AwsCftTools
|
6
|
+
class Template
|
7
|
+
##
|
8
|
+
# Manage template and parameter files.
|
9
|
+
#
|
10
|
+
module FileSystem
|
11
|
+
##
|
12
|
+
# Returns the path to the cloud formation template.
|
13
|
+
#
|
14
|
+
# @return [Pathname]
|
15
|
+
def template_file
|
16
|
+
filename_path(:template_dir, filename)
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Returns the path to the template parameters file.
|
21
|
+
#
|
22
|
+
# @return [Pathname]
|
23
|
+
def parameter_file
|
24
|
+
filename_path(:parameter_dir, filename)
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# The unparsed source of the template.
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
def template_source
|
32
|
+
@template_source ||= @options[:template_content] || read_file(template_file)
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# The unparsed source of the parameters file for this template.
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
def parameters_source
|
40
|
+
@parameters_source ||= @options[:parameters_content] || read_file(parameter_file)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def read_file(file)
|
46
|
+
file ? file.read : nil
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Given the filename relative to the template/parameter root and a symbol indicating which type of
|
51
|
+
# file to point to, returns the full path to the file
|
52
|
+
#
|
53
|
+
# @return [Pathname]
|
54
|
+
def filename_path(dir, filename)
|
55
|
+
# we need to check .yaml, .yml, and .json versions
|
56
|
+
filename = filename.to_s.sub(/\.[^.]*$/, '')
|
57
|
+
base = @options[:root] + @options[dir]
|
58
|
+
%w[.yaml .yml .json .rb].map { |ext| base + (filename + ext) }.detect(&:exist?)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module AwsCftTools
|
6
|
+
class Template
|
7
|
+
##
|
8
|
+
# Simple derived information about templates.
|
9
|
+
#
|
10
|
+
module Metadata
|
11
|
+
##
|
12
|
+
# Mapping of filename extensions to content types.
|
13
|
+
#
|
14
|
+
CONTENT_TYPES = {
|
15
|
+
'.json' => 'json',
|
16
|
+
'.rb' => 'dsl',
|
17
|
+
'.yml' => 'yaml',
|
18
|
+
'.yaml' => 'yaml'
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
##
|
22
|
+
# The type of template content.
|
23
|
+
#
|
24
|
+
# @return [String] One of +dsl+, +json+, or +yaml+.
|
25
|
+
def template_type
|
26
|
+
content_type(template_file)
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Queries if the template source looks like a CloudFormation template.
|
31
|
+
#
|
32
|
+
# @return [Boolean]
|
33
|
+
def template?
|
34
|
+
template && template['AWSTemplateFormatVersion']
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# The name of the stack built by this template.
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
def name
|
42
|
+
@name ||= @options[:environment] + '-' +
|
43
|
+
filename.to_s.sub(/\.(ya?ml|json|rb)$/, '').split(%r{/}).reverse.join('-')
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# The parsed template as a Ruby data structure.
|
48
|
+
#
|
49
|
+
# @return [Hash]
|
50
|
+
def template
|
51
|
+
@template ||= template_content_for_filename(template_file)
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# The JSON or YAML source that can be submitted to AWS to build the stack.
|
56
|
+
#
|
57
|
+
# @return [String]
|
58
|
+
def template_source_for_aws
|
59
|
+
template_type == 'dsl' ? JSON.pretty_generate(template) : template_source
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# The parsed parameters for this template in the deployment environment.
|
64
|
+
#
|
65
|
+
# @return [Hash]
|
66
|
+
def parameters
|
67
|
+
@parameters ||= parameters_for_filename_and_environment(parameters_source, @options[:environment])
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def content_type(file)
|
73
|
+
CONTENT_TYPES[file.extname] if file
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Loads the contents of the full path and returns the content as a Ruby data structure
|
78
|
+
#
|
79
|
+
# @return [String]
|
80
|
+
def template_content_for_filename(file)
|
81
|
+
type = content_type(file)
|
82
|
+
return {} unless type
|
83
|
+
send(:"template_content_for_#{type}!")
|
84
|
+
rescue => exception
|
85
|
+
raise AwsCftTools::ParseException, "Error while parsing #{template_file}: #{exception}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def template_content_for_yaml!
|
89
|
+
YAML.safe_load(template_source, [Date], [], true) || {}
|
90
|
+
end
|
91
|
+
|
92
|
+
def template_content_for_json!
|
93
|
+
JSON.parse(template_source) || {}
|
94
|
+
end
|
95
|
+
|
96
|
+
def template_content_for_dsl!
|
97
|
+
with_environment { JSON.parse(DSLContext.module_eval(template_source).to_json) }
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Loads the contents of the full path and passes it through ERB before parsing as YAML. Returns
|
102
|
+
# a Ruby structure.
|
103
|
+
#
|
104
|
+
# If no file exists, then a simple hash with the +Environment+ key set.
|
105
|
+
#
|
106
|
+
def parameters_for_filename_and_environment(param_source, env)
|
107
|
+
parameters_for_filename_and_environment!(param_source, env)
|
108
|
+
rescue AwsCftTools::ToolingException
|
109
|
+
raise
|
110
|
+
rescue => exception
|
111
|
+
raise AwsCftTools::ParseException, "Error while reading and parsing #{parameter_file}: #{exception}"
|
112
|
+
end
|
113
|
+
|
114
|
+
def parameters_for_filename_and_environment!(param_source, env)
|
115
|
+
return { Environment: env } unless param_source
|
116
|
+
|
117
|
+
params = YAML.safe_load(process_erb_file(param_source), [], [], true)[env] || {}
|
118
|
+
params.update(Environment: env)
|
119
|
+
end
|
120
|
+
|
121
|
+
def process_erb_file(content)
|
122
|
+
with_environment { ERB.new(content).result }
|
123
|
+
end
|
124
|
+
|
125
|
+
def with_environment
|
126
|
+
return unless block_given?
|
127
|
+
prior = ENV.to_h
|
128
|
+
ENV.update(aws_env)
|
129
|
+
yield
|
130
|
+
ensure
|
131
|
+
ENV.update(prior)
|
132
|
+
end
|
133
|
+
|
134
|
+
def aws_env
|
135
|
+
region = @options[:region]
|
136
|
+
{
|
137
|
+
'AWS_REGION' => region,
|
138
|
+
'EC2_REGION' => region,
|
139
|
+
'AWS_PROFILE' => @options[:profile]
|
140
|
+
}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|