cumulus-aws 0.11.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.
Files changed (173) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +12 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +29 -0
  6. data/LICENSE +202 -0
  7. data/README.md +41 -0
  8. data/autocomplete +137 -0
  9. data/bin/cumulus +658 -0
  10. data/cumulus +2 -0
  11. data/cumulus-aws.gemspec +20 -0
  12. data/lib/autoscaling/AutoScaling.rb +40 -0
  13. data/lib/autoscaling/loader/Loader.rb +56 -0
  14. data/lib/autoscaling/manager/Manager.rb +360 -0
  15. data/lib/autoscaling/models/AlarmConfig.rb +165 -0
  16. data/lib/autoscaling/models/AlarmDiff.rb +172 -0
  17. data/lib/autoscaling/models/AutoScalingDiff.rb +178 -0
  18. data/lib/autoscaling/models/GroupConfig.rb +330 -0
  19. data/lib/autoscaling/models/PolicyConfig.rb +135 -0
  20. data/lib/autoscaling/models/PolicyDiff.rb +73 -0
  21. data/lib/autoscaling/models/ScheduledActionDiff.rb +53 -0
  22. data/lib/autoscaling/models/ScheduledConfig.rb +96 -0
  23. data/lib/aws_extensions/ec2/DhcpOptions.rb +41 -0
  24. data/lib/aws_extensions/ec2/Instance.rb +29 -0
  25. data/lib/aws_extensions/ec2/NetworkAcl.rb +25 -0
  26. data/lib/aws_extensions/ec2/NetworkInterface.rb +14 -0
  27. data/lib/aws_extensions/ec2/RouteTable.rb +26 -0
  28. data/lib/aws_extensions/ec2/SecurityGroup.rb +16 -0
  29. data/lib/aws_extensions/ec2/Subnet.rb +28 -0
  30. data/lib/aws_extensions/ec2/Volume.rb +24 -0
  31. data/lib/aws_extensions/ec2/Vpc.rb +14 -0
  32. data/lib/aws_extensions/ec2/VpcEndpoint.rb +11 -0
  33. data/lib/aws_extensions/elb/BackendServerDescription.rb +12 -0
  34. data/lib/aws_extensions/elb/PolicyDescription.rb +14 -0
  35. data/lib/aws_extensions/kinesis/StreamDescription.rb +12 -0
  36. data/lib/aws_extensions/route53/AliasTarget.rb +21 -0
  37. data/lib/aws_extensions/s3/Bucket.rb +33 -0
  38. data/lib/aws_extensions/s3/BucketAcl.rb +28 -0
  39. data/lib/aws_extensions/s3/BucketCors.rb +17 -0
  40. data/lib/aws_extensions/s3/BucketLifecycle.rb +21 -0
  41. data/lib/aws_extensions/s3/BucketLogging.rb +18 -0
  42. data/lib/aws_extensions/s3/BucketNotification.rb +23 -0
  43. data/lib/aws_extensions/s3/BucketPolicy.rb +18 -0
  44. data/lib/aws_extensions/s3/BucketTagging.rb +15 -0
  45. data/lib/aws_extensions/s3/BucketVersioning.rb +14 -0
  46. data/lib/aws_extensions/s3/BucketWebsite.rb +49 -0
  47. data/lib/aws_extensions/s3/CORSRule.rb +27 -0
  48. data/lib/aws_extensions/s3/ReplicationConfiguration.rb +22 -0
  49. data/lib/cloudfront/CloudFront.rb +83 -0
  50. data/lib/cloudfront/loader/Loader.rb +31 -0
  51. data/lib/cloudfront/manager/Manager.rb +183 -0
  52. data/lib/cloudfront/models/CacheBehaviorConfig.rb +237 -0
  53. data/lib/cloudfront/models/CacheBehaviorDiff.rb +211 -0
  54. data/lib/cloudfront/models/CustomOriginConfig.rb +51 -0
  55. data/lib/cloudfront/models/CustomOriginDiff.rb +74 -0
  56. data/lib/cloudfront/models/DistributionConfig.rb +183 -0
  57. data/lib/cloudfront/models/DistributionDiff.rb +131 -0
  58. data/lib/cloudfront/models/InvalidationConfig.rb +37 -0
  59. data/lib/cloudfront/models/OriginConfig.rb +144 -0
  60. data/lib/cloudfront/models/OriginDiff.rb +86 -0
  61. data/lib/cloudfront/models/OriginSslProtocols.rb +28 -0
  62. data/lib/cloudfront/models/OriginSslProtocolsDiff.rb +39 -0
  63. data/lib/common/BaseLoader.rb +80 -0
  64. data/lib/common/manager/Manager.rb +148 -0
  65. data/lib/common/models/Diff.rb +114 -0
  66. data/lib/common/models/ListChange.rb +21 -0
  67. data/lib/common/models/TagsDiff.rb +55 -0
  68. data/lib/common/models/UTCTimeSource.rb +17 -0
  69. data/lib/conf/Configuration.rb +365 -0
  70. data/lib/ec2/EC2.rb +503 -0
  71. data/lib/ec2/IPProtocolMapping.rb +165 -0
  72. data/lib/ec2/loaders/EbsLoader.rb +19 -0
  73. data/lib/ec2/loaders/InstanceLoader.rb +32 -0
  74. data/lib/ec2/managers/EbsManager.rb +176 -0
  75. data/lib/ec2/managers/InstanceManager.rb +509 -0
  76. data/lib/ec2/models/EbsGroupConfig.rb +133 -0
  77. data/lib/ec2/models/EbsGroupDiff.rb +48 -0
  78. data/lib/ec2/models/InstanceConfig.rb +202 -0
  79. data/lib/ec2/models/InstanceDiff.rb +95 -0
  80. data/lib/elb/ELB.rb +148 -0
  81. data/lib/elb/loader/Loader.rb +65 -0
  82. data/lib/elb/manager/Manager.rb +581 -0
  83. data/lib/elb/models/AccessLogConfig.rb +82 -0
  84. data/lib/elb/models/AccessLogDiff.rb +47 -0
  85. data/lib/elb/models/HealthCheckConfig.rb +91 -0
  86. data/lib/elb/models/HealthCheckDiff.rb +50 -0
  87. data/lib/elb/models/ListenerConfig.rb +99 -0
  88. data/lib/elb/models/ListenerDiff.rb +91 -0
  89. data/lib/elb/models/LoadBalancerConfig.rb +239 -0
  90. data/lib/elb/models/LoadBalancerDiff.rb +265 -0
  91. data/lib/iam/IAM.rb +36 -0
  92. data/lib/iam/loader/Loader.rb +117 -0
  93. data/lib/iam/manager/IamGroups.rb +98 -0
  94. data/lib/iam/manager/IamResource.rb +288 -0
  95. data/lib/iam/manager/IamRoles.rb +112 -0
  96. data/lib/iam/manager/IamUsers.rb +54 -0
  97. data/lib/iam/manager/Manager.rb +29 -0
  98. data/lib/iam/migration/AssumeRoleUnifier.rb +34 -0
  99. data/lib/iam/migration/PolicyUnifier.rb +90 -0
  100. data/lib/iam/models/GroupConfig.rb +40 -0
  101. data/lib/iam/models/IamDiff.rb +132 -0
  102. data/lib/iam/models/PolicyConfig.rb +67 -0
  103. data/lib/iam/models/ResourceWithPolicy.rb +208 -0
  104. data/lib/iam/models/RoleConfig.rb +53 -0
  105. data/lib/iam/models/StatementConfig.rb +35 -0
  106. data/lib/iam/models/UserConfig.rb +21 -0
  107. data/lib/kinesis/Kinesis.rb +94 -0
  108. data/lib/kinesis/loader/Loader.rb +19 -0
  109. data/lib/kinesis/manager/Manager.rb +206 -0
  110. data/lib/kinesis/models/StreamConfig.rb +75 -0
  111. data/lib/kinesis/models/StreamDiff.rb +58 -0
  112. data/lib/lambda/Lambda.rb +41 -0
  113. data/lib/route53/loader/Loader.rb +32 -0
  114. data/lib/route53/manager/Manager.rb +241 -0
  115. data/lib/route53/models/AliasTarget.rb +86 -0
  116. data/lib/route53/models/RecordConfig.rb +178 -0
  117. data/lib/route53/models/RecordDiff.rb +140 -0
  118. data/lib/route53/models/Vpc.rb +24 -0
  119. data/lib/route53/models/ZoneConfig.rb +156 -0
  120. data/lib/route53/models/ZoneDiff.rb +118 -0
  121. data/lib/s3/S3.rb +89 -0
  122. data/lib/s3/loader/Loader.rb +66 -0
  123. data/lib/s3/manager/Manager.rb +296 -0
  124. data/lib/s3/models/BucketConfig.rb +321 -0
  125. data/lib/s3/models/BucketDiff.rb +167 -0
  126. data/lib/s3/models/GrantConfig.rb +189 -0
  127. data/lib/s3/models/GrantDiff.rb +50 -0
  128. data/lib/s3/models/LifecycleConfig.rb +142 -0
  129. data/lib/s3/models/LifecycleDiff.rb +46 -0
  130. data/lib/s3/models/LoggingConfig.rb +81 -0
  131. data/lib/s3/models/NotificationConfig.rb +157 -0
  132. data/lib/s3/models/NotificationDiff.rb +62 -0
  133. data/lib/s3/models/ReplicationConfig.rb +133 -0
  134. data/lib/s3/models/ReplicationDiff.rb +60 -0
  135. data/lib/s3/models/WebsiteConfig.rb +107 -0
  136. data/lib/security/SecurityGroups.rb +39 -0
  137. data/lib/security/loader/Loader.rb +94 -0
  138. data/lib/security/manager/Manager.rb +246 -0
  139. data/lib/security/models/RuleConfig.rb +161 -0
  140. data/lib/security/models/RuleDiff.rb +72 -0
  141. data/lib/security/models/RuleMigration.rb +127 -0
  142. data/lib/security/models/SecurityGroupConfig.rb +172 -0
  143. data/lib/security/models/SecurityGroupDiff.rb +112 -0
  144. data/lib/sns/SNS.rb +40 -0
  145. data/lib/sqs/SQS.rb +62 -0
  146. data/lib/sqs/loader/Loader.rb +34 -0
  147. data/lib/sqs/manager/Manager.rb +128 -0
  148. data/lib/sqs/models/DeadLetterConfig.rb +70 -0
  149. data/lib/sqs/models/DeadLetterDiff.rb +35 -0
  150. data/lib/sqs/models/QueueConfig.rb +115 -0
  151. data/lib/sqs/models/QueueDiff.rb +89 -0
  152. data/lib/util/Colors.rb +111 -0
  153. data/lib/util/StatusCodes.rb +51 -0
  154. data/lib/vpc/loader/Loader.rb +73 -0
  155. data/lib/vpc/manager/Manager.rb +954 -0
  156. data/lib/vpc/models/AclEntryConfig.rb +150 -0
  157. data/lib/vpc/models/AclEntryDiff.rb +54 -0
  158. data/lib/vpc/models/DhcpConfig.rb +100 -0
  159. data/lib/vpc/models/DhcpDiff.rb +90 -0
  160. data/lib/vpc/models/EndpointConfig.rb +76 -0
  161. data/lib/vpc/models/EndpointDiff.rb +69 -0
  162. data/lib/vpc/models/NetworkAclConfig.rb +87 -0
  163. data/lib/vpc/models/NetworkAclDiff.rb +116 -0
  164. data/lib/vpc/models/RouteConfig.rb +82 -0
  165. data/lib/vpc/models/RouteDiff.rb +50 -0
  166. data/lib/vpc/models/RouteTableConfig.rb +92 -0
  167. data/lib/vpc/models/RouteTableDiff.rb +101 -0
  168. data/lib/vpc/models/SubnetConfig.rb +113 -0
  169. data/lib/vpc/models/SubnetDiff.rb +78 -0
  170. data/lib/vpc/models/VpcConfig.rb +173 -0
  171. data/lib/vpc/models/VpcDiff.rb +315 -0
  172. data/rakefile.rb +8 -0
  173. metadata +245 -0
