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,225 @@
1
+ module Enscalator
2
+ module Core
3
+ # Resources for cloudformation template dsl
4
+ module CfResources
5
+ # VPC resource
6
+ #
7
+ # @param [String] name of the vpc name
8
+ # @param [String] cidr ip address block in CIDR notation (Classless Inter-Domain Routing)
9
+ # @param [String] enable_dns_support enable dns support
10
+ # @param [String] enable_dns_hostnames enable dns hostname
11
+ # @param [Array] depends_on list of resources this vpc needs
12
+ # @param [Hash] tags tags
13
+ def vpc(name, cidr, enable_dns_support: nil, enable_dns_hostnames: nil, depends_on: [], tags: {})
14
+ properties = {
15
+ CidrBlock: cidr
16
+ }
17
+ properties[:EnableDnsSupport] = enable_dns_support unless enable_dns_support.nil?
18
+ properties[:EnableDnsHostnames] = enable_dns_hostnames unless enable_dns_hostnames.nil?
19
+ unless tags.include?('Name')
20
+ tags['Name'] = join('-', aws_stack_name, name)
21
+ end
22
+ properties[:Tags] = tags_to_properties(tags)
23
+ options = {
24
+ Type: 'AWS::EC2::VPC',
25
+ Properties: properties
26
+ }
27
+ options[:DependsOn] = depends_on unless depends_on.empty?
28
+ resource name, options
29
+ name
30
+ end
31
+
32
+ # Subnet resource
33
+ #
34
+ # @param [String] name of the vpc name
35
+ # @param [String] cidr ip address block in CIDR notation (Classless Inter-Domain Routing)
36
+ # @param [String] availability_zone where subnet gets created
37
+ # @param [Array] depends_on list of resources this vpc needs
38
+ # @param [Hash] tags tags
39
+ def subnet(name, vpc, cidr, availability_zone: '', depends_on: [], tags: {})
40
+ properties = {
41
+ VpcId: vpc,
42
+ CidrBlock: cidr
43
+ }
44
+ properties[:AvailabilityZone] = availability_zone unless availability_zone.empty?
45
+ unless tags.include?('Name')
46
+ tags['Name'] = join('-', aws_stack_name, name)
47
+ end
48
+ properties[:Tags] = tags_to_properties(tags)
49
+
50
+ options = {
51
+ Type: 'AWS::EC2::Subnet',
52
+ Properties: properties
53
+ }
54
+ options[:DependsOn] = depends_on unless depends_on.empty?
55
+ resource name, options
56
+ name
57
+ end
58
+
59
+ # Security group
60
+ #
61
+ # @param [String] name of the security group
62
+ # @param [String] description of security group
63
+ # @param [Array] security_group_egress list of outbound rules
64
+ # @param [Array] security_group_ingress list of inbound rules
65
+ # @param [Array] depends_on list of resources this vpc needs
66
+ # @param [Hash] tags tags
67
+ def security_group(name,
68
+ description,
69
+ security_group_egress: [],
70
+ security_group_ingress: [],
71
+ depends_on: [],
72
+ tags: {})
73
+ properties = {
74
+ GroupDescription: description
75
+ }
76
+ properties[:SecurityGroupEgress] = security_group_egress unless security_group_egress.empty?
77
+ properties[:SecurityGroupIngress] = security_group_ingress unless security_group_ingress.empty?
78
+ unless tags.include?('Name')
79
+ tags['Name'] = join('-', aws_stack_name, name)
80
+ end
81
+ properties[:Tags] = tags_to_properties(tags)
82
+ options = {
83
+ Type: 'AWS::EC2::SecurityGroup',
84
+ Properties: properties
85
+ }
86
+ options[:DependsOn] = depends_on unless depends_on.empty?
87
+ resource name, options
88
+ name
89
+ end
90
+
91
+ # VPC Security group
92
+ #
93
+ # @param [String] name of the security group
94
+ # @param [String] description of security group
95
+ # @param [Array] security_group_egress list of outbound rules
96
+ # @param [Array] security_group_ingress list of inbound rules
97
+ # @param [Array] depends_on list of resources this vpc needs
98
+ # @param [Hash] tags tags
99
+ def security_group_vpc(name,
100
+ description,
101
+ vpc,
102
+ security_group_egress: [],
103
+ security_group_ingress: [],
104
+ depends_on: [],
105
+ tags: {})
106
+ properties = {
107
+ VpcId: vpc,
108
+ GroupDescription: description
109
+ }
110
+ properties[:SecurityGroupEgress] = security_group_egress unless security_group_egress.empty?
111
+ properties[:SecurityGroupIngress] = security_group_ingress unless security_group_ingress.empty?
112
+ unless tags.include?('Name')
113
+ tags['Name'] = join('-', aws_stack_name, name)
114
+ end
115
+ properties[:Tags] = tags_to_properties(tags)
116
+ options = {
117
+ Type: 'AWS::EC2::SecurityGroup',
118
+ Properties: properties
119
+ }
120
+ options[:DependsOn] = depends_on unless depends_on.empty?
121
+ resource name, options
122
+ name
123
+ end
124
+
125
+ # IAM instance profile with full access policies to passed services
126
+ #
127
+ # @param [String] role_name iam role name
128
+ # @param [Array<String>] services a list of aws service name
129
+ # @return [String] iam instance profile name
130
+ def iam_instance_profile_with_full_access(role_name, *services)
131
+ resource "#{role_name}Role",
132
+ Type: 'AWS::IAM::Role',
133
+ Properties: {
134
+ AssumeRolePolicyDocument: {
135
+ Statement: [
136
+ {
137
+ Effect: 'Allow',
138
+ Principal: {
139
+ Service: ['ec2.amazonaws.com']
140
+ },
141
+ Action: ['sts:AssumeRole']
142
+ }
143
+ ]
144
+ },
145
+ Path: '/',
146
+ Policies: [
147
+ {
148
+ PolicyName: "#{role_name}Policy",
149
+ PolicyDocument: {
150
+ Statement: services.map do |s|
151
+ {
152
+ Effect: 'Allow',
153
+ Action: "#{s}:*",
154
+ Resource: '*'
155
+ }
156
+ end
157
+ }
158
+ }
159
+ ]
160
+ }
161
+
162
+ resource "#{role_name}InstanceProfile",
163
+ Type: 'AWS::IAM::InstanceProfile',
164
+ Properties: {
165
+ Path: '/',
166
+ Roles: [ref("#{role_name}Role")]
167
+ }
168
+
169
+ ref("#{role_name}InstanceProfile")
170
+ end
171
+
172
+ # Create ec2 instance in given vpc
173
+ #
174
+ # @param [String] name instance name
175
+ # @param [String] image_id instance ami_id
176
+ # @param [String] subnet instance subnet id
177
+ # @param [String] security_groups instance security_groups (string of Security Groups IDs)
178
+ # @param [Array] depends_on resources necessary to be create prior to this instance
179
+ # @param [Hash] properties other properties
180
+ def instance_vpc(name, image_id, subnet, security_groups, depends_on: [], properties: {})
181
+ fail "VPC instance #{name} can not contain non VPC SecurityGroups" if properties.include?(:SecurityGroups)
182
+ if properties.include?(:NetworkInterfaces)
183
+ fail "VPC instance #{name} can not contain NetworkInterfaces and subnet or security_groups"
184
+ end
185
+ properties[:ImageId] = image_id
186
+ properties[:SubnetId] = subnet
187
+ properties[:SecurityGroupIds] = security_groups
188
+ if properties[:Tags] && !properties[:Tags].any? { |x| x[:Key] == 'Name' }
189
+ properties[:Tags] << { Key: 'Name', Value: join('-', aws_stack_name, name) }
190
+ end
191
+ options = {
192
+ Type: 'AWS::EC2::Instance',
193
+ Properties: properties
194
+ }
195
+
196
+ options[:DependsOn] = depends_on unless depends_on.empty?
197
+ resource name, options
198
+ name
199
+ end
200
+
201
+ # Create ec2 instance with attached to it network interface
202
+ #
203
+ # @param [String] name instance name
204
+ # @param [String] image_id instance ami_id
205
+ # @param [String] network_interfaces network interfaces
206
+ # @param [Hash] properties other properties
207
+ def instance_with_network(name, image_id, network_interfaces, properties: {})
208
+ if ([:SubnetId, :SecurityGroups, :SecurityGroupIds] & properties).any?
209
+ fail "Instance with NetworkInterfaces #{name} can not contain instance subnet or security_groups"
210
+ end
211
+ properties[:ImageId] = image_id
212
+ properties[:NetworkInterfaces] = network_interfaces
213
+ if properties[:Tags] && !properties[:Tags].any? { |x| x[:Key] == 'Name' }
214
+ properties[:Tags] << { Key: 'Name', Value: join('-', aws_stack_name, name) }
215
+ end
216
+ options = {
217
+ Type: 'AWS::EC2::Instance',
218
+ Properties: properties
219
+ }
220
+ resource name, options
221
+ name
222
+ end
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,205 @@
1
+ module Enscalator
2
+ module Core
3
+ # Instance type
4
+ module InstanceType
5
+ # Generic Aws instance
6
+ class AwsInstance
7
+ attr_reader :current_generation, :previous_generation
8
+
9
+ # Create new AwsInstance
10
+ #
11
+ # @param [Hash] current generation instances
12
+ # @param [Hash] previous generation instances
13
+ def initialize(current = {}, previous = {})
14
+ fail('Unable to instantiate if its not Hash') unless current.is_a?(Hash) && previous.is_a?(Hash)
15
+ @current_generation ||= current
16
+ @previous_generation ||= previous
17
+ end
18
+
19
+ # Check if given instance type is either current or previous generation
20
+ #
21
+ # @param [String] type instance type
22
+ # @return [Boolean]
23
+ def supported?(type)
24
+ (@current_generation.values + @previous_generation.values).flatten.include? type
25
+ end
26
+
27
+ # Checks if given instance type is in previous generation
28
+ #
29
+ # @param [String] type instance type
30
+ # @return [Boolean]
31
+ def obsolete?(type)
32
+ @previous_generation.values.flatten.include? type
33
+ end
34
+
35
+ # List of all allowed values
36
+ #
37
+ # @param [String] type instance type
38
+ # @return [Array]
39
+ def allowed_values(type)
40
+ return [] unless self.supported?(type)
41
+ self.obsolete?(type) ? @previous_generation.values.flatten : @current_generation.values.flatten
42
+ end
43
+ end
44
+
45
+ # EC2 instance
46
+ class EC2 < AwsInstance
47
+ def initialize
48
+ super(current_generation, previous_generation)
49
+ end
50
+
51
+ # Current generation instance types
52
+ #
53
+ # @return [Hash] instance family and type
54
+ def current_generation
55
+ {
56
+ general_purpose: %w(
57
+ t2.micro t2.small t2.medium t2.large
58
+ m4.large m4.xlarge m4.2xlarge m4.4xlarge m4.10xlarge
59
+ m3.medium m3.large m3.xlarge m3.2xlarge
60
+ ),
61
+ compute_optimized: %w(
62
+ c4.large c4.xlarge c4.2xlarge c4.4xlarge c4.8xlarge
63
+ c3.large c3.xlarge c3.2xlarge c3.4xlarge c3.8xlarge
64
+ ),
65
+ memory_optimized: %w( r3.large r3.xlarge r3.2xlarge r3.4xlarge r3.8xlarge ),
66
+ gpu: %w( g2.2xlarge g2.8xlarge ),
67
+ high_io_optimized: %w( i2.xlarge i2.xlarge i2.4xlarge i2.8xlarge ),
68
+ dense_storage_optimized: %w( d2.xlarge d2.2xlarge d2.4xlarge d2.8xlarge )
69
+ }
70
+ end
71
+
72
+ # @deprecated Will be removed once Amazon fully stops supporting these instances
73
+ # Previous generation instance types
74
+ #
75
+ # @return [Hash] instance family and type
76
+ def previous_generation
77
+ {
78
+ general_purpose: %w( m1.small m1.medium m1.large m1.xlarge ),
79
+ compute_optimized: %w( c1.medium c1.xlarge cc2.8xlarge ),
80
+ gpu: %w( cg1.4xlarge ),
81
+ memory_optimized: %w( m2.xlarge m2.2xlarge m2.4xlarge cr1.8xlarge ),
82
+ storage_optimized: %w( hi1.4xlarge hs1.8xlarge ),
83
+ micro: %w( t1.micro )
84
+ }
85
+ end
86
+ end # class EC2
87
+
88
+ # ElastiCache instance
89
+ class ElastiCache < AwsInstance
90
+ def initialize
91
+ super(current_generation, previous_generation)
92
+ end
93
+
94
+ # Determine maximum available memory for given instance type
95
+ #
96
+ # @return [Hash] instance max memory
97
+ def max_memory(type)
98
+ {
99
+ 'cache.t1.micro': 142_606_336,
100
+ 'cache.t2.micro': 581_959_680,
101
+ 'cache.t2.small': 1_665_138_688,
102
+ 'cache.t2.medium': 3_461_349_376,
103
+ 'cache.m1.small': 943_718_400,
104
+ 'cache.m1.medium': 3_093_299_200,
105
+ 'cache.m1.large': 7_025_459_200,
106
+ 'cache.m1.xlarge': 14_889_779_200,
107
+ 'cache.m2.xlarge': 17_091_788_800,
108
+ 'cache.m2.2xlarge': 35_022_438_400,
109
+ 'cache.m2.4xlarge': 70_883_737_600,
110
+ 'cache.m3.medium': 2_988_441_600,
111
+ 'cache.m3.large': 6_501_171_200,
112
+ 'cache.m3.xlarge': 14_260_633_600,
113
+ 'cache.m3.2xlarge': 29_989_273_600,
114
+ 'cache.c1.xlarge': 6_501_171_200,
115
+ 'cache.r3.large': 14_470_348_800,
116
+ 'cache.r3.xlarge': 30_513_561_600,
117
+ 'cache.r3.2xlarge': 62_495_129_600,
118
+ 'cache.r3.4xlarge': 126_458_265_600,
119
+ 'cache.r3.8xlarge': 254_384_537_600
120
+ }.with_indifferent_access.fetch(type)
121
+ end
122
+
123
+ # Current generation instance types
124
+ #
125
+ # @return [Hash] instance family and type
126
+ def current_generation
127
+ {
128
+ standard: %w(
129
+ cache.t2.micro cache.t2.small cache.t2.medium
130
+ cache.m3.medium cache.m3.large cache.m3.xlarge cache.m3.2xlarge),
131
+ memory_optimized: %w(cache.r3.large cache.r3.xlarge cache.r3.2xlarge cache.r3.4xlarge cache.r3.8xlarge)
132
+ }
133
+ end
134
+
135
+ # @deprecated Will be removed once Amazon fully stops supporting these instances
136
+ # Previous generation instance types
137
+ #
138
+ # @return [Hash] instance family and type
139
+ def previous_generation
140
+ {
141
+ standard: %w(cache.m1.small cache.m1.medium cache.m1.large cache.m1.xlarge),
142
+ memory_optimized: %w(cache.m2.xlarge cache.m2.2xlarge cache.m2.4xlarge),
143
+ compute_optimized: %w(cache.c1.xlarge),
144
+ micro: %w(cache.t1.micro)
145
+ }
146
+ end
147
+ end
148
+
149
+ # RDS instance
150
+ class RDS < AwsInstance
151
+ def initialize
152
+ super(current_generation, previous_generation)
153
+ end
154
+
155
+ # Current generation instance types
156
+ #
157
+ # @return [Hash] instance family and type
158
+ def current_generation
159
+ {
160
+ standard: %w( db.m4.large db.m4.xlarge db.m4.2xlarge db.m4.4xlarge db.m4.10xlarge ),
161
+ memory_optimized: %w( db.r3.large db.r3.xlarge db.r3.2xlarge db.r3.4xlarge db.r3.8xlarge ),
162
+ burstable_performance: %w( db.t2.micro db.t2.small db.t2.medium )
163
+ }
164
+ end
165
+
166
+ # @deprecated Will be removed once Amazon fully stops supporting these instances
167
+ # Previous generation instance types
168
+ #
169
+ # @return [Hash] instance family and type
170
+ def previous_generation
171
+ {
172
+ standard: %w( db.m1.small db.m1.medium db.m1.large db.m1.xlarge
173
+ db.m3.medium db.m3.large db.m3.xlarge db.m3.2xlarge ),
174
+ memory_optimized: %w( db.m2.xlarge db.m2.2xlarge db.m2.4xlarge db.cr1.8xlarge ),
175
+ micro: %w( db.t1.micro )
176
+ }
177
+ end
178
+ end # class RDS
179
+
180
+ # Simple interface to directly access classes above using module methods
181
+ class << self
182
+ # Creates EC2 instance type with corresponding values set
183
+ #
184
+ # @return [Enscalator::InstanceType::EC2]
185
+ def ec2_instance_type
186
+ EC2.new
187
+ end
188
+
189
+ # Creates RDS instance type with corresponding values set
190
+ #
191
+ # @return [Enscalator::InstanceType::RDS]
192
+ def rds_instance_type
193
+ RDS.new
194
+ end
195
+
196
+ # Creates ElasticCache instance type with corresponding values set
197
+ #
198
+ # @return [Enscalator::InstanceType::ElastiCache]
199
+ def elasticache_instance_type
200
+ ElastiCache.new
201
+ end
202
+ end # class << self
203
+ end # module InstanceType
204
+ end # module Core
205
+ end # module Enscalator
@@ -0,0 +1,21 @@
1
+ module Enscalator
2
+ module Core
3
+ # Configuration specific for VPC setup
4
+ class NetworkConfig
5
+ # VPC network mapping
6
+ def self.mapping_vpc_net
7
+ {
8
+ 'us-east-1': { VPC: '10.0.0.0/16' },
9
+ 'us-west-1': { VPC: '10.16.0.0/16' },
10
+ 'us-west-2': { VPC: '10.8.0.0/16' },
11
+ 'eu-west-1': { VPC: '10.24.0.0/16' },
12
+ 'eu-central-1': { VPC: '10.32.0.0/16' },
13
+ 'ap-southeast-1': { VPC: '10.40.0.0/16' },
14
+ 'ap-northeast-1': { VPC: '10.48.0.0/16' },
15
+ 'ap-southeast-2': { VPC: '10.56.0.0/16' },
16
+ 'sa-east-1': { VPC: '10.64.0.0/16' }
17
+ }.with_indifferent_access
18
+ end # mapping_vpc_net
19
+ end # class NetworkConfig
20
+ end # module Core
21
+ end # module Enscalator
@@ -0,0 +1,10 @@
1
+ require_relative 'core/network_config'
2
+ require_relative 'core/instance_type'
3
+ require_relative 'core/cf_parameters'
4
+ require_relative 'core/cf_resources'
5
+
6
+ module Enscalator
7
+ # Namespace for enscalator core modules/classes
8
+ module Core
9
+ end
10
+ end