cumulus-aws 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
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