@@ -0,0 +1,330 @@
1
+ require "autoscaling/loader/Loader"
2
+ require "autoscaling/models/AutoScalingDiff"
3
+ require "autoscaling/models/PolicyConfig"
4
+ require "autoscaling/models/PolicyDiff"
5
+ require "autoscaling/models/ScheduledActionDiff"
6
+ require "autoscaling/models/ScheduledConfig"
7
+ require "common/models/UTCTimeSource"
8
+ require "ec2/EC2"
9
+
10
+ require "parse-cron"
11
+
12
+ module Cumulus
13
+ module AutoScaling
14
+ # Public: An object representing the configuration for an AutoScaling group.
15
+ class GroupConfig
16
+ attr_reader :check_grace
17
+ attr_reader :check_type
18
+ attr_reader :cooldown
19
+ attr_reader :desired
20
+ attr_reader :enabled_metrics
21
+ attr_reader :launch
22
+ attr_reader :load_balancers
23
+ attr_reader :max
24
+ attr_reader :min
25
+ attr_reader :name
26
+ attr_reader :policies
27
+ attr_reader :scheduled
28
+ attr_reader :subnets
29
+ attr_reader :tags
30
+ attr_reader :termination
31
+
32
+ # Public: Constructor
33
+ #
34
+ # name - the name of the group
35
+ # json - a hash containing the json configuration for the AutoScaling group
36
+ def initialize(name, json = nil)
37
+ @name = name
38
+ if !json.nil?
39
+ @cooldown = json["cooldown-seconds"]
40
+ @min = json["size"]["min"]
41
+ @max = json["size"]["max"]
42
+ @desired = json["size"]["desired"]
43
+ @enabled_metrics = json["enabled-metrics"]
44
+ @check_type = json["health-check-type"]
45
+ @check_grace = json["health-check-grace-seconds"]
46
+ @launch = json["launch-configuration"]
47
+ @load_balancers = json["load-balancers"]
48
+ @subnets = json["subnets"]
49
+ @tags = json["tags"]
50
+ @termination = json["termination"]
51
+ @scheduled = Hash[(json["scheduled"] || []).map { |json| [json["name"], ScheduledConfig.new(json)] }]
52
+
53
+ # load scaling policies
54
+ static_policies = json["policies"]["static"].map { |file| Loader.static_policy(file) }
55
+ template_policies = json["policies"]["templates"].map do |template|
56
+ Loader.template_policy(template["template"], template["vars"])
57
+ end
58
+ inline_policies = json["policies"]["inlines"].map { |inline| PolicyConfig.new(inline) }
59
+ @policies = static_policies + template_policies + inline_policies
60
+ @policies = Hash[@policies.map { |policy| [policy.name, policy] }]
61
+ else
62
+ @enabled_metrics = []
63
+ @load_balancers = []
64
+ @subnets = []
65
+ @tags = {}
66
+ @termination = []
67
+ end
68
+ end
69
+
70
+ # Public: Get the config as a prettified JSON string. All policies will be in
71
+ # inlines.
72
+ #
73
+ # Returns the JSON string.
74
+ def pretty_json
75
+ JSON.pretty_generate({
76
+ "cooldown-seconds" => @cooldown,
77
+ "enabled-metrics" => @enabled_metrics,
78
+ "health-check-type" => @check_type,
79
+ "health-check-grace-seconds" => @check_grace,
80
+ "launch-configuration" => @launch,
81
+ "load-balancers" => @load_balancers,
82
+ "policies" => {
83
+ "static" => [],
84
+ "templates" => [],
85
+ "inlines" => @policies.map { |p| p.hash }
86
+ },
87
+ "scheduled" => @scheduled.map { |s| s.hash },
88
+ "size" => {
89
+ "min" => @min,
90
+ "max" => @max,
91
+ "desired" => @desired
92
+ },
93
+ "subnets" => @subnets,
94
+ "tags" => @tags,
95
+ "termination" => @termination
96
+ }.reject { |k, v| v.nil? })
97
+ end
98
+
99
+ # Public: Generate the object that AWS expects to create or update an
100
+ # AutoScaling group
101
+ #
102
+ # include_min_max_desired - if true, min_size, max_size and desired_capacity
103
+ # will be included in the hash
104
+ #
105
+ # Returns a hash of the information that AWS expects
106
+ def to_aws(include_min_max_desired)
107
+ {
108
+ auto_scaling_group_name: @name,
109
+ min_size: if include_min_max_desired then @min end,
110
+ max_size: if include_min_max_desired then @max end,
111
+ desired_capacity: if include_min_max_desired then @desired end,
112
+ default_cooldown: @cooldown,
113
+ health_check_type: @check_type,
114
+ health_check_grace_period: @check_grace,
115
+ vpc_zone_identifier: if !@subnets.empty? then subnets_to_aws.map(&:subnet_id).join(",") end,
116
+ termination_policies: @termination,
117
+ launch_configuration_name: @launch
118
+ }
119
+ end
120
+
121
+ # Public: Produce the differences between this local configuration and the
122
+ # configuration in AWS
123
+ #
124
+ # aws - the aws resource
125
+ # autoscaling - the AWS client needed to get additional AWS resources
126
+ #
127
+ # Returns an Array of the AutoScalingDiffs that were found
128
+ def diff(aws, autoscaling)
129
+ diffs = []
130
+
131
+ if @cooldown != aws.default_cooldown
132
+ diffs << AutoScalingDiff.new(AutoScalingChange::COOLDOWN, aws, self)
133
+ end
134
+ if @enabled_metrics != aws.enabled_metrics
135
+ diffs << AutoScalingDiff.new(AutoScalingChange::METRICS, aws, self)
136
+ end
137
+ if @check_type != aws.health_check_type
138
+ diffs << AutoScalingDiff.new(AutoScalingChange::CHECK_TYPE, aws, self)
139
+ end
140
+ if @check_grace != aws.health_check_grace_period
141
+ diffs << AutoScalingDiff.new(AutoScalingChange::CHECK_GRACE, aws, self)
142
+ end
143
+ if @launch != aws.launch_configuration_name and Configuration.instance.autoscaling.override_launch_config_on_sync
144
+ diffs << AutoScalingDiff.new(AutoScalingChange::LAUNCH, aws, self)
145
+ end
146
+ if @load_balancers.sort != aws.load_balancer_names.sort
147
+ diffs << AutoScalingDiff.new(AutoScalingChange::LOAD_BALANCER, aws, self)
148
+ end
149
+
150
+ # Get the actual subnet objects from aws using either the id or vpc/subnet combination
151
+ local_subnets = subnets_to_aws.sort_by(&:subnet_id)
152
+ aws_subnets = aws.vpc_zone_identifier.split(",").map do |subnet_id|
153
+ EC2::id_subnets[subnet_id]
154
+ end.sort_by(&:subnet_id)
155
+
156
+ if local_subnets != aws_subnets
157
+ diffs << AutoScalingDiff.new(AutoScalingChange::SUBNETS, aws_subnets, local_subnets)
158
+ end
159
+
160
+ if @tags != Hash[aws.tags.map { |tag| [tag.key, tag.value] }]
161
+ diffs << AutoScalingDiff.new(AutoScalingChange::TAGS, aws, self)
162
+ end
163
+ if @termination != aws.termination_policies
164
+ diffs << AutoScalingDiff.new(AutoScalingChange::TERMINATION, aws, self)
165
+ end
166
+
167
+ # check for changes in scheduled actions
168
+ aws_scheduled = autoscaling.describe_scheduled_actions({
169
+ auto_scaling_group_name: @name
170
+ }).scheduled_update_group_actions
171
+
172
+ scheduled_diff = AutoScalingDiff.scheduled(aws_scheduled, @scheduled)
173
+ if scheduled_diff
174
+ diffs << scheduled_diff
175
+ end
176
+
177
+ aws_min = aws.min_size
178
+ aws_max = aws.max_size
179
+ aws_desired = aws.desired_capacity
180
+ local_min = @min
181
+ local_max = @max
182
+ local_desired = @desired
183
+ update_desired = Configuration.instance.autoscaling.force_size
184
+
185
+ # If there is local scheduled actions, use the most recent one to determine the local min/max
186
+ if !@scheduled.empty? and !Configuration.instance.autoscaling.force_size
187
+ local_last_scheduled = last_scheduled
188
+
189
+ if local_last_scheduled
190
+ local_min = local_last_scheduled.min
191
+ local_max = local_last_scheduled.max
192
+ local_desired = local_last_scheduled.desired
193
+ end
194
+ end
195
+
196
+ # If desired was not specified, assume it is the min
197
+ local_desired = local_min if !local_desired
198
+
199
+ # If the aws desired value is outside of the new min/max bounds then we need to
200
+ # update desired to be in the bounds
201
+ if local_min and aws_desired < local_min
202
+ local_desired = local_min if local_desired < local_min
203
+ update_desired = true
204
+ elsif local_max and aws_desired > local_max
205
+ local_desired = local_max if local_desired > local_max
206
+ update_desired = true
207
+ end
208
+
209
+ if local_min and local_min != aws_min
210
+ diffs << AutoScalingDiff.new(AutoScalingChange::MIN, aws_min, local_min)
211
+ end
212
+ if local_max and local_max != aws_max
213
+ diffs << AutoScalingDiff.new(AutoScalingChange::MAX, aws_max, local_max)
214
+ end
215
+ if update_desired
216
+ diffs << AutoScalingDiff.new(AutoScalingChange::DESIRED, aws_desired, local_desired)
217
+ end
218
+
219
+ # check for changes in scaling policies
220
+ aws_policies = autoscaling.describe_policies({
221
+ auto_scaling_group_name: @name
222
+ }).scaling_policies
223
+ policy_diffs = diff_policies(aws_policies)
224
+ if !policy_diffs.empty?
225
+ diffs << AutoScalingDiff.policies(self, policy_diffs)
226
+ end
227
+
228
+ diffs
229
+ end
230
+
231
+ def last_scheduled
232
+ time_source = Common::UTCTimeSource.new
233
+
234
+ @scheduled.values.sort_by do |scheduled|
235
+ cron_parser = CronParser.new(scheduled.recurrence, time_source)
236
+ cron_parser.last
237
+ end.last
238
+ end
239
+
240
+ # Public: Populate the GroupConfig from an existing AWS AutoScaling group
241
+ #
242
+ # resource - the aws resource to populate from
243
+ def populate(resource)
244
+ @check_grace = resource.health_check_grace_period
245
+ @check_type = resource.health_check_type
246
+ @cooldown = resource.default_cooldown
247
+ @desired = resource.desired_capacity unless resource.desired_capacity.nil?
248
+ @enabled_metrics = resource.enabled_metrics.map { |m| m.metric }
249
+ @launch = resource.launch_configuration_name
250
+ @load_balancers = resource.load_balancer_names
251
+ @max = resource.max_size
252
+ @min = resource.min_size
253
+ @subnets = resource.vpc_zone_identifier.split(",")
254
+ @tags = Hash[resource.tags.map { |tag| [tag.key, tag.value] }]
255
+ @termination = resource.termination_policies
256
+ end
257
+
258
+ # Public: Populate the scheduled actions from existing scheduled actions in
259
+ # AWS.
260
+ #
261
+ # actions - the scheduled actions to populate from
262
+ def populate_scheduled(actions)
263
+ @scheduled = actions.map do |action|
264
+ config = ScheduledConfig.new()
265
+ config.populate(action)
266
+ config
267
+ end
268
+ end
269
+
270
+ # Public: Populate the policies from existing scaling policies in AWS.
271
+ #
272
+ # policies - the policies to populate from
273
+ def populate_policies(policies)
274
+ @policies = policies.map do |policy|
275
+ config = PolicyConfig.new()
276
+ config.populate(policy)
277
+ config
278
+ end
279
+ end
280
+
281
+ private
282
+
283
+ # Internal: Convert the local subnet names/ids into aws Subnets
284
+ def subnets_to_aws
285
+ @subnets.map do |local_subnet|
286
+ if local_subnet =~ /^subnet-[a-zA-Z0-9]+$/
287
+ EC2::id_subnets[local_subnet]
288
+ else
289
+ # Assume its in vpc/subnet form
290
+ vpc, subnet = local_subnet.split("/")
291
+ aws_vpc = EC2::id_vpcs[vpc] || EC2::named_vpcs[vpc]
292
+ if !aws_vpc
293
+ raise "Could not find vpc for #{local_subnet}"
294
+ end
295
+ aws_subnet = EC2::vpc_subnets[aws_vpc.vpc_id].find { |s| s.subnet_id == subnet || s.name == subnet }
296
+ if !aws_subnet
297
+ raise "Could not find subnet for #{local_subnet}"
298
+ end
299
+ aws_subnet
300
+ end
301
+ end
302
+ end
303
+
304
+ # Internal: Determine changes in scaling policies.
305
+ #
306
+ # aws_policies - the scaling policies in AWS
307
+ #
308
+ # Returns an array of PolicyDiff's that represent differences between local
309
+ # and AWS configuration
310
+ def diff_policies(aws_policies)
311
+ diffs = []
312
+
313
+ aws_policies = Hash[aws_policies.map { |p| [p.policy_name, p] }]
314
+ aws_policies.reject { |k, v| @policies.include?(k) }.each do |name, aws|
315
+ diffs << PolicyDiff.unmanaged(aws)
316
+ end
317
+ @policies.each do |name, local|
318
+ if !aws_policies.include?(name)
319
+ diffs << PolicyDiff.added(local)
320
+ else
321
+ diffs << local.diff(aws_policies[name])
322
+ end
323
+ end
324
+
325
+ diffs.flatten
326
+ end
327
+
328
+ end
329
+ end
330
+ end
@@ -0,0 +1,135 @@
1
+ require "autoscaling/models/AlarmConfig"
2
+ require "autoscaling/models/AlarmDiff"
3
+ require "autoscaling/models/PolicyDiff"
4
+ require "conf/Configuration"
5
+
6
+ require "aws-sdk"
7
+
8
+ module Cumulus
9
+ module AutoScaling
10
+ # Public: A class that encapsulates data about the way a scaling policy is
11
+ # configured.
12
+ class PolicyConfig
13
+ attr_reader :adjustment
14
+ attr_reader :adjustment_type
15
+ attr_reader :alarms
16
+ attr_reader :cooldown
17
+ attr_reader :min_adjustment
18
+ attr_reader :name
19
+
20
+ # Public: Constructor
21
+ #
22
+ # json - a hash representing the JSON configuration for this scaling policy
23
+ def initialize(json = nil)
24
+ @@cloudwatch ||= Aws::CloudWatch::Client.new(Configuration.instance.client)
25
+
26
+ if !json.nil?
27
+ @name = json["name"]
28
+ @adjustment_type = json["adjustment-type"]
29
+ @adjustment = json["adjustment"]
30
+ @cooldown = json["cooldown"]
31
+ @min_adjustment = json["min-adjustment-step"]
32
+ @alarms = {}
33
+ if !json["alarms"].nil?
34
+ @alarms = Hash[json["alarms"].map { |alarm| [alarm["name"], AlarmConfig.new(alarm)] }]
35
+ end
36
+ end
37
+ end
38
+
39
+ # Public: Get the configuration as a hash
40
+ #
41
+ # Returns the hash
42
+ def hash
43
+ {
44
+ "name" => @name,
45
+ "adjustment-type" => @adjustment_type,
46
+ "adjustment" => @adjustment,
47
+ "cooldown" => @cooldown,
48
+ "min-adjustment-step" => @min_adjustment,
49
+ "alarms" => @alarms.map { |a| a.hash }
50
+ }.reject { |k, v| v.nil? }
51
+ end
52
+
53
+ # Public: Produce the differences between this local configuration and the
54
+ # configuration in AWS
55
+ #
56
+ # aws - the scaling policy in AWS
57
+ def diff(aws)
58
+ diffs = []
59
+
60
+ if @adjustment_type != aws.adjustment_type
61
+ diffs << PolicyDiff.new(PolicyChange::ADJUSTMENT_TYPE, aws, self)
62
+ end
63
+ if @adjustment != aws.scaling_adjustment
64
+ diffs << PolicyDiff.new(PolicyChange::ADJUSTMENT, aws, self)
65
+ end
66
+ if @cooldown != aws.cooldown
67
+ diffs << PolicyDiff.new(PolicyChange::COOLDOWN, aws, self)
68
+ end
69
+ if @min_adjustment != aws.min_adjustment_step
70
+ diffs << PolicyDiff.new(PolicyChange::MIN_ADJUSTMENT, aws, self)
71
+ end
72
+
73
+ # get all cloudwatch alarms that trigger this policy as their action
74
+ aws_alarms = @@cloudwatch.describe_alarms({
75
+ action_prefix: aws.policy_arn
76
+ }).metric_alarms
77
+ alarm_diffs = diff_alarms(aws_alarms, aws.policy_arn)
78
+ if !alarm_diffs.empty?
79
+ diffs << PolicyDiff.alarms(alarm_diffs, self, aws.policy_arn)
80
+ end
81
+
82
+ diffs
83
+ end
84
+
85
+ # Public: Populate the PolicyConfig from an existing AWS scaling policy
86
+ #
87
+ # resource - the aws resource to populate from
88
+ def populate(resource)
89
+ @name = resource.policy_name
90
+ @adjustment_type = resource.adjustment_type
91
+ @adjustment = resource.scaling_adjustment
92
+ @cooldown = resource.cooldown
93
+ @min_adjustment = resource.min_adjustment_step
94
+
95
+ alarms = @@cloudwatch.describe_alarms({
96
+ action_prefix: resource.policy_arn
97
+ }).metric_alarms
98
+ @alarms = alarms.map do |alarm|
99
+ config = AlarmConfig.new()
100
+ config.populate(resource.policy_arn, alarm)
101
+ config
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ # Internal: Determine changes in alarms
108
+ #
109
+ # aws_alarms - the Cloudwatch alarms in AWS
110
+ # policy_arn - the policy arn is the action the alarms for this policy should
111
+ # take
112
+ #
113
+ # Returns an array of AlarmDiff's that represent differences between local and
114
+ # AWS configuration.
115
+ def diff_alarms(aws_alarms, policy_arn)
116
+ diffs = []
117
+
118
+ aws_alarms = Hash[aws_alarms.map { |a| [a.alarm_name, a] }]
119
+ aws_alarms.reject { |k, v| @alarms.include?(k) }.each do |name, aws|
120
+ diffs << AlarmDiff.unmanaged(aws)
121
+ end
122
+ @alarms.each do |name, local|
123
+ if !aws_alarms.include?(name)
124
+ diffs << AlarmDiff.added(local)
125
+ else
126
+ diffs << local.diff(aws_alarms[name], policy_arn)
127
+ end
128
+ end
129
+
130
+ diffs.flatten
131
+ end
132
+
133
+ end
134
+ end
135
+ end