admiral-cloudformation 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ sublime.sublime-*
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3-p547
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in admiral.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Peter T. Brown
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # Admiral for AWS CloudFormation
2
+
3
+ An Admiral module that implements tasks for wielding AWS CloudFormation templates. Use it to manage CloudFormation templates and their parameters.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile (recommended):
8
+
9
+ gem 'admiral-cloudformation'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install admiral-cloudformation
18
+
19
+ ## Usage
20
+
21
+ On your command line type:
22
+
23
+ $ admiral cf help
24
+
25
+ To see a list of available commands. Make sure your bundle bin is in your PATH.
26
+
27
+ The following commands are available:
28
+
29
+ ```
30
+ Commands:
31
+ admiral cf create # Create new CloudFormation stack for environment.
32
+ admiral cf destroy # Destroy the existing CloudFormation stack.
33
+ admiral cf help [COMMAND] # Describe subcommands or one specific subcommand
34
+ admiral cf update # Update the existing CloudFormation stack
35
+
36
+ Options:
37
+ --env, [--environment=ENVIRONMENT] # The environment (e.g. staging or production). Can also be specified with ADMIRAL_ENV.
38
+ # Default: production
39
+ [--template=TEMPLATE] # Path to CloudFormation JSON template.
40
+ # Default: CloudFormation.template
41
+ [--params=PARAMS] # Path to override parameter definitions file. Defaults to <environment>.json
42
+ ```
43
+
44
+ # Setup and Configuration
45
+
46
+ Admiral CloudFormation is designed around the concept of deployment environments. You parameterize your CloudFormation templates, then encode specific parameter values in JSON files for each distinct environment.
47
+
48
+ For example you may have CloudFormation templates for your database servers and your web application servers, and distinct configurations for production, staging and test environments.
49
+
50
+ CloudFormation provides a facility to parameterize templates via the [`Parameters`](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) section. For example:
51
+
52
+ ```javascript
53
+ ...
54
+ "InstanceType": {
55
+ "Description": "The type of instance to launch.",
56
+ "Type": "String",
57
+ "Default": "t2.small"
58
+ },
59
+ ...
60
+ ```
61
+
62
+ Admiral CloudFormation let's you specify specific values. For example:
63
+
64
+ ```javascript
65
+ {
66
+ "InstanceCount":"2",
67
+ "InstanceType": "t2.medium",
68
+ }
69
+ ```
70
+
71
+ ## Examples
72
+
73
+ To create a new CloudFormation stack (and its associated resources) using a staging configuration:
74
+
75
+ $ admiral cf create --environment staging --template ./CloudFormation.template
76
+
77
+ # CloudFormation Templates
78
+
79
+ Example CloudFormation templates for ElasticSearch, Meteor and MongoDB are included in the `examples` directory.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/admiral.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "admiral-cloudformation"
7
+ spec.version = '0.0.2'
8
+ spec.authors = ["Peter T. Brown"]
9
+ spec.email = ["p@ptb.io"]
10
+ spec.description = %q{An Admiral module that implements tasks for wielding AWS CloudFormation templates. Use it to manage CloudFormation templates and their parameters.}
11
+ spec.summary = %q{A command line tool for wielding cloudformation templates.}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.3"
20
+ spec.add_development_dependency "rake"
21
+ spec.add_dependency 'aws-sdk', '< 2'
22
+ spec.add_dependency 'thor', '~> 0.19'
23
+ spec.add_dependency 'admiral', '~> 0.0.1'
24
+ end
@@ -0,0 +1,315 @@
1
+ {
2
+ "AWSTemplateFormatVersion": "2010-09-09",
3
+ "Parameters": {
4
+ "CookbookRepo": {
5
+ "Description": "GitURL",
6
+ "Type": "String",
7
+ "Default": "https://github.com/ThoughtWorksStudios/opsworks-elasticsearch-cookbook"
8
+ },
9
+
10
+ "CookbookRepoRevision": {
11
+ "Description": "Git Revision/Tag",
12
+ "Type": "String",
13
+ "Default": "0.0.1"
14
+ },
15
+
16
+ "ElasticSearchVersion": {
17
+ "Description": "The version of ElasticSearch to install.",
18
+ "Type": "String",
19
+ "Default": "1.3.5"
20
+ },
21
+
22
+ "AwsRegion": {
23
+ "Description": "The AWS region",
24
+ "Type": "String",
25
+ "Default": "us-west-2"
26
+ },
27
+
28
+ "ElasticSearchAWSCloudPluginVersion": {
29
+ "Description": "The version of the ElasticSearch AWS Cloud Plugin to install. Note that this version MUST correspond to the targeted version of ElasticSearch. See https://github.com/elasticsearch/elasticsearch-cloud-aws for the version compatibility table.",
30
+ "Type": "String",
31
+ "Default": "2.3.0"
32
+ },
33
+
34
+ "RecipeList": {
35
+ "Description": "The list of cookbooks to include when setting up the cluster.",
36
+ "Type": "CommaDelimitedList",
37
+ "Default":"apt, ark,elasticsearch, elasticsearch::aws, elasticsearch::proxy, java, layer-custom::esplugins, layer-custom::allocation-awareness, layer-custom::esmonit, layer-custom::cloudwatch-custom"
38
+ },
39
+
40
+ "SSLCertificateName": {
41
+ "Description": "The SSL certificate.",
42
+ "Type": "String"
43
+ },
44
+
45
+ "InstanceCount": {
46
+ "Description": "Number of nodes to spin up in the cluster. This also configures the `expected_nodes` setting in ElasticSearch, which serves as a hint when the cluster considers shard reallocation.",
47
+ "Type": "String"
48
+ },
49
+
50
+ "InstanceType": {
51
+ "Description": "The type of instance to launch.",
52
+ "Type": "String",
53
+ "Default": "t2.small"
54
+ },
55
+
56
+ "MinMasterNodes": {
57
+ "Description": "Number of master eligible nodes visible to a given node before accepting requests. When this criterion is not satisfied, a given node will assume it has split off from from the cluster. This setting this helps avoid a catastrophic split-brain scenario in the cluster. This is typically is set to [N/2 + 1] nodes.",
58
+ "Type": "String"
59
+ },
60
+
61
+ "SearchUser": {
62
+ "Description": "username to access the ElasticSearch cluster.",
63
+ "Type": "String"
64
+ },
65
+
66
+ "SearchPassword": {
67
+ "Description": "password to access the ElasticSearch cluster.",
68
+ "Type": "String"
69
+ },
70
+
71
+ "ClusterName": {
72
+ "Description": "The name of the ElasticSearch cluster.",
73
+ "Type": "String"
74
+ },
75
+
76
+ "Route53ZoneName": {
77
+ "Description": "Route53 zone under which to setup the DNS record.",
78
+ "Type": "String"
79
+ },
80
+
81
+ "SearchDomainName": {
82
+ "Description": "Domain name to register for the cluster under Route53.",
83
+ "Type": "String"
84
+ },
85
+
86
+ "SshKeyName": {
87
+ "Description": "SSH key name for EC2 instances.",
88
+ "Type": "String"
89
+ },
90
+
91
+ "PaperTrailHost": {
92
+ "Description": "The PaperTrail endpoint hostname. Only required if you add the papertrail cookbook.",
93
+ "Type": "String",
94
+ "Default": "logs.papertrailapp.com"
95
+ },
96
+
97
+ "PaperTrailPort": {
98
+ "Description": "The PaperTrail endpoint port. Only required if you add the papertrail cookbook.",
99
+ "Type": "Number",
100
+ "Default": 0,
101
+ "MinValue" : "0",
102
+ "MaxValue" : "65535"
103
+ },
104
+
105
+ "SecurityGroupLoadBalancer": {
106
+ "Description": "The load balancer security group.",
107
+ "Type": "String"
108
+ },
109
+
110
+ "SecurityGroupSearchLayer": {
111
+ "Description": "The search layer security group.",
112
+ "Type": "String"
113
+ }
114
+
115
+ },
116
+
117
+ "Outputs": {
118
+ "StackId": {
119
+ "Description": "opsworks stack id ",
120
+ "Value": { "Ref": "SearchStack"}
121
+ },
122
+
123
+ "LayerId": {
124
+ "Description": "opsworks search layer id ",
125
+ "Value": { "Ref": "SearchLayer"}
126
+ }
127
+
128
+ },
129
+
130
+ "Resources": {
131
+
132
+ "LoadBalancer" : {
133
+ "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
134
+ "Properties" : {
135
+ "AvailabilityZones" : { "Fn::GetAZs" : "" },
136
+ "Listeners" : [
137
+ {
138
+ "LoadBalancerPort" : "443",
139
+ "InstancePort" : "80",
140
+ "Protocol" : "HTTPS",
141
+ "SSLCertificateId": {
142
+ "Fn::Join": ["", ["arn:aws:iam::", { "Ref": "AWS::AccountId" }, ":server-certificate/", { "Ref" : "SSLCertificateName" }]]
143
+ }
144
+ }
145
+ ],
146
+ "HealthCheck" : {
147
+ "Target" : "TCP:80",
148
+ "HealthyThreshold" : "2",
149
+ "UnhealthyThreshold" : "8",
150
+ "Interval" : "30",
151
+ "Timeout" : "20"
152
+ },
153
+ "SecurityGroups": [
154
+ {"Ref": "SecurityGroupLoadBalancer"}
155
+ ]
156
+ }
157
+ },
158
+
159
+ "DNSRecord": {
160
+ "Type" : "AWS::Route53::RecordSet",
161
+ "Properties" : {
162
+ "HostedZoneName" : {"Ref": "Route53ZoneName"},
163
+ "Type" : "CNAME",
164
+ "Name" : { "Ref": "SearchDomainName"},
165
+ "ResourceRecords" : [ {"Fn::GetAtt":["LoadBalancer","DNSName"]}],
166
+ "TTL" : "30"
167
+ }
168
+ },
169
+
170
+ "ELBAttachment" : {
171
+ "Type" : "AWS::OpsWorks::ElasticLoadBalancerAttachment",
172
+ "Properties" : {
173
+ "ElasticLoadBalancerName" : { "Ref" : "LoadBalancer" },
174
+ "LayerId" : { "Ref" : "SearchLayer" }
175
+ }
176
+ },
177
+
178
+
179
+ "SearchStack": {
180
+ "Type": "AWS::OpsWorks::Stack",
181
+ "Properties": {
182
+ "Name": {
183
+ "Ref": "AWS::StackName"
184
+ },
185
+ "CustomJson": {
186
+ "java": {
187
+ "jdk_version": "7",
188
+ "oracle": {
189
+ "accept_oracle_download_terms": "true"
190
+ },
191
+ "accept_license_agreement": "true",
192
+ "install_flavor": "oracle"
193
+ },
194
+ "papertrail": {
195
+ "remote_host": { "Ref": "PaperTrailHost" },
196
+ "remote_port": { "Ref": "PaperTrailPort" },
197
+ "watch_files": [
198
+ { "filename": { "Fn::Join": ["", ["/usr/local/var/log/elasticsearch/", { "Ref": "ClusterName" }, ".log"]] }, "tag": "search" },
199
+ { "filename": { "Fn::Join": ["", ["/usr/local/var/log/elasticsearch/", { "Ref": "ClusterName" }, "_index_indexing_slowlog.log"]] }, "tag": "indexing-slowlog" },
200
+ { "filename": { "Fn::Join": ["", ["/usr/local/var/log/elasticsearch/", { "Ref": "ClusterName" }, "_index_search_slowlog.log"]] }, "tag": "search-slowlog" }
201
+ ]
202
+ },
203
+ "elasticsearch": {
204
+ "version": { "Ref": "ElasticSearchVersion" },
205
+ "plugins" : {
206
+ "elasticsearch/elasticsearch-cloud-aws": {
207
+ "version": { "Ref": "ElasticSearchAWSCloudPluginVersion" }
208
+ }
209
+ },
210
+ "nginx": {
211
+ "users": [{
212
+ "username": { "Ref": "SearchUser" },
213
+ "password": { "Ref": "SearchPassword" }
214
+ }],
215
+ "allow_cluster_api": "true",
216
+ "port": 80
217
+ },
218
+ "cluster": {
219
+ "name": { "Ref" : "ClusterName" }
220
+ },
221
+ "gateway": {
222
+ "expected_nodes": { "Ref": "InstanceCount" }
223
+ },
224
+ "discovery": {
225
+ "type": "ec2",
226
+ "zen": {
227
+ "minimum_master_nodes": { "Ref": "MinMasterNodes" },
228
+ "ping": {
229
+ "multicast": {
230
+ "enabled": false
231
+ }
232
+ }
233
+ },
234
+ "ec2": {
235
+ "tag": {
236
+ "opsworks:stack": {
237
+ "Ref": "AWS::StackName"
238
+ }
239
+ }
240
+ }
241
+ },
242
+ "path": {
243
+ "data": "/mnt/elasticsearch-data"
244
+ },
245
+ "cloud": {
246
+ "aws": {
247
+ "region": { "Ref": "AwsRegion" }
248
+ }
249
+ },
250
+ "custom_config": {
251
+ "cluster.routing.allocation.awareness.attributes": "rack_id",
252
+ "index": "\n analysis:\n analyzer:\n default_index:\n filter:\n - standard\n - lowercase\n - snowball\n tokenizer: standard\n default_search:\n tokenizer: standard\n filter:\n - standard\n - lowercase\n - snowball\n"
253
+ }
254
+ }
255
+ },
256
+ "ServiceRoleArn": {
257
+ "Fn::Join": ["", ["arn:aws:iam::", { "Ref": "AWS::AccountId" }, ":role/aws-opsworks-service-role"]]
258
+ },
259
+ "DefaultInstanceProfileArn": {
260
+ "Fn::Join": ["", ["arn:aws:iam::", { "Ref": "AWS::AccountId" }, ":instance-profile/aws-opsworks-ec2-role"]]
261
+ },
262
+ "ConfigurationManager": {
263
+ "Name": "Chef",
264
+ "Version": "11.10"
265
+ },
266
+ "ChefConfiguration": {
267
+ "BerkshelfVersion": "3.1.3",
268
+ "ManageBerkshelf": true
269
+ },
270
+ "DefaultOs": "Amazon Linux 2015.03",
271
+ "DefaultRootDeviceType": "ebs",
272
+ "DefaultSshKeyName": { "Ref": "SshKeyName" },
273
+ "UseCustomCookbooks": true,
274
+ "UseOpsworksSecurityGroups": false,
275
+ "CustomCookbooksSource": {
276
+ "Type": "git",
277
+ "Url": {
278
+ "Ref": "CookbookRepo"
279
+ },
280
+ "Revision": { "Ref": "CookbookRepoRevision" }
281
+ }
282
+ }
283
+ },
284
+
285
+ "SearchLayer": {
286
+ "Type": "AWS::OpsWorks::Layer",
287
+ "Properties": {
288
+ "StackId": {
289
+ "Ref": "SearchStack"
290
+ },
291
+ "Name": "Search",
292
+ "Type": "custom",
293
+ "Shortname": "search",
294
+ "CustomRecipes": {
295
+ "Setup": { "Ref": "RecipeList" }
296
+ },
297
+ "EnableAutoHealing": false,
298
+ "AutoAssignElasticIps": false,
299
+ "AutoAssignPublicIps": true,
300
+ "VolumeConfigurations": [
301
+ {
302
+ "MountPoint": "/mnt/elasticsearch-data",
303
+ "NumberOfDisks": 1,
304
+ "Size": 200,
305
+ "VolumeType": "gp2"
306
+ }
307
+ ],
308
+ "CustomSecurityGroupIds": [
309
+ {"Ref": "SecurityGroupSearchLayer"}
310
+ ]
311
+ }
312
+ }
313
+
314
+ }
315
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "Route53ZoneName": "example.io.",
3
+ "SearchDomainName": "search.example.io",
4
+ "SSLCertificateName": "search.example.io",
5
+ "SshKeyName": "production",
6
+ "InstanceCount":"2",
7
+ "InstanceType": "t2.medium",
8
+ "ElasticSearchVersion": "1.4.4",
9
+ "ElasticSearchAWSCloudPluginVersion": "2.4.1",
10
+ "SearchUser":"admin",
11
+ "SearchPassword":"example-password",
12
+ "ClusterName": "staging-cluster",
13
+ "MinMasterNodes": "1",
14
+ "SecurityGroupLoadBalancer": "sg-8aab365ef",
15
+ "SecurityGroupSearchLayer": "sg-9e9d35f8"
16
+ }
@@ -0,0 +1,249 @@
1
+ {
2
+ "AWSTemplateFormatVersion": "2010-09-09",
3
+ "Parameters": {
4
+ "CookbookRepo": {
5
+ "Description": "GitURL",
6
+ "Type": "String",
7
+ "Default": "https://github.com/flippyhead/chef-mongodb"
8
+ },
9
+
10
+ "CookbookRepoRevision": {
11
+ "Description": "Git Revision/Tag",
12
+ "Type": "String",
13
+ "Default": "0.0.1"
14
+ },
15
+
16
+ "Route53ZoneName": {
17
+ "Description": "Route53 zone under which to setup the DNS record.",
18
+ "Type": "String"
19
+ },
20
+
21
+ "AppDomainName": {
22
+ "Description": "Domain name to register for the app under Route53.",
23
+ "Type": "String"
24
+ },
25
+
26
+ "SSLCertificateName": {
27
+ "Description": "The SSL certificate.",
28
+ "Type": "String"
29
+ },
30
+
31
+ "SshKeyName": {
32
+ "Description": "SSH key name for EC2 instances.",
33
+ "Type": "String"
34
+ },
35
+
36
+ "InstanceCount": {
37
+ "Description": "The number of instances to launch.",
38
+ "Type": "Number",
39
+ "Default": 1
40
+ },
41
+
42
+ "InstanceType": {
43
+ "Description": "The type of instance to launch.",
44
+ "Type": "String",
45
+ "Default": "t2.small"
46
+ },
47
+
48
+ "SecurityGroupLoadBalancer": {
49
+ "Description": "The load balancer security group.",
50
+ "Type": "String"
51
+ },
52
+
53
+ "SecurityGroupMeteorLayer": {
54
+ "Description": "The meteor layer security group.",
55
+ "Type": "String"
56
+ }
57
+
58
+ },
59
+
60
+ "Outputs": {
61
+ "StackId": {
62
+ "Description": "opsworks stack id ",
63
+ "Value": { "Ref": "MeteorStack"}
64
+ },
65
+
66
+ "LayerId": {
67
+ "Description": "opsworks search layer id ",
68
+ "Value": { "Ref": "MeteorLayer"}
69
+ },
70
+
71
+ "PrimaryAppId": {
72
+ "Description": "fetching app id ",
73
+ "Value": { "Ref": "FetchingApp"}
74
+ },
75
+
76
+ "SecondaryAppId": {
77
+ "Description": "exporter app id ",
78
+ "Value": { "Ref": "FetchingExporter"}
79
+ }
80
+
81
+ },
82
+
83
+ "Resources": {
84
+
85
+ "LoadBalancer" : {
86
+ "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
87
+ "Properties" : {
88
+ "AvailabilityZones" : { "Fn::GetAZs" : "" },
89
+ "Listeners" : [
90
+ {
91
+ "LoadBalancerPort" : "443",
92
+ "InstancePort" : "80",
93
+ "Protocol" : "SSL",
94
+ "SSLCertificateId": {
95
+ "Fn::Join": ["", ["arn:aws:iam::", { "Ref": "AWS::AccountId" }, ":server-certificate/", { "Ref" : "SSLCertificateName" }]]
96
+ }
97
+ },
98
+ {
99
+ "LoadBalancerPort" : "80",
100
+ "InstancePort" : "80",
101
+ "Protocol" : "HTTP"
102
+ }
103
+ ],
104
+ "HealthCheck" : {
105
+ "Target" : "TCP:80",
106
+ "HealthyThreshold" : "2",
107
+ "UnhealthyThreshold" : "8",
108
+ "Interval" : "30",
109
+ "Timeout" : "20"
110
+ },
111
+ "SecurityGroups": [
112
+ {"Ref": "SecurityGroupLoadBalancer"}
113
+ ]
114
+ }
115
+ },
116
+
117
+ "DNSRecord": {
118
+ "Type" : "AWS::Route53::RecordSet",
119
+ "Properties" : {
120
+ "HostedZoneName" : {"Ref": "Route53ZoneName"},
121
+ "Type" : "CNAME",
122
+ "Name" : { "Ref": "AppDomainName"},
123
+ "ResourceRecords" : [ {"Fn::GetAtt":["LoadBalancer","DNSName"]}],
124
+ "TTL" : "30"
125
+ }
126
+ },
127
+
128
+ "ELBAttachment" : {
129
+ "Type" : "AWS::OpsWorks::ElasticLoadBalancerAttachment",
130
+ "Properties" : {
131
+ "ElasticLoadBalancerName" : { "Ref" : "LoadBalancer" },
132
+ "LayerId" : { "Ref" : "MeteorLayer" }
133
+ }
134
+ },
135
+
136
+ "MeteorStack": {
137
+ "Type": "AWS::OpsWorks::Stack",
138
+ "Properties": {
139
+ "Name": {
140
+ "Ref": "AWS::StackName"
141
+ },
142
+ "CustomJson": {
143
+ "opsworks_nodejs":{
144
+ "version":"0.10.38"
145
+ },
146
+ "deploy": {
147
+ "primary-app": {
148
+ "nodejs": {
149
+ "port": 80
150
+ },
151
+ "environment_variables": {
152
+ "METEOR_SETTINGS": "{}"
153
+ }
154
+ },
155
+ "secondary-app": {
156
+ "nodejs": {
157
+ "port": 8081
158
+ },
159
+ "environment_variables": {
160
+ "METEOR_SETTINGS": "{}"
161
+ }
162
+ }
163
+ }
164
+ },
165
+ "ServiceRoleArn": {
166
+ "Fn::Join": ["", ["arn:aws:iam::", { "Ref": "AWS::AccountId" }, ":role/aws-opsworks-service-role"]]
167
+ },
168
+ "DefaultInstanceProfileArn": {
169
+ "Fn::Join": ["", ["arn:aws:iam::", { "Ref": "AWS::AccountId" }, ":instance-profile/aws-opsworks-ec2-role"]]
170
+ },
171
+ "ConfigurationManager": {
172
+ "Name": "Chef",
173
+ "Version": "11.10"
174
+ },
175
+ "ChefConfiguration": {
176
+ "BerkshelfVersion": "3.1.3",
177
+ "ManageBerkshelf": true
178
+ },
179
+ "DefaultOs": "Amazon Linux 2015.03",
180
+ "DefaultRootDeviceType": "ebs",
181
+ "DefaultSshKeyName": { "Ref": "SshKeyName" },
182
+ "UseCustomCookbooks": false,
183
+ "UseOpsworksSecurityGroups": false,
184
+ "CustomCookbooksSource": {
185
+ "Type": "git",
186
+ "Url": {
187
+ "Ref": "CookbookRepo"
188
+ },
189
+ "Revision": { "Ref": "CookbookRepoRevision" }
190
+ }
191
+ }
192
+ },
193
+
194
+ "MeteorLayer": {
195
+ "Type": "AWS::OpsWorks::Layer",
196
+ "Properties": {
197
+ "StackId": {
198
+ "Ref": "MeteorStack"
199
+ },
200
+ "Name": "Meteor",
201
+ "Type": "nodejs-app",
202
+ "Shortname": "meteor",
203
+ "EnableAutoHealing": false,
204
+ "AutoAssignElasticIps": false,
205
+ "AutoAssignPublicIps": true,
206
+ "CustomSecurityGroupIds": [
207
+ {"Ref": "SecurityGroupMeteorLayer"}
208
+ ]
209
+ }
210
+ },
211
+
212
+ "PrimaryApp": {
213
+ "Type":"AWS::OpsWorks::App",
214
+ "Properties": {
215
+ "Type": "nodejs",
216
+ "Name": "Fetching Application",
217
+ "Shortname": "fetching-app",
218
+ "StackId": {
219
+ "Ref": "MeteorStack"
220
+ },
221
+ "AppSource": {
222
+ "Username": "AKDIKDSKSKEWS",
223
+ "Password": "x6gYSTr+qDSKDFJSLdksldjfLAKDjdRE8mKi1bAZXm",
224
+ "Type": "s3",
225
+ "Url":"https://s3-us-west-2.amazonaws.com/primary-builds/primary-app.tar.gz"
226
+ }
227
+ }
228
+ },
229
+
230
+ "SecondaryApp": {
231
+ "Type":"AWS::OpsWorks::App",
232
+ "Properties": {
233
+ "Type": "nodejs",
234
+ "Name": "Fetching Exporter",
235
+ "Shortname": "fetching-exporter",
236
+ "StackId": {
237
+ "Ref": "MeteorStack"
238
+ },
239
+ "AppSource": {
240
+ "Username": "AKDIKDSKSKEWS",
241
+ "Password": "x6gYSTr+qDSKDFJSLdksldjfLAKDjdRE8mKi1bAZXm",
242
+ "Type": "s3",
243
+ "Url":"https://s3-us-west-2.amazonaws.com/secondary-builds/secondary-app.tar.gz"
244
+ }
245
+ }
246
+ }
247
+
248
+ }
249
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "Route53ZoneName": "example.io.",
3
+ "AppDomainName": "app.example.io",
4
+ "SSLCertificateName": "app.example.io",
5
+ "SshKeyName": "production",
6
+ "InstanceCount":"1",
7
+ "InstanceType": "t2.small",
8
+ "SecurityGroupLoadBalancer": "sg-8ad62234ef",
9
+ "SecurityGroupMeteorLayer": "sg-2265dsd7"
10
+ }
@@ -0,0 +1,132 @@
1
+ {
2
+ "AWSTemplateFormatVersion": "2010-09-09",
3
+ "Parameters": {
4
+ "CookbookRepo": {
5
+ "Description": "GitURL",
6
+ "Type": "String",
7
+ "Default": "https://github.com/flippyhead/chef-mongodb"
8
+ },
9
+
10
+ "MongoVersion": {
11
+ "Description": "The version of MongoDB to install.",
12
+ "Type": "String",
13
+ "Default": "2.6.1"
14
+ },
15
+
16
+ "RecipeList": {
17
+ "Description": "The list of cookbooks to include when setting up the cluster.",
18
+ "Type": "CommaDelimitedList",
19
+ "Default": "mongodb::10gen_repo, mongodb::default"
20
+ },
21
+
22
+ "SshKeyName": {
23
+ "Description": "SSH key name for EC2 instances.",
24
+ "Type": "String"
25
+ },
26
+
27
+ "InstanceCount": {
28
+ "Description": "The number of instances to launch.",
29
+ "Type": "Number",
30
+ "Default": 1
31
+ },
32
+
33
+ "InstanceType": {
34
+ "Description": "The type of instance to launch.",
35
+ "Type": "String",
36
+ "Default": "t2.small"
37
+ },
38
+
39
+ "SecurityGroupMongoLayer": {
40
+ "Description": "The mongo layer security group.",
41
+ "Type": "String"
42
+ }
43
+
44
+ },
45
+
46
+ "Outputs": {
47
+ "StackId": {
48
+ "Description": "opsworks stack id ",
49
+ "Value": { "Ref": "MongoStack"}
50
+ },
51
+
52
+ "LayerId": {
53
+ "Description": "opsworks mongo layer id ",
54
+ "Value": { "Ref": "MongoLayer"}
55
+ }
56
+
57
+ },
58
+
59
+ "Resources": {
60
+
61
+ "MongoStack": {
62
+ "Type": "AWS::OpsWorks::Stack",
63
+ "Properties": {
64
+ "Name": {
65
+ "Ref": "AWS::StackName"
66
+ },
67
+ "CustomJson": {
68
+ "mongodb": {
69
+ "config":{
70
+ "dbpath": "/mnt/mongodb-data"
71
+ }
72
+ }
73
+ },
74
+ "ServiceRoleArn": {
75
+ "Fn::Join": ["", ["arn:aws:iam::", { "Ref": "AWS::AccountId" }, ":role/aws-opsworks-service-role"]]
76
+ },
77
+ "DefaultInstanceProfileArn": {
78
+ "Fn::Join": ["", ["arn:aws:iam::", { "Ref": "AWS::AccountId" }, ":instance-profile/aws-opsworks-ec2-role"]]
79
+ },
80
+ "ConfigurationManager": {
81
+ "Name": "Chef",
82
+ "Version": "11.10"
83
+ },
84
+ "ChefConfiguration": {
85
+ "BerkshelfVersion": "3.1.3",
86
+ "ManageBerkshelf": true
87
+ },
88
+ "DefaultOs": "Ubuntu 14.04 LTS",
89
+ "DefaultRootDeviceType": "ebs",
90
+ "DefaultSshKeyName": { "Ref": "SshKeyName" },
91
+ "UseCustomCookbooks": true,
92
+ "UseOpsworksSecurityGroups": false,
93
+ "CustomCookbooksSource": {
94
+ "Type": "git",
95
+ "Url": {
96
+ "Ref": "CookbookRepo"
97
+ }
98
+ }
99
+ }
100
+ },
101
+
102
+ "MongoLayer": {
103
+ "Type": "AWS::OpsWorks::Layer",
104
+ "Properties": {
105
+ "StackId": {
106
+ "Ref": "MongoStack"
107
+ },
108
+ "Name": "Mongo",
109
+ "Type": "custom",
110
+ "Shortname": "mongo",
111
+ "CustomRecipes": {
112
+ "Setup": { "Ref": "RecipeList" }
113
+ },
114
+ "EnableAutoHealing": false,
115
+ "AutoAssignElasticIps": false,
116
+ "AutoAssignPublicIps": true,
117
+ "VolumeConfigurations": [
118
+ {
119
+ "MountPoint": "/mnt/mongodb-data",
120
+ "NumberOfDisks": 1,
121
+ "Size": 200,
122
+ "VolumeType": "gp2"
123
+ }
124
+ ],
125
+ "CustomSecurityGroupIds": [
126
+ {"Ref": "SecurityGroupMongoLayer"}
127
+ ]
128
+ }
129
+ }
130
+
131
+ }
132
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "SshKeyName": "production",
3
+ "InstanceCount":"1",
4
+ "InstanceType": "t2.small",
5
+ "MongoVersion": "2.6.1",
6
+ "SecurityGroupMongoLayer": "sg-334rt5fc"
7
+ }
@@ -0,0 +1 @@
1
+ require "admiral-cloudformation/tasks"
@@ -0,0 +1,50 @@
1
+ require 'json'
2
+ require 'thor'
3
+ require 'admiral/base'
4
+ require_relative 'util'
5
+
6
+ module Admiral
7
+ module Tasks
8
+ class CloudFormation < Thor
9
+ extend Admiral::Base
10
+ include Util::CloudFormation
11
+
12
+ NAME = 'cf'
13
+ USAGE = 'cf <command> <options>'
14
+ DESCRIPTION = 'Commands for wielding AWS CloudFormation templates.'
15
+
16
+ namespace :cf
17
+
18
+ class_option :template,
19
+ desc: 'Path to CloudFormation JSON template.',
20
+ default: 'CloudFormation.template'
21
+
22
+ class_option :params,
23
+ desc: 'Path to override parameter definitions file. Defaults to <environment>.json'
24
+
25
+
26
+ desc 'create', 'Create new CloudFormation stack for environment.'
27
+
28
+ def create
29
+ template = File.read options[:template]
30
+ create_stack stack_name(options[:environment]), template, params(options[:environment])
31
+ end
32
+
33
+
34
+ desc 'update', 'Update the existing CloudFormation stack'
35
+
36
+ def update
37
+ template = File.read options[:template]
38
+ update_stack stack_name(options[:environment]), template, params(options[:environment])
39
+ end
40
+
41
+
42
+ desc 'destroy', 'Destroy the existing CloudFormation stack.'
43
+
44
+ def destroy
45
+ super stack_name options[:environment]
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,100 @@
1
+ require 'aws-sdk-v1'
2
+
3
+ module Admiral
4
+ module Util
5
+ module CloudFormation
6
+
7
+ SUCCESS_STATS = [:create_complete, :update_complete, :update_rollback_complete]
8
+ FAILED_STATS = [:create_failed, :update_failed, :rollback_complete]
9
+ DEFAULT_RECIPES = [].join(",")
10
+
11
+ def client
12
+ AWS::CloudFormation.new
13
+ end
14
+
15
+ def create_stack(stack_name, template, params)
16
+ stack = client.stacks[stack_name]
17
+
18
+ if stack.exists?
19
+ raise '[admiral] Stack already exists. Use update command instead.'
20
+ end
21
+
22
+ puts "[admiral] Creating CloudFormation stack #{stack_name}."
23
+ begin
24
+ stack = client.stacks.create(stack_name, template, :parameters => params)
25
+ wait_for_stack_op_to_finish stack
26
+ rescue => e
27
+ puts "[admiral] Error creating stack #{stack_name}: #{e}"
28
+ end
29
+ end
30
+
31
+ def update_stack(stack_name, template, params)
32
+ stack = client.stacks[stack_name]
33
+
34
+ unless stack.exists?
35
+ raise "[admiral] CloudFormation stack #{stack_name} doesn't exist. Use create instead."
36
+ end
37
+
38
+ begin
39
+ puts "[admiral] Updating CloudFormation stack #{stack_name}"
40
+ stack.update(:template => template, :parameters => params)
41
+ wait_for_stack_op_to_finish stack
42
+ rescue => e
43
+ puts "[admiral] Error updating stack #{stack_name}: #{e}"
44
+ # raise unless e.message =~ /No updates are to be performed/
45
+ # puts "Your CloudFormation stack is already up to date"
46
+ end
47
+ end
48
+
49
+ def destroy(stack_name)
50
+ stack = client.stacks[stack_name]
51
+
52
+ if stack.exists?
53
+ puts "Deleting stack #{stack_name}"
54
+ stack.delete
55
+ else
56
+ puts "Environment does not exist"
57
+ end
58
+ end
59
+
60
+ def stack_name(env)
61
+ "#{env}-#{name}"
62
+ end
63
+
64
+ def name
65
+ ENV["ADMIRAL_NAME"] || "test"
66
+ end
67
+
68
+ def params(env, options = {})
69
+ JSON.parse File.read(options[:params] || "#{env}.json")
70
+ end
71
+
72
+ private
73
+
74
+ def wait_for_stack_op_to_finish(stack)
75
+ stats = stack.status.downcase.to_sym
76
+ puts "[admiral] Stack #{stack.name} current status: #{stats}"
77
+
78
+ while !SUCCESS_STATS.include?(stats)
79
+ sleep 15
80
+ stats = stack.status.downcase.to_sym
81
+ raise "[admiral] Resource stack update failed." if FAILED_STATS.include?(stats)
82
+ puts "[admiral] Stack #{stack.name} current status: #{stats}"
83
+ end
84
+ end
85
+
86
+ def cf_query_output(stack, key)
87
+ output = stack.outputs.find do |o|
88
+ /#{key}/i =~ o.key
89
+ end
90
+ output && output.value
91
+ end
92
+
93
+ def all_availability_zones
94
+ ec2 = AWS::EC2.new
95
+ ec2.availability_zones.map(&:name)
96
+ end
97
+
98
+ end
99
+ end
100
+ end
data/spec/test.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "Key": "Value"
3
+ }
@@ -0,0 +1 @@
1
+ {}
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: admiral-cloudformation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Peter T. Brown
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-05-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: aws-sdk
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - <
52
+ - !ruby/object:Gem::Version
53
+ version: '2'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - <
60
+ - !ruby/object:Gem::Version
61
+ version: '2'
62
+ - !ruby/object:Gem::Dependency
63
+ name: thor
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '0.19'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '0.19'
78
+ - !ruby/object:Gem::Dependency
79
+ name: admiral
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 0.0.1
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.0.1
94
+ description: An Admiral module that implements tasks for wielding AWS CloudFormation
95
+ templates. Use it to manage CloudFormation templates and their parameters.
96
+ email:
97
+ - p@ptb.io
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - .ruby-version
104
+ - Gemfile
105
+ - LICENSE.txt
106
+ - README.md
107
+ - Rakefile
108
+ - admiral.gemspec
109
+ - examples/elasticsearch/CloudFormation.template
110
+ - examples/elasticsearch/production.json
111
+ - examples/meteor/CloudFormation.template
112
+ - examples/meteor/production.json
113
+ - examples/mongo/CloudFormation.template
114
+ - examples/mongo/production.json
115
+ - lib/admiral-cloudformation.rb
116
+ - lib/admiral-cloudformation/tasks.rb
117
+ - lib/admiral-cloudformation/util.rb
118
+ - spec/test.json
119
+ - spec/test.template
120
+ homepage: ''
121
+ licenses:
122
+ - MIT
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 1.8.23.2
142
+ signing_key:
143
+ specification_version: 3
144
+ summary: A command line tool for wielding cloudformation templates.
145
+ test_files:
146
+ - spec/test.json
147
+ - spec/test.template