dslh 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 22c5f3ef5ed8d62be6f01f66185d03c69746a21f
4
- data.tar.gz: 07f1988d59dd1f91dde43e9dcc7b9412122dc3b0
3
+ metadata.gz: 041bb7cf886d6a16fb6be02ba6ef356bf31810c7
4
+ data.tar.gz: b96cb8ee97322d53745dda628eca4e8fe6ace944
5
5
  SHA512:
6
- metadata.gz: 7c6d12ec8eed101cd59bf56c8bf452086c224196428f38275769bc89ef688c3db64f120d907b3d9737542e379c4ec33bac13dd512a9b5c3e301aab0d38637090
7
- data.tar.gz: 4278f2189e6ca73c321b5d341835b4e6e0b645f337ca288ad016481bf90f241f27fe2129fb207866c08c61b5f4b9d85490bc3ec739258373c8d1b90415b2ca68
6
+ metadata.gz: 6753cfa8efa4438bcdfb2193bb827c4268c65bef24f302d2494c759047de84442d3b318dc79871e013214641aca7e19e99e0c102e9256c53eb47fd8dab069d0a
7
+ data.tar.gz: 7d43a7ca6c3633460e47e5251dbadcb7336f7f6e342965bda4404737c2426fc9fe17125d718b221de5b33860bd6c36c706670282da265e5dfd46c0fcb93b8e8c
data/lib/dslh.rb CHANGED
@@ -76,6 +76,7 @@ class Dslh
76
76
  next_indent = (INDENT_SPACES * (depth + 1))
77
77
  key_conv = @options[:key_conv] || @options[:conv]
78
78
  value_conv = @options[:value_conv] || @options[:conv]
79
+ nested = false
79
80
 
80
81
  if exclude_key?(key_conv, hash.keys)
81
82
  buf.puts('(' + ("\n" + hash.pretty_inspect.strip).gsub("\n", "\n" + indent) + ')')
@@ -83,86 +84,96 @@ class Dslh
83
84
  end
84
85
 
85
86
  hash.each do |key, value|
86
- key = key_conv.call(key) if key_conv
87
- buf.print(indent + key)
87
+ value_proc = proc do |value_buf|
88
+ case value
89
+ when Hash
90
+ if exclude_key?(key_conv, value.keys)
91
+ value_buf.puts('(' + ("\n" + value.pretty_inspect.strip).gsub("\n", "\n" + next_indent) + ')')
92
+ else
93
+ nested = true
94
+ value_buf.puts(' do')
95
+ deval0(value, depth + 1, value_buf)
96
+ value_buf.puts(indent + 'end')
97
+ end
98
+ when Array
99
+ if value.any? {|v| [Array, Hash].any? {|c| v.kind_of?(c) }}
100
+ nested = true
101
+ value_buf.puts(' [')
102
+
103
+ value.each_with_index do |v, i|
104
+ if v.kind_of?(Hash)
105
+ value_buf.puts(next_indent + '_{')
106
+ deval0(v, depth + 2, value_buf)
107
+ value_buf.print(next_indent + '}')
108
+ else
109
+ value_buf.print(next_indent + v.pretty_inspect.strip.gsub("\n", "\n" + next_indent))
110
+ end
111
+
112
+ value_buf.puts(i < (value.length - 1) ? ',' : '')
113
+ end
88
114
 
89
- case value
90
- when Hash
91
- if exclude_key?(key_conv, value.keys)
92
- buf.puts('(' + ("\n" + value.pretty_inspect.strip).gsub("\n", "\n" + next_indent) + ')')
115
+ value_buf.puts(indent + ']')
116
+ elsif value.length == 1
117
+ value_buf.puts(' ' + value.inspect)
118
+ else
119
+ value_buf.puts(' ' + value.map {|v|
120
+ v = value_conv.call(v) if value_conv
121
+
122
+ if v.kind_of?(Hash)
123
+ '(' + v.inspect + ')'
124
+ else
125
+ v.inspect
126
+ end
127
+ }.join(', '))
128
+ end
93
129
  else
94
- buf.puts(' do')
95
- deval0(value, depth + 1, buf)
96
- buf.puts(indent + 'end')
130
+ value = value_conv.call(value) if value_conv
131
+ value_buf.puts(' ' + value.inspect)
97
132
  end
