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.
- checksums.yaml +15 -0
- data/.gitignore +3 -0
- data/.travis.yml +12 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +29 -0
- data/LICENSE +202 -0
- data/README.md +41 -0
- data/autocomplete +137 -0
- data/bin/cumulus +658 -0
- data/cumulus +2 -0
- data/cumulus-aws.gemspec +20 -0
- data/lib/autoscaling/AutoScaling.rb +40 -0
- data/lib/autoscaling/loader/Loader.rb +56 -0
- data/lib/autoscaling/manager/Manager.rb +360 -0
- data/lib/autoscaling/models/AlarmConfig.rb +165 -0
- data/lib/autoscaling/models/AlarmDiff.rb +172 -0
- data/lib/autoscaling/models/AutoScalingDiff.rb +178 -0
- data/lib/autoscaling/models/GroupConfig.rb +330 -0
- data/lib/autoscaling/models/PolicyConfig.rb +135 -0
- data/lib/autoscaling/models/PolicyDiff.rb +73 -0
- data/lib/autoscaling/models/ScheduledActionDiff.rb +53 -0
- data/lib/autoscaling/models/ScheduledConfig.rb +96 -0
- data/lib/aws_extensions/ec2/DhcpOptions.rb +41 -0
- data/lib/aws_extensions/ec2/Instance.rb +29 -0
- data/lib/aws_extensions/ec2/NetworkAcl.rb +25 -0
- data/lib/aws_extensions/ec2/NetworkInterface.rb +14 -0
- data/lib/aws_extensions/ec2/RouteTable.rb +26 -0
- data/lib/aws_extensions/ec2/SecurityGroup.rb +16 -0
- data/lib/aws_extensions/ec2/Subnet.rb +28 -0
- data/lib/aws_extensions/ec2/Volume.rb +24 -0
- data/lib/aws_extensions/ec2/Vpc.rb +14 -0
- data/lib/aws_extensions/ec2/VpcEndpoint.rb +11 -0
- data/lib/aws_extensions/elb/BackendServerDescription.rb +12 -0
- data/lib/aws_extensions/elb/PolicyDescription.rb +14 -0
- data/lib/aws_extensions/kinesis/StreamDescription.rb +12 -0
- data/lib/aws_extensions/route53/AliasTarget.rb +21 -0
- data/lib/aws_extensions/s3/Bucket.rb +33 -0
- data/lib/aws_extensions/s3/BucketAcl.rb +28 -0
- data/lib/aws_extensions/s3/BucketCors.rb +17 -0
- data/lib/aws_extensions/s3/BucketLifecycle.rb +21 -0
- data/lib/aws_extensions/s3/BucketLogging.rb +18 -0
- data/lib/aws_extensions/s3/BucketNotification.rb +23 -0
- data/lib/aws_extensions/s3/BucketPolicy.rb +18 -0
- data/lib/aws_extensions/s3/BucketTagging.rb +15 -0
- data/lib/aws_extensions/s3/BucketVersioning.rb +14 -0
- data/lib/aws_extensions/s3/BucketWebsite.rb +49 -0
- data/lib/aws_extensions/s3/CORSRule.rb +27 -0
- data/lib/aws_extensions/s3/ReplicationConfiguration.rb +22 -0
- data/lib/cloudfront/CloudFront.rb +83 -0
- data/lib/cloudfront/loader/Loader.rb +31 -0
- data/lib/cloudfront/manager/Manager.rb +183 -0
- data/lib/cloudfront/models/CacheBehaviorConfig.rb +237 -0
- data/lib/cloudfront/models/CacheBehaviorDiff.rb +211 -0
- data/lib/cloudfront/models/CustomOriginConfig.rb +51 -0
- data/lib/cloudfront/models/CustomOriginDiff.rb +74 -0
- data/lib/cloudfront/models/DistributionConfig.rb +183 -0
- data/lib/cloudfront/models/DistributionDiff.rb +131 -0
- data/lib/cloudfront/models/InvalidationConfig.rb +37 -0
- data/lib/cloudfront/models/OriginConfig.rb +144 -0
- data/lib/cloudfront/models/OriginDiff.rb +86 -0
- data/lib/cloudfront/models/OriginSslProtocols.rb +28 -0
- data/lib/cloudfront/models/OriginSslProtocolsDiff.rb +39 -0
- data/lib/common/BaseLoader.rb +80 -0
- data/lib/common/manager/Manager.rb +148 -0
- data/lib/common/models/Diff.rb +114 -0
- data/lib/common/models/ListChange.rb +21 -0
- data/lib/common/models/TagsDiff.rb +55 -0
- data/lib/common/models/UTCTimeSource.rb +17 -0
- data/lib/conf/Configuration.rb +365 -0
- data/lib/ec2/EC2.rb +503 -0
- data/lib/ec2/IPProtocolMapping.rb +165 -0
- data/lib/ec2/loaders/EbsLoader.rb +19 -0
- data/lib/ec2/loaders/InstanceLoader.rb +32 -0
- data/lib/ec2/managers/EbsManager.rb +176 -0
- data/lib/ec2/managers/InstanceManager.rb +509 -0
- data/lib/ec2/models/EbsGroupConfig.rb +133 -0
- data/lib/ec2/models/EbsGroupDiff.rb +48 -0
- data/lib/ec2/models/InstanceConfig.rb +202 -0
- data/lib/ec2/models/InstanceDiff.rb +95 -0
- data/lib/elb/ELB.rb +148 -0
- data/lib/elb/loader/Loader.rb +65 -0
- data/lib/elb/manager/Manager.rb +581 -0
- data/lib/elb/models/AccessLogConfig.rb +82 -0
- data/lib/elb/models/AccessLogDiff.rb +47 -0
- data/lib/elb/models/HealthCheckConfig.rb +91 -0
- data/lib/elb/models/HealthCheckDiff.rb +50 -0
- data/lib/elb/models/ListenerConfig.rb +99 -0
- data/lib/elb/models/ListenerDiff.rb +91 -0
- data/lib/elb/models/LoadBalancerConfig.rb +239 -0
- data/lib/elb/models/LoadBalancerDiff.rb +265 -0
- data/lib/iam/IAM.rb +36 -0
- data/lib/iam/loader/Loader.rb +117 -0
- data/lib/iam/manager/IamGroups.rb +98 -0
- data/lib/iam/manager/IamResource.rb +288 -0
- data/lib/iam/manager/IamRoles.rb +112 -0
- data/lib/iam/manager/IamUsers.rb +54 -0
- data/lib/iam/manager/Manager.rb +29 -0
- data/lib/iam/migration/AssumeRoleUnifier.rb +34 -0
- data/lib/iam/migration/PolicyUnifier.rb +90 -0
- data/lib/iam/models/GroupConfig.rb +40 -0
- data/lib/iam/models/IamDiff.rb +132 -0
- data/lib/iam/models/PolicyConfig.rb +67 -0
- data/lib/iam/models/ResourceWithPolicy.rb +208 -0
- data/lib/iam/models/RoleConfig.rb +53 -0
- data/lib/iam/models/StatementConfig.rb +35 -0
- data/lib/iam/models/UserConfig.rb +21 -0
- data/lib/kinesis/Kinesis.rb +94 -0
- data/lib/kinesis/loader/Loader.rb +19 -0
- data/lib/kinesis/manager/Manager.rb +206 -0
- data/lib/kinesis/models/StreamConfig.rb +75 -0
- data/lib/kinesis/models/StreamDiff.rb +58 -0
- data/lib/lambda/Lambda.rb +41 -0
- data/lib/route53/loader/Loader.rb +32 -0
- data/lib/route53/manager/Manager.rb +241 -0
- data/lib/route53/models/AliasTarget.rb +86 -0
- data/lib/route53/models/RecordConfig.rb +178 -0
- data/lib/route53/models/RecordDiff.rb +140 -0
- data/lib/route53/models/Vpc.rb +24 -0
- data/lib/route53/models/ZoneConfig.rb +156 -0
- data/lib/route53/models/ZoneDiff.rb +118 -0
- data/lib/s3/S3.rb +89 -0
- data/lib/s3/loader/Loader.rb +66 -0
- data/lib/s3/manager/Manager.rb +296 -0
- data/lib/s3/models/BucketConfig.rb +321 -0
- data/lib/s3/models/BucketDiff.rb +167 -0
- data/lib/s3/models/GrantConfig.rb +189 -0
- data/lib/s3/models/GrantDiff.rb +50 -0
- data/lib/s3/models/LifecycleConfig.rb +142 -0
- data/lib/s3/models/LifecycleDiff.rb +46 -0
- data/lib/s3/models/LoggingConfig.rb +81 -0
- data/lib/s3/models/NotificationConfig.rb +157 -0
- data/lib/s3/models/NotificationDiff.rb +62 -0
- data/lib/s3/models/ReplicationConfig.rb +133 -0
- data/lib/s3/models/ReplicationDiff.rb +60 -0
- data/lib/s3/models/WebsiteConfig.rb +107 -0
- data/lib/security/SecurityGroups.rb +39 -0
- data/lib/security/loader/Loader.rb +94 -0
- data/lib/security/manager/Manager.rb +246 -0
- data/lib/security/models/RuleConfig.rb +161 -0
- data/lib/security/models/RuleDiff.rb +72 -0
- data/lib/security/models/RuleMigration.rb +127 -0
- data/lib/security/models/SecurityGroupConfig.rb +172 -0
- data/lib/security/models/SecurityGroupDiff.rb +112 -0
- data/lib/sns/SNS.rb +40 -0
- data/lib/sqs/SQS.rb +62 -0
- data/lib/sqs/loader/Loader.rb +34 -0
- data/lib/sqs/manager/Manager.rb +128 -0
- data/lib/sqs/models/DeadLetterConfig.rb +70 -0
- data/lib/sqs/models/DeadLetterDiff.rb +35 -0
- data/lib/sqs/models/QueueConfig.rb +115 -0
- data/lib/sqs/models/QueueDiff.rb +89 -0
- data/lib/util/Colors.rb +111 -0
- data/lib/util/StatusCodes.rb +51 -0
- data/lib/vpc/loader/Loader.rb +73 -0
- data/lib/vpc/manager/Manager.rb +954 -0
- data/lib/vpc/models/AclEntryConfig.rb +150 -0
- data/lib/vpc/models/AclEntryDiff.rb +54 -0
- data/lib/vpc/models/DhcpConfig.rb +100 -0
- data/lib/vpc/models/DhcpDiff.rb +90 -0
- data/lib/vpc/models/EndpointConfig.rb +76 -0
- data/lib/vpc/models/EndpointDiff.rb +69 -0
- data/lib/vpc/models/NetworkAclConfig.rb +87 -0
- data/lib/vpc/models/NetworkAclDiff.rb +116 -0
- data/lib/vpc/models/RouteConfig.rb +82 -0
- data/lib/vpc/models/RouteDiff.rb +50 -0
- data/lib/vpc/models/RouteTableConfig.rb +92 -0
- data/lib/vpc/models/RouteTableDiff.rb +101 -0
- data/lib/vpc/models/SubnetConfig.rb +113 -0
- data/lib/vpc/models/SubnetDiff.rb +78 -0
- data/lib/vpc/models/VpcConfig.rb +173 -0
- data/lib/vpc/models/VpcDiff.rb +315 -0
- data/rakefile.rb +8 -0
- metadata +245 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require "common/models/Diff"
|
|
2
|
+
require "util/Colors"
|
|
3
|
+
|
|
4
|
+
module Cumulus
|
|
5
|
+
module SQS
|
|
6
|
+
# Public: The types of changes that can be made to a dead letter config
|
|
7
|
+
module QueueChange
|
|
8
|
+
include Common::DiffChange
|
|
9
|
+
|
|
10
|
+
DELAY = Common::DiffChange.next_change_id
|
|
11
|
+
MESSAGE_SIZE = Common::DiffChange.next_change_id
|
|
12
|
+
MESSAGE_RETENTION = Common::DiffChange.next_change_id
|
|
13
|
+
RECEIVE_WAIT = Common::DiffChange.next_change_id
|
|
14
|
+
VISIBILITY = Common::DiffChange.next_change_id
|
|
15
|
+
DEAD = Common::DiffChange.next_change_id
|
|
16
|
+
POLICY = Common::DiffChange.next_change_id
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Public: Represents a single difference between local configuration and AWS configuration
|
|
20
|
+
class QueueDiff < Common::Diff
|
|
21
|
+
include QueueChange
|
|
22
|
+
|
|
23
|
+
def asset_type
|
|
24
|
+
"Queue"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def aws_name
|
|
28
|
+
@aws.name
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def diff_string
|
|
32
|
+
case @type
|
|
33
|
+
when DELAY
|
|
34
|
+
[
|
|
35
|
+
"Delay",
|
|
36
|
+
Colors.aws_changes("\tAWS - #{aws} seconds"),
|
|
37
|
+
Colors.local_changes("\tLocal - #{local} seconds")
|
|
38
|
+
].join("\n")
|
|
39
|
+
when MESSAGE_SIZE
|
|
40
|
+
[
|
|
41
|
+
"Max Message Size",
|
|
42
|
+
Colors.aws_changes("\tAWS - #{aws} bytes"),
|
|
43
|
+
Colors.local_changes("\tLocal - #{local} bytes")
|
|
44
|
+
].join("\n")
|
|
45
|
+
when MESSAGE_RETENTION
|
|
46
|
+
[
|
|
47
|
+
"Message Retention Period",
|
|
48
|
+
Colors.aws_changes("\tAWS - #{aws} seconds"),
|
|
49
|
+
Colors.local_changes("\tLocal - #{local} seconds")
|
|
50
|
+
].join("\n")
|
|
51
|
+
when RECEIVE_WAIT
|
|
52
|
+
[
|
|
53
|
+
"Receive Wait Time",
|
|
54
|
+
Colors.aws_changes("\tAWS - #{aws} seconds"),
|
|
55
|
+
Colors.local_changes("\tLocal - #{local} seconds")
|
|
56
|
+
].join("\n")
|
|
57
|
+
when VISIBILITY
|
|
58
|
+
[
|
|
59
|
+
"Message Visibility",
|
|
60
|
+
Colors.aws_changes("\tAWS - #{aws} seconds"),
|
|
61
|
+
Colors.local_changes("\tLocal - #{local} seconds")
|
|
62
|
+
].join("\n")
|
|
63
|
+
when DEAD
|
|
64
|
+
[
|
|
65
|
+
"Dead Letter Queue",
|
|
66
|
+
@changes.join("\n").lines.map { |l| "\t#{l}".chomp("\n") }
|
|
67
|
+
].flatten.join("\n")
|
|
68
|
+
when POLICY
|
|
69
|
+
[
|
|
70
|
+
"Policy:",
|
|
71
|
+
if aws
|
|
72
|
+
Colors.unmanaged([
|
|
73
|
+
"\tRemoving:",
|
|
74
|
+
JSON.pretty_generate(aws).lines.map { |l| "\t\t#{l}".chomp("\n") }
|
|
75
|
+
].join("\n"))
|
|
76
|
+
end,
|
|
77
|
+
if local
|
|
78
|
+
Colors.added([
|
|
79
|
+
"\tAdding:",
|
|
80
|
+
JSON.pretty_generate(local).lines.map { |l| "\t\t#{l}".chomp("\n") }
|
|
81
|
+
].join("\n"))
|
|
82
|
+
end
|
|
83
|
+
].reject(&:nil?).join("\n")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
data/lib/util/Colors.rb
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require "conf/Configuration"
|
|
2
|
+
|
|
3
|
+
module Cumulus
|
|
4
|
+
# Public: Provides methods for creating strings with different colors in the
|
|
5
|
+
# console.
|
|
6
|
+
class Colors
|
|
7
|
+
@@colors_enabled = Configuration.instance.colors_enabled
|
|
8
|
+
@@color_prefix = "\033["
|
|
9
|
+
@@no_color = "#{@@color_prefix}0m"
|
|
10
|
+
@@red = "#{@@color_prefix}0;31m"
|
|
11
|
+
@@green = "#{@@color_prefix}0;32m"
|
|
12
|
+
@@orange = "#{@@color_prefix}1;33m"
|
|
13
|
+
@@blue = "#{@@color_prefix}1;34m"
|
|
14
|
+
|
|
15
|
+
# Public: color format a string that describes an added resource
|
|
16
|
+
#
|
|
17
|
+
# s - the string to format
|
|
18
|
+
#
|
|
19
|
+
# Returns the formatted string
|
|
20
|
+
def self.added(s)
|
|
21
|
+
self.green(s)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Public: color format a string that describes an unmanaged resource
|
|
25
|
+
#
|
|
26
|
+
# s - the string to format
|
|
27
|
+
#
|
|
28
|
+
# Returns the formatted string
|
|
29
|
+
def self.unmanaged(s)
|
|
30
|
+
self.red(s)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Public: color format a string the describes a removed resource
|
|
34
|
+
#
|
|
35
|
+
# s - the string to format
|
|
36
|
+
#
|
|
37
|
+
# Returns the formatted string
|
|
38
|
+
def self.removed(s)
|
|
39
|
+
self.red(s)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Public: color format a string that describes the changes in AWS
|
|
43
|
+
#
|
|
44
|
+
# s - the string to format
|
|
45
|
+
#
|
|
46
|
+
# Returns the formatted string
|
|
47
|
+
def self.aws_changes(s)
|
|
48
|
+
self.blue(s)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Public: color format a string that describes the local changes
|
|
52
|
+
#
|
|
53
|
+
# s - the string to format
|
|
54
|
+
#
|
|
55
|
+
# Returns the formatted string
|
|
56
|
+
def self.local_changes(s)
|
|
57
|
+
self.orange(s)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Public: create a string that has a specific color. Will not output color
|
|
61
|
+
# if `colors_enabled` is set to false. This can be set in "configuration.json"
|
|
62
|
+
#
|
|
63
|
+
# s - the string to format
|
|
64
|
+
# color - the color to use
|
|
65
|
+
#
|
|
66
|
+
# Returns the formatted string
|
|
67
|
+
def self.colorize(s, color)
|
|
68
|
+
if @@colors_enabled
|
|
69
|
+
"#{color}#{s}#{@@no_color}"
|
|
70
|
+
else
|
|
71
|
+
s
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Public: Create a string that is red.
|
|
76
|
+
#
|
|
77
|
+
# s - the string to format
|
|
78
|
+
#
|
|
79
|
+
# Returns the red string
|
|
80
|
+
def self.red(s)
|
|
81
|
+
Colors.colorize(s, @@red)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Public: Create a string that is green.
|
|
85
|
+
#
|
|
86
|
+
# s - the string to format
|
|
87
|
+
#
|
|
88
|
+
# Returns the green string
|
|
89
|
+
def self.green(s)
|
|
90
|
+
Colors.colorize(s, @@green)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Public: Create a string that is blue.
|
|
94
|
+
#
|
|
95
|
+
# s - the string to format
|
|
96
|
+
#
|
|
97
|
+
# Returns the blue string
|
|
98
|
+
def self.blue(s)
|
|
99
|
+
Colors.colorize(s, @@blue)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Public: Create a string that is orange.
|
|
103
|
+
#
|
|
104
|
+
# s - the string to format
|
|
105
|
+
#
|
|
106
|
+
# Returns the orange string
|
|
107
|
+
def self.orange(s)
|
|
108
|
+
Colors.colorize(s, @@orange)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Cumulus
|
|
2
|
+
|
|
3
|
+
# Public: Provide methods for setting the status code that
|
|
4
|
+
# Cumulus should exit with
|
|
5
|
+
module StatusCodes
|
|
6
|
+
|
|
7
|
+
# Indicates that we are exiting normally
|
|
8
|
+
OK = 0
|
|
9
|
+
|
|
10
|
+
# Indicates there was an exception during execution
|
|
11
|
+
EXCEPTION = 1
|
|
12
|
+
|
|
13
|
+
# Indicates that there were diffs
|
|
14
|
+
DIFFS = 2
|
|
15
|
+
|
|
16
|
+
# Indicates that there were diffs and they were synced
|
|
17
|
+
SYNC_DIFFS = 3
|
|
18
|
+
|
|
19
|
+
# Static attributes and methods for keeping track of status codes
|
|
20
|
+
class << self
|
|
21
|
+
# Holds the value for the current status
|
|
22
|
+
@@CURRENT_STATUS = OK
|
|
23
|
+
|
|
24
|
+
# Public: Sets the status code if it is more severe than the current status code
|
|
25
|
+
def set_status(status)
|
|
26
|
+
|
|
27
|
+
# Only set the status if we are not already in exception state
|
|
28
|
+
if @@CURRENT_STATUS != EXCEPTION
|
|
29
|
+
|
|
30
|
+
# Only set the status if it is more severe (higher) than the current status
|
|
31
|
+
if status > @@CURRENT_STATUS
|
|
32
|
+
@@CURRENT_STATUS = status
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# On exit, if the exit was successful, exit with the
|
|
39
|
+
# status codes that describes what happened while running
|
|
40
|
+
at_exit do
|
|
41
|
+
|
|
42
|
+
if $!.nil? || ($!.is_a?(SystemExit) && $!.success?)
|
|
43
|
+
exit @@CURRENT_STATUS
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require "common/BaseLoader"
|
|
2
|
+
require "conf/Configuration"
|
|
3
|
+
require "vpc/models/RouteTableConfig"
|
|
4
|
+
require "vpc/models/SubnetConfig"
|
|
5
|
+
require "vpc/models/VpcConfig"
|
|
6
|
+
|
|
7
|
+
require "aws-sdk"
|
|
8
|
+
|
|
9
|
+
# Public: Load VPC assets
|
|
10
|
+
module Cumulus
|
|
11
|
+
module VPC
|
|
12
|
+
module Loader
|
|
13
|
+
include Common::BaseLoader
|
|
14
|
+
|
|
15
|
+
@@vpcs_dir = Configuration.instance.vpc.vpcs_directory
|
|
16
|
+
@@subnets_dir = Configuration.instance.vpc.subnets_directory
|
|
17
|
+
@@route_tables_dir = Configuration.instance.vpc.route_tables_directory
|
|
18
|
+
@@policies_dir = Configuration.instance.vpc.policies_directory
|
|
19
|
+
@@network_acls_dir = Configuration.instance.vpc.network_acls_directory
|
|
20
|
+
|
|
21
|
+
# Public: Load all the VPC configurations as VpcConfig objects
|
|
22
|
+
#
|
|
23
|
+
# Returns an array of VpcConfig
|
|
24
|
+
def self.vpcs
|
|
25
|
+
Common::BaseLoader::resources(@@vpcs_dir, &VpcConfig.method(:new))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Public: Load a single VPC configuration
|
|
29
|
+
#
|
|
30
|
+
# Returns a VpcConfig
|
|
31
|
+
def self.vpc(vpc_name)
|
|
32
|
+
Common::BaseLoader::resource(vpc_name, @@vpcs_dir, &VpcConfig.method(:new))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Public: Load the specified policy as a JSON object
|
|
36
|
+
#
|
|
37
|
+
# Returns the JSON object for the policy
|
|
38
|
+
def self.policy(policy_name)
|
|
39
|
+
Common::BaseLoader::resource(policy_name, @@policies_dir) do |policy_name, policy|
|
|
40
|
+
policy
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Public: Load all subnets as SubnetConfig objects
|
|
45
|
+
#
|
|
46
|
+
# Returns an array of SubnetConfig
|
|
47
|
+
def self.subnets
|
|
48
|
+
Common::BaseLoader::resources(@@subnets_dir, &SubnetConfig.method(:new))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Public: Load a subnet as a SubnetConfig
|
|
52
|
+
#
|
|
53
|
+
# Returns the SubnetConfig
|
|
54
|
+
def self.subnet(subnet_name)
|
|
55
|
+
Common::BaseLoader::resource(subnet_name, @@subnets_dir, &SubnetConfig.method(:new))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Public: Load a route table as a RouteTableConfig
|
|
59
|
+
#
|
|
60
|
+
# Returns the RouteTableConfig
|
|
61
|
+
def self.route_table(rt_name)
|
|
62
|
+
Common::BaseLoader::resource(rt_name, @@route_tables_dir, &RouteTableConfig.method(:new))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Public: Load a network acl as a NetworkAclConfig
|
|
66
|
+
#
|
|
67
|
+
# Returns the NetworkAclConfig
|
|
68
|
+
def self.network_acl(acl_name)
|
|
69
|
+
Common::BaseLoader::resource(acl_name, @@network_acls_dir, &NetworkAclConfig.method(:new))
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,954 @@
|
|
|
1
|
+
require "common/manager/Manager"
|
|
2
|
+
require "conf/Configuration"
|
|
3
|
+
require "util/Colors"
|
|
4
|
+
require "vpc/loader/Loader"
|
|
5
|
+
require "vpc/models/VpcDiff"
|
|
6
|
+
require "vpc/models/VpcConfig"
|
|
7
|
+
require "vpc/models/RouteTableDiff"
|
|
8
|
+
require "vpc/models/RouteTableConfig"
|
|
9
|
+
require "vpc/models/EndpointDiff"
|
|
10
|
+
require "vpc/models/NetworkAclDiff"
|
|
11
|
+
require "vpc/models/SubnetDiff"
|
|
12
|
+
require "vpc/models/SubnetConfig"
|
|
13
|
+
require "ec2/EC2"
|
|
14
|
+
require "ec2/IPProtocolMapping"
|
|
15
|
+
|
|
16
|
+
require "aws-sdk"
|
|
17
|
+
require "json"
|
|
18
|
+
|
|
19
|
+
module Cumulus
|
|
20
|
+
module VPC
|
|
21
|
+
class Manager < Common::Manager
|
|
22
|
+
|
|
23
|
+
include VpcChange
|
|
24
|
+
|
|
25
|
+
def initialize
|
|
26
|
+
super()
|
|
27
|
+
@create_asset = false
|
|
28
|
+
@client = Aws::EC2::Client.new(Configuration.instance.client)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def resource_name
|
|
32
|
+
"Virtual Private Cloud"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def local_resources
|
|
36
|
+
@local_resources ||= Hash[Loader.vpcs.map { |local| [local.name, local] }]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def aws_resources
|
|
40
|
+
@aws_resources ||= EC2::named_vpcs
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def unmanaged_diff(aws)
|
|
44
|
+
VpcDiff.unmanaged(aws)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def added_diff(local)
|
|
48
|
+
VpcDiff.added(local)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def diff_resource(local, aws)
|
|
52
|
+
local.diff(aws)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def update(local, diffs)
|
|
56
|
+
aws_vpc = EC2::named_vpcs[local.name]
|
|
57
|
+
|
|
58
|
+
diffs.each do |diff|
|
|
59
|
+
case diff.type
|
|
60
|
+
when CIDR
|
|
61
|
+
puts Colors.blue("CIDR Block cannot be updated. You must create a new VPC.")
|
|
62
|
+
when TENANCY
|
|
63
|
+
puts Colors.blue("Tenancy cannot be updated. You must create a new VPC.")
|
|
64
|
+
when DHCP
|
|
65
|
+
puts Colors.blue("Updating DHCP Options...")
|
|
66
|
+
update_dhcp_options(aws_vpc, local.dhcp)
|
|
67
|
+
when ROUTE_TABLES
|
|
68
|
+
puts Colors.blue("Updating Route Tables...")
|
|
69
|
+
update_route_tables(aws_vpc, diff.changes)
|
|
70
|
+
when ENDPOINTS
|
|
71
|
+
puts Colors.blue("Updating Endpoints...")
|
|
72
|
+
update_endpoints(aws_vpc, diff.changes)
|
|
73
|
+
when ADDRESSES
|
|
74
|
+
puts Colors.blue("Updating Address Associations...")
|
|
75
|
+
update_address_associations(aws_vpc, diff.changes)
|
|
76
|
+
when NETWORK_ACLS
|
|
77
|
+
puts Colors.blue("Updating Network ACLs")
|
|
78
|
+
update_network_acls(aws_vpc, diff.changes)
|
|
79
|
+
when SUBNETS
|
|
80
|
+
puts Colors.blue("Updating Subnets...")
|
|
81
|
+
update_subnets(aws_vpc, diff.changes)
|
|
82
|
+
when TAGS
|
|
83
|
+
puts Colors.blue("Updating Tags...")
|
|
84
|
+
|
|
85
|
+
if !diff.tags_to_remove.empty?
|
|
86
|
+
delete_tags(aws_vpc.vpc_id, diff.tags_to_remove)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
if !diff.tags_to_add.empty?
|
|
90
|
+
create_tags(aws_vpc.vpc_id, diff.tags_to_add)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Public: Renames an asset and all references to it and syncs the name tag change to AWS.
|
|
97
|
+
def rename(asset_type, old_name, new_name)
|
|
98
|
+
|
|
99
|
+
# Strip .json from the old_name and new_name
|
|
100
|
+
old_name = old_name.end_with?(".json") ? old_name[0...-5] : old_name
|
|
101
|
+
new_name = new_name.end_with?(".json") ? new_name[0...-5] : new_name
|
|
102
|
+
|
|
103
|
+
vpcs_dir = Configuration.instance.vpc.vpcs_directory
|
|
104
|
+
subnets_dir = Configuration.instance.vpc.subnets_directory
|
|
105
|
+
route_tables_dir = Configuration.instance.vpc.route_tables_directory
|
|
106
|
+
policies_dir = Configuration.instance.vpc.policies_directory
|
|
107
|
+
network_acls_dir = Configuration.instance.vpc.network_acls_directory
|
|
108
|
+
|
|
109
|
+
case asset_type
|
|
110
|
+
when "network-acl"
|
|
111
|
+
|
|
112
|
+
puts Colors.blue("Renaming Network ACL #{old_name} to #{new_name}")
|
|
113
|
+
|
|
114
|
+
# Update the Name tag and resave the file
|
|
115
|
+
acl_local = Loader.network_acl(old_name)
|
|
116
|
+
acl_local.tags["Name"] = new_name
|
|
117
|
+
json = JSON.pretty_generate(acl_local.to_hash)
|
|
118
|
+
File.open("#{network_acls_dir}/#{new_name}.json", "w") { |f| f.write(json) }
|
|
119
|
+
|
|
120
|
+
# Update the tags in AWS
|
|
121
|
+
acl_aws = EC2::named_network_acls[old_name]
|
|
122
|
+
create_tags(acl_aws.network_acl_id, { "Name" => new_name})
|
|
123
|
+
|
|
124
|
+
# Update the vpc references to it
|
|
125
|
+
Loader.vpcs.each do |vpc|
|
|
126
|
+
vpc.network_acls.collect! { |acl_name| if acl_name == old_name then new_name else acl_name end }
|
|
127
|
+
|
|
128
|
+
json = JSON.pretty_generate(vpc.to_hash)
|
|
129
|
+
File.open("#{vpcs_dir}/#{vpc.name}.json", "w") { |f| f.write(json) }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Update the subnet references to it
|
|
133
|
+
Loader.subnets.each do |subnet|
|
|
134
|
+
if subnet.network_acl == old_name
|
|
135
|
+
subnet.network_acl = new_name
|
|
136
|
+
|
|
137
|
+
json = JSON.pretty_generate(subnet.to_hash)
|
|
138
|
+
File.open("#{subnets_dir}/#{subnet.name}.json", "w") { |f| f.write(json) }
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Delete the old file
|
|
143
|
+
File.delete("#{network_acls_dir}/#{old_name}.json")
|
|
144
|
+
|
|
145
|
+
when "policy"
|
|
146
|
+
|
|
147
|
+
puts Colors.blue("Renaming policy #{old_name} to #{new_name}")
|
|
148
|
+
|
|
149
|
+
# Rename the file
|
|
150
|
+
File.rename("#{policies_dir}/#{old_name}.json", "#{policies_dir}/#{new_name}.json")
|
|
151
|
+
|
|
152
|
+
# Update the references to it in vpc endpoint
|
|
153
|
+
Loader.vpcs.each do |vpc|
|
|
154
|
+
|
|
155
|
+
endpoints_updated = false
|
|
156
|
+
vpc.endpoints.each do |endpoint|
|
|
157
|
+
if endpoint.policy == old_name
|
|
158
|
+
endpoint.policy = new_name
|
|
159
|
+
endpoints_updated = true
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if endpoints_updated
|
|
164
|
+
json = JSON.pretty_generate(vpc.to_hash)
|
|
165
|
+
File.open("#{vpcs_dir}/#{vpc.name}.json", "w") { |f| f.write(json) }
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
when "route-table"
|
|
170
|
+
puts Colors.blue("Renaming route table #{old_name} to #{new_name}")
|
|
171
|
+
|
|
172
|
+
# Update the Name tag and resave the file
|
|
173
|
+
rt_local = Loader.route_table(old_name)
|
|
174
|
+
rt_local.tags["Name"] = new_name
|
|
175
|
+
json = JSON.pretty_generate(rt_local.to_hash)
|
|
176
|
+
File.open("#{route_tables_dir}/#{new_name}.json", "w") { |f| f.write(json) }
|
|
177
|
+
|
|
178
|
+
# Update the tags in AWS
|
|
179
|
+
rt_aws = EC2::named_route_tables[old_name]
|
|
180
|
+
create_tags(rt_aws.route_table_id, { "Name" => new_name})
|
|
181
|
+
|
|
182
|
+
# Update the vpc references to it
|
|
183
|
+
Loader.vpcs.each do |vpc|
|
|
184
|
+
vpc.route_tables.collect! { |rt_name| if rt_name == old_name then new_name else rt_name end }
|
|
185
|
+
|
|
186
|
+
json = JSON.pretty_generate(vpc.to_hash)
|
|
187
|
+
File.open("#{vpcs_dir}/#{vpc.name}.json", "w") { |f| f.write(json) }
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Update the subnet references to it
|
|
191
|
+
Loader.subnets.each do |subnet|
|
|
192
|
+
if subnet.route_table == old_name
|
|
193
|
+
subnet.route_table = new_name
|
|
194
|
+
json = JSON.pretty_generate(subnet.to_hash)
|
|
195
|
+
File.open("#{subnets_dir}/#{subnet.name}.json", "w") { |f| f.write(json) }
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Delete the old file
|
|
200
|
+
File.delete("#{route_tables_dir}/#{old_name}.json")
|
|
201
|
+
when "subnet"
|
|
202
|
+
puts Colors.blue("Renaming subnet #{old_name} to #{new_name}")
|
|
203
|
+
|
|
204
|
+
# Update the Name tag and resave the file
|
|
205
|
+
subnet_local = Loader.subnet(old_name)
|
|
206
|
+
subnet_local.tags["Name"] = new_name
|
|
207
|
+
json = JSON.pretty_generate(subnet_local.to_hash)
|
|
208
|
+
File.open("#{subnets_dir}/#{new_name}.json", "w") { |f| f.write(json) }
|
|
209
|
+
|
|
210
|
+
# Update the tags in AWS
|
|
211
|
+
subnet_aws = EC2::named_subnets[old_name]
|
|
212
|
+
create_tags(subnet_aws.subnet_id, { "Name" => new_name})
|
|
213
|
+
|
|
214
|
+
# Update the vpc references to it
|
|
215
|
+
Loader.vpcs.each do |vpc|
|
|
216
|
+
vpc.subnets.collect! { |subnet_name| if subnet_name == old_name then new_name else subnet_name end }
|
|
217
|
+
|
|
218
|
+
json = JSON.pretty_generate(vpc.to_hash)
|
|
219
|
+
File.open("#{vpcs_dir}/#{vpc.name}.json", "w") { |f| f.write(json) }
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Delete the old file
|
|
223
|
+
File.delete("#{subnets_dir}/#{old_name}.json")
|
|
224
|
+
when "vpc"
|
|
225
|
+
puts Colors.blue("Renaming vpc #{old_name} to #{new_name}")
|
|
226
|
+
|
|
227
|
+
# Update the Name tag and resave the file
|
|
228
|
+
vpc_local = Loader.vpc(old_name)
|
|
229
|
+
vpc_local.tags["Name"] = new_name
|
|
230
|
+
json = JSON.pretty_generate(vpc_local.to_hash)
|
|
231
|
+
File.open("#{vpcs_dir}/#{new_name}.json", "w") { |f| f.write(json) }
|
|
232
|
+
|
|
233
|
+
# Update the tags in AWS
|
|
234
|
+
vpc_aws = EC2::named_vpcs[old_name]
|
|
235
|
+
create_tags(vpc_aws.vpc_id, { "Name" => new_name})
|
|
236
|
+
|
|
237
|
+
# Delete the old file
|
|
238
|
+
File.delete("#{vpcs_dir}/#{old_name}.json")
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Public: Migrates the existing AWS config to Cumulus
|
|
243
|
+
def migrate
|
|
244
|
+
# Create the directories
|
|
245
|
+
vpc_dir = "#{@migration_root}/vpc"
|
|
246
|
+
policies_dir = "#{vpc_dir}/policies"
|
|
247
|
+
route_tables_dir = "#{vpc_dir}/route-tables"
|
|
248
|
+
network_acls_dir = "#{vpc_dir}/network-acls"
|
|
249
|
+
subnets_dir = "#{vpc_dir}/subnets"
|
|
250
|
+
vpcs_dir = "#{vpc_dir}/vpcs"
|
|
251
|
+
|
|
252
|
+
if !Dir.exists?(@migration_root)
|
|
253
|
+
Dir.mkdir(@migration_root)
|
|
254
|
+
end
|
|
255
|
+
if !Dir.exists?(vpc_dir)
|
|
256
|
+
Dir.mkdir(vpc_dir)
|
|
257
|
+
end
|
|
258
|
+
if !Dir.exists?(policies_dir)
|
|
259
|
+
Dir.mkdir(policies_dir)
|
|
260
|
+
end
|
|
261
|
+
if !Dir.exists?(route_tables_dir)
|
|
262
|
+
Dir.mkdir(route_tables_dir)
|
|
263
|
+
end
|
|
264
|
+
if !Dir.exists?(network_acls_dir)
|
|
265
|
+
Dir.mkdir(network_acls_dir)
|
|
266
|
+
end
|
|
267
|
+
if !Dir.exists?(subnets_dir)
|
|
268
|
+
Dir.mkdir(subnets_dir)
|
|
269
|
+
end
|
|
270
|
+
if !Dir.exists?(vpcs_dir)
|
|
271
|
+
Dir.mkdir(vpcs_dir)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Migrate the different assets
|
|
275
|
+
migrate_policies(policies_dir)
|
|
276
|
+
route_table_names = migrate_route_tables(route_tables_dir)
|
|
277
|
+
network_acl_names = migrate_network_acls(network_acls_dir)
|
|
278
|
+
subnet_names = migrate_subnets(subnets_dir, route_table_names, network_acl_names)
|
|
279
|
+
migrate_vpcs(vpcs_dir, route_table_names, subnet_names, network_acl_names)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# Public: Migrates the endpoint policies. Uses Version to name the file
|
|
283
|
+
#
|
|
284
|
+
# dir - the directory to store policies in
|
|
285
|
+
def migrate_policies(dir)
|
|
286
|
+
puts Colors.blue("Migrating policies to #{dir}")
|
|
287
|
+
# Get the policies for each endpoint
|
|
288
|
+
policies = EC2::endpoints.map { |endpoint| endpoint.parsed_policy }
|
|
289
|
+
policies.each do |policy|
|
|
290
|
+
name = policy["Version"]
|
|
291
|
+
puts "Migrating policy #{name}"
|
|
292
|
+
json = JSON.pretty_generate(policy)
|
|
293
|
+
File.open("#{dir}/#{name}.json", "w") { |f| f.write(json) }
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Public: Migrates route tables. Uses name if available or id to name file.
|
|
298
|
+
#
|
|
299
|
+
# dir - the directory to store route table configurations in
|
|
300
|
+
#
|
|
301
|
+
# Returns a Hash of route table id to file name
|
|
302
|
+
def migrate_route_tables(dir)
|
|
303
|
+
puts Colors.blue("Migrating route tables to #{dir}")
|
|
304
|
+
Hash[EC2::named_route_tables.map do |name, route_table|
|
|
305
|
+
puts "Migrating route table #{name}"
|
|
306
|
+
|
|
307
|
+
cumulus_rt = RouteTableConfig.new(name).populate!(route_table)
|
|
308
|
+
|
|
309
|
+
json = JSON.pretty_generate(cumulus_rt.to_hash)
|
|
310
|
+
File.open("#{dir}/#{name}.json", "w") { |f| f.write(json) }
|
|
311
|
+
|
|
312
|
+
[route_table.route_table_id, name]
|
|
313
|
+
end]
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# Public: Migrate Network ACLs. Uses name if available or id to name file.
|
|
317
|
+
#
|
|
318
|
+
# dir - the directory to store network acl configurations in
|
|
319
|
+
#
|
|
320
|
+
# Returns a Hash of network acl id to file name
|
|
321
|
+
def migrate_network_acls(dir)
|
|
322
|
+
puts Colors.blue("Migrating network acls to #{dir}")
|
|
323
|
+
Hash[EC2::named_network_acls.map do |name, network_acl|
|
|
324
|
+
puts "Migrating network acl #{name}"
|
|
325
|
+
|
|
326
|
+
cumulus_acl = NetworkAclConfig.new(name).populate!(network_acl)
|
|
327
|
+
|
|
328
|
+
json = JSON.pretty_generate(cumulus_acl.to_hash)
|
|
329
|
+
File.open("#{dir}/#{name}.json", "w") { |f| f.write(json) }
|
|
330
|
+
|
|
331
|
+
[network_acl.network_acl_id, name]
|
|
332
|
+
end]
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# Public: Migrates subnets. Uses name if available or id to name file.
|
|
336
|
+
#
|
|
337
|
+
# dir - the directory to store subnet configurations in
|
|
338
|
+
# rt_map - a map of route table ids to names to substitute for in the subnet config
|
|
339
|
+
# acl_map - a map of network acl ids to names to substitute for in the subnet config
|
|
340
|
+
#
|
|
341
|
+
# Returns a hash of subnet id to file name
|
|
342
|
+
def migrate_subnets(dir, rt_map, acl_map)
|
|
343
|
+
puts Colors.blue("Migrating subnets to #{dir}")
|
|
344
|
+
Hash[EC2::named_subnets.map do |name, subnet|
|
|
345
|
+
puts "Migrating subnet #{name}"
|
|
346
|
+
|
|
347
|
+
cumulus_subnet = SubnetConfig.new(name).populate!(subnet, rt_map, acl_map)
|
|
348
|
+
|
|
349
|
+
json = JSON.pretty_generate(cumulus_subnet.to_hash)
|
|
350
|
+
File.open("#{dir}/#{name}.json", "w") { |f| f.write(json) }
|
|
351
|
+
|
|
352
|
+
[subnet.subnet_id, name]
|
|
353
|
+
end]
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
# Public: Migrates vpcs. Uses name if available or id to name file.
|
|
357
|
+
#
|
|
358
|
+
# dir - the directory to store vpc configurations in
|
|
359
|
+
# rt_map - a map of route table ids to names to substitute for in the vpc config
|
|
360
|
+
# subnet_map - a map of subnet ids to names to substitute for in the vpc config
|
|
361
|
+
# acl_map - a map of network acl ids to names to substitute fo rin the vpc config
|
|
362
|
+
def migrate_vpcs(dir, rt_map, subnet_map, acl_map)
|
|
363
|
+
puts Colors.blue("Migrating vpcs to #{dir}")
|
|
364
|
+
Hash[EC2::named_vpcs.map do |name, vpc|
|
|
365
|
+
puts "Migrating vpc #{name}"
|
|
366
|
+
|
|
367
|
+
cumulus_vpc = (VpcConfig.new(name)).populate!(vpc, rt_map, subnet_map, acl_map)
|
|
368
|
+
|
|
369
|
+
json = JSON.pretty_generate(cumulus_vpc.to_hash)
|
|
370
|
+
File.open("#{dir}/#{name}.json", "w") { |f| f.write(json) }
|
|
371
|
+
end]
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
private
|
|
375
|
+
|
|
376
|
+
def create_tags(resource_id, tags)
|
|
377
|
+
@client.create_tags({
|
|
378
|
+
resources: [resource_id],
|
|
379
|
+
tags: tags.map do |key, value|
|
|
380
|
+
{
|
|
381
|
+
key: key,
|
|
382
|
+
value: value
|
|
383
|
+
}
|
|
384
|
+
end
|
|
385
|
+
})
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def delete_tags(resource_id, tags)
|
|
389
|
+
@client.delete_tags({
|
|
390
|
+
resources: [resource_id],
|
|
391
|
+
tags: tags.map do |key, value|
|
|
392
|
+
{
|
|
393
|
+
key: key,
|
|
394
|
+
value: value
|
|
395
|
+
}
|
|
396
|
+
end
|
|
397
|
+
})
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def update_dhcp_options(aws_vpc, dhcp_config)
|
|
401
|
+
old_options_id = aws_vpc.dhcp_options_id
|
|
402
|
+
|
|
403
|
+
options_id = if !dhcp_config or dhcp_config.to_aws.empty?
|
|
404
|
+
"default"
|
|
405
|
+
else
|
|
406
|
+
@client.create_dhcp_options({
|
|
407
|
+
dhcp_configurations: dhcp_config.to_aws
|
|
408
|
+
}).dhcp_options.dhcp_options_id
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
@client.associate_dhcp_options({
|
|
412
|
+
vpc_id: aws_vpc.vpc_id,
|
|
413
|
+
dhcp_options_id: options_id
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
EC2::refresh_vpcs!
|
|
417
|
+
|
|
418
|
+
# Delete the old options if no other vpc depends on it
|
|
419
|
+
if old_options_id != "default" and !EC2::vpcs.any? { |vpc| vpc.dhcp_options_id == old_options_id }
|
|
420
|
+
@client.delete_dhcp_options({
|
|
421
|
+
dhcp_options_id: old_options_id
|
|
422
|
+
})
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def update_route_tables(aws_vpc, rt_changes)
|
|
427
|
+
# Added route tables
|
|
428
|
+
rt_changes.added.each do |rt_name, added_diff|
|
|
429
|
+
added_rt = added_diff.local
|
|
430
|
+
|
|
431
|
+
puts "Creating route table #{rt_name}"
|
|
432
|
+
create_route_table(aws_vpc.vpc_id, added_rt)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
# Removed route tables
|
|
436
|
+
rt_changes.removed.each do |rt_name, removed_diff|
|
|
437
|
+
removed_rt = removed_diff.aws
|
|
438
|
+
|
|
439
|
+
# Make sure it is not the main route table
|
|
440
|
+
if removed_rt.associations.any? { |assoc| assoc.main }
|
|
441
|
+
puts Colors.red("Cannot delete main route table #{rt_name}")
|
|
442
|
+
else
|
|
443
|
+
puts "Deleting route table #{rt_name}"
|
|
444
|
+
delete_route_table(removed_rt)
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
# Modified route tables
|
|
449
|
+
rt_changes.modified.each do |rt_name, modified_diff|
|
|
450
|
+
puts "Updating #{rt_name}"
|
|
451
|
+
aws_rt = EC2::named_route_tables[rt_name]
|
|
452
|
+
aws_rt_id = aws_rt.route_table_id
|
|
453
|
+
|
|
454
|
+
modified_diff.changes.each do |diff|
|
|
455
|
+
case diff.type
|
|
456
|
+
when RouteTableChange::ROUTES
|
|
457
|
+
# Added routes
|
|
458
|
+
diff.changes.added.each do |cidr, route_diff|
|
|
459
|
+
create_route(aws_rt_id, route_diff.local)
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
# Removed routes
|
|
463
|
+
diff.changes.removed.each do |cidr, route_diff|
|
|
464
|
+
delete_route(aws_rt_id, route_diff.aws.destination_cidr_block)
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
# Modified routes
|
|
468
|
+
diff.changes.modified.each do |cidr, route_diff|
|
|
469
|
+
replace_route(aws_rt_id, route_diff.local)
|
|
470
|
+
end
|
|
471
|
+
when RouteTableChange::VGWS
|
|
472
|
+
# Added vgws
|
|
473
|
+
diff.changes.added.each do |vgw|
|
|
474
|
+
enable_vgw(aws_rt_id, vgw)
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
# Removed vgws
|
|
478
|
+
diff.changes.removed.each do |vgw|
|
|
479
|
+
disable_vgw(aws_rt_id, vgw)
|
|
480
|
+
end
|
|
481
|
+
when RouteTableChange::TAGS
|
|
482
|
+
if !diff.tags_to_remove.empty?
|
|
483
|
+
delete_tags(aws_rt_id, diff.tags_to_remove)
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
if !diff.tags_to_add.empty?
|
|
487
|
+
create_tags(aws_rt_id, diff.tags_to_add)
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
def create_route_table(vpc_id, rt)
|
|
495
|
+
rt_id = @client.create_route_table({
|
|
496
|
+
vpc_id: vpc_id
|
|
497
|
+
}).route_table.route_table_id
|
|
498
|
+
|
|
499
|
+
if !rt.tags.empty?
|
|
500
|
+
create_tags(rt_id, rt.tags)
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
rt.propagate_vgws.each do |vgw|
|
|
504
|
+
enable_vgw(rt_id, vgw)
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
rt.routes.each do |route|
|
|
508
|
+
create_route(rt_id, route)
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def delete_route_table(aws_rt)
|
|
513
|
+
# First have to disassociate all of the subnets from the route table
|
|
514
|
+
aws_rt.associations.each do |assoc|
|
|
515
|
+
@client.disassociate_route_table({
|
|
516
|
+
association_id: assoc.route_table_association_id
|
|
517
|
+
})
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
# Delete the route table
|
|
521
|
+
@client.delete_route_table({
|
|
522
|
+
route_table_id: aws_rt.route_table_id
|
|
523
|
+
})
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
def create_route(rt_id, route)
|
|
527
|
+
puts "Creating route #{route.dest_cidr}"
|
|
528
|
+
@client.create_route({
|
|
529
|
+
route_table_id: rt_id,
|
|
530
|
+
destination_cidr_block: route.dest_cidr,
|
|
531
|
+
gateway_id: if route.gateway_id then route.gateway_id end,
|
|
532
|
+
network_interface_id: if route.network_interface_id then route.network_interface_id end,
|
|
533
|
+
vpc_peering_connection_id: if route.vpc_peering_connection_id then route.vpc_peering_connection_id end
|
|
534
|
+
})
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
def delete_route(rt_id, dest_cidr)
|
|
538
|
+
puts "Deleting route #{dest_cidr}"
|
|
539
|
+
@client.delete_route({
|
|
540
|
+
route_table_id: rt_id,
|
|
541
|
+
destination_cidr_block: dest_cidr
|
|
542
|
+
})
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
def replace_route(rt_id, route)
|
|
546
|
+
puts "Replacing route #{route.dest_cidr}"
|
|
547
|
+
@client.replace_route({
|
|
548
|
+
route_table_id: rt_id,
|
|
549
|
+
destination_cidr_block: route.dest_cidr,
|
|
550
|
+
gateway_id: if route.gateway_id then route.gateway_id end,
|
|
551
|
+
network_interface_id: if route.network_interface_id then route.network_interface_id end,
|
|
552
|
+
vpc_peering_connection_id: if route.vpc_peering_connection_id then route.vpc_peering_connection_id end
|
|
553
|
+
})
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
def enable_vgw(rt_id, vgw)
|
|
557
|
+
@client.enable_vgw_route_propagation({
|
|
558
|
+
route_table_id: rt_id,
|
|
559
|
+
gateway_id: vgw
|
|
560
|
+
})
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
def disable_vgw(rt_id, vgw)
|
|
564
|
+
@client.disable_vgw_route_propagation({
|
|
565
|
+
route_table_id: rt_id,
|
|
566
|
+
gateway_id: vgw
|
|
567
|
+
})
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
def update_endpoints(aws_vpc, endpoint_changes)
|
|
571
|
+
|
|
572
|
+
def rt_ids(rt_names)
|
|
573
|
+
rt_names.map do |rt_name|
|
|
574
|
+
aws_rt = EC2::named_route_tables[rt_name]
|
|
575
|
+
if aws_rt.nil?
|
|
576
|
+
puts Colors.red("Error updating endpoints. No route table found for #{rt_name}.")
|
|
577
|
+
exit 1
|
|
578
|
+
else
|
|
579
|
+
aws_rt.route_table_id
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
# Added endpoints
|
|
585
|
+
endpoint_changes.added.each do |endpoint_name, added_diff|
|
|
586
|
+
puts "Adding endpoint #{endpoint_name}"
|
|
587
|
+
endpoint = added_diff.local
|
|
588
|
+
|
|
589
|
+
@client.create_vpc_endpoint({
|
|
590
|
+
vpc_id: aws_vpc.vpc_id,
|
|
591
|
+
service_name: endpoint.service_name,
|
|
592
|
+
policy_document: if endpoint.policy then JSON.generate(Loader.policy(endpoint.policy)) end,
|
|
593
|
+
route_table_ids: rt_ids(endpoint.route_tables)
|
|
594
|
+
})
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
# Deleted endpoints
|
|
598
|
+
endpoint_changes.removed.each do |endpoint_name, removed_diff|
|
|
599
|
+
puts "Deleting endpoint #{endpoint_name}"
|
|
600
|
+
@client.delete_vpc_endpoints({
|
|
601
|
+
vpc_endpoint_ids: [removed_diff.aws.vpc_endpoint_id]
|
|
602
|
+
})
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
# Modified endpoints
|
|
606
|
+
endpoint_changes.modified.each do |endpoint_name, modified_diff|
|
|
607
|
+
puts "Updating endpoint #{endpoint_name}"
|
|
608
|
+
|
|
609
|
+
aws_endpoint = modified_diff.aws
|
|
610
|
+
local_endpoint = modified_diff.local
|
|
611
|
+
|
|
612
|
+
add_rt_ids = nil
|
|
613
|
+
remove_rt_ids = nil
|
|
614
|
+
|
|
615
|
+
modified_diff.changes.select { |d| d.type == EndpointChange::ROUTE_TABLES}.map do |endpoint_diff|
|
|
616
|
+
if !endpoint_diff.changes.added.empty?
|
|
617
|
+
add_rt_ids = rt_ids(endpoint_diff.changes.added)
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
if !endpoint_diff.changes.removed.empty?
|
|
621
|
+
remove_rt_ids = rt_ids(endpoint_diff.changes.removed)
|
|
622
|
+
end
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
@client.modify_vpc_endpoint({
|
|
626
|
+
vpc_endpoint_id: aws_endpoint.vpc_endpoint_id,
|
|
627
|
+
reset_policy: false,
|
|
628
|
+
policy_document: if local_endpoint.policy then JSON.generate(Loader.policy(local_endpoint.policy)) end,
|
|
629
|
+
add_route_table_ids: add_rt_ids,
|
|
630
|
+
remove_route_table_ids: remove_rt_ids
|
|
631
|
+
})
|
|
632
|
+
end
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
def update_address_associations(aws_vpc, address_changes)
|
|
636
|
+
# Added associations
|
|
637
|
+
address_changes.added.each do |ip, addr_change|
|
|
638
|
+
if addr_change.local == "any"
|
|
639
|
+
puts "#{ip} must be associated manually to any interface"
|
|
640
|
+
else
|
|
641
|
+
puts "Associating #{ip} to #{addr_change.local_name}"
|
|
642
|
+
aws_address = EC2::public_addresses[ip]
|
|
643
|
+
@client.associate_address({
|
|
644
|
+
allow_reassociation: false, # This makes the operation fail if it was already associated
|
|
645
|
+
allocation_id: aws_address.allocation_id,
|
|
646
|
+
network_interface_id: addr_change.local.network_interface_id
|
|
647
|
+
})
|
|
648
|
+
end
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
# Removed associations
|
|
652
|
+
address_changes.removed.each do |ip, addr_change|
|
|
653
|
+
puts "Disassociating #{ip} from #{addr_change.aws_name}"
|
|
654
|
+
aws_address = EC2::public_addresses[ip]
|
|
655
|
+
@client.disassociate_address({
|
|
656
|
+
association_id: aws_address.association_id
|
|
657
|
+
})
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
# Modified associations
|
|
661
|
+
address_changes.modified.each do |ip, addr_change|
|
|
662
|
+
puts "Changing association for #{ip} from #{addr_change.aws_name} to #{addr_change.local_name}"
|
|
663
|
+
aws_address = EC2::public_addresses[ip]
|
|
664
|
+
@client.associate_address({
|
|
665
|
+
allow_reassociation: true, # We know it was associated to something else so allow reassociation
|
|
666
|
+
allocation_id: aws_address.allocation_id,
|
|
667
|
+
network_interface_id: addr_change.local.network_interface_id
|
|
668
|
+
})
|
|
669
|
+
end
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
def update_network_acls(aws_vpc, network_changes)
|
|
673
|
+
# Added network acls
|
|
674
|
+
network_changes.added.each do |acl_name, added_diff|
|
|
675
|
+
puts "Creating Network ACL #{acl_name}"
|
|
676
|
+
created_id = @client.create_network_acl({
|
|
677
|
+
vpc_id: aws_vpc.vpc_id
|
|
678
|
+
}).network_acl.network_acl_id
|
|
679
|
+
|
|
680
|
+
acl_config = added_diff.local
|
|
681
|
+
|
|
682
|
+
# Associate tags
|
|
683
|
+
create_tags(created_id, acl_config.tags)
|
|
684
|
+
|
|
685
|
+
# Create outbound entries
|
|
686
|
+
acl_config.outbound.each do |entry|
|
|
687
|
+
puts "Creating outbound entry with rule #{entry.rule}"
|
|
688
|
+
create_network_acl_entry(created_id, entry, true)
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
# Create inbound entries
|
|
692
|
+
acl_config.inbound.each do |entry|
|
|
693
|
+
puts "Creating inbound entry with rule #{entry.rule}"
|
|
694
|
+
create_network_acl_entry(created_id, entry, false)
|
|
695
|
+
end
|
|
696
|
+
end
|
|
697
|
+
|
|
698
|
+
# Deleted network acls
|
|
699
|
+
network_changes.removed.each do |acl_name, removed_diff|
|
|
700
|
+
aws_acl = removed_diff.aws
|
|
701
|
+
|
|
702
|
+
# Make sure the user isn't trying to delete the default acl
|
|
703
|
+
if aws_acl.is_default
|
|
704
|
+
puts Colors.red("Cannot delete the default Network ACL #{acl_name}")
|
|
705
|
+
# Make sure there are no subnets associated with the acl
|
|
706
|
+
elsif !aws_acl.associations.empty?
|
|
707
|
+
puts Colors.red("Cannot delete a Network ACL with subnets associated to it")
|
|
708
|
+
else
|
|
709
|
+
puts "Deleting Network ACL #{acl_name}"
|
|
710
|
+
@client.delete_network_acl({
|
|
711
|
+
network_acl_id: aws_acl.network_acl_id
|
|
712
|
+
})
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
# Modified network acls
|
|
718
|
+
network_changes.modified.each do |acl_name, modified_diff|
|
|
719
|
+
acl_id = modified_diff.aws.network_acl_id
|
|
720
|
+
|
|
721
|
+
modified_diff.changes.each do |net_acl_diff|
|
|
722
|
+
case net_acl_diff.type
|
|
723
|
+
when NetworkAclChange::OUTBOUND
|
|
724
|
+
# Added outbound entries
|
|
725
|
+
net_acl_diff.changes.added.each do |rule, added_entry_diff|
|
|
726
|
+
puts "Creating outbound entry with rule #{rule}"
|
|
727
|
+
create_network_acl_entry(acl_id, added_entry_diff.local, true)
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
# Removed outbound entries
|
|
731
|
+
net_acl_diff.changes.removed.each do |rule, removed_entry_diff|
|
|
732
|
+
puts "Removing outbound entry with rule #{rule}"
|
|
733
|
+
delete_network_acl_entry(acl_id, rule, true)
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
# Modified outbound entries
|
|
737
|
+
net_acl_diff.changes.modified.each do |rule, modified_entry_diff|
|
|
738
|
+
puts "Updating outbound entry with rule #{rule}"
|
|
739
|
+
replace_network_acl_entry(acl_id, modified_entry_diff.local, true)
|
|
740
|
+
end
|
|
741
|
+
when NetworkAclChange::INBOUND
|
|
742
|
+
# Added inbound entries
|
|
743
|
+
net_acl_diff.changes.added.each do |rule, added_entry_diff|
|
|
744
|
+
puts "Creating inbound entry with rule #{rule}"
|
|
745
|
+
create_network_acl_entry(acl_id, added_entry_diff.local, false)
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
# Removed outbound entries
|
|
749
|
+
net_acl_diff.changes.removed.each do |rule, removed_entry_diff|
|
|
750
|
+
puts "Removing outbound entry with rule #{rule}"
|
|
751
|
+
delete_network_acl_entry(acl_id, rule, false)
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
# Modified outbound entries
|
|
755
|
+
net_acl_diff.changes.modified.each do |rule, modified_entry_diff|
|
|
756
|
+
puts "Updating outbound entry with rule #{rule}"
|
|
757
|
+
replace_network_acl_entry(acl_id, modified_entry_diff.local, false)
|
|
758
|
+
end
|
|
759
|
+
when NetworkAclChange::TAGS
|
|
760
|
+
if !net_acl_diff.tags_to_remove.empty?
|
|
761
|
+
delete_tags(acl_id, net_acl_diff.tags_to_remove)
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
if !net_acl_diff.tags_to_add.empty?
|
|
765
|
+
create_tags(acl_id, net_acl_diff.tags_to_add)
|
|
766
|
+
end
|
|
767
|
+
end
|
|
768
|
+
end
|
|
769
|
+
end
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
def create_network_acl_entry(network_acl_id, entry, egress)
|
|
773
|
+
@client.create_network_acl_entry({
|
|
774
|
+
network_acl_id: network_acl_id,
|
|
775
|
+
rule_number: entry.rule,
|
|
776
|
+
protocol: EC2::IPProtocolMapping.protocol(entry.protocol),
|
|
777
|
+
rule_action: entry.action,
|
|
778
|
+
egress: egress,
|
|
779
|
+
cidr_block: entry.cidr_block,
|
|
780
|
+
icmp_type_code:
|
|
781
|
+
if entry.icmp_type || entry.icmp_code
|
|
782
|
+
{
|
|
783
|
+
type: entry.icmp_type,
|
|
784
|
+
code: entry.icmp_code
|
|
785
|
+
}
|
|
786
|
+
end,
|
|
787
|
+
port_range:
|
|
788
|
+
if entry.ports
|
|
789
|
+
from_port, to_port = entry.expand_ports
|
|
790
|
+
{
|
|
791
|
+
from: from_port,
|
|
792
|
+
to: to_port
|
|
793
|
+
}
|
|
794
|
+
end
|
|
795
|
+
})
|
|
796
|
+
end
|
|
797
|
+
|
|
798
|
+
def delete_network_acl_entry(network_acl_id, rule, egress)
|
|
799
|
+
@client.delete_network_acl_entry({
|
|
800
|
+
network_acl_id: network_acl_id,
|
|
801
|
+
rule_number: rule,
|
|
802
|
+
egress: egress
|
|
803
|
+
})
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
def replace_network_acl_entry(network_acl_id, entry, egress)
|
|
807
|
+
@client.replace_network_acl_entry({
|
|
808
|
+
network_acl_id: network_acl_id,
|
|
809
|
+
rule_number: entry.rule,
|
|
810
|
+
protocol: EC2::IPProtocolMapping.protocol(entry.protocol),
|
|
811
|
+
rule_action: entry.action,
|
|
812
|
+
egress: egress,
|
|
813
|
+
cidr_block: entry.cidr_block,
|
|
814
|
+
icmp_type_code:
|
|
815
|
+
if entry.icmp_type || entry.icmp_code
|
|
816
|
+
{
|
|
817
|
+
type: entry.icmp_type,
|
|
818
|
+
code: entry.icmp_code
|
|
819
|
+
}
|
|
820
|
+
end,
|
|
821
|
+
port_range:
|
|
822
|
+
if entry.ports
|
|
823
|
+
from_port, to_port = entry.expand_ports
|
|
824
|
+
{
|
|
825
|
+
from: from_port,
|
|
826
|
+
to: to_port
|
|
827
|
+
}
|
|
828
|
+
end
|
|
829
|
+
})
|
|
830
|
+
end
|
|
831
|
+
|
|
832
|
+
def update_subnets(aws_vpc, subnet_changes)
|
|
833
|
+
# Refresh route tables so that the updated ones
|
|
834
|
+
# (if any) can be associated with subnets
|
|
835
|
+
EC2::refresh_route_tables!
|
|
836
|
+
|
|
837
|
+
# Created subnets
|
|
838
|
+
subnet_changes.added.each do |subnet_name, added_diff|
|
|
839
|
+
puts "Creating subnet #{subnet_name}"
|
|
840
|
+
|
|
841
|
+
subnet = added_diff.local
|
|
842
|
+
|
|
843
|
+
# Create the subnet
|
|
844
|
+
created_subnet = @client.create_subnet({
|
|
845
|
+
vpc_id: aws_vpc.vpc_id,
|
|
846
|
+
cidr_block: subnet.cidr_block,
|
|
847
|
+
availability_zone: subnet.availability_zone
|
|
848
|
+
}).subnet
|
|
849
|
+
|
|
850
|
+
# Add tags
|
|
851
|
+
if !subnet.tags.empty?
|
|
852
|
+
create_tags(created_subnet.subnet_id, subnet.tags)
|
|
853
|
+
end
|
|
854
|
+
|
|
855
|
+
# Map public ip if needed
|
|
856
|
+
if created_subnet.map_public_ip_on_launch != subnet.map_public_ip
|
|
857
|
+
@client.modify_subnet_attribute({
|
|
858
|
+
subnet_id: created_subnet.subnet_id,
|
|
859
|
+
map_public_ip_on_launch: {
|
|
860
|
+
value: subnet.map_public_ip
|
|
861
|
+
}
|
|
862
|
+
})
|
|
863
|
+
end
|
|
864
|
+
|
|
865
|
+
set_subnet_route_table(created_subnet.subnet_id, subnet.route_table)
|
|
866
|
+
|
|
867
|
+
# Refresh network acls since a subnet is automatically associatd with the deafult one
|
|
868
|
+
# and that association is needed to update it
|
|
869
|
+
EC2::refresh_network_acls!
|
|
870
|
+
set_subnet_network_acl(created_subnet.subnet_id, subnet.network_acl)
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
# Modified subnets
|
|
874
|
+
subnet_changes.modified.each do |subnet_name, modified_diff|
|
|
875
|
+
puts "Updating Subnet #{subnet_name}"
|
|
876
|
+
local_subnet = modified_diff.local
|
|
877
|
+
subnet_id = modified_diff.aws.subnet_id
|
|
878
|
+
|
|
879
|
+
modified_diff.changes.each do |subnet_diff|
|
|
880
|
+
case subnet_diff.type
|
|
881
|
+
when SubnetChange::CIDR
|
|
882
|
+
puts "Cannot update CIDR Block"
|
|
883
|
+
when SubnetChange::AZ
|
|
884
|
+
puts "Cannot update Availability Zone"
|
|
885
|
+
when SubnetChange::ROUTE_TABLE
|
|
886
|
+
puts "Updating Route Table"
|
|
887
|
+
set_subnet_route_table(subnet_id, local_subnet.route_table)
|
|
888
|
+
when SubnetChange::NETWORK_ACL
|
|
889
|
+
puts "Updating Network ACL"
|
|
890
|
+
set_subnet_network_acl(subnet_id, local_subnet.network_acl)
|
|
891
|
+
when SubnetChange::TAGS
|
|
892
|
+
puts "Updating Tags"
|
|
893
|
+
if !subnet_diff.tags_to_remove.empty?
|
|
894
|
+
delete_tags(subnet_id, subnet_diff.tags_to_remove)
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
if !subnet_diff.tags_to_add.empty?
|
|
898
|
+
create_tags(subnet_id, subnet_diff.tags_to_add)
|
|
899
|
+
end
|
|
900
|
+
end
|
|
901
|
+
end
|
|
902
|
+
end
|
|
903
|
+
end
|
|
904
|
+
|
|
905
|
+
def set_subnet_route_table(subnet_id, rt_name)
|
|
906
|
+
# Get the association for the subnet
|
|
907
|
+
aws_rt = EC2::subnet_route_tables[subnet_id]
|
|
908
|
+
association_id = if aws_rt and !aws_rt.associations.empty?
|
|
909
|
+
subnet_assoc = aws_rt.associations.select { |assoc| assoc.subnet_id = subnet_id }.first
|
|
910
|
+
if subnet_assoc
|
|
911
|
+
subnet_assoc.route_table_association_id
|
|
912
|
+
end
|
|
913
|
+
end
|
|
914
|
+
|
|
915
|
+
rt_id = if rt_name then EC2::named_route_tables[rt_name].route_table_id end
|
|
916
|
+
|
|
917
|
+
if association_id
|
|
918
|
+
# If there was an association then replace or disassociate
|
|
919
|
+
if rt_id
|
|
920
|
+
# Replace
|
|
921
|
+
@client.replace_route_table_association({
|
|
922
|
+
association_id: association_id,
|
|
923
|
+
route_table_id: rt_id
|
|
924
|
+
})
|
|
925
|
+
else
|
|
926
|
+
# Disassociate
|
|
927
|
+
@client.disassociate_route_table({
|
|
928
|
+
association_id: association_id
|
|
929
|
+
})
|
|
930
|
+
end
|
|
931
|
+
elsif rt_id
|
|
932
|
+
# Create a new association
|
|
933
|
+
@client.associate_route_table({
|
|
934
|
+
subnet_id: subnet_id,
|
|
935
|
+
route_table_id: rt_id
|
|
936
|
+
})
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
end
|
|
940
|
+
|
|
941
|
+
def set_subnet_network_acl(subnet_id, acl_name)
|
|
942
|
+
# Get the association for the subnet
|
|
943
|
+
association_id = EC2::subnet_network_acls[subnet_id].associations.select { |assoc| assoc.subnet_id = subnet_id }.first.network_acl_association_id
|
|
944
|
+
acl_id = EC2::named_network_acls[acl_name].network_acl_id
|
|
945
|
+
|
|
946
|
+
@client.replace_network_acl_association({
|
|
947
|
+
association_id: association_id,
|
|
948
|
+
network_acl_id: acl_id
|
|
949
|
+
})
|
|
950
|
+
end
|
|
951
|
+
|
|
952
|
+
end
|
|
953
|
+
end
|
|
954
|
+
end
|