stacker-yaml 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.
@@ -0,0 +1,76 @@
1
+ require 'memoist'
2
+ require 'stacker/differ'
3
+ require 'stacker/stack/component'
4
+ require 'stacker/stack/parameter'
5
+
6
+ module Stacker
7
+ class Stack
8
+ class Parameters < Component
9
+
10
+ extend Memoist
11
+
12
+ # everything required by the template
13
+ def template_definitions
14
+ stack.template.local.fetch 'Parameters', {}
15
+ end
16
+
17
+ def region_defaults
18
+ stack.region.defaults.fetch 'parameters', {}
19
+ end
20
+
21
+ # template defaults merged with region and stack-specific overrides
22
+ def local
23
+ region_defaults = stack.region.defaults.fetch 'parameters', {}
24
+
25
+ template_defaults = Hash[
26
+ template_definitions.select { |_, opts|
27
+ opts.key?('Default')
28
+ }.map { |name, opts|
29
+ [name, opts['Default']]
30
+ }
31
+ ]
32
+
33
+ available = template_defaults.merge(
34
+ region_defaults
35
+ ).merge(
36
+ stack.options.fetch 'parameters', {}
37
+ )
38
+
39
+ available.slice(*template_definitions.keys)
40
+ end
41
+
42
+ def missing
43
+ template_definitions.keys - local.keys
44
+ end
45
+
46
+ def remote
47
+ Hash[client.parameters.map do |p|
48
+ [p.parameter_key, p.parameter_value]
49
+ end]
50
+ end
51
+ memoize :remote
52
+
53
+ def resolved
54
+ Hash[parameters.map { |k, v| [ k, v.resolved ] }]
55
+ end
56
+ memoize :resolved
57
+
58
+ def dependencies
59
+ parameters.map(&:last).map(&:dependencies).flatten
60
+ end
61
+ memoize :dependencies
62
+
63
+ def diff *args
64
+ Differ.yaml_diff Hash[resolved.sort], Hash[remote.sort], *args
65
+ end
66
+ memoize :diff
67
+
68
+ private
69
+
70
+ def parameters
71
+ local.map { |k, v| [k, Parameter.new(v, stack.region)] }
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,126 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+ require 'json'
3
+ require 'yaml'
4
+ require 'memoist'
5
+ require 'stacker/differ'
6
+ require 'stacker/stack'
7
+ require 'stacker/stack/component'
8
+
9
+ module Stacker
10
+ class Stack
11
+ class Template < Component
12
+
13
+ FORMAT_VERSION = '2010-09-09'
14
+
15
+ extend Memoist
16
+
17
+ def exists?
18
+ File.exists? path
19
+ end
20
+
21
+ def local_raw
22
+ File.read path
23
+ end
24
+ memoize :local_raw
25
+
26
+ def local
27
+ raise TemplateDoesNotExistError.new name unless exists?
28
+ @local ||= begin
29
+ template = if json?
30
+ JSON.parse local_raw
31
+ else
32
+ YAML.load local_raw
33
+ end
34
+ template['AWSTemplateFormatVersion'] ||= FORMAT_VERSION
35
+ template
36
+ end
37
+ rescue JSON::ParserError, Psych::SyntaxError
38
+ raise TemplateSyntaxError.new path
39
+ end
40
+
41
+ def remote_raw
42
+ stack.region.client.get_template(
43
+ stack_name: stack.name
44
+ ).template_body
45
+ end
46
+ memoize :remote_raw
47
+
48
+ def remote
49
+ @remote ||= json? ? JSON.parse(remote_raw) : YAML.parse(remote_raw)
50
+ rescue Aws::CloudFormation::Errors::ValidationError => err
51
+ if err.message =~ /does not exist/
52
+ raise DoesNotExistError.new err.message
53
+ else
54
+ raise Error.new err.message
55
+ end
56
+ end
57
+
58
+ def diff *args
59
+ if json?
60
+ Differ.json_diff local, remote, *args
61
+ else
62
+ Differ.diff local_raw, remote_raw, *args
63
+ end
64
+ end
65
+ memoize :diff
66
+
67
+ def write value = local
68
+ File.write path, JSONFormatter.format(value)
69
+ end
70
+
71
+ def dump
72
+ write remote
73
+ end
74
+
75
+ private
76
+
77
+ def name
78
+ stack.options.fetch('template_name', stack.name)
79
+ end
80
+
81
+ def path_with_ext ext
82
+ File.join(
83
+ stack.region.templates_path,
84
+ "#{name}.#{ext}"
85
+ )
86
+ end
87
+
88
+ def path
89
+ json = path_with_ext 'json'
90
+ yaml = path_with_ext 'yml'
91
+ File.exists?(json) ? json : yaml
92
+ end
93
+ memoize :path
94
+
95
+ def json?
96
+ path.end_with? '.json'
97
+ end
98
+
99
+ def yaml?
100
+ path.end_with? '.yml'
101
+ end
102
+
103
+ class JSONFormatter
104
+ STR = '\"[^\"]+\"'
105
+
106
+ def self.format object
107
+ formatted = JSON.pretty_generate object
108
+
109
+ # put empty arrays on a single line
110
+ formatted.gsub! /: \[\s*\]/m, ': []'
111
+
112
+ # put { "Ref": ... } on a single line
113
+ formatted.gsub! /\{\s+\"Ref\"\:\s+(?<ref>#{STR})\s+\}/m,
114
+ '{ "Ref": \\k<ref> }'
115
+
116
+ # put { "Fn::GetAtt": ... } on a single line
117
+ formatted.gsub! /\{\s+\"Fn::GetAtt\"\: \[\s+(?<key>#{STR}),\s+(?<val>#{STR})\s+\]\s+\}/m,
118
+ '{ "Fn::GetAtt": [ \\k<key>, \\k<val> ] }'
119
+
120
+ formatted + "\n"
121
+ end
122
+ end
123
+
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,3 @@
1
+ module Stacker
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,273 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stacker-yaml
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Cotap, Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-06-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: coderay
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: diffy
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: indentation
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: jsonlint
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.2.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.2.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: memoist
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.14'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.14'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rainbow
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.1'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.1'
125
+ - !ruby/object:Gem::Dependency
126
+ name: thor
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.18'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.18'
139
+ - !ruby/object:Gem::Dependency
140
+ name: yamllint
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 0.0.9
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 0.0.9
153
+ - !ruby/object:Gem::Dependency
154
+ name: pry
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rake
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '10.4'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '10.4'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rspec
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '3.0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '3.0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: rspec-its
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: rspec-expectations
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '3.5'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '3.5'
223
+ description: Stacker helps you assemple and manage CloudFormation stacks and dependencies.
224
+ email:
225
+ - martin@cotap.com
226
+ - evan@cotap.com
227
+ executables:
228
+ - stacker
229
+ extensions: []
230
+ extra_rdoc_files: []
231
+ files:
232
+ - bin/stacker
233
+ - lib/stacker.rb
234
+ - lib/stacker/cli.rb
235
+ - lib/stacker/differ.rb
236
+ - lib/stacker/logging.rb
237
+ - lib/stacker/region.rb
238
+ - lib/stacker/resolvers/file_resolver.rb
239
+ - lib/stacker/resolvers/resolver.rb
240
+ - lib/stacker/resolvers/stack_output_resolver.rb
241
+ - lib/stacker/stack.rb
242
+ - lib/stacker/stack/capabilities.rb
243
+ - lib/stacker/stack/component.rb
244
+ - lib/stacker/stack/errors.rb
245
+ - lib/stacker/stack/parameter.rb
246
+ - lib/stacker/stack/parameters.rb
247
+ - lib/stacker/stack/template.rb
248
+ - lib/stacker/version.rb
249
+ homepage: https://github.com/cotap/stacker
250
+ licenses:
251
+ - MIT
252
+ metadata: {}
253
+ post_install_message:
254
+ rdoc_options: []
255
+ require_paths:
256
+ - lib
257
+ required_ruby_version: !ruby/object:Gem::Requirement
258
+ requirements:
259
+ - - ">="
260
+ - !ruby/object:Gem::Version
261
+ version: 1.9.3
262
+ required_rubygems_version: !ruby/object:Gem::Requirement
263
+ requirements:
264
+ - - ">="
265
+ - !ruby/object:Gem::Version
266
+ version: '0'
267
+ requirements: []
268
+ rubyforge_project:
269
+ rubygems_version: 2.6.10
270
+ signing_key:
271
+ specification_version: 4
272
+ summary: Easily assemble CloudFormation stacks.
273
+ test_files: []