enscalator 0.4.0.pre.alpha.pre.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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