enscalator 0.4.0.pre.alpha.pre.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +9 -0
- data/.rubocop_todo.yml +59 -0
- data/.travis.yml +22 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +148 -0
- data/Rakefile +43 -0
- data/bin/console +11 -0
- data/bin/setup +7 -0
- data/enscalator.gemspec +57 -0
- data/exe/enscalator +13 -0
- data/lib/enscalator/core/cf_parameters.rb +146 -0
- data/lib/enscalator/core/cf_resources.rb +225 -0
- data/lib/enscalator/core/instance_type.rb +205 -0
- data/lib/enscalator/core/network_config.rb +21 -0
- data/lib/enscalator/core.rb +10 -0
- data/lib/enscalator/enapp.rb +248 -0
- data/lib/enscalator/helpers/dns.rb +62 -0
- data/lib/enscalator/helpers/stack.rb +107 -0
- data/lib/enscalator/helpers/sub_process.rb +72 -0
- data/lib/enscalator/helpers/wrappers.rb +55 -0
- data/lib/enscalator/helpers.rb +127 -0
- data/lib/enscalator/plugins/amazon_linux.rb +93 -0
- data/lib/enscalator/plugins/auto_scale.rb +80 -0
- data/lib/enscalator/plugins/core_os.rb +88 -0
- data/lib/enscalator/plugins/couchbase.rb +98 -0
- data/lib/enscalator/plugins/debian.rb +71 -0
- data/lib/enscalator/plugins/elastic_beanstalk.rb +74 -0
- data/lib/enscalator/plugins/elasticache.rb +168 -0
- data/lib/enscalator/plugins/elasticsearch_amazon.rb +75 -0
- data/lib/enscalator/plugins/elasticsearch_bitnami.rb +198 -0
- data/lib/enscalator/plugins/elasticsearch_opsworks.rb +225 -0
- data/lib/enscalator/plugins/elb.rb +139 -0
- data/lib/enscalator/plugins/nat_gateway.rb +71 -0
- data/lib/enscalator/plugins/rds.rb +141 -0
- data/lib/enscalator/plugins/redis.rb +38 -0
- data/lib/enscalator/plugins/rethink_db.rb +21 -0
- data/lib/enscalator/plugins/route53.rb +143 -0
- data/lib/enscalator/plugins/ubuntu.rb +85 -0
- data/lib/enscalator/plugins/user-data/elasticsearch +367 -0
- data/lib/enscalator/plugins/vpc_peering_connection.rb +48 -0
- data/lib/enscalator/plugins.rb +30 -0
- data/lib/enscalator/rich_template_dsl.rb +209 -0
- data/lib/enscalator/templates/vpc_peering.rb +112 -0
- data/lib/enscalator/templates.rb +20 -0
- data/lib/enscalator/version.rb +5 -0
- data/lib/enscalator/vpc.rb +11 -0
- data/lib/enscalator/vpc_with_nat_gateway.rb +311 -0
- data/lib/enscalator/vpc_with_nat_instance.rb +402 -0
- data/lib/enscalator.rb +103 -0
- metadata +427 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
module Enscalator
|
2
|
+
module Templates
|
3
|
+
# VPC Peering connection between two VPCs
|
4
|
+
class VPCPeering < Enscalator::RichTemplateDSL
|
5
|
+
include Enscalator::Plugins::VPCPeeringConnection
|
6
|
+
|
7
|
+
# Retrieve local VPC configuration from provisioned stack
|
8
|
+
# @return [Aws::CloudFormation::Stack]
|
9
|
+
def local_vpc_stack
|
10
|
+
@local_vpc_stack ||= cfn_resource(cfn_client(region)).stack(vpc_stack_name)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Interface for VPC
|
14
|
+
# @param [String] id logical id of VPC
|
15
|
+
# @return [Aws::EC2::Vpc]
|
16
|
+
def vpc(id: get_resource(local_vpc_stack, 'VPC'))
|
17
|
+
Aws::EC2::Vpc.new(id: id, region: region)
|
18
|
+
end
|
19
|
+
|
20
|
+
# VPC Peering connection can be created only when
|
21
|
+
#
|
22
|
+
# - both VPCs are in the same region
|
23
|
+
# - connected VPCs has distinct CIDR blocks
|
24
|
+
#
|
25
|
+
# Route tables should be created in the following way:
|
26
|
+
#
|
27
|
+
# VPC Local's route table
|
28
|
+
# 172.16.0.0/16 -> Local
|
29
|
+
# 10.0.0.0/16 -> pcx-11112222
|
30
|
+
#
|
31
|
+
# VPC Remote's route table
|
32
|
+
# 10.0.0.0/16 Local
|
33
|
+
# 172.16.0.0/16 pcx-11112222
|
34
|
+
def tpl
|
35
|
+
connection_name = 'PrivateConnection'
|
36
|
+
local_vpc_id_ref, remote_vpc_id_ref = %W(#{connection_name}VpcId #{connection_name}PeerVpcId)
|
37
|
+
|
38
|
+
def validate_params(*params)
|
39
|
+
params.each do |param|
|
40
|
+
fail "Unable to find required parameter #{param}" unless @parameters.key?(param)
|
41
|
+
end
|
42
|
+
rescue RuntimeError => e
|
43
|
+
puts e
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
|
47
|
+
validate_params(*[remote_vpc_id_ref])
|
48
|
+
|
49
|
+
local_vpc, remote_vpc = [vpc, vpc(id: @parameters[remote_vpc_id_ref])]
|
50
|
+
|
51
|
+
description 'Stack to create peering connection between two VPCs'
|
52
|
+
|
53
|
+
parameter_vpc_id(local_vpc_id_ref,
|
54
|
+
'VpcId from where connection gets created',
|
55
|
+
local_vpc.id)
|
56
|
+
|
57
|
+
parameter_vpc_id(remote_vpc_id_ref,
|
58
|
+
'VpcId where peering connection should go',
|
59
|
+
remote_vpc.id)
|
60
|
+
|
61
|
+
# Initialize Peering connection
|
62
|
+
vpc_peering_init(connection_name,
|
63
|
+
tags: [
|
64
|
+
{
|
65
|
+
Key: 'Name',
|
66
|
+
Value: connection_name
|
67
|
+
}
|
68
|
+
])
|
69
|
+
|
70
|
+
def read_vpc_route_tables(vpc)
|
71
|
+
routes = []
|
72
|
+
vpc.route_tables.each do |rt|
|
73
|
+
routes << rt
|
74
|
+
end
|
75
|
+
routes
|
76
|
+
end
|
77
|
+
|
78
|
+
# Add rules to local VPC routing table
|
79
|
+
read_vpc_route_tables(local_vpc).map(&:id).each_with_index do |rt_id, i|
|
80
|
+
local_vpc_route_rule = "LocalVPCPeeringRoute#{i + 1}"
|
81
|
+
resource local_vpc_route_rule,
|
82
|
+
Type: 'AWS::EC2::Route',
|
83
|
+
Properties: {
|
84
|
+
RouteTableId: rt_id,
|
85
|
+
DestinationCidrBlock: remote_vpc.cidr_block,
|
86
|
+
VpcPeeringConnectionId: ref(connection_name)
|
87
|
+
}
|
88
|
+
|
89
|
+
output local_vpc_route_rule,
|
90
|
+
Description: "Local VPC Peering connection for #{rt_id}",
|
91
|
+
Value: ref(local_vpc_route_rule)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Add rules to remote VPC routing table
|
95
|
+
read_vpc_route_tables(remote_vpc).map(&:id).each_with_index do |rt_id, i|
|
96
|
+
remote_vpc_route_rule = "RemoteVPCPeeringRoute#{i + 1}"
|
97
|
+
resource remote_vpc_route_rule,
|
98
|
+
Type: 'AWS::EC2::Route',
|
99
|
+
Properties: {
|
100
|
+
RouteTableId: rt_id,
|
101
|
+
DestinationCidrBlock: local_vpc.cidr_block,
|
102
|
+
VpcPeeringConnectionId: ref(connection_name)
|
103
|
+
}
|
104
|
+
|
105
|
+
output remote_vpc_route_rule,
|
106
|
+
Description: "Remote VPC Peering connection for #{rt_id}",
|
107
|
+
Value: ref(remote_vpc_route_rule)
|
108
|
+
end
|
109
|
+
end # tpl
|
110
|
+
end # class VPCPeering
|
111
|
+
end # module Plugins
|
112
|
+
end # module Enscalator
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'templates/vpc_peering'
|
2
|
+
|
3
|
+
module Enscalator
|
4
|
+
# Namespace for template collection
|
5
|
+
module Templates
|
6
|
+
# Get all loaded template classes
|
7
|
+
# @return [Array]
|
8
|
+
def self.all
|
9
|
+
namespace = Enscalator::Templates
|
10
|
+
templates = namespace.constants
|
11
|
+
templates.map { |t| (namespace.to_s.split('::') << t.to_s).join('::').constantize }
|
12
|
+
end
|
13
|
+
|
14
|
+
# Verify if all loaded templates have required tpl method
|
15
|
+
# @return [Boolean]
|
16
|
+
def self.all_valid?
|
17
|
+
all.map { |t| t.instance_methods.include?(:tpl) }.all?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Enscalator
|
2
|
+
module Templates
|
3
|
+
# Amazon AWS Virtual Private Cloud template (defaults to template with NAT gateway)
|
4
|
+
class VPC < Enscalator::Templates::VPCWithNATGateway
|
5
|
+
# Call method with same name from superclass
|
6
|
+
def tpl
|
7
|
+
super
|
8
|
+
end
|
9
|
+
end # class VPC
|
10
|
+
end # module Templates
|
11
|
+
end # module Enscalator
|
@@ -0,0 +1,311 @@
|
|
1
|
+
module Enscalator
|
2
|
+
module Templates
|
3
|
+
# Amazon AWS Virtual Private Cloud template with NAT gateway
|
4
|
+
class VPCWithNATGateway < Enscalator::RichTemplateDSL
|
5
|
+
include Enscalator::Plugins::NATGateway
|
6
|
+
|
7
|
+
# Subnet size (256 addresses)
|
8
|
+
SUBNET_CIDR_BLOCK_SIZE = 24
|
9
|
+
|
10
|
+
# Template method
|
11
|
+
def tpl
|
12
|
+
description = <<-EOS.gsub(/^\s+\|/, '')
|
13
|
+
|AWS CloudFormation template for the VPC environment.
|
14
|
+
|For each availability zone stack creates: the public subnet, internet and NAT gateways,
|
15
|
+
|internet access from private subnets, routing configuration for corresponding subnets
|
16
|
+
|and security groups.
|
17
|
+
EOS
|
18
|
+
|
19
|
+
value Description: description
|
20
|
+
|
21
|
+
mapping 'AWSRegionNetConfig', Core::NetworkConfig.mapping_vpc_net
|
22
|
+
|
23
|
+
resource 'VPC',
|
24
|
+
Type: 'AWS::EC2::VPC',
|
25
|
+
Properties: {
|
26
|
+
CidrBlock: find_in_map('AWSRegionNetConfig', ref('AWS::Region'), 'VPC'),
|
27
|
+
EnableDnsSupport: 'true',
|
28
|
+
EnableDnsHostnames: 'true',
|
29
|
+
Tags: [
|
30
|
+
{
|
31
|
+
Key: 'Name',
|
32
|
+
Value: aws_stack_name
|
33
|
+
},
|
34
|
+
{
|
35
|
+
Key: 'Application',
|
36
|
+
Value: aws_stack_name
|
37
|
+
},
|
38
|
+
{
|
39
|
+
Key: 'Network',
|
40
|
+
Value: 'Public'
|
41
|
+
}
|
42
|
+
]
|
43
|
+
}
|
44
|
+
|
45
|
+
resource 'InternetGateway',
|
46
|
+
Type: 'AWS::EC2::InternetGateway',
|
47
|
+
Properties: {
|
48
|
+
Tags: [
|
49
|
+
{
|
50
|
+
Key: 'Name',
|
51
|
+
Value: 'Public Gateway'
|
52
|
+
},
|
53
|
+
{
|
54
|
+
Key: 'Application',
|
55
|
+
Value: aws_stack_name
|
56
|
+
},
|
57
|
+
{
|
58
|
+
Key: 'Network',
|
59
|
+
Value: 'Public'
|
60
|
+
}
|
61
|
+
]
|
62
|
+
}
|
63
|
+
|
64
|
+
resource 'GatewayToInternet',
|
65
|
+
DependsOn: %w( VPC InternetGateway ),
|
66
|
+
Type: 'AWS::EC2::VPCGatewayAttachment',
|
67
|
+
Properties: {
|
68
|
+
VpcId: ref('VPC'),
|
69
|
+
InternetGatewayId: ref('InternetGateway')
|
70
|
+
}
|
71
|
+
|
72
|
+
resource 'PublicRouteTable',
|
73
|
+
DependsOn: ['VPC'],
|
74
|
+
Type: 'AWS::EC2::RouteTable',
|
75
|
+
Properties: {
|
76
|
+
VpcId: ref('VPC'),
|
77
|
+
Tags: [
|
78
|
+
{
|
79
|
+
Key: 'Name',
|
80
|
+
Value: 'Public'
|
81
|
+
},
|
82
|
+
{
|
83
|
+
Key: 'Application',
|
84
|
+
Value: aws_stack_name
|
85
|
+
},
|
86
|
+
{
|
87
|
+
Key: 'Network',
|
88
|
+
Value: 'Public'
|
89
|
+
}
|
90
|
+
]
|
91
|
+
}
|
92
|
+
|
93
|
+
resource 'PublicRoute',
|
94
|
+
DependsOn: %w( PublicRouteTable InternetGateway ),
|
95
|
+
Type: 'AWS::EC2::Route',
|
96
|
+
Properties: {
|
97
|
+
RouteTableId: ref('PublicRouteTable'),
|
98
|
+
DestinationCidrBlock: '0.0.0.0/0',
|
99
|
+
GatewayId: ref('InternetGateway')
|
100
|
+
}
|
101
|
+
|
102
|
+
resource 'PublicNetworkAcl',
|
103
|
+
DependsOn: ['VPC'],
|
104
|
+
Type: 'AWS::EC2::NetworkAcl',
|
105
|
+
Properties: {
|
106
|
+
VpcId: ref('VPC'),
|
107
|
+
Tags: [
|
108
|
+
{
|
109
|
+
Key: 'Name',
|
110
|
+
Value: 'Public'
|
111
|
+
},
|
112
|
+
{
|
113
|
+
Key: 'Application',
|
114
|
+
Value: aws_stack_name
|
115
|
+
},
|
116
|
+
{
|
117
|
+
Key: 'Network',
|
118
|
+
Value: 'Public'
|
119
|
+
}
|
120
|
+
]
|
121
|
+
}
|
122
|
+
|
123
|
+
resource 'InboundHTTPPublicNetworkAclEntry',
|
124
|
+
DependsOn: ['PublicNetworkAcl'],
|
125
|
+
Type: 'AWS::EC2::NetworkAclEntry',
|
126
|
+
Properties: {
|
127
|
+
NetworkAclId: ref('PublicNetworkAcl'),
|
128
|
+
RuleNumber: '100',
|
129
|
+
Protocol: '-1',
|
130
|
+
RuleAction: 'allow',
|
131
|
+
Egress: 'false',
|
132
|
+
CidrBlock: '0.0.0.0/0',
|
133
|
+
PortRange: { From: '0', To: '65535' }
|
134
|
+
}
|
135
|
+
|
136
|
+
resource 'OutboundHTTPPublicNetworkAclEntry',
|
137
|
+
DependsOn: ['PublicNetworkAcl'],
|
138
|
+
Type: 'AWS::EC2::NetworkAclEntry',
|
139
|
+
Properties: {
|
140
|
+
NetworkAclId: ref('PublicNetworkAcl'),
|
141
|
+
RuleNumber: '100',
|
142
|
+
Protocol: '-1',
|
143
|
+
RuleAction: 'allow',
|
144
|
+
Egress: 'true',
|
145
|
+
CidrBlock: '0.0.0.0/0',
|
146
|
+
PortRange: { From: '0', To: '65535' }
|
147
|
+
}
|
148
|
+
|
149
|
+
resource 'PrivateNetworkAcl',
|
150
|
+
DependsOn: ['VPC'],
|
151
|
+
Type: 'AWS::EC2::NetworkAcl',
|
152
|
+
Properties: {
|
153
|
+
VpcId: ref('VPC'),
|
154
|
+
Tags: [
|
155
|
+
{
|
156
|
+
Key: 'Name',
|
157
|
+
Value: 'Private'
|
158
|
+
},
|
159
|
+
{
|
160
|
+
Key: 'Application',
|
161
|
+
Value: aws_stack_name
|
162
|
+
},
|
163
|
+
{
|
164
|
+
Key: 'Network',
|
165
|
+
Value: 'Private'
|
166
|
+
}
|
167
|
+
]
|
168
|
+
}
|
169
|
+
|
170
|
+
resource 'InboundPrivateNetworkAclEntry',
|
171
|
+
DependsOn: ['PrivateNetworkAcl'],
|
172
|
+
Type: 'AWS::EC2::NetworkAclEntry',
|
173
|
+
Properties: {
|
174
|
+
NetworkAclId: ref('PrivateNetworkAcl'),
|
175
|
+
RuleNumber: '100',
|
176
|
+
Protocol: '6',
|
177
|
+
RuleAction: 'allow',
|
178
|
+
Egress: 'false',
|
179
|
+
CidrBlock: '0.0.0.0/0',
|
180
|
+
PortRange: { From: '0', To: '65535' }
|
181
|
+
}
|
182
|
+
|
183
|
+
resource 'OutBoundPrivateNetworkAclEntry',
|
184
|
+
DependsOn: ['PrivateNetworkAcl'],
|
185
|
+
Type: 'AWS::EC2::NetworkAclEntry',
|
186
|
+
Properties: {
|
187
|
+
NetworkAclId: ref('PrivateNetworkAcl'),
|
188
|
+
RuleNumber: '100',
|
189
|
+
Protocol: '6',
|
190
|
+
RuleAction: 'allow',
|
191
|
+
Egress: 'true',
|
192
|
+
CidrBlock: '0.0.0.0/0',
|
193
|
+
PortRange: { From: '0', To: '65535' }
|
194
|
+
}
|
195
|
+
|
196
|
+
resource 'PrivateSecurityGroup',
|
197
|
+
DependsOn: ['VPC'],
|
198
|
+
Type: 'AWS::EC2::SecurityGroup',
|
199
|
+
Properties: {
|
200
|
+
GroupDescription: 'Allow the Application instances to access the NAT device',
|
201
|
+
VpcId: ref('VPC'),
|
202
|
+
SecurityGroupEgress: [
|
203
|
+
{
|
204
|
+
IpProtocol: 'tcp',
|
205
|
+
FromPort: '0',
|
206
|
+
ToPort: '65535',
|
207
|
+
CidrIp: '10.0.0.0/8'
|
208
|
+
}
|
209
|
+
],
|
210
|
+
SecurityGroupIngress: [
|
211
|
+
{
|
212
|
+
IpProtocol: 'tcp',
|
213
|
+
FromPort: '0',
|
214
|
+
ToPort: '65535',
|
215
|
+
CidrIp: '10.0.0.0/8'
|
216
|
+
}
|
217
|
+
],
|
218
|
+
Tags: [
|
219
|
+
{
|
220
|
+
Key: 'Name',
|
221
|
+
Value: 'Private'
|
222
|
+
}
|
223
|
+
]
|
224
|
+
}
|
225
|
+
|
226
|
+
current_cidr_block = Core::NetworkConfig.mapping_vpc_net[region.to_sym][:VPC]
|
227
|
+
public_cidr_blocks =
|
228
|
+
IPAddress(current_cidr_block).subnet(SUBNET_CIDR_BLOCK_SIZE).map(&:to_string).first(availability_zones.size)
|
229
|
+
|
230
|
+
availability_zones.zip(public_cidr_blocks).each do |pair, cidr_block|
|
231
|
+
suffix = pair.first
|
232
|
+
public_subnet_name = "PublicSubnet#{suffix.upcase}"
|
233
|
+
resource public_subnet_name,
|
234
|
+
DependsOn: ['VPC'],
|
235
|
+
Type: 'AWS::EC2::Subnet',
|
236
|
+
Properties: {
|
237
|
+
VpcId: ref('VPC'),
|
238
|
+
AvailabilityZone: join('', ref('AWS::Region'), suffix.to_s),
|
239
|
+
CidrBlock: cidr_block,
|
240
|
+
Tags: [
|
241
|
+
{
|
242
|
+
Key: 'Name',
|
243
|
+
Value: "Public #{suffix.upcase}"
|
244
|
+
},
|
245
|
+
{
|
246
|
+
Key: 'Application',
|
247
|
+
Value: aws_stack_name
|
248
|
+
},
|
249
|
+
{
|
250
|
+
Key: 'Network',
|
251
|
+
Value: 'Public'
|
252
|
+
}
|
253
|
+
]
|
254
|
+
}
|
255
|
+
|
256
|
+
resource "PublicSubnetRouteTableAssociation#{suffix.upcase}",
|
257
|
+
DependsOn: [public_subnet_name, 'PublicRouteTable'],
|
258
|
+
Type: 'AWS::EC2::SubnetRouteTableAssociation',
|
259
|
+
Properties: {
|
260
|
+
SubnetId: ref(public_subnet_name),
|
261
|
+
RouteTableId: ref('PublicRouteTable')
|
262
|
+
}
|
263
|
+
|
264
|
+
private_route_table_name = "PrivateRouteTable#{suffix.upcase}"
|
265
|
+
resource private_route_table_name,
|
266
|
+
DependsOn: ['VPC'],
|
267
|
+
Type: 'AWS::EC2::RouteTable',
|
268
|
+
Properties: {
|
269
|
+
VpcId: ref('VPC'),
|
270
|
+
Tags: [
|
271
|
+
{
|
272
|
+
Key: 'Name',
|
273
|
+
Value: "Private #{suffix.upcase}"
|
274
|
+
},
|
275
|
+
{
|
276
|
+
Key: 'Application',
|
277
|
+
Value: aws_stack_name
|
278
|
+
},
|
279
|
+
{
|
280
|
+
Key: 'Network',
|
281
|
+
Value: 'Private'
|
282
|
+
}
|
283
|
+
]
|
284
|
+
}
|
285
|
+
|
286
|
+
# Important!
|
287
|
+
# When updating stack that was previously deployed using VPC template with NAT EC2 instance:
|
288
|
+
# 1. Comment out lines related to NAT device below
|
289
|
+
# 2. Update stack using this template (it will remove NAT instances and related security and routing rules)
|
290
|
+
# 3. Revert changes from 1. (i.e. uncomment lines below)
|
291
|
+
# 4. Update stack again (this time it will create new NAT Gateway, EIP and routing rule resources)
|
292
|
+
nat_device_name = "NATDevice#{suffix.upcase}"
|
293
|
+
nat_gateway_init(nat_device_name, public_subnet_name, private_route_table_name,
|
294
|
+
depends_on: [public_subnet_name, 'PublicRouteTable', 'GatewayToInternet'])
|
295
|
+
|
296
|
+
output public_subnet_name,
|
297
|
+
Description: "Created Subnet #{suffix.upcase}",
|
298
|
+
Value: ref(public_subnet_name)
|
299
|
+
end # each availability zone
|
300
|
+
|
301
|
+
output 'VpcId',
|
302
|
+
Description: 'Created VPC',
|
303
|
+
Value: ref('VPC')
|
304
|
+
|
305
|
+
output 'PrivateSecurityGroup',
|
306
|
+
Description: 'SecurityGroup to add private resources',
|
307
|
+
Value: ref('PrivateSecurityGroup')
|
308
|
+
end # def tpl
|
309
|
+
end # class VPC
|
310
|
+
end # module Templates
|
311
|
+
end # module Enscalator
|