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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rubocop.yml +9 -0
  4. data/.rubocop_todo.yml +59 -0
  5. data/.travis.yml +22 -0
  6. data/CODE_OF_CONDUCT.md +13 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +148 -0
  10. data/Rakefile +43 -0
  11. data/bin/console +11 -0
  12. data/bin/setup +7 -0
  13. data/enscalator.gemspec +57 -0
  14. data/exe/enscalator +13 -0
  15. data/lib/enscalator/core/cf_parameters.rb +146 -0
  16. data/lib/enscalator/core/cf_resources.rb +225 -0
  17. data/lib/enscalator/core/instance_type.rb +205 -0
  18. data/lib/enscalator/core/network_config.rb +21 -0
  19. data/lib/enscalator/core.rb +10 -0
  20. data/lib/enscalator/enapp.rb +248 -0
  21. data/lib/enscalator/helpers/dns.rb +62 -0
  22. data/lib/enscalator/helpers/stack.rb +107 -0
  23. data/lib/enscalator/helpers/sub_process.rb +72 -0
  24. data/lib/enscalator/helpers/wrappers.rb +55 -0
  25. data/lib/enscalator/helpers.rb +127 -0
  26. data/lib/enscalator/plugins/amazon_linux.rb +93 -0
  27. data/lib/enscalator/plugins/auto_scale.rb +80 -0
  28. data/lib/enscalator/plugins/core_os.rb +88 -0
  29. data/lib/enscalator/plugins/couchbase.rb +98 -0
  30. data/lib/enscalator/plugins/debian.rb +71 -0
  31. data/lib/enscalator/plugins/elastic_beanstalk.rb +74 -0
  32. data/lib/enscalator/plugins/elasticache.rb +168 -0
  33. data/lib/enscalator/plugins/elasticsearch_amazon.rb +75 -0
  34. data/lib/enscalator/plugins/elasticsearch_bitnami.rb +198 -0
  35. data/lib/enscalator/plugins/elasticsearch_opsworks.rb +225 -0
  36. data/lib/enscalator/plugins/elb.rb +139 -0
  37. data/lib/enscalator/plugins/nat_gateway.rb +71 -0
  38. data/lib/enscalator/plugins/rds.rb +141 -0
  39. data/lib/enscalator/plugins/redis.rb +38 -0
  40. data/lib/enscalator/plugins/rethink_db.rb +21 -0
  41. data/lib/enscalator/plugins/route53.rb +143 -0
  42. data/lib/enscalator/plugins/ubuntu.rb +85 -0
  43. data/lib/enscalator/plugins/user-data/elasticsearch +367 -0
  44. data/lib/enscalator/plugins/vpc_peering_connection.rb +48 -0
  45. data/lib/enscalator/plugins.rb +30 -0
  46. data/lib/enscalator/rich_template_dsl.rb +209 -0
  47. data/lib/enscalator/templates/vpc_peering.rb +112 -0
  48. data/lib/enscalator/templates.rb +20 -0
  49. data/lib/enscalator/version.rb +5 -0
  50. data/lib/enscalator/vpc.rb +11 -0
  51. data/lib/enscalator/vpc_with_nat_gateway.rb +311 -0
  52. data/lib/enscalator/vpc_with_nat_instance.rb +402 -0
  53. data/lib/enscalator.rb +103 -0
  54. 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,5 @@
1
+ # Enscalator
2
+ module Enscalator
3
+ # Current version
4
+ VERSION = '0.4.0'
5
+ 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