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,239 @@
1
+ require "conf/Configuration"
2
+ require "elb/models/LoadBalancerDiff"
3
+ require "elb/models/ListenerConfig"
4
+ require "elb/models/HealthCheckConfig"
5
+ require "elb/models/AccessLogConfig"
6
+ require "elb/loader/Loader"
7
+ require "elb/ELB"
8
+ require "ec2/EC2"
9
+ require "security/SecurityGroups"
10
+
11
+ require "json"
12
+
13
+ module Cumulus
14
+ module ELB
15
+
16
+ # Public: An object representing configuration for a load balancer
17
+ class LoadBalancerConfig
18
+ attr_reader :name
19
+ attr_reader :listeners
20
+ attr_reader :availability_zones
21
+ attr_reader :subnets
22
+ attr_reader :security_groups
23
+ attr_reader :internal
24
+ attr_reader :tags
25
+ attr_reader :manage_instances
26
+ attr_reader :health_check
27
+ attr_reader :cross_zone
28
+ attr_reader :access_log
29
+ attr_reader :connection_draining
30
+ attr_reader :idle_timeout
31
+ attr_reader :backend_policies
32
+
33
+ require "aws_extensions/elb/BackendServerDescription"
34
+ Aws::ElasticLoadBalancing::Types::BackendServerDescription.send(:include, AwsExtensions::ELB::BackendServerDescription)
35
+
36
+ # Public: Constructor
37
+ #
38
+ # json - a hash containing the JSON configuration for the load balancer
39
+ def initialize(name, json = nil)
40
+ @name = name
41
+ if !json.nil?
42
+
43
+ # load the included listeners and templates
44
+ @listeners = []
45
+ if json["listeners"]
46
+ if json["listeners"]["includes"]
47
+ json["listeners"]["includes"].each do |template_json|
48
+ @listeners << Loader.listener(template_json["template"], template_json["vars"])
49
+ end
50
+ end
51
+ if json["listeners"]["inlines"]
52
+ json["listeners"]["inlines"].each do |inline|
53
+ @listeners << ListenerConfig.new(inline)
54
+ end
55
+ end
56
+ end
57
+
58
+ # Map subnets to their actual subnet description from aws
59
+ @subnets = (json["subnets"] || []).map do |subnet|
60
+ full_subnet = EC2::named_subnets[subnet]
61
+
62
+ if full_subnet.nil?
63
+ raise "#{subnet} is not a valid subnet name or id"
64
+ else
65
+ full_subnet
66
+ end
67
+ end
68
+
69
+ # Map backend policies to the Aws::ElasticLoadBalancing::Types::BackendServerDescription
70
+ # reject any local polices with empty policies array which means it should be deleted from aws
71
+ @backend_policies = (json["backend-policies"] || []).map do |backend|
72
+ Aws::ElasticLoadBalancing::Types::BackendServerDescription.new({
73
+ instance_port: backend["port"],
74
+ policy_names: backend["policies"]
75
+ })
76
+ end.reject { |backend| backend.policy_names.empty? }
77
+
78
+ @security_groups = json["security-groups"] || []
79
+ @internal = json["internal"] || false
80
+ @tags = json["tags"] || {}
81
+ @manage_instances = json["manage-instances"] || false
82
+ @health_check = if json["health-check"] then HealthCheckConfig.new(json["health-check"]) end
83
+ @cross_zone = json["cross-zone"] || false
84
+ @access_log = if json["access-log"] then AccessLogConfig.new(json["access-log"]) else false end
85
+ @connection_draining = json["connection-draining"] || false
86
+ @idle_timeout = json["idle-timeout"]
87
+ end
88
+ end
89
+
90
+ # Public: Returns the vpc id for the load balancer config using the first subnet
91
+ def vpc_id
92
+ first_subnet = @subnets.first
93
+ first_subnet.vpc_id if first_subnet
94
+ end
95
+
96
+ # Public: Get the config as a prettified JSON string.
97
+ #
98
+ # Returns the JSON string
99
+ def pretty_json
100
+ JSON.pretty_generate({
101
+ "listeners" => {
102
+ "includes" => [],
103
+ "inlines" => @listeners.map(&:to_hash)
104
+ },
105
+ "subnets" => @subnets.map { |s| s.name || s.subnet_id },
106
+ "security-groups" => @security_groups,
107
+ "internal" => @internal,
108
+ "tags" => @tags,
109
+ "manage-instances" => @manage_instances,
110
+ "health-check" => @health_check.to_hash,
111
+ "backend-policies" => @backend_policies.map do |backend_policy|
112
+ {
113
+ "port" => backend_policy.instance_port,
114
+ "policies" => backend_policy.policy_names
115
+ }
116
+ end,
117
+ "cross-zone" => @cross_zone,
118
+ "access-log" => if @access_log then @access_log.to_hash else @access_log end,
119
+ "connection-draining" => @connection_draining,
120
+ "idle-timeout" => @idle_timeout,
121
+ })
122
+ end
123
+
124
+ # Public: populates the fields of a LoadBalancerConfig from AWS config
125
+ #
126
+ # aws_elb - the elb
127
+ def populate!(aws_elb, aws_tags, aws_attributes)
128
+ @listeners = aws_elb.listener_descriptions.map do |l|
129
+ config = ListenerConfig.new
130
+ config.populate!(l)
131
+ config
132
+ end
133
+ @subnets = aws_elb.subnets.map { |subnet_id| EC2::id_subnets[subnet_id] }
134
+ @security_groups = aws_elb.security_groups.map do |sg_id|
135
+ SecurityGroups::id_security_groups[sg_id].group_name
136
+ end
137
+ @internal = aws_elb.scheme == "internal"
138
+ @tags = Hash[aws_tags.map do |tag|
139
+ [tag.key, tag.value]
140
+ end]
141
+ @manage_instances = aws_elb.instances.map { |i| i.instance_id }
142
+ @health_check = HealthCheckConfig.new
143
+ @health_check.populate!(aws_elb.health_check)
144
+ @backend_policies = aws_elb.backend_server_descriptions
145
+ @cross_zone = aws_attributes.cross_zone_load_balancing.enabled
146
+ @access_log = AccessLogConfig.new
147
+ @access_log.populate!(aws_attributes.access_log)
148
+ @connection_draining = aws_attributes.connection_draining.enabled && aws_attributes.connection_draining.timeout
149
+ @idle_timeout = aws_attributes.connection_settings.idle_timeout
150
+ end
151
+
152
+ # Public: Produce an array of differences between this local configuration and the
153
+ # configuration in AWS
154
+ #
155
+ # aws - the AWS resource
156
+ #
157
+ # Returns an array of the LoadBalancerDiffs that were found
158
+ def diff(aws)
159
+ diffs = []
160
+
161
+ listener_diff = LoadBalancerDiff.listeners(aws.listener_descriptions, @listeners)
162
+ if listener_diff
163
+ diffs << listener_diff
164
+ end
165
+
166
+ aws_subnets = aws.subnets.map { |subnet_id| EC2::id_subnets[subnet_id] }
167
+ if @subnets.sort != aws_subnets.sort
168
+ diffs << LoadBalancerDiff.subnets(aws_subnets, @subnets)
169
+ end
170
+
171
+ named_aws_security_groups = aws.security_groups.map do |sg_id|
172
+ SecurityGroups::id_security_groups[sg_id].group_name
173
+ end
174
+ if @security_groups.sort != named_aws_security_groups.sort
175
+ diffs << LoadBalancerDiff.security_groups(named_aws_security_groups, @security_groups)
176
+ end
177
+
178
+ aws_internal = (aws.scheme == "internal")
179
+ if @internal != aws_internal
180
+ diffs << LoadBalancerDiff.internal(aws_internal, @internal)
181
+ end
182
+
183
+ aws_tags = Hash[ELB::elb_tags(@name).map { |tag| [tag.key, tag.value] }]
184
+ if @tags != aws_tags
185
+ diffs << LoadBalancerDiff.tags(aws_tags, @tags)
186
+ end
187
+
188
+ aws_instances = (aws.instances || []).map { |i| i.instance_id }
189
+ if (@manage_instances != false) && @manage_instances.sort != aws_instances.sort
190
+ diffs << LoadBalancerDiff.instances(aws_instances, @manage_instances)
191
+ end
192
+
193
+ aws_health_check = aws.health_check
194
+ health_diffs = @health_check.diff(aws_health_check)
195
+ if !health_diffs.empty?
196
+ diffs << LoadBalancerDiff.health_check(health_diffs)
197
+ end
198
+
199
+ aws_backend_policies = aws.backend_server_descriptions
200
+ if @backend_policies.sort != aws_backend_policies.sort
201
+ diffs << LoadBalancerDiff.backend_policies(aws_backend_policies, @backend_policies)
202
+ end
203
+
204
+ aws_attributes = ELB::elb_attributes(@name)
205
+
206
+ aws_cross_zone = (aws_attributes.cross_zone_load_balancing.enabled) rescue false
207
+ if @cross_zone != aws_cross_zone
208
+ diffs << LoadBalancerDiff.new(LoadBalancerChange::CROSS, aws_cross_zone, @cross_zone)
209
+ end
210
+
211
+ aws_access_log = aws_attributes.access_log
212
+ if @access_log == false
213
+ if aws_access_log.enabled == true
214
+ log_diffs = (AccessLogConfig.new).diff(aws_access_log)
215
+ diffs << LoadBalancerDiff.access_log(log_diffs)
216
+ end
217
+ else
218
+ log_diffs = @access_log.diff(aws_access_log)
219
+ if !log_diffs.empty?
220
+ diffs << LoadBalancerDiff.access_log(log_diffs)
221
+ end
222
+ end
223
+
224
+ aws_connection_draining = if aws_attributes.connection_draining.enabled then aws_attributes.connection_draining.timeout else false end
225
+ if @connection_draining != aws_connection_draining
226
+ diffs << LoadBalancerDiff.new(LoadBalancerChange::DRAINING, aws_connection_draining, @connection_draining)
227
+ end
228
+
229
+ aws_idle_timeout = aws_attributes.connection_settings.idle_timeout
230
+ if @idle_timeout != aws_idle_timeout
231
+ diffs << LoadBalancerDiff.new(LoadBalancerChange::IDLE, aws_idle_timeout, @idle_timeout)
232
+ end
233
+
234
+ diffs.flatten
235
+ end
236
+
237
+ end
238
+ end
239
+ end
@@ -0,0 +1,265 @@
1
+ require "common/models/Diff"
2
+ require "common/models/ListChange"
3
+ require "elb/models/ListenerDiff"
4
+ require "util/Colors"
5
+
6
+ module Cumulus
7
+ module ELB
8
+ # Public: The types of changes that can be made to a load balancer
9
+ module LoadBalancerChange
10
+ include Common::DiffChange
11
+
12
+ LISTENERS = Common::DiffChange.next_change_id
13
+ SUBNETS = Common::DiffChange.next_change_id
14
+ SECURITY = Common::DiffChange.next_change_id
15
+ INTERNAL = Common::DiffChange.next_change_id
16
+ TAGS = Common::DiffChange.next_change_id
17
+ INSTANCES = Common::DiffChange.next_change_id
18
+ HEALTH = Common::DiffChange.next_change_id
19
+ BACKEND = Common::DiffChange.next_change_id
20
+ CROSS = Common::DiffChange.next_change_id
21
+ LOG = Common::DiffChange.next_change_id
22
+ DRAINING = Common::DiffChange.next_change_id
23
+ IDLE = Common::DiffChange.next_change_id
24
+ end
25
+
26
+ # Public: Represents a single difference between local configuration and
27
+ # an AWS Load Balancer.
28
+ class LoadBalancerDiff < Common::Diff
29
+ include LoadBalancerChange
30
+
31
+ attr_accessor :listeners
32
+ attr_accessor :subnets
33
+ attr_accessor :security_groups
34
+ attr_accessor :tags
35
+ attr_accessor :instances
36
+ attr_accessor :health_diffs
37
+ attr_accessor :backend_policies
38
+ attr_accessor :log_diffs
39
+
40
+ def self.listeners(aws, local)
41
+ # map listeners to load balancer port
42
+ aws_listeners = Hash[aws.map { |l| [l.listener.load_balancer_port, l] }]
43
+ local_listeners = Hash[local.map { |l| [l.load_balancer_port, l] }]
44
+
45
+ added_listeners = local_listeners.reject { |k, v| aws_listeners.has_key? k }
46
+ removed_listeners = aws_listeners.reject { |k, v| local_listeners.has_key? k }
47
+ modified_listeners = local_listeners.select { |k, v| aws_listeners.has_key? k }
48
+
49
+ added_diffs = Hash[added_listeners.map { |port, added| [port, ListenerDiff.added(added)] }]
50
+ removed_diffs = Hash[removed_listeners.map { |port, removed| [port, ListenerDiff.unmanaged(removed)] }]
51
+ modified_diffs = Hash[modified_listeners.map do |port, modified|
52
+ [port, modified.diff(aws_listeners[port])]
53
+ end].reject { |k, v| v.empty? }
54
+
55
+ if !added_diffs.empty? or !removed_diffs.empty? or !modified_diffs.empty?
56
+ diff = LoadBalancerDiff.new(LISTENERS, aws, local)
57
+ diff.listeners = Common::ListChange.new(added_diffs, removed_diffs, modified_diffs)
58
+ diff
59
+ end
60
+ end
61
+
62
+ def self.subnets(aws, local)
63
+ local_ids = local.map { |s| s.subnet_id }
64
+ aws_ids = aws.map { |s| s.subnet_id }
65
+
66
+ added = local.reject { |s| aws_ids.include? s.subnet_id }
67
+ removed = aws.reject { |s| local_ids.include? s.subnet_id }
68
+ diff = LoadBalancerDiff.new(SUBNETS, aws, local)
69
+ diff.subnets = Common::ListChange.new(added, removed)
70
+ diff
71
+ end
72
+
73
+ def self.security_groups(aws, local)
74
+ added = local - aws
75
+ removed = aws - local
76
+ diff = LoadBalancerDiff.new(SECURITY, aws, local)
77
+ diff.security_groups = Common::ListChange.new(added, removed)
78
+ diff
79
+ end
80
+
81
+ def self.internal(aws, local)
82
+ LoadBalancerDiff.new(INTERNAL, aws, local)
83
+ end
84
+
85
+ TagChange = Struct.new(:key, :aws, :local)
86
+ def self.tags(aws, local)
87
+ added = []
88
+ removed = []
89
+ modified = []
90
+
91
+ aws.each_pair do |key, val|
92
+ if local.has_key?(key)
93
+ if local[key] != val
94
+ modified << TagChange.new(key, val, local[key])
95
+ end
96
+ else
97
+ removed << TagChange.new(key, val, nil)
98
+ end
99
+ end
100
+
101
+ local.each_pair do |key, val|
102
+ if !aws.has_key?(key)
103
+ added << TagChange.new(key, nil, val)
104
+ end
105
+ end
106
+
107
+ diff = LoadBalancerDiff.new(TAGS, aws, local)
108
+ diff.tags = Common::ListChange.new(added, removed, modified)
109
+ diff
110
+ end
111
+
112
+ def self.instances(aws, local)
113
+ added = local - aws
114
+ removed = aws - local
115
+ diff = LoadBalancerDiff.new(INSTANCES, aws, local)
116
+ diff.instances = Common::ListChange.new(added, removed)
117
+ diff
118
+ end
119
+
120
+ def self.health_check(health_diffs)
121
+ diff = LoadBalancerDiff.new(HEALTH, nil, nil)
122
+ diff.health_diffs = health_diffs
123
+ diff
124
+ end
125
+
126
+ BackendChange = Struct.new(:port, :aws_policies, :local_policies)
127
+ def self.backend_policies(aws, local)
128
+ # map the aws and local policies to their ports
129
+ aws_backends = Hash[aws.map { |b| [b.instance_port, b.policy_names] }]
130
+ local_backends = Hash[local.map { |b| [b.instance_port, b.policy_names] }]
131
+
132
+ added = local_backends.reject { |port, _| aws_backends.has_key? port }.map do |port, policies|
133
+ BackendChange.new(port, nil, policies)
134
+ end
135
+ removed = aws_backends.reject { |port, _| local_backends.has_key? port }.map do |port, policies|
136
+ BackendChange.new(port, policies, nil)
137
+ end
138
+ modified = local_backends.reject { |port, _| !aws_backends.has_key? port }.map do |port, policies|
139
+ if aws_backends[port].sort != policies.sort
140
+ BackendChange.new(port, aws_backends[port], policies)
141
+ end
142
+ end.reject(&:nil?)
143
+
144
+ diff = LoadBalancerDiff.new(BACKEND, aws, local)
145
+ diff.backend_policies = Common::ListChange.new(added, removed, modified)
146
+ diff
147
+ end
148
+
149
+ def self.access_log(log_diffs)
150
+ diff = LoadBalancerDiff.new(LOG, nil, nil)
151
+ diff.log_diffs = log_diffs
152
+ diff
153
+ end
154
+
155
+ def asset_type
156
+ "Load Balancer"
157
+ end
158
+
159
+ def aws_name
160
+ @aws.load_balancer_name
161
+ end
162
+
163
+ def diff_string
164
+ case @type
165
+ when LISTENERS
166
+ [
167
+ "listeners:",
168
+ @listeners.removed.map { |_, diff| "\t#{diff}" },
169
+ @listeners.added.map { |_, diff| "\t#{diff}" },
170
+ @listeners.modified.map do |port, diffs|
171
+ [
172
+ "\tListener for port #{port}:",
173
+ diffs.map do |diff|
174
+ diff.to_s.lines.map { |l| "\t\t#{l}".chomp("\n") }
175
+ end
176
+ ].join("\n")
177
+ end
178
+ ].flatten.join("\n")
179
+ when SUBNETS
180
+ [
181
+ "subnets:",
182
+ @subnets.removed.map { |s| Colors.removed("\t#{s.subnet_id} (#{s.name})") },
183
+ @subnets.added.map { |s| Colors.added("\t#{s.subnet_id} (#{s.name})") },
184
+ ].flatten.join("\n")
185
+ when SECURITY
186
+ [
187
+ "security groups:",
188
+ @security_groups.removed.map { |s| Colors.removed("\t#{s}") },
189
+ @security_groups.added.map { |s| Colors.added("\t#{s}") },
190
+ ].flatten.join("\n")
191
+ when INTERNAL
192
+ [
193
+ "internal:",
194
+ Colors.aws_changes("\tAWS - #{aws}"),
195
+ Colors.local_changes("\tLocal - #{local}"),
196
+ ].join("\n")
197
+ when TAGS
198
+ [
199
+ "tags:",
200
+ @tags.removed.map { |t| Colors.removed("\t#{t.key}: #{t.aws}") },
201
+ @tags.added.map { |t| Colors.added("\t#{t.key}: #{t.local}") },
202
+ @tags.modified.map do |t|
203
+ [
204
+ "\t#{t.key}:",
205
+ Colors.aws_changes("(AWS) #{t.aws}"),
206
+ Colors.local_changes("(Local) #{t.local}")
207
+ ].join(" ")
208
+ end
209
+ ].flatten.join("\n")
210
+ when INSTANCES
211
+ [
212
+ "managed instances:",
213
+ @instances.removed.map { |i| Colors.removed("\t#{i}") },
214
+ @instances.added.map { |i| Colors.added("\t#{i}") },
215
+ ].flatten.join("\n")
216
+ when HEALTH
217
+ [
218
+ "health check:",
219
+ @health_diffs.map do |d|
220
+ d.to_s.lines.map { |l| "\t#{l}".chomp("\n") }
221
+ end
222
+ ].join("\n")
223
+ when BACKEND
224
+ [
225
+ "backend policies:",
226
+ @backend_policies.removed.map { |bc| Colors.removed("\tinstance port #{bc.port}: #{bc.aws_policies.join(" ")}") },
227
+ @backend_policies.added.map { |bc| Colors.added("\tinstance port #{bc.port}: #{bc.local_policies.join(" ")}") },
228
+ @backend_policies.modified.map do |bc|
229
+ [
230
+ "\tinstance port #{bc.port}:",
231
+ (bc.aws_policies - bc.local_policies).map { |p| Colors.removed("#{p}") },
232
+ (bc.local_policies - bc.aws_policies).map { |p| Colors.added("#{p}") },
233
+ ].flatten.join(" ")
234
+ end
235
+ ].flatten.join("\n")
236
+ when CROSS
237
+ [
238
+ "cross zone load balancing:",
239
+ Colors.aws_changes("\tAWS - #{aws}"),
240
+ Colors.local_changes("\tLocal - #{local}"),
241
+ ].flatten.join("\n")
242
+ when LOG
243
+ [
244
+ "access log:",
245
+ @log_diffs.map do |d|
246
+ d.to_s.lines.map { |l| "\t#{l}".chomp("\n") }
247
+ end
248
+ ].join("\n")
249
+ when DRAINING
250
+ [
251
+ "connection draining:",
252
+ Colors.aws_changes("\tAWS - #{aws}"),
253
+ Colors.local_changes("\tLocal - #{local}"),
254
+ ].join("\n")
255
+ when IDLE
256
+ [
257
+ "idle timeout:",
258
+ Colors.aws_changes("\tAWS - #{aws}"),
259
+ Colors.local_changes("\tLocal - #{local}"),
260
+ ].join("\n")
261
+ end
262
+ end
263
+ end
264
+ end
265
+ end