humidifier 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +88 -0
  4. data/ext/humidifier/extconf.rb +2 -0
  5. data/ext/humidifier/humidifier.c +93 -0
  6. data/ext/humidifier/humidifier.h +14 -0
  7. data/lib/humidifier/aws_adapters/base.rb +64 -0
  8. data/lib/humidifier/aws_adapters/noop.rb +18 -0
  9. data/lib/humidifier/aws_adapters/sdkv1.rb +56 -0
  10. data/lib/humidifier/aws_adapters/sdkv2.rb +43 -0
  11. data/lib/humidifier/aws_shim.rb +60 -0
  12. data/lib/humidifier/condition.rb +17 -0
  13. data/lib/humidifier/fn.rb +28 -0
  14. data/lib/humidifier/humidifier.bundle +0 -0
  15. data/lib/humidifier/loader.rb +53 -0
  16. data/lib/humidifier/mapping.rb +17 -0
  17. data/lib/humidifier/output.rb +20 -0
  18. data/lib/humidifier/parameter.rb +27 -0
  19. data/lib/humidifier/props.rb +127 -0
  20. data/lib/humidifier/ref.rb +17 -0
  21. data/lib/humidifier/resource.rb +108 -0
  22. data/lib/humidifier/sdk_payload.rb +30 -0
  23. data/lib/humidifier/serializer.rb +18 -0
  24. data/lib/humidifier/sleeper.rb +25 -0
  25. data/lib/humidifier/stack.rb +66 -0
  26. data/lib/humidifier/utils.rb +21 -0
  27. data/lib/humidifier/version.rb +4 -0
  28. data/lib/humidifier.rb +50 -0
  29. data/specs/ApiGateway-Account.cf +6 -0
  30. data/specs/ApiGateway-ApiKey.cf +9 -0
  31. data/specs/ApiGateway-Authorizer.cf +13 -0
  32. data/specs/ApiGateway-BasePathMapping.cf +9 -0
  33. data/specs/ApiGateway-ClientCertificate.cf +6 -0
  34. data/specs/ApiGateway-Deployment.cf +9 -0
  35. data/specs/ApiGateway-Method.cf +15 -0
  36. data/specs/ApiGateway-Model.cf +10 -0
  37. data/specs/ApiGateway-Resource.cf +8 -0
  38. data/specs/ApiGateway-RestApi.cf +12 -0
  39. data/specs/ApiGateway-Stage.cf +14 -0
  40. data/specs/AutoScaling-AutoScalingGroup.cf +21 -0
  41. data/specs/AutoScaling-LaunchConfiguration.cf +22 -0
  42. data/specs/AutoScaling-LifecycleHook.cf +12 -0
  43. data/specs/AutoScaling-ScalingPolicy.cf +14 -0
  44. data/specs/AutoScaling-ScheduledAction.cf +12 -0
  45. data/specs/CloudFormation-Authentication.cf +18 -0
  46. data/specs/CloudFormation-CustomResource.cf +8 -0
  47. data/specs/CloudFormation-Interface.cf +9 -0
  48. data/specs/CloudFormation-Stack.cf +10 -0
  49. data/specs/CloudFormation-WaitCondition.cf +8 -0
  50. data/specs/CloudFormation-WaitConditionHandle.cf +5 -0
  51. data/specs/CloudFront-Distribution.cf +6 -0
  52. data/specs/CloudTrail-Trail.cf +16 -0
  53. data/specs/CloudWatch-Alarm.cf +20 -0
  54. data/specs/CodeDeploy-Application.cf +6 -0
  55. data/specs/CodeDeploy-DeploymentConfig.cf +7 -0
  56. data/specs/CodeDeploy-DeploymentGroup.cf +13 -0
  57. data/specs/CodePipeline-CustomActionType.cf +12 -0
  58. data/specs/CodePipeline-Pipeline.cf +11 -0
  59. data/specs/Config-ConfigRule.cf +11 -0
  60. data/specs/Config-ConfigurationRecorder.cf +8 -0
  61. data/specs/Config-DeliveryChannel.cf +10 -0
  62. data/specs/DataPipeline-Pipeline.cf +12 -0
  63. data/specs/DirectoryService-MicrosoftAD.cf +11 -0
  64. data/specs/DirectoryService-SimpleAD.cf +13 -0
  65. data/specs/DynamoDB-Table.cf +12 -0
  66. data/specs/EC2-CustomerGateway.cf +9 -0
  67. data/specs/EC2-DHCPOptions.cf +11 -0
  68. data/specs/EC2-EIP.cf +7 -0
  69. data/specs/EC2-EIPAssociation.cf +10 -0
  70. data/specs/EC2-FlowLog.cf +10 -0
  71. data/specs/EC2-Host.cf +8 -0
  72. data/specs/EC2-Instance.cf +32 -0
  73. data/specs/EC2-InternetGateway.cf +6 -0
  74. data/specs/EC2-NatGateway.cf +7 -0
  75. data/specs/EC2-NetworkAcl.cf +7 -0
  76. data/specs/EC2-NetworkAclEntry.cf +13 -0
  77. data/specs/EC2-NetworkInterface.cf +13 -0
  78. data/specs/EC2-NetworkInterfaceAttachment.cf +9 -0
  79. data/specs/EC2-PlacementGroup.cf +6 -0
  80. data/specs/EC2-Route.cf +12 -0
  81. data/specs/EC2-RouteTable.cf +7 -0
  82. data/specs/EC2-SecurityGroup.cf +10 -0
  83. data/specs/EC2-SecurityGroupEgress.cf +11 -0
  84. data/specs/EC2-SecurityGroupIngress.cf +14 -0
  85. data/specs/EC2-SpotFleet.cf +6 -0
  86. data/specs/EC2-Subnet.cf +10 -0
  87. data/specs/EC2-SubnetNetworkAclAssociation.cf +5 -0
  88. data/specs/EC2-SubnetRouteTableAssociation.cf +7 -0
  89. data/specs/EC2-VPC.cf +10 -0
  90. data/specs/EC2-VPCDHCPOptionsAssociation.cf +7 -0
  91. data/specs/EC2-VPCEndpoint.cf +9 -0
  92. data/specs/EC2-VPCGatewayAttachment.cf +8 -0
  93. data/specs/EC2-VPCPeeringConnection.cf +8 -0
  94. data/specs/EC2-VPNConnection.cf +10 -0
  95. data/specs/EC2-VPNConnectionRoute.cf +7 -0
  96. data/specs/EC2-VPNGateway.cf +7 -0
  97. data/specs/EC2-VPNGatewayRoutePropagation.cf +7 -0
  98. data/specs/EC2-Volume.cf +14 -0
  99. data/specs/EC2-VolumeAttachment.cf +8 -0
  100. data/specs/ECR-Repository.cf +7 -0
  101. data/specs/ECS-Cluster.cf +6 -0
  102. data/specs/ECS-Service.cf +11 -0
  103. data/specs/ECS-TaskDefinition.cf +7 -0
  104. data/specs/EFS-FileSystem.cf +6 -0
  105. data/specs/EFS-MountTarget.cf +9 -0
  106. data/specs/EMR-Cluster.cf +17 -0
  107. data/specs/EMR-InstanceGroupConfig.cf +14 -0
  108. data/specs/EMR-Step.cf +9 -0
  109. data/specs/ElastiCache-CacheCluster.cf +27 -0
  110. data/specs/ElastiCache-ParameterGroup.cf +8 -0
  111. data/specs/ElastiCache-ReplicationGroup.cf +23 -0
  112. data/specs/ElastiCache-SecurityGroup.cf +7 -0
  113. data/specs/ElastiCache-SecurityGroupIngress.cf +9 -0
  114. data/specs/ElastiCache-SubnetGroup.cf +7 -0
  115. data/specs/ElasticBeanstalk-Application.cf +7 -0
  116. data/specs/ElasticBeanstalk-ApplicationVersion.cf +8 -0
  117. data/specs/ElasticBeanstalk-ConfigurationTemplate.cf +11 -0
  118. data/specs/ElasticBeanstalk-Environment.cf +15 -0
  119. data/specs/ElasticLoadBalancing-LoadBalancer.cf +21 -0
  120. data/specs/Elasticsearch-Domain.cf +12 -0
  121. data/specs/Events-Rule.cf +12 -0
  122. data/specs/GameLift-Alias.cf +8 -0
  123. data/specs/GameLift-Build.cf +8 -0
  124. data/specs/GameLift-Fleet.cf +16 -0
  125. data/specs/IAM-AccessKey.cf +8 -0
  126. data/specs/IAM-Group.cf +8 -0
  127. data/specs/IAM-InstanceProfile.cf +7 -0
  128. data/specs/IAM-ManagedPolicy.cf +11 -0
  129. data/specs/IAM-Policy.cf +10 -0
  130. data/specs/IAM-Role.cf +9 -0
  131. data/specs/IAM-User.cf +10 -0
  132. data/specs/IAM-UserToGroupAddition.cf +7 -0
  133. data/specs/KMS-Key.cf +9 -0
  134. data/specs/Kinesis-Stream.cf +8 -0
  135. data/specs/KinesisFirehose-DeliveryStream.cf +9 -0
  136. data/specs/Lambda-Alias.cf +9 -0
  137. data/specs/Lambda-EventSourceMapping.cf +10 -0
  138. data/specs/Lambda-Function.cf +14 -0
  139. data/specs/Lambda-Permission.cf +10 -0
  140. data/specs/Lambda-Version.cf +8 -0
  141. data/specs/Logs-Destination.cf +9 -0
  142. data/specs/Logs-LogGroup.cf +6 -0
  143. data/specs/Logs-LogStream.cf +7 -0
  144. data/specs/Logs-MetricFilter.cf +8 -0
  145. data/specs/Logs-SubscriptionFilter.cf +9 -0
  146. data/specs/OpsWorks-App.cf +16 -0
  147. data/specs/OpsWorks-ElasticLoadBalancerAttachment.cf +7 -0
  148. data/specs/OpsWorks-Instance.cf +19 -0
  149. data/specs/OpsWorks-Layer.cf +21 -0
  150. data/specs/OpsWorks-Stack.cf +23 -0
  151. data/specs/RDS-DBCluster.cf +23 -0
  152. data/specs/RDS-DBClusterParameterGroup.cf +9 -0
  153. data/specs/RDS-DBInstance.cf +38 -0
  154. data/specs/RDS-DBParameterGroup.cf +9 -0
  155. data/specs/RDS-DBSecurityGroup.cf +10 -0
  156. data/specs/RDS-DBSecurityGroupIngress.cf +10 -0
  157. data/specs/RDS-DBSubnetGroup.cf +8 -0
  158. data/specs/RDS-EventSubscription.cf +10 -0
  159. data/specs/RDS-OptionGroup.cf +10 -0
  160. data/specs/Redshift-Cluster.cf +30 -0
  161. data/specs/Redshift-ClusterParameterGroup.cf +8 -0
  162. data/specs/Redshift-ClusterSecurityGroup.cf +6 -0
  163. data/specs/Redshift-ClusterSecurityGroupIngress.cf +9 -0
  164. data/specs/Redshift-ClusterSubnetGroup.cf +7 -0
  165. data/specs/Route53-HealthCheck.cf +7 -0
  166. data/specs/Route53-HostedZone.cf +9 -0
  167. data/specs/Route53-RecordSet.cf +19 -0
  168. data/specs/Route53-RecordSetGroup.cf +9 -0
  169. data/specs/S3-Bucket.cf +15 -0
  170. data/specs/S3-BucketPolicy.cf +7 -0
  171. data/specs/SDB-Domain.cf +6 -0
  172. data/specs/SNS-Topic.cf +8 -0
  173. data/specs/SNS-TopicPolicy.cf +8 -0
  174. data/specs/SQS-Queue.cf +12 -0
  175. data/specs/SQS-QueuePolicy.cf +7 -0
  176. data/specs/SSM-Document.cf +6 -0
  177. data/specs/WAF-ByteMatchSet.cf +7 -0
  178. data/specs/WAF-IPSet.cf +7 -0
  179. data/specs/WAF-Rule.cf +8 -0
  180. data/specs/WAF-SizeConstraintSet.cf +7 -0
  181. data/specs/WAF-SqlInjectionMatchSet.cf +7 -0
  182. data/specs/WAF-WebACL.cf +9 -0
  183. data/specs/WAF-XssMatchSet.cf +7 -0
  184. data/specs/WorkSpaces-Workspace.cf +11 -0
  185. metadata +356 -0