98
- when Array
99
- if value.any? {|v| [Array, Hash].any? {|c| v.kind_of?(c) }}
100
- buf.puts(' [')
101
-
102
- value.each_with_index do |v, i|
103
- if v.kind_of?(Hash)
104
- buf.puts(next_indent + '_{')
105
- deval0(v, depth + 2, buf)
106
- buf.print(next_indent + '}')
107
- else
108
- buf.print(next_indent + v.pretty_inspect.strip.gsub("\n", "\n" + next_indent))
109
- end
133
+ end
110
134
 
111
- buf.puts(i < (value.length - 1) ? ',' : '')
112
- end
135
+ key = key_conv.call(key) if key_conv
113
136
 
114
- buf.puts(indent + ']')
115
- elsif value.length == 1
116
- buf.puts(' ' + value.inspect)
117
- else
118
- buf.puts(' ' + value.map {|v|
119
- v = value_conv.call(v) if value_conv
137
+ if key.kind_of?(Proc)
138
+ tmp_buf = StringIO.new
139
+ value_proc.call(tmp_buf)
120
140
 
121
- if v.kind_of?(Hash)
122
- '(' + v.inspect + ')'
123
- else
124
- v.inspect
125
- end
126
- }.join(', '))
127
- end
141
+ key_value = case key.arity
142
+ when 0
143
+ key.call
144
+ when 1
145
+ key.call(tmp_buf.string.strip)
146
+ else
147
+ key.call(tmp_buf.string.strip, nested)
148
+ end
149
+
150
+ buf.puts(indent + key_value)
128
151
  else
129
- value = value_conv.call(value) if value_conv
130
- buf.puts(' ' + value.inspect)
152
+ buf.print(indent + key)
153
+ value_proc.call(buf)
131
154
  end
132
155
  end
133
156
  end
134
157
 
135
158
  def exclude_key?(key_conv, keys)
136
159
  exclude_key = @options[:exclude_key] || proc {|k| k.to_s !~ /\A[_a-z]\w+\Z/i }
137
- exclude_key and (key_conv ? keys.map {|k| key_conv.call(k) } : keys).any? {|k| exclude_key.call(k) }
160
+
161
+ if not @options.has_key?(:exclude_key) and key_conv
162
+ keys = keys.map {|k| key_conv.call(k) }
163
+ end
164
+
165
+ keys.any? {|k| exclude_key.call(k) }
138
166
  end
139
167
 
140
168
  class Scope
141
169
  def _(&block)
142
- if block
143
- hash_orig = @__hash__
144
- @__hash__ = {}
145
- self.instance_eval(&block)
146
- nested_hash = @__hash__
147
- @__hash__ = hash_orig
148
- return nested_hash
149
- end
170
+ ScopeBlock.nest(binding, 'block')
150
171
  end
151
172
 
152
173
  def method_missing(method_name, *args, &block)
153
174
  key_conv = @__options__[:key_conv] || @__options__[:conv]
154
175
  value_conv = @__options__[:value_conv] || @__options__[:conv]
155
-
156
- nested_hash = nil
157
-
158
- if block
159
- hash_orig = @__hash__
160
- @__hash__ = {}
161
- self.instance_eval(&block)
162
- nested_hash = @__hash__
163
- @__hash__ = hash_orig
164
- end
165
-
176
+ nested_hash = ScopeBlock.nest(binding, 'block')
166
177
  method_name = key_conv.call(method_name) if key_conv
167
178
 
168
179
  if args.empty?
@@ -183,4 +194,21 @@ class Dslh
183
194
  end
184
195
  end
185
196
  end # of Scope
