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,133 @@
1
+ require "conf/Configuration"
2
+ require "ec2/models/EbsGroupDiff"
3
+
4
+ require "json"
5
+
6
+ module Cumulus
7
+ module EC2
8
+
9
+ VolumeGroup = Struct.new(:size, :type, :iops, :count, :encrypted, :kms_key) do
10
+ def to_hash
11
+ {
12
+ "size" => self.size,
13
+ "type" => self.type,
14
+ "iops" => self.iops,
15
+ "count" => self.count,
16
+ "encrypted" => self.encrypted,
17
+ "kms-key" => self.kms_key
18
+ }.reject { |k, v| v.nil? }
19
+ end
20
+
21
+ def description
22
+ [
23
+ "#{self.size}GiB",
24
+ "#{self.type}",
25
+ if self.type == "io1" then "#{self.iops} IOPS" end,
26
+ if self.encrypted then "encrypted" else "unencrypted" end,
27
+ if self.kms_key then "KMS #{self.kms_key}" end,
28
+ ].reject(&:nil?).join("/")
29
+ end
30
+
31
+ def hash_key
32
+ "#{self.size}|#{self.type}|#{self.iops}|#{self.encrypted}|#{self.kms_key}"
33
+ end
34
+ end
35
+
36
+ # Public: An object representing configuration for a group of EBS volumes
37
+ class EbsGroupConfig
38
+ attr_reader :name
39
+ attr_reader :volume_groups
40
+ attr_reader :availability_zone
41
+
42
+ # Public: Constructor
43
+ #
44
+ # json - a hash containing the JSON configuration for the group
45
+ def initialize(name, json = nil)
46
+ @name = name
47
+ if !json.nil?
48
+ @availability_zone = json["availability-zone"]
49
+ @volume_groups = (json["volumes"] || []).map do |vg_json|
50
+ VolumeGroup.new(
51
+ vg_json["size"],
52
+ vg_json["type"],
53
+ if vg_json["type"] == "io1" then vg_json["iops"] end,
54
+ vg_json["count"],
55
+ vg_json["encrypted"] || false,
56
+ if vg_json["encrypted"] then vg_json["kms-key"] end
57
+ )
58
+ end
59
+ end
60
+ end
61
+
62
+ def to_hash
63
+ {
64
+ "availability-zone" => @availability_zone,
65
+ "volumes" => @volume_groups.map(&:to_hash),
66
+ }
67
+ end
68
+
69
+ # Public: Populate a config object with AWS configuration
70
+ #
71
+ # aws - the ebs volumes in the group. All volumes should be in the same AZ
72
+ def populate!(aws)
73
+ # Group the aws volumes by size, type, iops, encryped, kms-key
74
+ vol_groups = aws.group_by { |vol| "#{vol.size}|#{vol.volume_type}|#{vol.iops}|#{vol.encrypted}|#{vol.kms_key_id}" }
75
+
76
+ @volume_groups = vol_groups.map do |_, vols|
77
+ VolumeGroup.new(
78
+ vols.first.size,
79
+ vols.first.volume_type,
80
+ if vols.first.volume_type == "io1" then vols.first.iops end,
81
+ vols.length,
82
+ vols.first.encrypted,
83
+ vols.first.kms_key_id
84
+ )
85
+ end
86
+
87
+ # Get the AZ of the first volume
88
+ @availability_zone = aws.first.availability_zone
89
+
90
+ self
91
+ end
92
+
93
+ # Public: Produce an array of differences between this local configuration and the
94
+ # configuration in AWS
95
+ #
96
+ # aws - the AWS resource
97
+ #
98
+ # Returns an array of the EbsGroupDiffs that were found
99
+ def diff(aws)
100
+ diffs = []
101
+
102
+ if @availability_zone != aws.availability_zone
103
+ diffs << EbsGroupDiff.new(EbsGroupChange::AZ, aws.availability_zone, @availability_zone)
104
+ end
105
+
106
+ # Group the aws and local versions by hash_key
107
+ aws_grouped = Hash[aws.volume_groups.map { |vg| [vg.hash_key, vg] }]
108
+ local_grouped = Hash[@volume_groups.map { |vg| [vg.hash_key, vg] }]
109
+
110
+ # added
111
+ local_grouped.reject { |key, vg| aws_grouped.has_key? key }.each do |key, vg|
112
+ diffs << EbsGroupDiff.new(EbsGroupChange::VG_ADDED, nil, vg)
113
+ end
114
+
115
+ # removed
116
+ aws_grouped.reject { |key, vg| local_grouped.has_key? key }.each do |key, vg|
117
+ diffs << EbsGroupDiff.new(EbsGroupChange::VG_REMOVED, vg, nil)
118
+ end
119
+
120
+ # count is different
121
+ local_grouped.select { |key, vg| aws_grouped.has_key? key }.each do |key, local_vg|
122
+ aws_vg = aws_grouped[key]
123
+ if local_vg.count != aws_vg.count
124
+ diffs << EbsGroupDiff.new(EbsGroupDiff::VG_COUNT, aws_vg, local_vg)
125
+ end
126
+ end
127
+
128
+ diffs.sort_by { |diff| diff.type }
129
+ end
130
+
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,48 @@
1
+ require "common/models/Diff"
2
+ require "util/Colors"
3
+
4
+ require 'json'
5
+
6
+ module Cumulus
7
+ module EC2
8
+ # Public: The types of changes that can be made to an EBS volume group
9
+ module EbsGroupChange
10
+ include Common::DiffChange
11
+
12
+ AZ = Common::DiffChange.next_change_id
13
+ VG_ADDED = Common::DiffChange.next_change_id
14
+ VG_REMOVED = Common::DiffChange.next_change_id
15
+ VG_COUNT = Common::DiffChange.next_change_id
16
+ end
17
+
18
+ # Public: Represents a single difference between local configuration and AWS configuration
19
+ class EbsGroupDiff < Common::Diff
20
+ include EbsGroupChange
21
+
22
+ def asset_type
23
+ "EBS Volume Group"
24
+ end
25
+
26
+ def aws_name
27
+ @aws.name
28
+ end
29
+
30
+ def diff_string
31
+ case @type
32
+ when AZ
33
+ [
34
+ "Availability Zone:",
35
+ Colors.aws_changes("\tAWS - #{aws}"),
36
+ Colors.local_changes("\tLocal - #{local}"),
37
+ ].join("\n")
38
+ when VG_ADDED
39
+ Colors.added("Volume Group Added: #{local.count} x #{local.description}")
40
+ when VG_REMOVED
41
+ Colors.unmanaged("Volume Group Unmanaged: #{aws.count} x #{aws.description}")
42
+ when VG_COUNT
43
+ Colors.local_changes("Count changed from #{aws.count} to #{local.count}: #{local.description}")
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,202 @@
1
+ require "common/models/ListChange"
2
+ require "conf/Configuration"
3
+ require "ec2/models/EbsGroupConfig"
4
+ require "ec2/models/EbsGroupDiff"
5
+ require "ec2/models/InstanceDiff"
6
+ require "ec2/EC2"
7
+ require "security/SecurityGroups"
8
+
9
+ require "json"
10
+
11
+ module Cumulus
12
+ module EC2
13
+
14
+ # Public: An object representing configuration for a network interface
15
+ class InstanceConfig
16
+ attr_reader :name
17
+ attr_reader :ebs_optimized
18
+ attr_reader :placement_group
19
+ attr_reader :profile
20
+ attr_reader :image
21
+ attr_reader :key_name
22
+ attr_reader :monitoring
23
+ attr_reader :network_interfaces
24
+ attr_reader :source_dest_check
25
+ attr_reader :private_ip_address
26
+ attr_reader :security_groups
27
+ attr_reader :subnet
28
+ attr_reader :tenancy
29
+ attr_reader :type
30
+ attr_reader :user_data
31
+ attr_reader :volume_groups
32
+ attr_reader :tags
33
+
34
+ # Public: Constructor
35
+ #
36
+ # json - a hash containing the JSON configuration for the group
37
+ def initialize(name, json = nil)
38
+ @name = name
39
+ if !json.nil?
40
+ @ebs_optimized = json["ebs-optimized"] || false
41
+ @placement_group = json["placement-group"]
42
+ @profile = json["profile"]
43
+ @image = json["image"]
44
+ @key_name = json["key-name"]
45
+ @monitoring = json["monitoring"] || false
46
+ @network_interfaces = json["network-interfaces"] || 0
47
+ @source_dest_check = json["source-dest-check"]
48
+ @private_ip_address = json["private-ip-address"]
49
+ @security_groups = json["security-groups"] || []
50
+ @subnet = json["subnet"]
51
+ @tenancy = json["tenancy"] || "default"
52
+ @type = json["type"]
53
+ @user_data = json["user-data"]
54
+ @volume_groups = json["volume-groups"] || []
55
+ @tags = json["tags"] || {}
56
+ end
57
+ end
58
+
59
+ def to_hash
60
+ {
61
+ "ebs-optimized" => @ebs_optimized,
62
+ "placement-group" => @placement_group,
63
+ "profile" => @profile,
64
+ "image" => @image,
65
+ "key-name" => @key_name,
66
+ "monitoring" => @monitoring,
67
+ "network-interfaces" => @network_interfaces,
68
+ "source-dest-check" => @source_dest_check,
69
+ "private-ip-address" => @private_ip_address,
70
+ "security-groups" => @security_groups,
71
+ "subnet" => @subnet,
72
+ "tenancy" => @tenancy,
73
+ "type" => @type,
74
+ "user-data" => @user_data,
75
+ "volume-groups" => @volume_groups,
76
+ "tags" => @tags,
77
+ }
78
+ end
79
+
80
+ # Public: Populate a config object with AWS configuration
81
+ #
82
+ # aws_instance - the instance from AWS
83
+ # user_data_file - the name of the user data script file
84
+ # tags - a Hash of tags for the instance
85
+ def populate!(aws_instance, user_data_file, tags)
86
+ @ebs_optimized = aws_instance.ebs_optimized
87
+ @placement_group = aws_instance.placement.group_name
88
+ if @placement_group.empty? then @placement_group = nil end
89
+
90
+ profile_arn = (aws_instance.iam_instance_profile.arn rescue nil)
91
+ @profile = if profile_arn then profile_arn[profile_arn.rindex("/") + 1 .. profile_arn.length] end
92
+
93
+ @image = aws_instance.image_id
94
+ @key_name = aws_instance.key_name
95
+ @monitoring = ["enabled", "pending"].include? aws_instance.monitoring.state
96
+ @network_interfaces = aws_instance.network_interfaces.length
97
+ @source_dest_check = aws_instance.source_dest_check
98
+ @private_ip_address = aws_instance.private_ip_address
99
+ @security_groups = aws_instance.security_groups.map(&:group_id).map { |id| SecurityGroups::id_security_groups[id].group_name }.sort
100
+ @subnet = EC2::id_subnets[aws_instance.subnet_id].name
101
+ @tenancy = aws_instance.placement.tenancy
102
+ @type = aws_instance.instance_type
103
+ @user_data = user_data_file
104
+
105
+ # Get the volumes for each device mapping
106
+ @volume_groups = aws_instance.nonroot_devices.map do |m|
107
+ EC2::id_ebs_volumes[m.ebs.volume_id]
108
+ end.map(&:group).reject(&:nil?).uniq.sort
109
+
110
+ @tags = tags
111
+
112
+ self
113
+ end
114
+
115
+ # Public: Produce an array of differences between this local configuration and the
116
+ # configuration in AWS
117
+ #
118
+ # aws - the AWS resource
119
+ #
120
+ # Returns an array of the InterfaceDiffs that were found
121
+ def diff(aws)
122
+ diffs = []
123
+
124
+ if aws.ebs_optimized != @ebs_optimized
125
+ diffs << InstanceDiff.new(InstanceChange::EBS, aws.ebs_optimized, @ebs_optimized)
126
+ end
127
+
128
+ if aws.profile != @profile
129
+ diffs << InstanceDiff.new(InstanceChange::PROFILE, aws.profile, @profile)
130
+ end
131
+
132
+ if aws.monitoring != @monitoring
133
+ diffs << InstanceDiff.new(InstanceChange::MONITORING, aws.monitoring, @monitoring)
134
+ end
135
+
136
+ if aws.network_interfaces != @network_interfaces
137
+ diffs << InstanceDiff.new(InstanceChange::INTERFACES, aws.network_interfaces, @network_interfaces)
138
+ end
139
+
140
+ if aws.source_dest_check != @source_dest_check
141
+ diffs << InstanceDiff.new(InstanceChange::SDCHECK, aws.source_dest_check, @source_dest_check)
142
+ end
143
+
144
+ if aws.security_groups.sort != @security_groups.sort
145
+ changes = Common::ListChange::simple_list_diff(aws.security_groups, @security_groups)
146
+ diffs << InstanceDiff.new(InstanceChange::SECURITY_GROUPS, aws.security_groups, @security_groups, changes)
147
+ end
148
+
149
+ if aws.subnet != @subnet
150
+ diffs << InstanceDiff.new(InstanceChange::SUBNET, aws.subnet, @subnet)
151
+ end
152
+
153
+ if aws.type != @type
154
+ diffs << InstanceDiff.new(InstanceChange::TYPE, aws.type, @type)
155
+ end
156
+
157
+ if aws.tenancy != @tenancy
158
+ diffs << InstanceDiff.new(InstanceChange::TENANCY, aws.tenancy, @tenancy)
159
+ end
160
+
161
+ if aws.tags != @tags
162
+ diffs << InstanceDiff.new(InstanceChange::TAGS, aws.tags, @tags)
163
+ end
164
+
165
+ # Check for diffs in volume groups and diffs in how many volumes are attached
166
+
167
+ # Get the volumes that are attached to the instance
168
+ aws_instance = EC2::named_instances[aws.name]
169
+ attached_volumes = aws_instance.nonroot_devices.map do |m|
170
+ EC2::id_ebs_volumes[m.ebs.volume_id]
171
+ end
172
+ # Group by volume group, reject nil groups
173
+ group_volumes = attached_volumes.group_by(&:group).reject { |k, v| k.nil? }
174
+
175
+ aws_ebs_groups = Hash[group_volumes.map { |group, vols| [group, EbsGroupConfig.new(group).populate!(vols)] }]
176
+ local_ebs_groups = Hash[@volume_groups.map { |vg| [vg, EC2::group_ebs_volumes[vg]] }]
177
+
178
+ added_groups = Hash[local_ebs_groups.reject { |k, v| aws_ebs_groups.has_key?(k) }.map do |group_name, group_config|
179
+ [group_name, EbsGroupDiff.added(group_config)]
180
+ end]
181
+ removed_groups = Hash[aws_ebs_groups.reject { |k, v| aws_ebs_groups.has_key?(k) }.map do |group_name, group_config|
182
+ [group_name, EbsGroupDiff.unmanaged(group_config)]
183
+ end]
184
+ changed_groups = Hash[local_ebs_groups.select { |k, v| aws_ebs_groups.has_key?(k) }.map do |group_name, group_config|
185
+ aws_config = aws_ebs_groups[group_name]
186
+ group_diffs = group_config.diff(aws_config)
187
+ if !group_diffs.empty?
188
+ [group_name, EbsGroupDiff.modified(aws_config, group_config, group_diffs)]
189
+ end
190
+ end].reject { |k, v| v.nil? }
191
+
192
+ ebs_changes = Common::ListChange.new(added_groups, removed_groups, changed_groups)
193
+ if !ebs_changes.empty?
194
+ diffs << InstanceDiff.new(InstanceChange::VOLUME_GROUPS, aws_ebs_groups, local_ebs_groups, ebs_changes)
195
+ end
196
+
197
+ diffs
198
+ end
199
+
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,95 @@
1
+ require "common/models/Diff"
2
+ require "common/models/TagsDiff"
3
+ require "util/Colors"
4
+
5
+ require 'json'
6
+
7
+ module Cumulus
8
+ module EC2
9
+ # Public: The types of changes that can be made to an EBS volume group
10
+ module InstanceChange
11
+ include Common::DiffChange
12
+
13
+ EBS = Common::DiffChange.next_change_id
14
+ PROFILE = Common::DiffChange.next_change_id
15
+ MONITORING = Common::DiffChange.next_change_id
16
+ INTERFACES = Common::DiffChange.next_change_id
17
+ SDCHECK = Common::DiffChange.next_change_id
18
+ SECURITY_GROUPS = Common::DiffChange.next_change_id
19
+ SUBNET = Common::DiffChange.next_change_id
20
+ TYPE = Common::DiffChange.next_change_id
21
+ TENANCY = Common::DiffChange.next_change_id
22
+ VOLUME_GROUPS = Common::DiffChange.next_change_id
23
+ TAGS = Common::DiffChange.next_change_id
24
+ end
25
+
26
+ # Public: Represents a single difference between local configuration and AWS configuration
27
+ class InstanceDiff < Common::Diff
28
+ include InstanceChange
29
+ include Common::TagsDiff
30
+
31
+ def asset_type
32
+ case @type
33
+ when EBS then "EBS Optimized"
34
+ when PROFILE then "Instance Profile"
35
+ when MONITORING then "Monitoring"
36
+ when INTERFACES then "Network Interfaces"
37
+ when SDCHECK then "Source Dest Check"
38
+ when SECURITY_GROUPS then "Security Groups"
39
+ when SUBNET then "Subnet"
40
+ when TYPE then "Type"
41
+ when TENANCY then "Tenancy"
42
+ when VOLUME_GROUPS then "Volume Groups"
43
+ when TAGS then "Tags"
44
+ else
45
+ "EC2 Instance"
46
+ end
47
+ end
48
+
49
+ def aws_name
50
+ @aws.name
51
+ end
52
+
53
+ def local_tags
54
+ @local
55
+ end
56
+
57
+ def aws_tags
58
+ @aws
59
+ end
60
+
61
+ def diff_string
62
+ case @type
63
+ when EBS, PROFILE, MONITORING, INTERFACES, SDCHECK, SUBNET, TYPE, TENANCY
64
+ [
65
+ "#{asset_type}:",
66
+ Colors.aws_changes("\tAWS - #{aws}"),
67
+ Colors.local_changes("\tLocal - #{local}"),
68
+ ].join("\n")
69
+ when SECURITY_GROUPS
70
+ [
71
+ "#{asset_type}:",
72
+ @changes.removed.map { |sg| Colors.unmanaged("\t#{sg}") },
73
+ @changes.added.map { |sg| Colors.added("\t#{sg}") }
74
+ ].flatten.join("\n")
75
+ when VOLUME_GROUPS
76
+ [
77
+ "#{asset_type}:",
78
+ @changes.removed.map { |vg, _| Colors.unmanaged("\t#{vg} is attached but not managed by Cumulus") },
79
+ @changes.added.map { |vg, _| Colors.added("\t#{vg} will be attached to the instance") },
80
+ @changes.modified.map do |vg, diff|
81
+ [
82
+ "\t#{vg}:",
83
+ diff.changes.map do |diff|
84
+ diff.to_s.lines.map { |l| "\t\t#{l}".chomp("\n") }
85
+ end
86
+ ]
87
+ end
88
+ ].flatten.join("\n")
89
+ when TAGS
90
+ tags_diff_string
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end