@@ -0,0 +1,127 @@
1
+ module Humidifier
2
+
3
+ # Container for property of CFN resources
4
+ module Props
5
+
6
+ # Superclass for all CFN properties
7
+ class Base
8
+
9
+ # The list of classes that are valid beyond the normal values for each prop
10
+ WHITELIST = [Fn, Ref].freeze
11
+
12
+ attr_accessor :key
13
+ attr_reader :value
14
+
15
+ def initialize(key = nil)
16
+ self.key = key
17
+ end
18
+
19
+ # true if the property type knows how to convert its values
20
+ def convertable?
21
+ respond_to?(:convert)
22
+ end
23
+
24
+ # the name of the property
25
+ def name
26
+ @name ||= Utils.underscore(key)
27
+ end
28
+
29
+ # CFN stack syntax
30
+ def to_cf(value)
31
+ [key, Serializer.dump(value)]
32
+ end
33
+
34
+ # true if the given value is of a type contained in the whitelist
35
+ def whitelisted_value?(value)
36
+ WHITELIST.any? { |clazz| value.is_a?(clazz) }
37
+ end
38
+ end
39
+
40
+ # An array property
41
+ class ArrayProp < Base
42
+ def valid?(value)
43
+ value.is_a?(Array)
44
+ end
45
+ end
46
+
47
+ # A boolean property
48
+ class BooleanProp < Base
49
+ # converts through value == 'true'
50
+ def convert(value)
51
+ if %w[true false].include?(value)
52
+ puts "WARNING: Property #{name} should be a boolean, not a string"
53
+ value == 'true'
54
+ else
55
+ value
56
+ end
57
+ end
58
+
59
+ # true if it is a boolean
60
+ def valid?(value)
61
+ value.is_a?(TrueClass) || value.is_a?(FalseClass)
62
+ end
63
+ end
64
+
65
+ # A JSON property (and the default)
66
+ class JSONProp < Base
67
+ def valid?(value)
68
+ whitelisted_value?(value) || value.is_a?(Hash) || value.is_a?(Array)
69
+ end
70
+ end
71
+
72
+ # An integer property
73
+ class IntegerProp < Base
74
+ # converts the value through #to_i unless it is whitelisted
75
+ def convert(value)
76
+ puts "WARNING: Property #{name} should be an integer" unless valid?(value)
77
+ value.to_i
78
+ end
79
+
80
+ # true if it is whitelisted or a Fixnum
81
+ def valid?(value)
82
+ whitelisted_value?(value) || value.is_a?(Fixnum)
83
+ end
84
+ end
85
+
86
+ # A string property
87
+ class StringProp < Base
88
+ # converts the value through #to_s unless it is whitelisted
89
+ def convert(value)
90
+ puts "WARNING: Property #{name} should be a string" unless valid?(value)
91
+ whitelisted_value?(value) ? value : value.to_s
92
+ end
93
+
94
+ # true if it is whitelisted or a String
95
+ def valid?(value)
96
+ whitelisted_value?(value) || value.is_a?(String)
97
+ end
98
+ end
99
+
100
+ class << self
101
+ # builds the appropriate prop object from the given spec line
102
+ def from(spec_line)
103
+ key, type = parse(spec_line)
104
+
105
+ case type
106
+ when 'Boolean' then BooleanProp.new(key)
107
+ when 'Integer' then IntegerProp.new(key)
108
+ when 'String' then StringProp.new(key)
109
+ when /\[.*?\]/ then ArrayProp.new(key)
110
+ else JSONProp.new(key)
111
+ end
112
+ end
113
+
114
+ # parses a spec line to return a key and type
115
+ def parse(spec_line)
116
+ spec_line.strip!
117
+
118
+ if spec_line.include?(':')
119
+ key, type = spec_line.gsub(/,\z/, '').split(': ').map(&:strip)
120
+ [key[1..-2], type]
121
+ else
122
+ [nil, spec_line]
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,17 @@
1
+ module Humidifier
2
+
3
+ # Builds CFN references
4
+ class Ref
5
+
6
+ attr_accessor :reference
7
+
8
+ def initialize(reference)
9
+ self.reference = reference
10
+ end
11
+
12
+ # Builds CFN syntax
13
+ def to_cf
14
+ { 'Ref' => reference }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,108 @@
1
+ module Humidifier
2
+
3
+ # Superclass for all AWS resources
4
+ class Resource
5
+
6
+ # Attributes that are available to every stack
7
+ COMMON_ATTRIBUTES =
8
+ Utils.underscored(%w[Condition CreationPolicy DeletionPolicy DependsOn Metadata UpdatePolicy])
9
+
10
+ attr_accessor :properties, *COMMON_ATTRIBUTES.values
11
+
12
+ def initialize(properties = {}, raw = false)
13
+ self.properties = {}
14
+ update(properties, raw)
15
+ end
16
+
17
+ # Patches method_missing to include property accessors
18
+ # After the first method call, builds the accessor methods to get a speed boost
19
+ def method_missing(name, *args)
20
+ if !valid_accessor?(name)
21
+ super
22
+ elsif self.class.prop?(name.to_s)
23
+ self.class.build_property_reader(name)
24
+ send(name)
25
+ else
26
+ self.class.build_property_writer(name)
27
+ send(name, args.first)
28
+ end
29
+ end
30
+
31
+ # Patches respond_to_missing? to include property accessors
32
+ def respond_to_missing?(name, *)
33
+ valid_accessor?(name) || super
34
+ end
35
+
36
+ # CFN stack syntax
37
+ def to_cf
38
+ props_cf = Utils.enumerable_to_h(properties) { |(key, value)| self.class.props[key].to_cf(value) }
39
+ { 'Type' => self.class.aws_name, 'Properties' => props_cf }.merge(common_attributes)
40
+ end
41
+
42
+ # Update a set of properties defined by the given properties hash
43
+ def update(properties, raw = false)
44
+ properties.each { |property, value| update_property(property, value, raw) }
45
+ end
46
+
47
+ # Update an individual property on this resource
48
+ def update_property(property, value, raw = false)
49
+ property = property.to_s
50
+ property = validate_property(property, raw)
51
+ value = validate_value(property, value, raw)
52
+ properties[property] = value
53
+ end
54
+
55
+ class << self
56
+ attr_accessor :aws_name, :props
57
+
58
+ # @private builds a cached method for a property reader
59
+ def build_property_reader(name)
60
+ define_method(name) do
61
+ properties[name.to_s]
62
+ end
63
+ end
64
+
65
+ # @private builds a cached method for a property writer
66
+ def build_property_writer(name)
67
+ define_method(name) do |value|
68
+ update_property(name.to_s[0..-2], value)
69
+ end
70
+ end
71
+
72
+ # true if this resource has the given property
73
+ def prop?(prop)
74
+ props.key?(prop)
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def common_attributes
81
+ COMMON_ATTRIBUTES.each_with_object({}) do |(name, prop), result|
82
+ value = send(prop)
83
+ result[name] = value if value
84
+ end
85
+ end
86
+
87
+ def valid_accessor?(method)
88
+ (self.class.props.keys & [method.to_s, method.to_s[0..-2]]).any?
89
+ end
90
+
91
+ def validate_property(property, raw)
92
+ property = Utils.underscore(property) if raw
93
+ unless self.class.prop?(property)
94
+ raise ArgumentError, "Attempting to set invalid property for #{self.class.name}: #{property}"
95
+ end
96
+ property
97
+ end
98
+
99
+ def validate_value(property, value, raw)
100
+ prop = self.class.props[property]
101
+ value = prop.convert(value) if raw && prop.convertable?
102
+ unless prop.valid?(value)
103
+ raise ArgumentError, "Invalid value for #{property}: #{value.inspect}"
104
+ end
105
+ value
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,30 @@
1
+ module Humidifier
2
+
3
+ # The payload sent to the shim methods, representing the stack and the options
4
+ class SdkPayload
5
+
6
+ # The maximum amount of time that Humidifier should wait for a stack to complete a CRUD operation
7
+ MAX_WAIT = 180
8
+
9
+ attr_accessor :stack, :options, :max_wait
10
+
11
+ extend Forwardable
12
+ def_delegators :stack, :id=, :identifier, :name, :to_cf
13
+
14
+ def initialize(stack, options)
15
+ self.stack = stack
16
+ self.options = options
17
+ self.max_wait = options.delete(:max_wait) || MAX_WAIT
18
+ end
19
+
20
+ # True if the stack and options are the same as the other (used for testing)
21
+ def ==(other)
22
+ stack == other.stack && options == other.options
23
+ end
24
+
25
+ # Merge in options
26
+ def merge(new_options)
27
+ self.options = new_options.merge(options)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ module Humidifier
2
+
3
+ # Dumps an object to CFN syntax
4
+ class Serializer
5
+
6
+ class << self
7
+ # dumps the given object out to CFN syntax recursively
8
+ def dump(node)
9
+ case node
10
+ when Hash then Utils.enumerable_to_h(node) { |(key, value)| [key, dump(value)] }
11
+ when Array then node.map { |value| dump(value) }
12
+ when Ref, Fn then dump(node.to_cf)
13
+ else node
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ module Humidifier
2
+
3
+ # Manages waiting for stack events for v1 of the SDK
4
+ class Sleeper
5
+
6
+ attr_accessor :attempts
7
+
8
+ # Store attempts and wait for the block to return true
9
+ def initialize(attempts, &block)
10
+ self.attempts = attempts
11
+ hibernate_until(&block)
12
+ end
13
+
14
+ private
15
+
16
+ def hibernate_until(&block)
17
+ raise 'Waited too long, giving up' if attempts.zero?
18
+ return if yield
19
+
20
+ self.attempts -= 1
21
+ sleep 1
22
+ hibernate_until(&block)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,66 @@
1
+ module Humidifier
2
+
3
+ # Represents a CFN stack
4
+ class Stack
5
+
6
+ # Single settings on the stack
7
+ STATIC_RESOURCES = Utils.underscored(%w[AWSTemplateFormatVersion Description Metadata])
8
+
9
+ # Lists of objects linked to the stack
10
+ ENUMERABLE_RESOURCES = Utils.underscored(%w[Conditions Mappings Outputs Parameters Resources])
11
+
12
+ attr_accessor :id, :name, *ENUMERABLE_RESOURCES.values, *STATIC_RESOURCES.values
13
+
14
+ def initialize(opts = {})
15
+ self.name = opts[:name]
16
+ self.id = opts[:id]
17
+
18
+ ENUMERABLE_RESOURCES.values.each { |prop| send(:"#{prop}=", opts.fetch(prop, {})) }
19
+ STATIC_RESOURCES.values.each { |prop| send(:"#{prop}=", opts[prop]) }
20
+ end
21
+
22
+ # Add a resource to the stack
23
+ def add(name, resource)
24
+ resources[name] = resource
25
+ end
26
+
27
+ # The identifier used by the shim to find the stack in CFN, prefers id to name
28
+ def identifier
29
+ id || name
30
+ end
31
+
32
+ # A string representation of the stack that's valid for CFN
33
+ def to_cf
34
+ JSON.pretty_generate(enumerable_resources.merge(static_resources))
35
+ end
36
+
37
+ %i[condition mapping output parameter].each do |resource_type|
38
+ define_method(:"add_#{resource_type}") do |name, opts = {}|
39
+ send(:"#{resource_type}s")[name] = Humidifier.const_get(resource_type.capitalize).new(opts)
40
+ end
41
+ end
42
+
43
+ AwsShim::STACK_METHODS.each do |method|
44
+ define_method(method) { |opts = {}| AwsShim.send(method, SdkPayload.new(self, opts)) }
45
+ end
46
+
47
+ private
48
+
49
+ def enumerable_resources
50
+ ENUMERABLE_RESOURCES.each_with_object({}) do |(name, prop), list|
51
+ resources = send(prop)
52
+ next if resources.empty?
53
+ list[name] = Utils.enumerable_to_h(resources) do |resource_name, resource|
54
+ [resource_name, resource.to_cf]
55
+ end
56
+ end
57
+ end
58
+
59
+ def static_resources
60
+ STATIC_RESOURCES.each_with_object({}) do |(name, prop), list|
61
+ resource = send(prop)
62
+ list[name] = resource if resource
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,21 @@
1
+ module Humidifier
2
+
3
+ # Dumps an object to CFN syntax
4
+ module Utils
5
+
6
+ class << self
7
+ # back-supporting ruby 2.0's lack of Enumerable#to_h
8
+ def enumerable_to_h(enumerable)
9
+ enumerable.each_with_object({}) do |item, result|
10
+ key, value = yield item
11
+ result[key] = value
12
+ end
13
+ end
14
+
15
+ # a frozen hash of the given names mapped to their underscored version
16
+ def underscored(names)
17
+ names.each_with_object({}) { |name, map| map[name] = underscore(name).to_sym }.freeze
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ module Humidifier
2
+ # Gem version
3
+ VERSION = '0.1.0'.freeze
4
+ end
data/lib/humidifier.rb ADDED
@@ -0,0 +1,50 @@
1
+ require 'forwardable'
2
+ require 'json'
3
+ require 'pathname'
4
+
5
+ require 'humidifier/humidifier'
6
+ require 'humidifier/utils'
7
+
8
+ require 'humidifier/fn'
9
+ require 'humidifier/ref'
10
+ require 'humidifier/props'
11
+
12
+ require 'humidifier/aws_shim'
13
+ require 'humidifier/condition'
14
+ require 'humidifier/loader'
15
+ require 'humidifier/mapping'
16
+ require 'humidifier/output'
17
+ require 'humidifier/parameter'
18
+ require 'humidifier/resource'
19
+ require 'humidifier/sdk_payload'
20
+ require 'humidifier/serializer'
21
+ require 'humidifier/sleeper'
22
+ require 'humidifier/stack'
23
+ require 'humidifier/version'
24
+
25
+ # container module for all gem classes
26
+ module Humidifier
27
+ class << self
28
+ # convenience method for calling cloudformation functions
29
+ def fn
30
+ Fn
31
+ end
32
+
33
+ # convenience method for creating references
34
+ def ref(reference)
35
+ Ref.new(reference)
36
+ end
37
+
38
+ # the list of all registered resources
39
+ def registry
40
+ @registry ||= {}
41
+ end
42
+
43
+ # convenience method for finding classes by AWS name
44
+ def [](aws_name)
45
+ registry[aws_name]
46
+ end
47
+ end
48
+ end
49
+
50
+ Humidifier::Loader.load
@@ -0,0 +1,6 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::Account",
3
+ "Properties" : {
4
+ "CloudWatchRoleArn" : String
5
+ }
6
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::ApiKey",
3
+ "Properties" : {
4
+ "Description" : String,
5
+ "Enabled" : Boolean,
6
+ "Name" : String,
7
+ "StageKeys" : [ StageKey, ... ]
8
+ }
9
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::Authorizer",
3
+ "Properties" : {
4
+ "AuthorizerCredentials" : String,
5
+ "AuthorizerResultTtlInSeconds" : Integer,
6
+ "AuthorizerUri" : String,
7
+ "IdentitySource" : String,
8
+ "IdentityValidationExpression" : String,
9
+ "Name" : String,
10
+ "RestApiId" : String,
11
+ "Type" : String
12
+ }
13
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::BasePathMapping",
3
+ "Properties" : {
4
+ "BasePath" : String,
5
+ "DomainName" : String,
6
+ "RestApiId" : String,
7
+ "Stage" : String
8
+ }
9
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::ClientCertificate",
3
+ "Properties" : {
4
+ "Description" : String
5
+ }
6
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::Deployment",
3
+ "Properties" : {
4
+ "Description" : String,
5
+ "RestApiId" : String,
6
+ "StageDescription" : StageDescription,
7
+ "StageName" : String
8
+ }
9
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::Method",
3
+ "Properties" : {
4
+ "ApiKeyRequired" : Boolean,
5
+ "AuthorizationType" : String,
6
+ "AuthorizerId" : String,
7
+ "HttpMethod" : String,
8
+ "Integration" : Integration,
9
+ "MethodResponses" : [ MethodResponse, ... ],
10
+ "RequestModels" : { String:String, ... },
11
+ "RequestParameters" : { String:Boolean, ... },
12
+ "ResourceId" : String,
13
+ "RestApiId" : String
14
+ }
15
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::Model",
3
+ "Properties" : {
4
+ "ContentType" : String,
5
+ "Description" : String,
6
+ "Name" : String,
7
+ "RestApiId" : String,
8
+ "Schema" : String
9
+ }
10
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::Resource",
3
+ "Properties" : {
4
+ "ParentId" : String,
5
+ "PathPart" : String,
6
+ "RestApiId" : String
7
+ }
8
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::RestApi",
3
+ "Properties" : {
4
+ "Body" : String,
5
+ "BodyS3Location" : S3Location,
6
+ "CloneFrom" : String,
7
+ "Description" : String,
8
+ "FailOnWarnings" : Boolean,
9
+ "Name" : String,
10
+ "Parameters" : [ String, ... ]
11
+ }
12
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "Type" : "AWS::ApiGateway::Stage",
3
+ "Properties" : {
4
+ "CacheClusterEnabled" : Boolean,
5
+ "CacheClusterSize" : String,
6
+ "ClientCertificateId" : String,
7
+ "DeploymentId" : String,
8
+ "Description" : String,
9
+ "MethodSettings" : [ MethodSetting ],
10
+ "RestApiId" : String,
11
+ "StageName" : String,
12
+ "Variables" : { String:String, ... }
13
+ }
14
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "Type" : "AWS::AutoScaling::AutoScalingGroup",
3
+ "Properties" : {
4
+ "AvailabilityZones" : [ String, ... ],
5
+ "Cooldown" : String,
6
+ "DesiredCapacity" : String,
7
+ "HealthCheckGracePeriod" : Integer,
8
+ "HealthCheckType" : String,
9
+ "InstanceId" : String,
10
+ "LaunchConfigurationName" : String,
11
+ "LoadBalancerNames" : [ String, ... ],
12
+ "MaxSize" : String,
13
+ "MetricsCollection" : [ MetricsCollection, ... ]
14
+ "MinSize" : String,
15
+ "NotificationConfigurations" : [ NotificationConfigurations, ... ],
16
+ "PlacementGroup" : String,
17
+ "Tags" : [ Auto Scaling Tag, ..., ],
18
+ "TerminationPolicies" : [ String, ..., ],
19
+ "VPCZoneIdentifier" : [ String, ... ]
20
+ }
21
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "Type" : "AWS::AutoScaling::LaunchConfiguration",
3
+ "Properties" : {
4
+ "AssociatePublicIpAddress" : Boolean,
5
+ "BlockDeviceMappings" : [ BlockDeviceMapping, ... ],
6
+ "ClassicLinkVPCId" : String,
7
+ "ClassicLinkVPCSecurityGroups" : [ String, ... ],
8
+ "EbsOptimized" : Boolean,
9
+ "IamInstanceProfile" : String,
10
+ "ImageId" : String,
11
+ "InstanceId" : String,
12
+ "InstanceMonitoring" : Boolean,
13
+ "InstanceType" : String,
14
+ "KernelId" : String,
15
+ "KeyName" : String,
16
+ "PlacementTenancy" : String,
17
+ "RamDiskId" : String,
18
+ "SecurityGroups" : [ SecurityGroup, ... ],
19
+ "SpotPrice" : String,
20
+ "UserData" : String
21
+ }
22
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "Type" : "AWS::AutoScaling::LifecycleHook",
3
+ "Properties" : {
4
+ "AutoScalingGroupName" : String,
5
+ "DefaultResult" : String,
6
+ "HeartbeatTimeout" : Integer,
7
+ "LifecycleTransition" : String,
8
+ "NotificationMetadata" : String,
9
+ "NotificationTargetARN" : String,
10
+ "RoleARN" : String
11
+ }
12
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "Type" : "AWS::AutoScaling::ScalingPolicy",
3
+ "Properties" : {
4
+ "AdjustmentType" : String,
5
+ "AutoScalingGroupName" : String,
6
+ "Cooldown" : String,
7
+ "EstimatedInstanceWarmup" : Integer,
8
+ "MetricAggregationType" : String,
9
+ "MinAdjustmentMagnitude" : Integer,
10
+ "PolicyType" : String,
11
+ "ScalingAdjustment" : Integer,
12
+ "StepAdjustments" : [ StepAdjustments, ... ]
13
+ }
14
+ }