197
+
198
+ class ScopeBlock
199
+ def self.nest(bind, block_var)
200
+ eval(<<-EOS, bind)
201
+ if #{block_var}
202
+ __hash_orig = @__hash__
203
+ @__hash__ = {}
204
+ self.instance_eval(&#{block_var})
205
+ __nested_hash = @__hash__
206
+ @__hash__ = __hash_orig
207
+ __nested_hash
208
+ else
209
+ nil
210
+ end
211
+ EOS
212
+ end
213
+ end
186
214
  end
data/lib/dslh/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Dslh
2
- VERSION = '0.1.8'
2
+ VERSION = '0.1.9'
3
3
  end
@@ -0,0 +1,455 @@
1
+ {
2
+ "AWSTemplateFormatVersion" : "2010-09-09",
3
+
4
+ "Description" : "AWS CloudFormation Sample Template Drupal_Multi_AZ. Drupal is an open source content management platform powering millions of websites and applications. This template installs a highly-available, scalable Drupal deployment using a multi-az Amazon RDS database instance for storage. It uses the AWS CloudFormation bootstrap scripts to install packages and files at instance launch time. **WARNING** This template creates one or more Amazon EC2 instances, an Elastic Load Balancer and an Amazon RDS database. You will be billed for the AWS resources used if you create a stack from this template.",
5
+
6
+ "Parameters" : {
7
+
8
+ "KeyName": {
9
+ "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances",
10
+ "Type": "String",
11
+ "MinLength": "1",
12
+ "MaxLength": "255",
13
+ "AllowedPattern" : "[\\x20-\\x7E]*",
14
+ "ConstraintDescription" : "can contain only ASCII characters."
15
+ },
16
+
17
+ "InstanceType" : {
18
+ "Description" : "WebServer EC2 instance type",
19
+ "Type" : "String",
20
+ "Default" : "m1.small",
21
+ "ConstraintDescription" : "must be a valid EC2 instance type."
22
+ },
23
+
24
+ "SiteName": {
25
+ "Default": "My Site",
26
+ "Description" : "The name of the Drupal Site",
27
+ "Type": "String"
28
+ },
29
+
30
+ "SiteEMail": {
31
+ "Description" : "EMail for site adminitrator",
32
+ "Type": "String"
33
+ },
34
+
35
+ "SiteAdmin": {
36
+ "Description" : "The Drupal site admin account username",
37
+ "Type": "String",
38
+ "MinLength": "1",
39
+ "MaxLength": "16",
40
+ "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
41
+ "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
42
+ },
43
+
44
+ "SitePassword": {
45
+ "NoEcho": "true",
46
+ "Description" : "The Drupal site admin account password",
47
+ "Type": "String",
48
+ "MinLength": "1",
49
+ "MaxLength": "41",
50
+ "AllowedPattern" : "[a-zA-Z0-9]*",
51
+ "ConstraintDescription" : "must contain only alphanumeric characters."
52
+ },
53
+
54
+ "DBName": {
55
+ "Default": "drupaldb",
56
+ "Description" : "The Drupal database name",
57
+ "Type": "String",
58
+ "MinLength": "1",
59
+ "MaxLength": "64",
60
+ "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
61
+ "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
62
+ },
63
+
64
+ "DBUsername": {
65
+ "Default": "admin",
66
+ "NoEcho": "true",
67
+ "Description" : "The Drupal database admin account username",
68
+ "Type": "String",
69
+ "MinLength": "1",
70
+ "MaxLength": "16",
71
+ "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
72
+ "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
73
+ },
74
+
75
+ "DBPassword": {
76
+ "Default": "password",
77
+ "NoEcho": "true",
78
+ "Description" : "The Drupal database admin account password",
79
+ "Type": "String",
80
+ "MinLength": "8",
81
+ "MaxLength": "41",
82
+ "AllowedPattern" : "[a-zA-Z0-9]*",
83
+ "ConstraintDescription" : "must contain only alphanumeric characters."
84
+ },
85
+
86
+ "DBClass" : {
87
+ "Default" : "db.m1.small",
88
+ "Description" : "Database instance class",
89
+ "Type" : "String",
90
+ "AllowedValues" : [ "db.m1.small", "db.m1.large", "db.m1.xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge" ],
91
+ "ConstraintDescription" : "must select a valid database instance type."
92
+ },
93
+
94
+ "DBAllocatedStorage" : {
95
+ "Default": "5",
96
+ "Description" : "The size of the database (Gb)",
97
+ "Type": "Number",
98
+ "MinValue": "5",
99
+ "MaxValue": "1024",
100
+ "ConstraintDescription" : "must be between 5 and 1024Gb."
101
+ },
102
+
103
+ "MultiAZDatabase": {
104
+ "Default": "true",
105
+ "Description" : "Create a multi-AZ MySQL Amazon RDS database instance",
106
+ "Type": "String",
107
+ "AllowedValues" : [ "true", "false" ],
108
+ "ConstraintDescription" : "must be either true or false."
109
+ },
110
+
111
+ "WebServerCapacity": {
112
+ "Default": "2",
113
+ "Description" : "The initial number of WebServer instances",
114
+ "Type": "Number",
115
+ "MinValue": "1",
116
+ "MaxValue": "5",
117
+ "ConstraintDescription" : "must be between 1 and 5 EC2 instances."
118
+ },
119
+ "SSHLocation" : {
120
+ "Description" : "The IP address range that can be used to SSH to the EC2 instances",
121
+ "Type": "String",
122
+ "MinLength": "9",
123
+ "MaxLength": "18",
124
+ "Default": "0.0.0.0/0",
125
+ "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
126
+ "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
127
+ }
128
+ },
129
+
130
+ "Mappings" : {
131
+ "AWSInstanceType2Arch" : {
132
+ "t1.micro" : { "Arch" : "64" },
133
+ "m1.small" : { "Arch" : "64" },
134
+ "m1.medium" : { "Arch" : "64" },
135
+ "m1.large" : { "Arch" : "64" },
136
+ "m1.xlarge" : { "Arch" : "64" },
137
+ "m2.xlarge" : { "Arch" : "64" },
138
+ "m2.2xlarge" : { "Arch" : "64" },
139
+ "m2.4xlarge" : { "Arch" : "64" },
140
+ "m3.xlarge" : { "Arch" : "64" },
141
+ "m3.2xlarge" : { "Arch" : "64" },
142
+ "c1.medium" : { "Arch" : "64" },
143
+ "c1.xlarge" : { "Arch" : "64" },
144
+ "cc1.4xlarge" : { "Arch" : "64HVM" },
145
+ "cc2.8xlarge" : { "Arch" : "64HVM" },
146
+ "cg1.4xlarge" : { "Arch" : "64HVM" }
147
+ },
148
+
149
+ "AWSRegionArch2AMI" : {
150
+ "us-east-1" : { "32" : "ami-a0cd60c9", "64" : "ami-aecd60c7", "64HVM" : "ami-a8cd60c1" },
151
+ "us-west-2" : { "32" : "ami-46da5576", "64" : "ami-48da5578", "64HVM" : "NOT_YET_SUPPORTED" },
152
+ "us-west-1" : { "32" : "ami-7d4c6938", "64" : "ami-734c6936", "64HVM" : "NOT_YET_SUPPORTED" },
153
+ "eu-west-1" : { "32" : "ami-61555115", "64" : "ami-6d555119", "64HVM" : "ami-67555113" },
154
+ "ap-southeast-1" : { "32" : "ami-220b4a70", "64" : "ami-3c0b4a6e", "64HVM" : "NOT_YET_SUPPORTED" },
155
+ "ap-southeast-2" : { "32" : "ami-8f990eb5", "64" : "ami-95990eaf", "64HVM" : "NOT_YET_SUPPORTED" },
156
+ "ap-northeast-1" : { "32" : "ami-2a19aa2b", "64" : "ami-2819aa29", "64HVM" : "NOT_YET_SUPPORTED" },
157
+ "sa-east-1" : { "32" : "ami-f836e8e5", "64" : "ami-fe36e8e3", "64HVM" : "NOT_YET_SUPPORTED" }
158
+ }
159
+ },
160
+
161
+ "Resources" : {
162
+
163
+ "S3Bucket" : {
164
+ "Type" : "AWS::S3::Bucket",
165
+ "DeletionPolicy" : "Retain"
166
+ },
167
+
168
+ "BucketPolicy" : {
169
+ "Type" : "AWS::S3::BucketPolicy",
170
+ "Properties" : {
171
+ "PolicyDocument": {
172
+ "Version" : "2008-10-17",
173
+ "Id" : "UploadPolicy",
174
+ "Statement" : [{
175
+ "Sid" : "EnableReadWrite",
176
+ "Action" : ["s3:GetObject", "s3:PutObject", "s3:PutObjectACL" ],
177
+ "Effect" : "Allow",
178
+ "Resource" : { "Fn::Join" : ["", ["arn:aws:s3:::", {"Ref" : "S3Bucket"} , "/*"]]},
179
+ "Principal" : { "AWS": {"Fn::GetAtt" : ["S3User", "Arn"]} }
180
+ }]
181
+ },
182
+ "Bucket" : {"Ref" : "S3Bucket"}
183
+ }
184
+ },
185
+
186
+ "S3User" : {
187
+ "Type" : "AWS::IAM::User",
188
+ "Properties" : {
189
+ "Path": "/",
190
+ "Policies": [{
191
+ "PolicyName": "root",
192
+ "PolicyDocument": { "Statement":[{
193
+ "Effect":"Allow",
194
+ "Action":"s3:*",
195
+ "Resource":"*"
196
+ }]}
197
+ }]
198
+ }
199
+ },
200
+
201
+ "S3Keys" : {
202
+ "Type" : "AWS::IAM::AccessKey",
203
+ "Properties" : {
204
+ "UserName" : {"Ref": "S3User"}
205
+ }
206
+ },
207
+
208
+ "ElasticLoadBalancer" : {
209
+ "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
210
+ "Metadata" : {
211
+ "Comment" : "Configure the Load Balancer with a simple health check and cookie-based stickiness"
212
+ },
213
+ "Properties" : {
214
+ "AvailabilityZones" : { "Fn::GetAZs" : "" },
215
+ "LBCookieStickinessPolicy" : [ {
216
+ "PolicyName" : "CookieBasedPolicy",
217
+ "CookieExpirationPeriod" : "30"
218
+ } ],
219
+ "Listeners" : [ {
220
+ "LoadBalancerPort" : "80",
221
+ "InstancePort" : "80",
222
+ "Protocol" : "HTTP",
223
+ "PolicyNames" : [ "CookieBasedPolicy" ]
224
+ } ],
225
+ "HealthCheck" : {
226
+ "Target" : "HTTP:80/",
227
+ "HealthyThreshold" : "2",
228
+ "UnhealthyThreshold" : "5",
229
+ "Interval" : "10",
230
+ "Timeout" : "5"
231
+ }
232
+ }
233
+ },
234
+
235
+ "WebServerGroup" : {
236
+ "Type" : "AWS::AutoScaling::AutoScalingGroup",
237
+ "Properties" : {
238
+ "AvailabilityZones" : { "Fn::GetAZs" : "" },
239
+ "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
240
+ "MinSize" : "1",
241
+ "MaxSize" : "5",
242
+ "DesiredCapacity" : { "Ref" : "WebServerCapacity" },
243
+ "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ]
244
+ }
245
+ },
246
+
247
+ "LaunchConfig": {
248
+ "Type" : "AWS::AutoScaling::LaunchConfiguration",
249
+ "Metadata" : {
250
+ "AWS::CloudFormation::Init" : {
251
+ "config" : {
252
+ "packages" : {
253
+ "yum" : {
254
+ "httpd" : [],
255
+ "php" : [],
256
+ "php-mysql" : [],
257
+ "php-gd" : [],
258
+ "php-xml" : [],
259
+ "php-mbstring" : [],
260
+ "mysql" : [],
261
+ "gcc" : [],
262
+ "make" : [],
263
+ "libstdc++-devel" : [],
264
+ "gcc-c++" : [],
265
+ "fuse" : [],
266
+ "fuse-devel" : [],
267
+ "libcurl-devel" : [],
268
+ "libxml2-devel" : [],
269
+ "openssl-devel" : [],
270
+ "mailcap" : []
271
+
272
+ }
273
+ },
274
+
275
+ "sources" : {
276
+ "/var/www/html" : "http://ftp.drupal.org/files/projects/drupal-7.8.tar.gz",
277
+ "/home/ec2-user" : "http://ftp.drupal.org/files/projects/drush-7.x-4.5.tar.gz",
278
+ "/home/ec2-user/s3fs" : "http://s3fs.googlecode.com/files/s3fs-1.61.tar.gz"
279
+ },
280
+
281
+ "files" : {
282
+ "/etc/passwd-s3fs" : {
283
+ "content" : { "Fn::Join" : ["", [ { "Ref" : "S3Keys" }, ":", {"Fn::GetAtt": ["S3Keys", "SecretAccessKey"]}, "\n" ]]},
284
+ "mode" : "000400",
285
+ "owner" : "root",
286
+ "group" : "root"
287
+ },
288
+
289
+ "/home/ec2-user/settings.php" : {
290
+ "content" : { "Fn::Join" : ["", [
291
+ "<?php\n",
292
+ "\n",
293
+ "$databases = array (\n",
294
+ " 'default' =>\n",
295
+ " array (\n",
296
+ " 'default' =>\n",
297
+ " array (\n",
298
+ " 'database' => '", { "Ref" : "DBName" }, "',\n",
299
+ " 'username' => '", { "Ref" : "DBUsername" }, "',\n",
300
+ " 'password' => '", { "Ref" : "DBPassword" }, "',\n",
301
+ " 'host' => '", {"Fn::GetAtt" : ["DBInstance", "Endpoint.Address"]}, "',\n",
302
+ " 'port' => '", {"Fn::GetAtt" : ["DBInstance", "Endpoint.Port"]}, "',\n",
303
+ " 'driver' => 'mysql',\n",
304
+ " 'prefix' => 'drupal_',\n",
305
+ " ),\n",
306
+ " ),\n",
307
+ ");\n",
308
+ "\n",
309
+ "$update_free_access = FALSE;\n",
310
+ "\n",
311
+ "$drupal_hash_salt = '0c3R8noNALe3shsioQr5hK1dMHdwRfikLoSfqn0_xpA';\n",
312
+ "\n",
313
+ "ini_set('session.gc_probability', 1);\n",
314
+ "ini_set('session.gc_divisor', 100);\n",
315
+ "ini_set('session.gc_maxlifetime', 200000);\n",
316
+ "ini_set('session.cookie_lifetime', 2000000);\n"
317
+ ]]},
318
+ "mode" : "000400",
319
+ "owner" : "root",
320
+ "group" : "root"
321
+ }
322
+ },
323
+
324
+ "services" : {
325
+ "sysvinit" : {
326
+ "httpd" : { "enabled" : "true", "ensureRunning" : "true" },
327
+ "sendmail" : { "enabled" : "false", "ensureRunning" : "false" }
328
+ }
329
+ }
330
+ }
331
+ }
332
+ },
333
+ "Properties": {
334
+ "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
335
+ { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
336
+ "InstanceType" : { "Ref" : "InstanceType" },
337
+ "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
338
+ "KeyName" : { "Ref" : "KeyName" },
339
+ "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
340
+ "#!/bin/bash -v\n",
341
+ "yum update -y aws-cfn-bootstrap\n",
342
+
343
+ "# Helper function\n",
344
+ "function error_exit\n",
345
+ "{\n",
346
+ " /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '", { "Ref" : "WaitHandle" }, "'\n",
347
+ " exit 1\n",
348
+ "}\n",
349
+
350
+ "# Install Apache Web Server, MySQL and Drupal\n",
351
+ "/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r LaunchConfig ",
352
+ " --region ", { "Ref" : "AWS::Region" }, " || error_exit 'Failed to run cfn-init'\n",
353
+
354
+ "# Install s3fs\n",
355
+ "cd /home/ec2-user/s3fs/s3fs-1.61\n",
356
+ "./configure --prefix=/usr\n",
357
+ "make\n",
358
+ "make install\n",
359
+
360
+ "# Move the website files to the top level\n",
361
+ "mv /var/www/html/drupal-7.8/* /var/www/html\n",
362
+ "mv /var/www/html/drupal-7.8/.htaccess /var/www/html\n",
363
+ "rm -Rf /var/www/html/drupal-7.8\n",
364
+
365
+ "# Mount the S3 bucket\n",
366
+ "mv /var/www/html/sites/default/files /var/www/html/sites/default/files_original\n",
367
+ "mkdir -p /var/www/html/sites/default/files\n",
368
+ "s3fs -o allow_other -o use_cache=/tmp ", { "Ref" : "S3Bucket" } ," /var/www/html/sites/default/files || error_exit 'Failed to mount the S3 bucket'\n",
369
+ "echo `hostname` >> /var/www/html/sites/default/files/hosts\n",
370
+
371
+ "# Make changes to Apache Web Server configuration\n",
372
+ "sed -i 's/AllowOverride None/AllowOverride All/g' /etc/httpd/conf/httpd.conf\n",
373
+ "service httpd restart\n",
374
+
375
+ "# Only execute the site install if we are the first host up - otherwise we'll end up losing all the data\n",
376
+ "read first < /var/www/html/sites/default/files/hosts\n",
377
+ "if [ `hostname` = $first ]\n",
378
+ "then\n",
379
+ " # Create the site in Drupal\n",
380
+ " cd /var/www/html\n",
381
+ " ~ec2-user/drush/drush site-install standard --yes",
382
+ " --site-name='", { "Ref" : "SiteName" }, "' --site-mail=", { "Ref" : "SiteEMail" },
383
+ " --account-name=", { "Ref" : "SiteAdmin" }, " --account-pass=", { "Ref" : "SitePassword" },
384
+ " --db-url=mysql://", { "Ref" : "DBUsername" }, ":", { "Ref" : "DBPassword" }, "@", {"Fn::GetAtt" : ["DBInstance", "Endpoint.Address"]}, ":", {"Fn::GetAtt" : ["DBInstance", "Endpoint.Port"]}, "/", { "Ref" : "DBName" },
385
+ " --db-prefix=drupal_\n",
386
+ " # use the S3 bucket for shared file storage\n",
387
+ " cp -R sites/default/files_original/* sites/default/files\n",
388
+ " cp -R sites/default/files_original/.htaccess sites/default/files\n",
389
+ "else\n",
390
+ " # Copy settings.php file since everything else is configured\n",
391
+ " cp /home/ec2-user/settings.php /var/www/html/sites/default\n",
392
+ "fi\n",
393
+ "rm /home/ec2-user/settings.php\n",
394
+
395
+ "# All is well so signal success\n",
396
+ "/opt/aws/bin/cfn-signal -e 0 -r \"Drupal setup complete\" '", { "Ref" : "WaitHandle" }, "'\n"
397
+
398
+ ]]}}
399
+ }
400
+ },
401
+
402
+ "WaitHandle" : {
403
+ "Type" : "AWS::CloudFormation::WaitConditionHandle"
404
+ },
405
+
406
+ "WaitCondition" : {
407
+ "Type" : "AWS::CloudFormation::WaitCondition",
408
+ "DependsOn" : "WebServerGroup",
409
+ "Properties" : {
410
+ "Handle" : {"Ref" : "WaitHandle"},
411
+ "Timeout" : "600"
412
+ }
413
+ },
414
+
415
+ "DBInstance" : {
416
+ "Type": "AWS::RDS::DBInstance",
417
+ "Properties": {
418
+ "DBName" : { "Ref" : "DBName" },
419
+ "Engine" : "MySQL",
420
+ "MultiAZ" : { "Ref": "MultiAZDatabase" },
421
+ "MasterUsername" : { "Ref" : "DBUsername" },
422
+ "DBInstanceClass" : { "Ref" : "DBClass" },
423
+ "DBSecurityGroups" : [{ "Ref" : "DBSecurityGroup" }],
424
+ "AllocatedStorage" : { "Ref" : "DBAllocatedStorage" },
425
+ "MasterUserPassword": { "Ref" : "DBPassword" }
426
+ }
427
+ },
428
+
429
+ "DBSecurityGroup": {
430
+ "Type": "AWS::RDS::DBSecurityGroup",
431
+ "Properties": {
432
+ "DBSecurityGroupIngress": { "EC2SecurityGroupName": { "Ref": "WebServerSecurityGroup"} },
433
+ "GroupDescription" : "Frontend Access"
434
+ }
435
+ },
436
+
437
+ "WebServerSecurityGroup" : {
438
+ "Type" : "AWS::EC2::SecurityGroup",
439
+ "Properties" : {
440
+ "GroupDescription" : "Enable HTTP access via port 80, locked down to requests from the load balancer only and SSH access",
441
+ "SecurityGroupIngress" : [
442
+ {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "SourceSecurityGroupOwnerId" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"]},"SourceSecurityGroupName" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.GroupName"]}},
443
+ {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}}
444
+ ]
445
+ }
446
+ }
447
+ },
448
+
449
+ "Outputs" : {
450
+ "WebsiteURL" : {
451
+ "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]}]] },
452
+ "Description" : "Drupal Website"
453
+ }
454
+ }
455
+ }