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,118 @@
|
|
|
1
|
+
require "conf/Configuration"
|
|
2
|
+
require "common/models/Diff"
|
|
3
|
+
require "route53/models/RecordDiff"
|
|
4
|
+
require "util/Colors"
|
|
5
|
+
|
|
6
|
+
module Cumulus
|
|
7
|
+
module Route53
|
|
8
|
+
# Public: The types of changes that can be made to zones
|
|
9
|
+
module ZoneChange
|
|
10
|
+
include Common::DiffChange
|
|
11
|
+
|
|
12
|
+
COMMENT = Common::DiffChange::next_change_id
|
|
13
|
+
DOMAIN = Common::DiffChange::next_change_id
|
|
14
|
+
PRIVATE = Common::DiffChange::next_change_id
|
|
15
|
+
RECORD = Common::DiffChange::next_change_id
|
|
16
|
+
VPC = Common::DiffChange::next_change_id
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Public: Represents a single difference between local configuration and AWS
|
|
20
|
+
# configuration of zones.
|
|
21
|
+
class ZoneDiff < Common::Diff
|
|
22
|
+
include ZoneChange
|
|
23
|
+
|
|
24
|
+
attr_accessor :changed_records
|
|
25
|
+
|
|
26
|
+
# Public: Static method that produces a diff representing changes in records
|
|
27
|
+
#
|
|
28
|
+
# changed_records - the RecordDiffs
|
|
29
|
+
# local - the local configuration for the zone
|
|
30
|
+
#
|
|
31
|
+
# Returns the diff
|
|
32
|
+
def self.records(changed_records, local)
|
|
33
|
+
diff = ZoneDiff.new(RECORD, nil, local)
|
|
34
|
+
diff.changed_records = changed_records
|
|
35
|
+
diff
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def asset_type
|
|
39
|
+
"Zone"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def aws_name
|
|
43
|
+
access = if @aws.config.private_zone then "private" else "public" end
|
|
44
|
+
"#{@aws.name} (#{access})"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def add_string
|
|
48
|
+
"has been added locally, but must be created in AWS manually."
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def diff_string
|
|
52
|
+
case @type
|
|
53
|
+
when COMMENT
|
|
54
|
+
[
|
|
55
|
+
"Comment:",
|
|
56
|
+
Colors.aws_changes("\tAWS - #{@aws.config.comment}"),
|
|
57
|
+
Colors.local_changes("\tLocal - #{@local.comment}")
|
|
58
|
+
].join("\n")
|
|
59
|
+
when DOMAIN
|
|
60
|
+
[
|
|
61
|
+
"Domain: AWS - #{Colors.aws_changes(@aws.name)}, Local - #{Colors.local_changes(@local.domain)}",
|
|
62
|
+
"\tAWS doesn't allow you to change the domain for a zone."
|
|
63
|
+
].join("\n")
|
|
64
|
+
when PRIVATE
|
|
65
|
+
[
|
|
66
|
+
"Private: AWS - #{Colors.aws_changes(@aws.config.private_zone)}, Local - #{Colors.local_changes(@local.private)}",
|
|
67
|
+
"\tAWS doesn't allow you to change whether a zone is private."
|
|
68
|
+
].join("\n")
|
|
69
|
+
when RECORD
|
|
70
|
+
if Configuration.instance.route53.print_all_ignored
|
|
71
|
+
[
|
|
72
|
+
"Records:",
|
|
73
|
+
@changed_records.map { |r| "\t#{r}" }
|
|
74
|
+
].flatten.join("\n")
|
|
75
|
+
else
|
|
76
|
+
[
|
|
77
|
+
"Records:",
|
|
78
|
+
@changed_records.reject { |r| r.type == RecordChange::IGNORED }.map { |r| "\t#{r}" },
|
|
79
|
+
"\tYour blacklist ignored #{@changed_records.select { |r| r.type == RecordChange::IGNORED }.size} records."
|
|
80
|
+
].flatten.join("\n")
|
|
81
|
+
end
|
|
82
|
+
when VPC
|
|
83
|
+
[
|
|
84
|
+
"VPCs:",
|
|
85
|
+
added_vpc_ids.map { |vpc| Colors.added("\t#{vpc["id"]} | #{vpc["region"]}") },
|
|
86
|
+
removed_vpc_ids.map { |vpc| Colors.removed("\t#{vpc["id"]} | #{vpc["region"]}") }
|
|
87
|
+
].flatten.join("\n")
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Public: Get the VPCs that have been added locally.
|
|
92
|
+
#
|
|
93
|
+
# Returns an array of vpc ids
|
|
94
|
+
def added_vpc_ids
|
|
95
|
+
@local.vpc - @aws.vpc
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Public: Get the VPCs that have been removed locally.
|
|
99
|
+
#
|
|
100
|
+
# Returns an array of vpc ids
|
|
101
|
+
def removed_vpc_ids
|
|
102
|
+
@aws.vpc - @local.vpc
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Public: Override the info_only attribute such that if this diff is a record diff and it
|
|
106
|
+
# contains only ignored record diffs, we return true.
|
|
107
|
+
#
|
|
108
|
+
# Returns whether or not this is an info only diff
|
|
109
|
+
def info_only
|
|
110
|
+
if @type == RECORD
|
|
111
|
+
@changed_records.all? { |r| r.type == RecordChange::IGNORED }
|
|
112
|
+
else
|
|
113
|
+
false
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
data/lib/s3/S3.rb
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require "conf/Configuration"
|
|
2
|
+
|
|
3
|
+
require "aws-sdk"
|
|
4
|
+
|
|
5
|
+
module Cumulus
|
|
6
|
+
module S3
|
|
7
|
+
class << self
|
|
8
|
+
def client(region = nil)
|
|
9
|
+
@clients ||= {}
|
|
10
|
+
if !region then region = "us-east-1" end
|
|
11
|
+
@clients[region] ||= Aws::S3::Client.new(Configuration.instance.client.merge({:force_path_style => true, :region => region}))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
@@zone_ids = {
|
|
15
|
+
"ap-northeast-1" => "Z2M4EHUR26P7ZW",
|
|
16
|
+
"ap-southeast-1" => "Z3O0J2DXBE1FTB",
|
|
17
|
+
"ap-southeast-2" => "Z1WCIGYICN2BYD",
|
|
18
|
+
"eu-central-1" => "Z21DNDUVLTQW6Q",
|
|
19
|
+
"eu-west-1" => "Z1BKCTXD74EZPE",
|
|
20
|
+
"sa-east-1" => "Z7KQH4QJS55SO",
|
|
21
|
+
"us-east-1" => "Z3AQBSTGFYJSTF",
|
|
22
|
+
"us-gov-west-1" => "Z31GFT0UA1I2HV",
|
|
23
|
+
"us-west-1" => "Z2F56UZL2M1ACD",
|
|
24
|
+
"us-west-2" => "Z3BJ6K6RIION7M",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# Public: A mapping of region name to its hosted zone id. This mapping is needed because
|
|
28
|
+
# the S3 API doesn't expose the hosted ids, you have to get them at
|
|
29
|
+
# http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region.
|
|
30
|
+
def zone_ids
|
|
31
|
+
@@zone_ids
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Public: Static method that will get an S3 bucket from AWS by its name
|
|
35
|
+
#
|
|
36
|
+
# name - the name of the bucket to get
|
|
37
|
+
#
|
|
38
|
+
# Returns the Aws::S3::Types::Bucket by that name
|
|
39
|
+
def get_aws(name)
|
|
40
|
+
buckets.fetch(name)
|
|
41
|
+
rescue KeyError
|
|
42
|
+
puts "No S3 bucket named #{name}"
|
|
43
|
+
exit
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Public: Get the full data for a bucket. Lazily loads resources only once.
|
|
47
|
+
#
|
|
48
|
+
# bucket_name - the name of the bucket to get
|
|
49
|
+
#
|
|
50
|
+
# Returns the full bucket
|
|
51
|
+
def full_bucket(bucket_name)
|
|
52
|
+
@monkey_patched ||= monkey_patch_bucket
|
|
53
|
+
@full_buckets ||= Hash.new
|
|
54
|
+
|
|
55
|
+
bucket = buckets[bucket_name]
|
|
56
|
+
@full_buckets[bucket_name] ||= Aws::S3::Bucket.new(name: bucket_name, client: client(bucket.location))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Public: Provide a mapping of S3 buckets to their names. Lazily loads resources.
|
|
60
|
+
#
|
|
61
|
+
# Returns the buckets mapped to their names
|
|
62
|
+
def buckets
|
|
63
|
+
@buckets ||= init_buckets
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Public: Refereshes the bucket list and full_buckets map
|
|
67
|
+
def refresh!
|
|
68
|
+
@buckets = init_buckets
|
|
69
|
+
@full_buckets = Hash.new
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
# Internal: Monkey patch Bucket so it can get its location
|
|
75
|
+
def monkey_patch_bucket
|
|
76
|
+
require "aws_extensions/s3/Bucket"
|
|
77
|
+
Aws::S3::Types::Bucket.send(:include, AwsExtensions::S3::Types::Bucket)
|
|
78
|
+
true
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Internal: Load the buckets and map them to their names.
|
|
82
|
+
#
|
|
83
|
+
# Returns the buckets mapped to their names
|
|
84
|
+
def init_buckets
|
|
85
|
+
Hash[client.list_buckets.buckets.map { |bucket| [bucket.name, bucket] }]
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require "common/BaseLoader"
|
|
2
|
+
require "conf/Configuration"
|
|
3
|
+
require "s3/models/BucketConfig"
|
|
4
|
+
|
|
5
|
+
require "aws-sdk"
|
|
6
|
+
|
|
7
|
+
module Cumulus
|
|
8
|
+
module S3
|
|
9
|
+
module Loader
|
|
10
|
+
include Common::BaseLoader
|
|
11
|
+
|
|
12
|
+
@@buckets_dir = Configuration.instance.s3.buckets_directory
|
|
13
|
+
@@cors_dir = Configuration.instance.s3.cors_directory
|
|
14
|
+
@@policies_dir = Configuration.instance.s3.policies_directory
|
|
15
|
+
|
|
16
|
+
# Public: Load all the bucket configurations a BucketConfig objects
|
|
17
|
+
#
|
|
18
|
+
# Returns an array of BucketConfigs
|
|
19
|
+
def self.buckets
|
|
20
|
+
Common::BaseLoader.resources(@@buckets_dir, &BucketConfig.method(:new))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Public: Load a specific CORS policy by name, applying any variables.
|
|
24
|
+
#
|
|
25
|
+
# name - the name of the file to load
|
|
26
|
+
# vars - the variables to apply to the template
|
|
27
|
+
#
|
|
28
|
+
# Returns the CORS policy as a string
|
|
29
|
+
def self.cors_policy(name, vars)
|
|
30
|
+
Common::BaseLoader.template(
|
|
31
|
+
name,
|
|
32
|
+
@@cors_dir,
|
|
33
|
+
vars,
|
|
34
|
+
&proc do |n, json| json.map do |rule|
|
|
35
|
+
Aws::S3::Types::CORSRule.new({
|
|
36
|
+
allowed_headers: rule.fetch("headers"),
|
|
37
|
+
allowed_methods: rule.fetch("methods"),
|
|
38
|
+
allowed_origins: rule.fetch("origins"),
|
|
39
|
+
expose_headers: rule.fetch("exposed-headers"),
|
|
40
|
+
max_age_seconds: rule.fetch("max-age-seconds")
|
|
41
|
+
})
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
)
|
|
45
|
+
rescue KeyError
|
|
46
|
+
puts "CORS configuration #{name} does not contain all required keys."
|
|
47
|
+
exit
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Public: Load a specific bucket policy by name, applying any variables
|
|
51
|
+
#
|
|
52
|
+
# name - the name of the file to load
|
|
53
|
+
# vars - the variables to apply to the template
|
|
54
|
+
#
|
|
55
|
+
# Returns the bucket policy as a string
|
|
56
|
+
def self.bucket_policy(name, vars)
|
|
57
|
+
Common::BaseLoader.template(
|
|
58
|
+
name,
|
|
59
|
+
@@policies_dir,
|
|
60
|
+
vars,
|
|
61
|
+
&proc { |n, json| json.to_json }
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
require "common/manager/Manager"
|
|
2
|
+
require "conf/Configuration"
|
|
3
|
+
require "s3/loader/Loader"
|
|
4
|
+
require "s3/models/BucketConfig"
|
|
5
|
+
require "s3/models/BucketDiff"
|
|
6
|
+
require "s3/S3"
|
|
7
|
+
require "util/Colors"
|
|
8
|
+
|
|
9
|
+
require "aws-sdk"
|
|
10
|
+
|
|
11
|
+
module Cumulus
|
|
12
|
+
module S3
|
|
13
|
+
class Manager < Common::Manager
|
|
14
|
+
def migrate
|
|
15
|
+
buckets_dir = "#{@migration_root}/buckets"
|
|
16
|
+
cors_dir = "#{@migration_root}/cors"
|
|
17
|
+
policy_dir = "#{@migration_root}/policies"
|
|
18
|
+
|
|
19
|
+
[@migration_root, buckets_dir, cors_dir, policy_dir].each do |dir|
|
|
20
|
+
if !Dir.exists?(dir)
|
|
21
|
+
Dir.mkdir(dir)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
cors = {}
|
|
26
|
+
policies = {}
|
|
27
|
+
|
|
28
|
+
aws_resources.each_value do |resource|
|
|
29
|
+
puts "Processing #{resource.name}..."
|
|
30
|
+
full_aws = S3.full_bucket(resource.name)
|
|
31
|
+
config = BucketConfig.new(resource.name)
|
|
32
|
+
new_policy_key, new_cors_key = config.populate!(full_aws, cors, policies)
|
|
33
|
+
|
|
34
|
+
puts "Writing #{resource.name} configuration to file..."
|
|
35
|
+
if new_policy_key
|
|
36
|
+
File.open("#{policy_dir}/#{new_policy_key}.json", "w") { |f| f.write(policies[new_policy_key]) }
|
|
37
|
+
end
|
|
38
|
+
if new_cors_key
|
|
39
|
+
File.open("#{cors_dir}/#{new_cors_key}.json", "w") { |f| f.write(cors[new_cors_key]) }
|
|
40
|
+
end
|
|
41
|
+
File.open("#{buckets_dir}/#{resource.name}.json", "w") { |f| f.write(config.pretty_json) }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def resource_name
|
|
46
|
+
"Bucket"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def local_resources
|
|
50
|
+
Hash[Loader.buckets.map { |bucket| [bucket.name, bucket] }]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def aws_resources
|
|
54
|
+
S3.buckets
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def unmanaged_diff(aws)
|
|
58
|
+
BucketDiff.unmanaged(aws)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def added_diff(local)
|
|
62
|
+
BucketDiff.added(local)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def diff_resource(local, aws)
|
|
66
|
+
if Configuration.instance.s3.print_progress
|
|
67
|
+
puts "checking for differences in #{local.name}"
|
|
68
|
+
end
|
|
69
|
+
full_aws = S3.full_bucket(aws.name)
|
|
70
|
+
local.diff(full_aws)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def create(local)
|
|
74
|
+
S3.client(local.region).create_bucket({
|
|
75
|
+
bucket: local.name,
|
|
76
|
+
create_bucket_configuration: if local.region != "us-east-1" then {
|
|
77
|
+
location_constraint: local.region
|
|
78
|
+
} end
|
|
79
|
+
})
|
|
80
|
+
S3.refresh!
|
|
81
|
+
update_policy(local.region, local.name, local.policy)
|
|
82
|
+
update_cors(local.region, local.name, local.cors)
|
|
83
|
+
update_grants(local.region, local.name, local.grants)
|
|
84
|
+
update_versioning(local.region, local.name, local.versioning)
|
|
85
|
+
update_logging(local.region, local.name, local.logging)
|
|
86
|
+
update_website(local.region, local.name, local.website)
|
|
87
|
+
update_lifecycle(local.region, local.name, local.lifecycle)
|
|
88
|
+
update_notifications(local.region, local.name, local.notifications)
|
|
89
|
+
update_replication(local.region, local.name, local.replication)
|
|
90
|
+
update_tags(local.region, local.name, local.tags) if !local.tags.empty?
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def update(local, diffs)
|
|
94
|
+
diffs.each do |diff|
|
|
95
|
+
if diff.type == BucketChange::TAGS
|
|
96
|
+
puts Colors.blue("\tupdating tags...")
|
|
97
|
+
update_tags(diff.local.region, diff.local.name, diff.local.tags)
|
|
98
|
+
elsif diff.type == BucketChange::POLICY
|
|
99
|
+
puts Colors.blue("\tupdating policy...")
|
|
100
|
+
update_policy(diff.local.region, diff.local.name, diff.local.policy)
|
|
101
|
+
elsif diff.type == BucketChange::CORS
|
|
102
|
+
puts Colors.blue("\tupdating CORS rules...")
|
|
103
|
+
update_cors(diff.local.region, diff.local.name, diff.local.cors)
|
|
104
|
+
elsif diff.type == BucketChange::WEBSITE
|
|
105
|
+
puts Colors.blue("\tupdating S3 bucket website...")
|
|
106
|
+
update_website(diff.local.region, diff.local.name, diff.local.website)
|
|
107
|
+
elsif diff.type == BucketChange::LOGGING
|
|
108
|
+
puts Colors.blue("\tupdating S3 bucket logging..")
|
|
109
|
+
update_logging(diff.local.region, diff.local.name, diff.local.logging)
|
|
110
|
+
elsif diff.type == BucketChange::VERSIONING
|
|
111
|
+
puts Colors.blue("\tupdating versioning status...")
|
|
112
|
+
update_versioning(diff.local.region, diff.local.name, diff.local.versioning)
|
|
113
|
+
elsif diff.type == BucketChange::GRANTS
|
|
114
|
+
puts Colors.blue("\tupdating grants...")
|
|
115
|
+
update_grants(diff.local.region, diff.local.name, diff.local.grants)
|
|
116
|
+
elsif diff.type == BucketChange::LIFECYCLE
|
|
117
|
+
puts Colors.blue("\tupdating lifecycle...")
|
|
118
|
+
update_lifecycle(diff.local.region, diff.local.name, diff.local.lifecycle)
|
|
119
|
+
elsif diff.type == BucketChange::NOTIFICATIONS
|
|
120
|
+
puts Colors.blue("\tupdating notifications...")
|
|
121
|
+
update_notifications(diff.local.region, diff.local.name, diff.local.notifications)
|
|
122
|
+
elsif diff.type == BucketChange::REPLICATION
|
|
123
|
+
puts Colors.blue("\tupdating replication...")
|
|
124
|
+
update_replication(diff.local.region, diff.local.name, diff.local.replication)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
private
|
|
130
|
+
|
|
131
|
+
# Internal: Update the tags for a bucket.
|
|
132
|
+
#
|
|
133
|
+
# region - the region of the bucket
|
|
134
|
+
# bucket_name - the name of the bucket
|
|
135
|
+
# tags - the tags that belong to the bucket
|
|
136
|
+
def update_tags(region, bucket_name, tags)
|
|
137
|
+
S3.client(region).put_bucket_tagging({
|
|
138
|
+
bucket: bucket_name,
|
|
139
|
+
tagging: {
|
|
140
|
+
tag_set: tags.map { |k, v| { key: k, value: v } }
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Internal: Update the policy for a bucket.
|
|
146
|
+
#
|
|
147
|
+
# region - the region of the bucket
|
|
148
|
+
# bucket_name - the name of the bucket
|
|
149
|
+
# policy - the policy to apply to the bucket
|
|
150
|
+
def update_policy(region, bucket_name, policy)
|
|
151
|
+
if policy
|
|
152
|
+
S3.client(region).put_bucket_policy({
|
|
153
|
+
bucket: bucket_name,
|
|
154
|
+
policy: policy
|
|
155
|
+
})
|
|
156
|
+
else
|
|
157
|
+
S3.client(region).delete_bucket_policy({
|
|
158
|
+
bucket: bucket_name
|
|
159
|
+
})
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Internal: Update the CORS rules for a bucket.
|
|
164
|
+
#
|
|
165
|
+
# region - the region of the bucket
|
|
166
|
+
# bucket_name - the name of the bucket
|
|
167
|
+
# cors - the cors rules for the bucket
|
|
168
|
+
def update_cors(region, bucket_name, cors)
|
|
169
|
+
if cors
|
|
170
|
+
S3.client(region).put_bucket_cors({
|
|
171
|
+
bucket: bucket_name,
|
|
172
|
+
cors_configuration: {
|
|
173
|
+
cors_rules: cors
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
else
|
|
177
|
+
S3.client(region).delete_bucket_cors({
|
|
178
|
+
bucket: bucket_name
|
|
179
|
+
})
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Internal: Update the bucket website configuration for the bucket.
|
|
184
|
+
#
|
|
185
|
+
# region - the region of the bucket
|
|
186
|
+
# bucket_name - the name of the bucket
|
|
187
|
+
# website - the website configuration for the bucket
|
|
188
|
+
def update_website(region, bucket_name, website)
|
|
189
|
+
if website
|
|
190
|
+
S3.client(region).put_bucket_website({
|
|
191
|
+
bucket: bucket_name,
|
|
192
|
+
website_configuration: website.to_aws
|
|
193
|
+
})
|
|
194
|
+
else
|
|
195
|
+
S3.client(region).delete_bucket_website({ bucket: bucket_name })
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Internal: Update the bucket logging configuration for the bucket.
|
|
200
|
+
#
|
|
201
|
+
# region - the region of the bucket
|
|
202
|
+
# bucket_name - the name of the bucket
|
|
203
|
+
# logging - the logging configuration for the bucket
|
|
204
|
+
def update_logging(region, bucket_name, logging)
|
|
205
|
+
S3.client(region).put_bucket_logging({
|
|
206
|
+
bucket: bucket_name,
|
|
207
|
+
bucket_logging_status: {
|
|
208
|
+
logging_enabled: (logging.to_aws rescue nil)
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Internal: Update the bucket versioning for the bucket.
|
|
214
|
+
#
|
|
215
|
+
# region - the region of the bucket
|
|
216
|
+
# bucket_name - the name of the bucket
|
|
217
|
+
# enabled - whether versioning should be enabled or not
|
|
218
|
+
def update_versioning(region, bucket_name, enabled)
|
|
219
|
+
S3.client(region).put_bucket_versioning({
|
|
220
|
+
bucket: bucket_name,
|
|
221
|
+
versioning_configuration: {
|
|
222
|
+
status: if enabled then "Enabled" else "Suspended" end
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Internal: Update the permission grants for the bucket.
|
|
228
|
+
#
|
|
229
|
+
# region - the region of the bucket
|
|
230
|
+
# bucket_name - the name of the bucket
|
|
231
|
+
# grants - the grants for the bucket
|
|
232
|
+
def update_grants(region, bucket_name, grants)
|
|
233
|
+
S3.client(region).put_bucket_acl({
|
|
234
|
+
bucket: bucket_name,
|
|
235
|
+
access_control_policy: {
|
|
236
|
+
grants: grants.values.map(&:to_aws).flatten,
|
|
237
|
+
owner: S3.full_bucket(bucket_name).acl.owner
|
|
238
|
+
}
|
|
239
|
+
})
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Internal: Update the lifecycle rules for the bucket.
|
|
243
|
+
#
|
|
244
|
+
# region - the region of the bucket
|
|
245
|
+
# bucket_name - the name of the bucket
|
|
246
|
+
# lifecycle - the lifecycle rules for the bucket
|
|
247
|
+
def update_lifecycle(region, bucket_name, lifecycle)
|
|
248
|
+
if lifecycle.empty?
|
|
249
|
+
S3.client(region).delete_bucket_lifecycle({
|
|
250
|
+
bucket: bucket_name
|
|
251
|
+
})
|
|
252
|
+
else
|
|
253
|
+
S3.client(region).put_bucket_lifecycle({
|
|
254
|
+
bucket: bucket_name,
|
|
255
|
+
lifecycle_configuration: {
|
|
256
|
+
rules: lifecycle.values.map(&:to_aws)
|
|
257
|
+
}
|
|
258
|
+
})
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Internal: Update the notification rules for the bucket.
|
|
263
|
+
#
|
|
264
|
+
# bucket_name - the name of the bucket
|
|
265
|
+
# notifications - the notification rules for the bucket
|
|
266
|
+
def update_notifications(region, bucket_name, notifications)
|
|
267
|
+
S3.client(region).put_bucket_notification_configuration({
|
|
268
|
+
bucket: bucket_name,
|
|
269
|
+
notification_configuration: {
|
|
270
|
+
topic_configurations: notifications.values.select { |n| n.type == "sns" }.map(&:to_aws),
|
|
271
|
+
queue_configurations: notifications.values.select { |n| n.type == "sqs" }.map(&:to_aws),
|
|
272
|
+
lambda_function_configurations: notifications.values.select { |n| n.type == "lambda" }.map(&:to_aws)
|
|
273
|
+
}
|
|
274
|
+
})
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# Internal: Update the replication rules for the bucket.
|
|
278
|
+
#
|
|
279
|
+
# region - the region of the bucket
|
|
280
|
+
# bucket_name - the name of the bucket
|
|
281
|
+
# replication - the replication rules for the bucket
|
|
282
|
+
def update_replication(region, bucket_name, replication)
|
|
283
|
+
if replication
|
|
284
|
+
S3.client(region).put_bucket_replication({
|
|
285
|
+
bucket: bucket_name,
|
|
286
|
+
replication_configuration: replication.to_aws
|
|
287
|
+
})
|
|
288
|
+
else
|
|
289
|
+
S3.client(region).delete_bucket_replication({
|
|
290
|
+
bucket: bucket_name
|
|
291
|
+
})
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|