humidifier 4.1.1 → 4.2.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 +4 -4
- data/.github/workflows/main.yml +1 -1
- data/.rubocop.yml +15 -1
- data/CHANGELOG.md +12 -1
- data/CloudFormationResourceSpecification.json +104326 -35227
- data/Gemfile +1 -1
- data/Gemfile.lock +31 -31
- data/README.md +5 -0
- data/Rakefile +11 -11
- data/exe/humidifier +5 -5
- data/humidifier.gemspec +29 -29
- data/lib/humidifier/cli.rb +30 -22
- data/lib/humidifier/config/mapper.rb +1 -1
- data/lib/humidifier/config/mapping.rb +2 -2
- data/lib/humidifier/config.rb +1 -1
- data/lib/humidifier/directory.rb +5 -5
- data/lib/humidifier/loader.rb +104 -48
- data/lib/humidifier/output.rb +3 -3
- data/lib/humidifier/parameter.rb +2 -2
- data/lib/humidifier/props.rb +73 -51
- data/lib/humidifier/ref.rb +1 -1
- data/lib/humidifier/resource.rb +3 -3
- data/lib/humidifier/serializer.rb +2 -2
- data/lib/humidifier/stack.rb +6 -6
- data/lib/humidifier/upgrade.rb +10 -10
- data/lib/humidifier/version.rb +1 -1
- data/lib/humidifier.rb +31 -31
- metadata +6 -6
data/lib/humidifier/loader.rb
CHANGED
@@ -4,39 +4,58 @@ module Humidifier
|
|
4
4
|
# Reads the specs/CloudFormationResourceSpecification.json file and load each
|
5
5
|
# resource as a class
|
6
6
|
module Loader
|
7
|
-
|
8
|
-
|
9
|
-
class PropertyTypes
|
10
|
-
attr_reader :structs
|
7
|
+
class Compiler
|
8
|
+
attr_reader :specification, :property_types
|
11
9
|
|
12
|
-
def initialize(
|
13
|
-
@
|
14
|
-
end
|
10
|
+
def initialize(specification)
|
11
|
+
@specification = specification
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
# Set an initial value for each property types so that we can handle
|
14
|
+
# cycles in the specification
|
15
|
+
@property_types = specification["PropertyTypes"].to_h do |name, _|
|
16
|
+
[name, {}]
|
17
|
+
end
|
21
18
|
end
|
22
19
|
|
23
|
-
|
20
|
+
def compile
|
21
|
+
# Loop through every property type that's already defined and build up
|
22
|
+
# each of the properties into the list
|
23
|
+
property_types.each do |property_type_name, property_type|
|
24
|
+
prefix = property_type_name.split(".", 2).first
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
subspec = specification["PropertyTypes"].fetch(property_type_name)
|
27
|
+
subspec.fetch("Properties") { {} }.each do |property_name, property|
|
28
|
+
property = build_property(prefix, property_name, property)
|
29
|
+
property_type[property.name] = property if property
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Loop through every resource type in the specification and define a
|
34
|
+
# class for each one dynamically.
|
35
|
+
specification["ResourceTypes"].each do |aws_name, resource_type|
|
36
|
+
_top, group, resource = aws_name.split("::")
|
37
|
+
|
38
|
+
properties = {}
|
39
|
+
resource_type["Properties"].each do |property_name, property|
|
40
|
+
property = build_property(aws_name, property_name, property)
|
41
|
+
properties[property.name] = property if property
|
42
|
+
end
|
29
43
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
44
|
+
resource_class =
|
45
|
+
Class.new(Resource) do
|
46
|
+
self.aws_name = aws_name
|
47
|
+
self.props = properties
|
48
|
+
end
|
35
49
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
50
|
+
group_module =
|
51
|
+
if Humidifier.const_defined?(group)
|
52
|
+
Humidifier.const_get(group)
|
53
|
+
else
|
54
|
+
Humidifier.const_set(group, Module.new)
|
55
|
+
end
|
56
|
+
|
57
|
+
Humidifier.registry[aws_name] =
|
58
|
+
group_module.const_set(resource, resource_class)
|
40
59
|
end
|
41
60
|
|
42
61
|
Humidifier.registry.freeze
|
@@ -44,35 +63,72 @@ module Humidifier
|
|
44
63
|
|
45
64
|
private
|
46
65
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
66
|
+
def build_primitive(type, name, spec)
|
67
|
+
case type
|
68
|
+
in "Boolean"
|
69
|
+
Props::BooleanProp.new(name, spec)
|
70
|
+
in "Double"
|
71
|
+
Props::DoubleProp.new(name, spec)
|
72
|
+
in "Integer" | "Long"
|
73
|
+
Props::IntegerProp.new(name, spec)
|
74
|
+
in "Json"
|
75
|
+
Props::JsonProp.new(name, spec)
|
76
|
+
in "String"
|
77
|
+
Props::StringProp.new(name, spec)
|
78
|
+
in "Timestamp"
|
79
|
+
Props::TimestampProp.new(name, spec)
|
55
80
|
end
|
56
81
|
end
|
57
82
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
83
|
+
def build_property(prefix, name, spec)
|
84
|
+
case spec.transform_keys(&:to_sym)
|
85
|
+
in { PrimitiveType: type }
|
86
|
+
build_primitive(type, name, spec)
|
87
|
+
in { Type: "List", PrimitiveItemType: type }
|
88
|
+
Props::ListProp.new(name, spec, build_primitive(type, name, spec))
|
89
|
+
in { Type: "Map", PrimitiveItemType: type }
|
90
|
+
Props::MapProp.new(name, spec, build_primitive(type, name, spec))
|
91
|
+
in { Type: "List", ItemType: "List" }
|
92
|
+
# specifically calling this out since
|
93
|
+
# AWS::Rekognition::StreamProcessor.PolygonRegionsOfInterest has a
|
94
|
+
# nested list structure that otherwise breaks the compiler
|
95
|
+
Props::ListProp.new(name, spec, Props::ListProp.new(name, spec))
|
96
|
+
in { Type: "List", ItemType: item_type }
|
97
|
+
Props::ListProp.new(
|
98
|
+
name,
|
99
|
+
spec,
|
100
|
+
Props::StructureProp.new(name, spec,
|
101
|
+
property_type(prefix, item_type))
|
102
|
+
)
|
103
|
+
in { Type: "Map", ItemType: item_type }
|
104
|
+
Props::MapProp.new(
|
105
|
+
name,
|
106
|
+
spec,
|
107
|
+
Props::StructureProp.new(name, spec,
|
108
|
+
property_type(prefix, item_type))
|
109
|
+
)
|
110
|
+
in { Type: type }
|
111
|
+
Props::StructureProp.new(name, spec, property_type(prefix, type))
|
112
|
+
else # rubocop:disable Layout/IndentationWidth
|
113
|
+
# It's possible to hit this clause if the specification has a property
|
114
|
+
# that is not currently supported by CloudFormation. In this case,
|
115
|
+
# we're not going to create a property at all for it.
|
116
|
+
end
|
63
117
|
end
|
64
118
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
unless Humidifier.const_defined?(group)
|
70
|
-
Humidifier.const_set(group, Module.new)
|
119
|
+
def property_type(prefix, type)
|
120
|
+
property_types.fetch("#{prefix}.#{type}") do
|
121
|
+
property_types.fetch(type)
|
71
122
|
end
|
72
|
-
|
73
|
-
Humidifier.const_get(group).const_set(resource, resource_class)
|
74
|
-
Humidifier.registry[aws_name] = resource_class
|
75
123
|
end
|
76
124
|
end
|
125
|
+
|
126
|
+
# loop through the specs and register each class
|
127
|
+
def self.load
|
128
|
+
filepath = File.expand_path("../../#{SPECIFICATION}", __dir__)
|
129
|
+
return unless File.file?(filepath)
|
130
|
+
|
131
|
+
Compiler.new(JSON.parse(File.read(filepath))).compile
|
132
|
+
end
|
77
133
|
end
|
78
134
|
end
|
data/lib/humidifier/output.rb
CHANGED
@@ -11,9 +11,9 @@ module Humidifier
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def to_cf
|
14
|
-
{
|
15
|
-
cf[
|
16
|
-
cf[
|
14
|
+
{ "Value" => Serializer.dump(value) }.tap do |cf|
|
15
|
+
cf["Description"] = description if description
|
16
|
+
cf["Export"] = { "Name" => export_name } if export_name
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
data/lib/humidifier/parameter.rb
CHANGED
@@ -15,12 +15,12 @@ module Humidifier
|
|
15
15
|
instance_variable_set(:"@#{property}", opts[property])
|
16
16
|
end
|
17
17
|
|
18
|
-
@type = opts.fetch(:type,
|
18
|
+
@type = opts.fetch(:type, "String")
|
19
19
|
end
|
20
20
|
|
21
21
|
# CFN stack syntax
|
22
22
|
def to_cf
|
23
|
-
{
|
23
|
+
{ "Type" => type }.tap do |cf|
|
24
24
|
PROPERTIES.each do |name, prop|
|
25
25
|
value = public_send(prop)
|
26
26
|
cf[name] = Serializer.dump(value) if value
|
data/lib/humidifier/props.rb
CHANGED
@@ -18,12 +18,12 @@ module Humidifier
|
|
18
18
|
|
19
19
|
# the link to the AWS docs
|
20
20
|
def documentation
|
21
|
-
spec[
|
21
|
+
spec["Documentation"]
|
22
22
|
end
|
23
23
|
|
24
24
|
# true if this property is required by the resource
|
25
25
|
def required?
|
26
|
-
spec[
|
26
|
+
spec["Required"]
|
27
27
|
end
|
28
28
|
|
29
29
|
# CFN stack syntax
|
@@ -34,7 +34,7 @@ module Humidifier
|
|
34
34
|
# the type of update that occurs when this property is updated on its
|
35
35
|
# associated resource
|
36
36
|
def update_type
|
37
|
-
spec[
|
37
|
+
spec["UpdateType"]
|
38
38
|
end
|
39
39
|
|
40
40
|
def valid?(value)
|
@@ -55,34 +55,70 @@ module Humidifier
|
|
55
55
|
|
56
56
|
class BooleanProp < Prop
|
57
57
|
allow_type TrueClass, FalseClass
|
58
|
+
|
59
|
+
def pretty_print(q)
|
60
|
+
q.text("(#{name}=boolean)")
|
61
|
+
end
|
58
62
|
end
|
59
63
|
|
60
64
|
class DoubleProp < Prop
|
61
65
|
allow_type Integer, Float
|
66
|
+
|
67
|
+
def pretty_print(q)
|
68
|
+
q.text("(#{name}=double)")
|
69
|
+
end
|
62
70
|
end
|
63
71
|
|
64
72
|
class IntegerProp < Prop
|
65
73
|
allow_type Integer
|
74
|
+
|
75
|
+
def pretty_print(q)
|
76
|
+
q.text("(#{name}=integer)")
|
77
|
+
end
|
66
78
|
end
|
67
79
|
|
68
80
|
class JsonProp < Prop
|
69
81
|
allow_type Hash
|
82
|
+
|
83
|
+
def pretty_print(q)
|
84
|
+
q.text("(#{name}=json)")
|
85
|
+
end
|
70
86
|
end
|
71
87
|
|
72
88
|
class StringProp < Prop
|
73
89
|
allow_type String
|
90
|
+
|
91
|
+
def pretty_print(q)
|
92
|
+
q.text("(#{name}=string)")
|
93
|
+
end
|
74
94
|
end
|
75
95
|
|
76
96
|
class TimestampProp < Prop
|
77
97
|
allow_type Time, Date
|
98
|
+
|
99
|
+
def pretty_print(q)
|
100
|
+
q.text("(#{name}=timestamp)")
|
101
|
+
end
|
78
102
|
end
|
79
103
|
|
80
104
|
class ListProp < Prop
|
81
105
|
attr_reader :subprop
|
82
106
|
|
83
|
-
def initialize(key, spec = {},
|
107
|
+
def initialize(key, spec = {}, subprop = nil)
|
84
108
|
super(key, spec)
|
85
|
-
@subprop =
|
109
|
+
@subprop = subprop
|
110
|
+
end
|
111
|
+
|
112
|
+
def pretty_print(q)
|
113
|
+
q.group do
|
114
|
+
q.text("(#{name}=list")
|
115
|
+
q.nest(2) do
|
116
|
+
q.breakable
|
117
|
+
q.pp(subprop)
|
118
|
+
end
|
119
|
+
q.breakable("")
|
120
|
+
q.text(")")
|
121
|
+
end
|
86
122
|
end
|
87
123
|
|
88
124
|
def to_cf(list)
|
@@ -106,9 +142,21 @@ module Humidifier
|
|
106
142
|
class MapProp < Prop
|
107
143
|
attr_reader :subprop
|
108
144
|
|
109
|
-
def initialize(key, spec = {},
|
145
|
+
def initialize(key, spec = {}, subprop = nil)
|
110
146
|
super(key, spec)
|
111
|
-
@subprop =
|
147
|
+
@subprop = subprop
|
148
|
+
end
|
149
|
+
|
150
|
+
def pretty_print(q)
|
151
|
+
q.group do
|
152
|
+
q.text("(#{name}=map")
|
153
|
+
q.nest(2) do
|
154
|
+
q.breakable
|
155
|
+
q.pp(subprop)
|
156
|
+
end
|
157
|
+
q.breakable("")
|
158
|
+
q.text(")")
|
159
|
+
end
|
112
160
|
end
|
113
161
|
|
114
162
|
def to_cf(map)
|
@@ -116,9 +164,9 @@ module Humidifier
|
|
116
164
|
if map.respond_to?(:to_cf)
|
117
165
|
map.to_cf
|
118
166
|
else
|
119
|
-
map.
|
167
|
+
map.to_h do |subkey, subvalue|
|
120
168
|
[subkey, subprop.to_cf(subvalue).last]
|
121
|
-
end
|
169
|
+
end
|
122
170
|
end
|
123
171
|
|
124
172
|
[key, cf_value]
|
@@ -134,9 +182,21 @@ module Humidifier
|
|
134
182
|
class StructureProp < Prop
|
135
183
|
attr_reader :subprops
|
136
184
|
|
137
|
-
def initialize(key, spec = {},
|
185
|
+
def initialize(key, spec = {}, subprops = {})
|
138
186
|
super(key, spec)
|
139
|
-
@subprops =
|
187
|
+
@subprops = subprops
|
188
|
+
end
|
189
|
+
|
190
|
+
def pretty_print(q)
|
191
|
+
q.group do
|
192
|
+
q.text("(#{name}=structure")
|
193
|
+
q.nest(2) do
|
194
|
+
q.breakable
|
195
|
+
q.seplist(subprops.values) { |subprop| q.pp(subprop) }
|
196
|
+
end
|
197
|
+
q.breakable("")
|
198
|
+
q.text(")")
|
199
|
+
end
|
140
200
|
end
|
141
201
|
|
142
202
|
def to_cf(struct)
|
@@ -144,9 +204,9 @@ module Humidifier
|
|
144
204
|
if struct.respond_to?(:to_cf)
|
145
205
|
struct.to_cf
|
146
206
|
else
|
147
|
-
struct.
|
207
|
+
struct.to_h do |subkey, subvalue|
|
148
208
|
subprops[subkey.to_s].to_cf(subvalue)
|
149
|
-
end
|
209
|
+
end
|
150
210
|
end
|
151
211
|
|
152
212
|
[key, cf_value]
|
@@ -158,49 +218,11 @@ module Humidifier
|
|
158
218
|
|
159
219
|
private
|
160
220
|
|
161
|
-
def subprops_from(substructs, type)
|
162
|
-
subprop_names = substructs.fetch(type, {}).fetch('Properties', {})
|
163
|
-
|
164
|
-
subprop_names.each_with_object({}) do |(key, config), subprops|
|
165
|
-
subprops[key.underscore] =
|
166
|
-
if config['ItemType'] == type
|
167
|
-
self
|
168
|
-
else
|
169
|
-
Props.from(key, config, substructs)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
221
|
def valid_struct?(struct)
|
175
222
|
struct.all? do |key, value|
|
176
223
|
subprops.key?(key.to_s) && subprops[key.to_s].valid?(value)
|
177
224
|
end
|
178
225
|
end
|
179
226
|
end
|
180
|
-
|
181
|
-
class << self
|
182
|
-
# builds the appropriate prop object from the given spec line
|
183
|
-
def from(key, spec, substructs = {})
|
184
|
-
case spec['Type']
|
185
|
-
when 'List' then ListProp.new(key, spec, substructs)
|
186
|
-
when 'Map' then MapProp.new(key, spec, substructs)
|
187
|
-
else singular_from(key, spec, substructs)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
# builds a prop that is not a List or Map type
|
192
|
-
# PrimitiveType is one of Boolean, Double, Integer, Json, String, or
|
193
|
-
# Timestamp
|
194
|
-
def singular_from(key, spec, substructs)
|
195
|
-
primitive = spec['PrimitiveItemType'] || spec['PrimitiveType']
|
196
|
-
|
197
|
-
if primitive && !%w[List Map].include?(primitive)
|
198
|
-
primitive = 'Integer' if primitive == 'Long'
|
199
|
-
const_get(:"#{primitive}Prop").new(key, spec)
|
200
|
-
else
|
201
|
-
StructureProp.new(key, spec, substructs)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
227
|
end
|
206
228
|
end
|
data/lib/humidifier/ref.rb
CHANGED
data/lib/humidifier/resource.rb
CHANGED
@@ -45,8 +45,8 @@ module Humidifier
|
|
45
45
|
end
|
46
46
|
|
47
47
|
common_attributes.merge!(
|
48
|
-
|
49
|
-
|
48
|
+
"Type" => self.class.aws_name,
|
49
|
+
"Properties" => props_cf.to_h
|
50
50
|
)
|
51
51
|
end
|
52
52
|
|
@@ -114,7 +114,7 @@ module Humidifier
|
|
114
114
|
|
115
115
|
def validate_property(property)
|
116
116
|
unless self.class.prop?(property)
|
117
|
-
raise ArgumentError,
|
117
|
+
raise ArgumentError, "Attempting to set invalid property for " \
|
118
118
|
"#{self.class.name}: #{property}"
|
119
119
|
end
|
120
120
|
|
@@ -5,9 +5,9 @@ module Humidifier
|
|
5
5
|
class Serializer
|
6
6
|
class << self
|
7
7
|
# dumps the given object out to CFN syntax recursively
|
8
|
-
def dump(node)
|
8
|
+
def dump(node)
|
9
9
|
case node
|
10
|
-
when Hash then node.
|
10
|
+
when Hash then node.to_h { |key, value| [key, dump(value)] }
|
11
11
|
when Array then node.map { |value| dump(value) }
|
12
12
|
when Ref, Fn then dump(node.to_cf)
|
13
13
|
when Date then node.iso8601
|
data/lib/humidifier/stack.rb
CHANGED
@@ -14,8 +14,8 @@ module Humidifier
|
|
14
14
|
super(
|
15
15
|
"Cannot use a template > #{MAX_TEMPLATE_URL_SIZE} bytes " \
|
16
16
|
"(currently #{bytesize} bytes), consider using nested stacks " \
|
17
|
-
|
18
|
-
|
17
|
+
"(http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide" \
|
18
|
+
"/aws-properties-stack.html)"
|
19
19
|
)
|
20
20
|
end
|
21
21
|
end
|
@@ -37,7 +37,7 @@ module Humidifier
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# The AWS region, can be set through the environment, defaults to us-east-1
|
40
|
-
AWS_REGION = ENV
|
40
|
+
AWS_REGION = ENV.fetch("AWS_REGION", "us-east-1")
|
41
41
|
|
42
42
|
# Lists of objects linked to the stack
|
43
43
|
ENUMERABLE_RESOURCES =
|
@@ -184,7 +184,7 @@ module Humidifier
|
|
184
184
|
perform_and_wait(:update, opts)
|
185
185
|
end
|
186
186
|
|
187
|
-
def upload
|
187
|
+
def upload
|
188
188
|
raise NoResourcesError.new(self, :upload) unless resources.any?
|
189
189
|
|
190
190
|
bucket = Humidifier.config.s3_bucket
|
@@ -231,9 +231,9 @@ module Humidifier
|
|
231
231
|
next if resources.empty?
|
232
232
|
|
233
233
|
list[name] =
|
234
|
-
resources.
|
234
|
+
resources.to_h do |resource_name, resource|
|
235
235
|
[resource_name, resource.to_cf]
|
236
|
-
end
|
236
|
+
end
|
237
237
|
end
|
238
238
|
end
|
239
239
|
|
data/lib/humidifier/upgrade.rb
CHANGED
@@ -2,19 +2,19 @@
|
|
2
2
|
|
3
3
|
module Humidifier
|
4
4
|
class Upgrade
|
5
|
-
PATH = -File.expand_path(File.join(
|
6
|
-
URL =
|
7
|
-
|
5
|
+
PATH = -File.expand_path(File.join("..", "..", SPECIFICATION), __dir__)
|
6
|
+
URL = "https://docs.aws.amazon.com/AWSCloudFormation/latest" \
|
7
|
+
"/UserGuide/cfn-resource-specification.html"
|
8
8
|
|
9
9
|
def perform
|
10
|
-
require
|
11
|
-
require
|
10
|
+
require "net/http"
|
11
|
+
require "nokogiri"
|
12
12
|
|
13
13
|
response = Net::HTTP.get_response(uri).body
|
14
14
|
parsed = JSON.parse(response)
|
15
15
|
|
16
16
|
File.write(PATH, JSON.pretty_generate(parsed))
|
17
|
-
parsed[
|
17
|
+
parsed["ResourceSpecificationVersion"]
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.perform
|
@@ -28,11 +28,11 @@ module Humidifier
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def uri
|
31
|
-
Nokogiri::HTML(page).css(
|
32
|
-
name = tr.at_css(
|
33
|
-
next if !name || name.text.strip !=
|
31
|
+
Nokogiri::HTML(page).css("table tr").detect do |tr|
|
32
|
+
name = tr.at_css("td:first-child p")
|
33
|
+
next if !name || name.text.strip != "US East (N. Virginia)"
|
34
34
|
|
35
|
-
break URI.parse(tr.at_css(
|
35
|
+
break URI.parse(tr.at_css("td:nth-child(3) p a").attr("href"))
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
data/lib/humidifier/version.rb
CHANGED
data/lib/humidifier.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
3
|
+
require "date"
|
4
|
+
require "json"
|
5
|
+
require "pathname"
|
6
|
+
require "yaml"
|
7
7
|
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
8
|
+
require "aws-sdk-cloudformation"
|
9
|
+
require "aws-sdk-s3"
|
10
|
+
require "fast_underscore"
|
11
|
+
require "thor"
|
12
|
+
require "thor/hollaback"
|
13
13
|
|
14
14
|
# Hook into the string extension and ensure it works for certain AWS acronyms
|
15
15
|
String.prepend(
|
@@ -23,7 +23,7 @@ String.prepend(
|
|
23
23
|
# container module for all gem classes
|
24
24
|
module Humidifier
|
25
25
|
# The file name of the specification for consistency.
|
26
|
-
SPECIFICATION =
|
26
|
+
SPECIFICATION = "CloudFormationResourceSpecification.json"
|
27
27
|
|
28
28
|
# A parent class for all Humidifier errors for easier rescuing.
|
29
29
|
class Error < StandardError; end
|
@@ -61,30 +61,30 @@ module Humidifier
|
|
61
61
|
|
62
62
|
# a frozen hash of the given names mapped to their underscored version
|
63
63
|
def underscore(names)
|
64
|
-
names.
|
64
|
+
names.to_h { |name| [name, name.underscore.to_sym] }.freeze
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
require
|
70
|
-
require
|
71
|
-
require
|
72
|
-
|
73
|
-
require
|
74
|
-
require
|
75
|
-
require
|
76
|
-
require
|
77
|
-
require
|
78
|
-
require
|
79
|
-
require
|
80
|
-
require
|
81
|
-
require
|
82
|
-
require
|
83
|
-
require
|
84
|
-
require
|
85
|
-
|
86
|
-
require
|
87
|
-
require
|
88
|
-
require
|
69
|
+
require "humidifier/fn"
|
70
|
+
require "humidifier/ref"
|
71
|
+
require "humidifier/props"
|
72
|
+
|
73
|
+
require "humidifier/cli"
|
74
|
+
require "humidifier/condition"
|
75
|
+
require "humidifier/directory"
|
76
|
+
require "humidifier/loader"
|
77
|
+
require "humidifier/mapping"
|
78
|
+
require "humidifier/output"
|
79
|
+
require "humidifier/parameter"
|
80
|
+
require "humidifier/resource"
|
81
|
+
require "humidifier/serializer"
|
82
|
+
require "humidifier/stack"
|
83
|
+
require "humidifier/upgrade"
|
84
|
+
require "humidifier/version"
|
85
|
+
|
86
|
+
require "humidifier/config"
|
87
|
+
require "humidifier/config/mapper"
|
88
|
+
require "humidifier/config/mapping"
|
89
89
|
|
90
90
|
Humidifier::Loader.load
|