mkstack 1.0.0 → 1.2.1
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/bin/mkstack +29 -13
- data/lib/mkstack.rb +39 -6
- data/lib/mkstack/template.rb +40 -44
- data/mkstack.gemspec +1 -1
- metadata +21 -23
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 156c6f1b2ce583f7723c9943105e5a56b27959cad2dcd3cab914065806d5371b
|
4
|
+
data.tar.gz: d994eee79d71b74e2a635059ed1a4ba47cf93d518e3606421a567f6b92bd53ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab4040c5feb8d08e926c58c36ffc9c6f7f70f17c433992cfbb4b227cabf03802ad1f0139fde972847037bf466877f5d6a212f44136e4aa7709135345c7c34550
|
7
|
+
data.tar.gz: f09c970148652460c653672016f60f97feae0df146fa487be7d942ea7f98a8470ed4af47467b864b020bc19d0ef42df65295377cc0ee61bf0aa0563e6cb6f61b
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/bin/mkstack
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
#!/usr/
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "logger"
|
4
4
|
require "optparse"
|
5
|
-
|
5
|
+
require_relative "../lib/mkstack"
|
6
|
+
|
7
|
+
version = "1.2.0"
|
6
8
|
|
7
9
|
|
8
10
|
##################################################
|
@@ -15,12 +17,11 @@ $logger.formatter = proc { |s, d, p, m|
|
|
15
17
|
"[%s] %5s [%5s] - %s\n" % [ d.strftime("%Y-%m-%d %H:%M:%S"), s, caller(4, 1).first.split(":")[1], m ]
|
16
18
|
}
|
17
19
|
|
18
|
-
|
19
20
|
# Default options
|
20
21
|
options = {}
|
21
22
|
options[:erb] = true
|
22
23
|
options[:format] = "json"
|
23
|
-
|
24
|
+
options[:erb_argv] = []
|
24
25
|
|
25
26
|
# Command line options
|
26
27
|
opts = OptionParser.new do |p|
|
@@ -30,13 +31,14 @@ opts = OptionParser.new do |p|
|
|
30
31
|
|
31
32
|
# Help
|
32
33
|
p.on("-h", "--help", "Display this message") { puts opts ; exit }
|
34
|
+
p.on("--version", "Show version") { puts version ; exit }
|
33
35
|
p.separator(" ")
|
34
36
|
|
35
37
|
# Verbosity
|
36
38
|
p.on("-d", "--debug", "Show debug messages") { $logger.level = Logger::DEBUG }
|
37
39
|
p.on("-v", "--verbose", "Be verbose") { $logger.level = Logger::INFO }
|
38
40
|
p.on("-q", "--quiet", "Only show errors") { $logger.level = Logger::ERROR }
|
39
|
-
p.on("-s", "--
|
41
|
+
p.on("-s", "--silent", "Don't show any log messages") { $logger.level = Logger::FATAL }
|
40
42
|
p.separator(" ")
|
41
43
|
|
42
44
|
# Output
|
@@ -49,18 +51,35 @@ opts = OptionParser.new do |p|
|
|
49
51
|
# Operations
|
50
52
|
p.on("--erb", "--[no-]erb", "Perform ERB processing (default is true)") { |x| options[:erb] = x }
|
51
53
|
p.on("--validate", "Call ValidateTemplate after merging") { options[:validate] = true }
|
54
|
+
p.separator(" ")
|
55
|
+
|
56
|
+
# ERB options
|
57
|
+
p.on("---", "Marks end of mkstack options") { p.terminate("---") }
|
58
|
+
p.on("%s Remaining arguments are available to ERB as an Array argv" % [ desc_padding ])
|
52
59
|
end
|
53
60
|
|
54
|
-
files
|
55
|
-
opts.parse
|
61
|
+
# Separate files from ERB arguments
|
62
|
+
args = opts.parse!
|
56
63
|
|
57
|
-
|
64
|
+
if args.index("---")
|
65
|
+
files = args[0..(args.index("---") - 1)]
|
66
|
+
options[:erb_argv] = args[(args.index("---") + 1)..nil]
|
67
|
+
else
|
68
|
+
files = args
|
69
|
+
end
|
58
70
|
|
71
|
+
# At least one file is required
|
72
|
+
files.uniq!
|
73
|
+
opts.parse "--help" if ((files.count == 0) or (files[0].eql?("---")))
|
59
74
|
|
60
75
|
# Merge files
|
76
|
+
template = MkStack::Template.new(options[:format], options[:erb_argv])
|
77
|
+
|
61
78
|
files.each do |file|
|
62
79
|
begin
|
63
|
-
Dir.chdir(File.dirname(file)) {
|
80
|
+
Dir.chdir(File.dirname(file)) {
|
81
|
+
template.merge(File.basename(file), options[:erb])
|
82
|
+
}
|
64
83
|
rescue KeyError => e
|
65
84
|
$logger.warn { "#{file}: already parsed" }
|
66
85
|
rescue Exception => e
|
@@ -68,7 +87,6 @@ files.each do |file|
|
|
68
87
|
end
|
69
88
|
end
|
70
89
|
|
71
|
-
|
72
90
|
# Check limits
|
73
91
|
$logger.debug { "Checking limits" }
|
74
92
|
|
@@ -79,19 +97,17 @@ end
|
|
79
97
|
$logger.warn { "At least one Resources member must be defined" } if template["Resources"].length == 0
|
80
98
|
$logger.warn { "Template too large (#{template.length} > #{template.limit})" } if template.exceeds_limit?
|
81
99
|
|
82
|
-
|
83
100
|
# Validate template
|
84
101
|
if options[:validate] then
|
85
102
|
begin
|
86
103
|
$logger.info { "Validating #{template.format} template" }
|
87
104
|
|
88
|
-
|
105
|
+
template.validate
|
89
106
|
rescue Exception => e
|
90
107
|
$logger.error { e.message }
|
91
108
|
end
|
92
109
|
end
|
93
110
|
|
94
|
-
|
95
111
|
# Save template
|
96
112
|
if options[:save] then
|
97
113
|
begin
|
data/lib/mkstack.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
require_relative "mkstack/template"
|
2
3
|
|
3
4
|
=begin rdoc
|
@@ -5,9 +6,10 @@ require_relative "mkstack/template"
|
|
5
6
|
Merge multiple CloudFormation template files into a single template.
|
6
7
|
Each file may be in either JSON or YAML format.
|
7
8
|
|
8
|
-
Get started with <i>template = MkStack::Template.new</i
|
9
|
+
Get started with <i>template = MkStack::Template.new</i>, or use the
|
10
|
+
command line tool <i>mkstack</i>.
|
9
11
|
|
10
|
-
|
12
|
+
= ERB
|
11
13
|
|
12
14
|
By default all files are run through an ERB (Embedded RuBy) processor.
|
13
15
|
|
@@ -62,7 +64,9 @@ tags defined in one file to be referenced in subsequent files.
|
|
62
64
|
"sg": {
|
63
65
|
"Type" : "AWS::EC2::SecurityGroup",
|
64
66
|
"Properties" : {
|
65
|
-
"GroupDescription" : {
|
67
|
+
"GroupDescription" : {
|
68
|
+
"Fn::Sub" : "Security Group for ${application}"
|
69
|
+
}
|
66
70
|
<%= tags_json %>
|
67
71
|
}
|
68
72
|
}
|
@@ -71,10 +75,39 @@ tags defined in one file to be referenced in subsequent files.
|
|
71
75
|
|
72
76
|
Note that foo.yaml is processed <i>before</i> bar.json.
|
73
77
|
|
74
|
-
|
78
|
+
= Command line tool
|
79
|
+
|
80
|
+
Usage: mkstack [ options ] file1 [ file2... ]
|
81
|
+
-h, --help Display this message
|
82
|
+
|
83
|
+
-d, --debug Show debug messages
|
84
|
+
-v, --verbose Be verbose
|
85
|
+
-q, --quiet Only show errors
|
86
|
+
-s, --silent Don't show any log messages
|
87
|
+
|
88
|
+
-o, --output=FILE Print final template to FILE
|
89
|
+
Use '-' for stdout
|
90
|
+
-f, --format=FORMAT Print as FORMAT
|
91
|
+
Supported formats: json (default), yaml
|
92
|
+
|
93
|
+
‐‐erb, --[no-]erb Perform ERB processing (default is true)
|
94
|
+
‐‐validate Call ValidateTemplate after merging
|
95
|
+
|
96
|
+
‐‐‐ Marks end of mkstack options
|
97
|
+
Remaining arguments are available to ERB as Array argv
|
98
|
+
|
99
|
+
== Passing arguments to ERB
|
100
|
+
|
101
|
+
Any command line arguments following "---" are added to an Array
|
102
|
+
called <b>argv</b>, which can be referenced in your ERB code.
|
103
|
+
|
104
|
+
=== foo.yaml
|
105
|
+
|
106
|
+
<% puts "#{argv.class} with #{argv.length} items: #{argv}" %>
|
107
|
+
=====
|
108
|
+
$ mkstack foo.yaml --- a 2 test
|
109
|
+
Array with 3 items: ["a", "2", "test"]
|
75
110
|
|
76
|
-
MkStack::Template
|
77
|
-
MkStack::Section
|
78
111
|
=end
|
79
112
|
|
80
113
|
module MkStack
|
data/lib/mkstack/template.rb
CHANGED
@@ -5,25 +5,49 @@ require "json"
|
|
5
5
|
require "yaml"
|
6
6
|
|
7
7
|
module MkStack
|
8
|
+
##################################################
|
9
|
+
# A class to represent undefined local tags.
|
10
|
+
#
|
11
|
+
# CloudFormation uses <b>!</b> to denote the YAML short form of
|
12
|
+
# intrinsic functions, which is the same prefix YAML uses for local
|
13
|
+
# tags. The default handler strips undefined local tags, leaving
|
14
|
+
# just the value.
|
15
|
+
#
|
16
|
+
# Loading a YAML file will force the output to be in YAML format.
|
17
|
+
|
18
|
+
class IntrinsicShort
|
19
|
+
def init_with(coder)
|
20
|
+
@coder = coder
|
21
|
+
end
|
22
|
+
|
23
|
+
def encode_with(coder)
|
24
|
+
coder.tag = @coder.tag
|
25
|
+
|
26
|
+
coder.map = @coder.map if @coder.type == :map
|
27
|
+
coder.scalar = @coder.scalar if @coder.type == :scalar
|
28
|
+
coder.seq = @coder.seq if @coder.type == :seq
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
8
32
|
##################################################
|
9
33
|
# A CloudFormation template
|
10
34
|
class Template
|
11
35
|
attr_reader :sections, :limit, :format
|
12
36
|
|
13
|
-
def initialize(format = "json")
|
37
|
+
def initialize(format = "json", argv = nil)
|
14
38
|
@format = format
|
15
39
|
|
16
40
|
@sections = {
|
17
41
|
"AWSTemplateFormatVersion" => Section.new("AWSTemplateFormatVersion", String, nil),
|
18
42
|
"Description" => Section.new("Description", String, 1024),
|
19
43
|
|
20
|
-
"Conditions"
|
21
|
-
"Mappings"
|
22
|
-
"Metadata"
|
23
|
-
"Outputs"
|
24
|
-
"Parameters"
|
25
|
-
"Resources"
|
26
|
-
"
|
44
|
+
"Conditions" => Section.new("Conditions", Hash, nil),
|
45
|
+
"Mappings" => Section.new("Mappings", Hash, 200),
|
46
|
+
"Metadata" => Section.new("Metadata", Hash, nil),
|
47
|
+
"Outputs" => Section.new("Outputs", Hash, 200),
|
48
|
+
"Parameters" => Section.new("Parameters", Hash, 200),
|
49
|
+
"Resources" => Section.new("Resources", Hash, 500),
|
50
|
+
"Transform" => Section.new("Transform", Hash, nil),
|
27
51
|
}
|
28
52
|
@limit = 51200
|
29
53
|
|
@@ -34,10 +58,6 @@ module MkStack
|
|
34
58
|
# every time we load a file. This allows ERB code in one file to
|
35
59
|
# be referenced in another.
|
36
60
|
@binding = binding
|
37
|
-
|
38
|
-
# See add_domain_types
|
39
|
-
@yaml_domain = "mlfs.org,2019"
|
40
|
-
@global_tag = "tag:#{@yaml_domain}:"
|
41
61
|
end
|
42
62
|
|
43
63
|
# Shorthand accessor for template sections
|
@@ -60,8 +80,9 @@ module MkStack
|
|
60
80
|
cfn = JSON.load(contents)
|
61
81
|
rescue Exception => e
|
62
82
|
# Try YAML
|
63
|
-
|
64
|
-
cfn = YAML.
|
83
|
+
add_tags
|
84
|
+
cfn = YAML.safe_load(contents, [IntrinsicShort])
|
85
|
+
@format = "yaml"
|
65
86
|
end
|
66
87
|
|
67
88
|
# Merge sections that are present in the file
|
@@ -90,9 +111,7 @@ module MkStack
|
|
90
111
|
when "json"
|
91
112
|
to_hash.to_json
|
92
113
|
when "yaml"
|
93
|
-
|
94
|
-
# And keep Psych from splitting "long" lines
|
95
|
-
to_hash.to_yaml({ line_width: -1 }).gsub(/"(#{@global_tag}[^"]+?)"/, '\1').gsub("#{@global_tag}", "!")
|
114
|
+
to_hash.to_yaml({ line_width: -1 }) # Keep Psych from splitting "long" lines
|
96
115
|
else
|
97
116
|
to_hash
|
98
117
|
end
|
@@ -127,20 +146,9 @@ module MkStack
|
|
127
146
|
|
128
147
|
|
129
148
|
#########################
|
130
|
-
#
|
131
|
-
|
132
|
-
|
133
|
-
# CloudFormation uses <b>!</b> to denote the YAML short form of
|
134
|
-
# intrinsic functions, which is the same prefix YAML uses for
|
135
|
-
# local tags. The default handler strips undefined local tags,
|
136
|
-
# leaving just the value.
|
137
|
-
#
|
138
|
-
# This puts the tags back, but in global tag format. The global
|
139
|
-
# tag prefix is converted back to <b>!</b> on output.
|
140
|
-
#
|
141
|
-
# Using the short form will force the output to be in YAML format.
|
142
|
-
def add_domain_types
|
143
|
-
functions = [
|
149
|
+
# List of intrinsic functions that look like undefined local tags
|
150
|
+
def add_tags
|
151
|
+
[
|
144
152
|
"Base64",
|
145
153
|
"Cidr",
|
146
154
|
"FindInMap",
|
@@ -157,21 +165,9 @@ module MkStack
|
|
157
165
|
"If",
|
158
166
|
"Not",
|
159
167
|
"Or",
|
160
|
-
].each do |function|
|
161
|
-
YAML::add_domain_type(@yaml_domain, function) do |type, val|
|
162
|
-
@format = "yaml"
|
163
|
-
"#{type} #{val}"
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
# The syntax for !Sub requires double-quotes around Strings
|
168
|
-
functions = [
|
169
168
|
"Sub",
|
170
169
|
].each do |function|
|
171
|
-
YAML::
|
172
|
-
@format = "yaml"
|
173
|
-
val.is_a?(String)? "#{type} \"#{val}\"" : "#{type} #{val}"
|
174
|
-
end
|
170
|
+
YAML::add_tag("!#{function}", IntrinsicShort)
|
175
171
|
end
|
176
172
|
end
|
177
173
|
end
|
data/mkstack.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "mkstack"
|
3
|
-
s.version = "1.
|
3
|
+
s.version = "1.2.1"
|
4
4
|
s.summary = "Merge multiple CloudFormation template files into a single template"
|
5
5
|
s.description = <<-EOF
|
6
6
|
Merge multiple CloudFormation template files into a single template. Each file may be in either JSON or YAML format. By default all files are run through an ERB (Embedded RuBy) processor.
|
metadata
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mkstack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Rosen
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain:
|
11
11
|
- |
|
12
12
|
-----BEGIN CERTIFICATE-----
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MIID/jCCAmagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQDDBphanIv
|
14
|
+
REM9Y29ycC9EQz1tbGZzL0RDPW9yZzAeFw0yMDA2MjMyMjA0MDdaFw0yMTA2MjMy
|
15
|
+
MjA0MDdaMCUxIzAhBgNVBAMMGmFqci9EQz1jb3JwL0RDPW1sZnMvREM9b3JnMIIB
|
16
16
|
ojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAqQ2xCUJ4wY8WujSzYd3OGTbj
|
17
17
|
JDMeU44pXOTLc49Rs8ydukGfd0YBvYMzifmiVRj6depGx2+Ln28Y2mT6IB+zHq8X
|
18
18
|
s1lrMdFCReztJjQ7OYS16YcZ6pmLkYClnHN3VNqayk1lQEJGCr8aawMeroSB01om
|
@@ -21,20 +21,19 @@ cert_chain:
|
|
21
21
|
JbnFW7mFQGtBpfh8zY8OCQ76Aw8cb5bEIPTI+Hd4FoJLPKnexTI28endSLigOUCF
|
22
22
|
76kLOiVOVOjdqZ8vEdSgWVugEAzIC30xW5b8yD6N7GdT7n3ktgoZu7jZMUW3D6PQ
|
23
23
|
wS6BaABVsXbeVtFrzK2tQ65EwLfRluRLTfbnQ7qvMIYCwC3Ib9DTMLavCiOot1vc
|
24
|
-
RBWXIrDex0tt3EN0dDIxP9O+7ciDgM4zPe6BvaF/
|
25
|
-
MAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBRDowzw+
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
4cVT/heohjMDtNBaDMVsTjTxtNq6oi/pvyLqBGmQ
|
24
|
+
RBWXIrDex0tt3EN0dDIxP9O+7ciDgM4zPe6BvaF/AgMBAAGjOTA3MAkGA1UdEwQC
|
25
|
+
MAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBRDowzw+kmcX6FV7T9BkQsUgmzLZjAN
|
26
|
+
BgkqhkiG9w0BAQsFAAOCAYEAAmnuLwfJOuo9JlIMPCArwX0wIZcuKJ1Ms5S9RpTT
|
27
|
+
MYqNwa52//SCZ5VG0bZknXNgHGs1qm4kHekxOVjjjdawVHQFZvDJJxblSvj1OTe0
|
28
|
+
J4OF7hiWldeUE7ezeHDpzcVpGkHBGYCPkLBPyjMkRwlZpgth9DVO7FP3mV9SMHyP
|
29
|
+
x1/55FYk0A62NgXSzmLghePC+trYllv54YURP4/R8RYnZPZNf5MFMjF94BoWGFzQ
|
30
|
+
9BKJ+1DbdAVwCMSWEcGOkw5euwofwf6PpvLlmhB9pM+acsjLJkaS/OU7v5/X0F6+
|
31
|
+
MkYSejwDmyV9/u/cPgStxlOOu4x7Ur2qOzfb8OEKMmautB7ZEdCivdG/Qa634dDq
|
32
|
+
dnrb3iC4VliJf0o5SVrYjRxBYn9WQV1eJaygRunfhVo9AqRPg+rcbkQ/XIWUQDeY
|
33
|
+
kLyoFawGT9fF6+lXyIT9XiaUzOCjQUJo94on5U601Y2GXB4Sa1oxLSBlEtkSwuD3
|
34
|
+
gMHlHdBRvoJurkVzYNWkN+Cz
|
36
35
|
-----END CERTIFICATE-----
|
37
|
-
date:
|
36
|
+
date: 2020-10-23 00:00:00.000000000 Z
|
38
37
|
dependencies:
|
39
38
|
- !ruby/object:Gem::Dependency
|
40
39
|
name: aws-sdk-cloudformation
|
@@ -54,7 +53,7 @@ description: 'Merge multiple CloudFormation template files into a single templat
|
|
54
53
|
file may be in either JSON or YAML format. By default all files are run through
|
55
54
|
an ERB (Embedded RuBy) processor.
|
56
55
|
|
57
|
-
'
|
56
|
+
'
|
58
57
|
email:
|
59
58
|
- ajr@corp.mlfs.org
|
60
59
|
executables:
|
@@ -71,7 +70,7 @@ homepage: https://github.com/ajrosen/AWS/tree/master/mkstack
|
|
71
70
|
licenses:
|
72
71
|
- GPL-3.0+
|
73
72
|
metadata: {}
|
74
|
-
post_install_message:
|
73
|
+
post_install_message:
|
75
74
|
rdoc_options: []
|
76
75
|
require_paths:
|
77
76
|
- lib
|
@@ -86,9 +85,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
85
|
- !ruby/object:Gem::Version
|
87
86
|
version: '0'
|
88
87
|
requirements: []
|
89
|
-
|
90
|
-
|
91
|
-
signing_key:
|
88
|
+
rubygems_version: 3.1.4
|
89
|
+
signing_key:
|
92
90
|
specification_version: 4
|
93
91
|
summary: Merge multiple CloudFormation template files into a single template
|
94
92
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|