kumogata 0.2.6 → 0.2.7
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.
- checksums.yaml +4 -4
- data/README.md +14 -12
- data/bin/kumogata +2 -1
- data/kumogata.gemspec +1 -0
- data/lib/kumogata.rb +1 -0
- data/lib/kumogata/argument_parser.rb +5 -0
- data/lib/kumogata/client.rb +15 -0
- data/lib/kumogata/ext/string_ext.rb +7 -2
- data/lib/kumogata/version.rb +1 -1
- data/spec/Drupal_Single_Instance.template +270 -0
- data/spec/Drupal_Single_Instance.template.rb +284 -0
- data/spec/kumogata_convert_spec.rb +75 -0
- data/spec/kumogata_diff_spec.rb +36 -0
- metadata +21 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db9de5e733c5ce3dbfb6cdcf818f7c6c8402f2e5
|
4
|
+
data.tar.gz: f6b43da8e971a28382d02450dc0666d50dfb270a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a4f8c5b24c73f584b2bee4290fba1465bbef3db577728a3c43065422e6ffb491fd1e1ac11a8678b3627877fdb783d92ccc39429dbacfa4bb6a9af7daa996613
|
7
|
+
data.tar.gz: 281264326c74826a608f8e63e520ee456d34ff02f00a16521b411aa1bd3934ee4523ac2a227f91d5977029f17e131db4331cac8104ca8732387a041a0a8d4bd3
|
data/README.md
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
|
6
6
|
Kumogata is a tool for [AWS CloudFormation](https://aws.amazon.com/cloudformation/).
|
7
7
|
|
8
|
-
[](http://badge.fury.io/rb/kumogata)
|
9
|
+
[](https://drone.io/github.com/winebarrel/kumogata/latest)
|
10
10
|
|
11
11
|
It can define a template in Ruby DSL, such as:
|
12
12
|
|
@@ -64,15 +64,16 @@ Ruby template structure is almost the same as [JSON template](http://docs.aws.am
|
|
64
64
|
Usage: kumogata <command> [args] [options]
|
65
65
|
|
66
66
|
Commands:
|
67
|
-
create PATH_OR_URL [STACK_NAME]
|
68
|
-
validate PATH_OR_URL
|
69
|
-
convert PATH_OR_URL
|
70
|
-
update PATH_OR_URL STACK_NAME
|
71
|
-
delete STACK_NAME
|
72
|
-
list [STACK_NAME]
|
73
|
-
export STACK_NAME
|
74
|
-
show-outputs STACK_NAME
|
75
|
-
show-resources STACK_NAME
|
67
|
+
create PATH_OR_URL [STACK_NAME] Create resources as specified in the template
|
68
|
+
validate PATH_OR_URL Validate a specified template
|
69
|
+
convert PATH_OR_URL Convert a template format
|
70
|
+
update PATH_OR_URL STACK_NAME Update a stack as specified in the template
|
71
|
+
delete STACK_NAME Delete a specified stack
|
72
|
+
list [STACK_NAME] List summary information for stacks
|
73
|
+
export STACK_NAME Export a template from a specified stack
|
74
|
+
show-outputs STACK_NAME Show outputs for a specified stack
|
75
|
+
show-resources STACK_NAME Show resources for a specified stack
|
76
|
+
diff PATH_OR_URL1 PATH_OR_URL2 Compare templates logically
|
76
77
|
|
77
78
|
Options:
|
78
79
|
-k, --access-key ACCESS_KEY
|
@@ -87,6 +88,7 @@ Options:
|
|
87
88
|
--timeout MINUTES
|
88
89
|
--result-log PATH
|
89
90
|
--force
|
91
|
+
-w, --ignore-all-space
|
90
92
|
--no-color
|
91
93
|
--debug
|
92
94
|
```
|
@@ -169,7 +171,7 @@ end
|
|
169
171
|
|
170
172
|
```ruby
|
171
173
|
Resources do
|
172
|
-
_include 'template2'
|
174
|
+
_include 'template2.rb'
|
173
175
|
end
|
174
176
|
```
|
175
177
|
|
data/bin/kumogata
CHANGED
@@ -24,7 +24,8 @@ begin
|
|
24
24
|
|
25
25
|
AWS.config(aws_opts) unless aws_opts.empty?
|
26
26
|
|
27
|
-
String.colorize = options.color?
|
27
|
+
String.colorize = ($stdout.tty? and options.color?)
|
28
|
+
Diffy::Diff.default_format = ($stdout.tty? and options.color?) ? :color : :text
|
28
29
|
|
29
30
|
if options.debug?
|
30
31
|
Kumogata.logger.set_debug(true)
|
data/kumogata.gemspec
CHANGED
data/lib/kumogata.rb
CHANGED
@@ -46,6 +46,10 @@ class Kumogata::ArgumentParser
|
|
46
46
|
:description => 'Show resources for a specified stack',
|
47
47
|
:arguments => [:stack_name]
|
48
48
|
},
|
49
|
+
:diff => {
|
50
|
+
:description => 'Compare templates logically',
|
51
|
+
:arguments => [:path_or_url1, :path_or_url2]
|
52
|
+
},
|
49
53
|
}
|
50
54
|
|
51
55
|
class << self
|
@@ -75,6 +79,7 @@ class Kumogata::ArgumentParser
|
|
75
79
|
opt.on('' , '--timeout MINUTES', Integer) {|v| options[:timeout] = v }
|
76
80
|
opt.on('' , '--result-log PATH') {|v| options[:result_log] = v }
|
77
81
|
opt.on('' , '--force') { options[:force] = true }
|
82
|
+
opt.on('-w', '--ignore-all-space') { options[:ignore_all_space] = true }
|
78
83
|
opt.on('' , '--no-color') { options[:color] = false }
|
79
84
|
opt.on('' , '--debug') { options[:debug] = true }
|
80
85
|
opt.parse!
|
data/lib/kumogata/client.rb
CHANGED
@@ -72,6 +72,21 @@ class Kumogata::Client
|
|
72
72
|
JSON.pretty_generate(resources)
|
73
73
|
end
|
74
74
|
|
75
|
+
def diff(path_or_url1, path_or_url2)
|
76
|
+
templates = [path_or_url1, path_or_url2].map do |path_or_url|
|
77
|
+
template = open_template(path_or_url)
|
78
|
+
JSON.pretty_generate(template)
|
79
|
+
end
|
80
|
+
|
81
|
+
diff_opts = '-U 3'
|
82
|
+
opts = {:include_diff_info => true, :diff => diff_opts}
|
83
|
+
diff_opts << ' -w' if @options.ignore_all_space?
|
84
|
+
|
85
|
+
diff = Diffy::Diff.new(*templates, opts).to_s
|
86
|
+
diff.sub(/^(\e\[\d+m)?\-\-\-(\s+)(\S+)/m) { "#{$1}---#{$2}#{path_or_url1}"}
|
87
|
+
.sub(/^(\e\[\d+m)?\+\+\+(\s+)(\S+)/m) { "#{$1}+++#{$2}#{path_or_url2}"}
|
88
|
+
end
|
89
|
+
|
75
90
|
private ###########################################################
|
76
91
|
|
77
92
|
def open_template(path_or_url)
|
@@ -30,8 +30,13 @@ class String
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def undent
|
33
|
-
min_space_num = self.split("\n").delete_if{|s| s=~ /^\s*$/ }.map{|s| s[/^\s+/].length }.min
|
34
|
-
|
33
|
+
min_space_num = self.split("\n").delete_if {|s| s =~ /^\s*$/ }.map {|s| (s[/^\s+/] || '').length }.min
|
34
|
+
|
35
|
+
if min_space_num and min_space_num > 0
|
36
|
+
gsub(/^[ \t]{,#{min_space_num}}/, '')
|
37
|
+
else
|
38
|
+
self
|
39
|
+
end
|
35
40
|
end
|
36
41
|
|
37
42
|
def fn_join(options = {})
|
data/lib/kumogata/version.rb
CHANGED
@@ -0,0 +1,270 @@
|
|
1
|
+
{
|
2
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
3
|
+
|
4
|
+
"Description" : "AWS CloudFormation Sample Template Drupal_Single_Instance.\n Drupal is an open source content management platform powering millions of websites and applications.\n This template installs a singe instance deployment with a local MySQL database for storage.\n It uses the AWS CloudFormation bootstrap scripts to install packages and files at instance launch time.\n\n **WARNING**\n This template creates an Amazon EC2 instance.\n You will be billed for the AWS resources used if you create a stack from this template.\n",
|
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
|
+
"AllowedValues" : [ "t1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m2.xlarge","m2.2xlarge","m2.4xlarge","m3.xlarge","m3.2xlarge","c1.medium","c1.xlarge","cc1.4xlarge","cc2.8xlarge","cg1.4xlarge"],
|
22
|
+
"ConstraintDescription" : "must be a valid EC2 instance type."
|
23
|
+
},
|
24
|
+
|
25
|
+
"SiteName": {
|
26
|
+
"Default": "My Site",
|
27
|
+
"Description" : "The name of the Drupal Site",
|
28
|
+
"Type": "String"
|
29
|
+
},
|
30
|
+
|
31
|
+
"SiteEMail": {
|
32
|
+
"Description" : "EMail for site adminitrator",
|
33
|
+
"Type": "String"
|
34
|
+
},
|
35
|
+
|
36
|
+
"SiteAdmin": {
|
37
|
+
"Description" : "The Drupal site admin account username",
|
38
|
+
"Type": "String",
|
39
|
+
"MinLength": "1",
|
40
|
+
"MaxLength": "16",
|
41
|
+
"AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
|
42
|
+
"ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
|
43
|
+
},
|
44
|
+
|
45
|
+
"SitePassword": {
|
46
|
+
"NoEcho": "true",
|
47
|
+
"Description" : "The Drupal site admin account password",
|
48
|
+
"Type": "String",
|
49
|
+
"MinLength": "1",
|
50
|
+
"MaxLength": "41",
|
51
|
+
"AllowedPattern" : "[a-zA-Z0-9]*",
|
52
|
+
"ConstraintDescription" : "must contain only alphanumeric characters."
|
53
|
+
},
|
54
|
+
|
55
|
+
"DBName": {
|
56
|
+
"Default": "drupaldb",
|
57
|
+
"Description" : "The Drupal database name",
|
58
|
+
"Type": "String",
|
59
|
+
"MinLength": "1",
|
60
|
+
"MaxLength": "64",
|
61
|
+
"AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
|
62
|
+
"ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
|
63
|
+
},
|
64
|
+
|
65
|
+
"DBUsername": {
|
66
|
+
"Default": "admin",
|
67
|
+
"NoEcho": "true",
|
68
|
+
"Description" : "The Drupal database admin account username",
|
69
|
+
"Type": "String",
|
70
|
+
"MinLength": "1",
|
71
|
+
"MaxLength": "16",
|
72
|
+
"AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
|
73
|
+
"ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
|
74
|
+
},
|
75
|
+
|
76
|
+
"DBPassword": {
|
77
|
+
"Default": "admin",
|
78
|
+
"NoEcho": "true",
|
79
|
+
"Description" : "The Drupal database admin account password",
|
80
|
+
"Type": "String",
|
81
|
+
"MinLength": "1",
|
82
|
+
"MaxLength": "41",
|
83
|
+
"AllowedPattern" : "[a-zA-Z0-9]*",
|
84
|
+
"ConstraintDescription" : "must contain only alphanumeric characters."
|
85
|
+
},
|
86
|
+
|
87
|
+
"DBRootPassword": {
|
88
|
+
"NoEcho": "true",
|
89
|
+
"Description" : "Root password for MySQL",
|
90
|
+
"Type": "String",
|
91
|
+
"MinLength": "1",
|
92
|
+
"MaxLength": "41",
|
93
|
+
"AllowedPattern" : "[a-zA-Z0-9]*",
|
94
|
+
"ConstraintDescription" : "must contain only alphanumeric characters."
|
95
|
+
},
|
96
|
+
"SSHLocation" : {
|
97
|
+
"Description" : "The IP address range that can be used to SSH to the EC2 instances",
|
98
|
+
"Type": "String",
|
99
|
+
"MinLength": "9",
|
100
|
+
"MaxLength": "18",
|
101
|
+
"Default": "0.0.0.0/0",
|
102
|
+
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
|
103
|
+
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
|
104
|
+
}
|
105
|
+
},
|
106
|
+
|
107
|
+
"Mappings" : {
|
108
|
+
"AWSInstanceType2Arch" : {
|
109
|
+
"t1.micro" : { "Arch" : "64" },
|
110
|
+
"m1.small" : { "Arch" : "64" },
|
111
|
+
"m1.medium" : { "Arch" : "64" },
|
112
|
+
"m1.large" : { "Arch" : "64" },
|
113
|
+
"m1.xlarge" : { "Arch" : "64" },
|
114
|
+
"m2.xlarge" : { "Arch" : "64" },
|
115
|
+
"m2.2xlarge" : { "Arch" : "64" },
|
116
|
+
"m2.4xlarge" : { "Arch" : "64" },
|
117
|
+
"m3.xlarge" : { "Arch" : "64" },
|
118
|
+
"m3.2xlarge" : { "Arch" : "64" },
|
119
|
+
"c1.medium" : { "Arch" : "64" },
|
120
|
+
"c1.xlarge" : { "Arch" : "64" },
|
121
|
+
"cc1.4xlarge" : { "Arch" : "64HVM" },
|
122
|
+
"cc2.8xlarge" : { "Arch" : "64HVM" },
|
123
|
+
"cg1.4xlarge" : { "Arch" : "64HVM" }
|
124
|
+
},
|
125
|
+
|
126
|
+
"AWSRegionArch2AMI" : {
|
127
|
+
"us-east-1" : { "32" : "ami-a0cd60c9", "64" : "ami-aecd60c7", "64HVM" : "ami-a8cd60c1" },
|
128
|
+
"us-west-2" : { "32" : "ami-46da5576", "64" : "ami-48da5578", "64HVM" : "NOT_YET_SUPPORTED" },
|
129
|
+
"us-west-1" : { "32" : "ami-7d4c6938", "64" : "ami-734c6936", "64HVM" : "NOT_YET_SUPPORTED" },
|
130
|
+
"eu-west-1" : { "32" : "ami-61555115", "64" : "ami-6d555119", "64HVM" : "ami-67555113" },
|
131
|
+
"ap-southeast-1" : { "32" : "ami-220b4a70", "64" : "ami-3c0b4a6e", "64HVM" : "NOT_YET_SUPPORTED" },
|
132
|
+
"ap-southeast-2" : { "32" : "ami-b3990e89", "64" : "ami-bd990e87", "64HVM" : "NOT_YET_SUPPORTED" },
|
133
|
+
"ap-northeast-1" : { "32" : "ami-2a19aa2b", "64" : "ami-2819aa29", "64HVM" : "NOT_YET_SUPPORTED" },
|
134
|
+
"sa-east-1" : { "32" : "ami-f836e8e5", "64" : "ami-fe36e8e3", "64HVM" : "NOT_YET_SUPPORTED" }
|
135
|
+
}
|
136
|
+
},
|
137
|
+
|
138
|
+
"Resources" : {
|
139
|
+
|
140
|
+
"WebServer": {
|
141
|
+
"Type": "AWS::EC2::Instance",
|
142
|
+
"Metadata" : {
|
143
|
+
"AWS::CloudFormation::Init" : {
|
144
|
+
"config" : {
|
145
|
+
"packages" : {
|
146
|
+
"yum" : {
|
147
|
+
"httpd" : [],
|
148
|
+
"php" : [],
|
149
|
+
"php-mysql" : [],
|
150
|
+
"php-gd" : [],
|
151
|
+
"php-xml" : [],
|
152
|
+
"php-mbstring" : [],
|
153
|
+
"mysql" : [],
|
154
|
+
"mysql-server" : [],
|
155
|
+
"mysql-devel" : [],
|
156
|
+
"mysql-libs" : []
|
157
|
+
|
158
|
+
}
|
159
|
+
},
|
160
|
+
|
161
|
+
"sources" : {
|
162
|
+
"/var/www/html" : "http://ftp.drupal.org/files/projects/drupal-7.8.tar.gz",
|
163
|
+
"/home/ec2-user" : "http://ftp.drupal.org/files/projects/drush-7.x-4.5.tar.gz"
|
164
|
+
},
|
165
|
+
|
166
|
+
"files" : {
|
167
|
+
"/tmp/setup.mysql" : {
|
168
|
+
"content" : { "Fn::Join" : ["", [
|
169
|
+
"CREATE DATABASE ", { "Ref" : "DBName" }, ";\n",
|
170
|
+
"CREATE USER '", { "Ref" : "DBUsername" }, "'@'localhost' IDENTIFIED BY '", { "Ref" : "DBPassword" }, "';\n",
|
171
|
+
"GRANT ALL ON ", { "Ref" : "DBName" }, ".* TO '", { "Ref" : "DBUsername" }, "'@'localhost';\n",
|
172
|
+
"FLUSH PRIVILEGES;\n"
|
173
|
+
]]},
|
174
|
+
"mode" : "000644",
|
175
|
+
"owner" : "root",
|
176
|
+
"group" : "root"
|
177
|
+
}
|
178
|
+
},
|
179
|
+
|
180
|
+
"services" : {
|
181
|
+
"sysvinit" : {
|
182
|
+
"httpd" : { "enabled" : "true", "ensureRunning" : "true" },
|
183
|
+
"mysqld" : { "enabled" : "true", "ensureRunning" : "true" },
|
184
|
+
"sendmail" : { "enabled" : "false", "ensureRunning" : "false" }
|
185
|
+
}
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
},
|
190
|
+
"Properties": {
|
191
|
+
"ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
|
192
|
+
{ "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
|
193
|
+
"InstanceType" : { "Ref" : "InstanceType" },
|
194
|
+
"SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
|
195
|
+
"KeyName" : { "Ref" : "KeyName" },
|
196
|
+
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
|
197
|
+
"#!/bin/bash -v\n",
|
198
|
+
"yum update -y aws-cfn-bootstrap\n",
|
199
|
+
|
200
|
+
|
201
|
+
"# Helper function\n",
|
202
|
+
"function error_exit\n",
|
203
|
+
"{\n",
|
204
|
+
" /opt/aws/bin/cfn-signal -e 0 -r \"$1\" '", { "Ref" : "WaitHandle" }, "'\n",
|
205
|
+
" exit 1\n",
|
206
|
+
"}\n",
|
207
|
+
|
208
|
+
"# Install Apache Web Server, MySQL, PHP and Drupal\n",
|
209
|
+
"/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServer --region ",
|
210
|
+
{ "Ref" : "AWS::Region" }, " || error_exit 'Failed to run cfn-init'\n",
|
211
|
+
|
212
|
+
"# Setup MySQL root password and create a user\n",
|
213
|
+
"mysqladmin -u root password '", { "Ref" : "DBRootPassword" }, "' || error_exit 'Failed to initialize root password'\n",
|
214
|
+
"mysql -u root --password='", { "Ref" : "DBRootPassword" }, "' < /tmp/setup.mysql || error_exit 'Failed to create database user'\n",
|
215
|
+
|
216
|
+
"# Make changes to Apache Web Server configuration\n",
|
217
|
+
"mv /var/www/html/drupal-7.8/* /var/www/html\n",
|
218
|
+
"mv /var/www/html/drupal-7.8/.* /var/www/html\n",
|
219
|
+
"rmdir /var/www/html/drupal-7.8\n",
|
220
|
+
"sed -i 's/AllowOverride None/AllowOverride All/g' /etc/httpd/conf/httpd.conf\n",
|
221
|
+
"service httpd restart\n",
|
222
|
+
|
223
|
+
"# Create the site in Drupal\n",
|
224
|
+
"cd /var/www/html\n",
|
225
|
+
"~ec2-user/drush/drush site-install standard --yes --site-name='",
|
226
|
+
{ "Ref" : "SiteName" }, "' --site-mail=", { "Ref" : "SiteEMail" },
|
227
|
+
" --account-name=", { "Ref" : "SiteAdmin" }, " --account-pass=", { "Ref" : "SitePassword" },
|
228
|
+
" --db-url=mysql://", { "Ref" : "DBUsername" }, ":", { "Ref" : "DBPassword" }, "@localhost/", { "Ref" : "DBName" },
|
229
|
+
" --db-prefix=drupal_\n",
|
230
|
+
"chown apache:apache sites/default/files\n",
|
231
|
+
|
232
|
+
"# All is well so signal success\n",
|
233
|
+
"/opt/aws/bin/cfn-signal -e 0 -r \"Drupal setup complete\" '", { "Ref" : "WaitHandle" }, "'\n"
|
234
|
+
|
235
|
+
]]}}
|
236
|
+
}
|
237
|
+
},
|
238
|
+
|
239
|
+
"WaitHandle" : {
|
240
|
+
"Type" : "AWS::CloudFormation::WaitConditionHandle"
|
241
|
+
},
|
242
|
+
|
243
|
+
"WaitCondition" : {
|
244
|
+
"Type" : "AWS::CloudFormation::WaitCondition",
|
245
|
+
"DependsOn" : "WebServer",
|
246
|
+
"Properties" : {
|
247
|
+
"Handle" : {"Ref" : "WaitHandle"},
|
248
|
+
"Timeout" : "300"
|
249
|
+
}
|
250
|
+
},
|
251
|
+
|
252
|
+
"WebServerSecurityGroup" : {
|
253
|
+
"Type" : "AWS::EC2::SecurityGroup",
|
254
|
+
"Properties" : {
|
255
|
+
"GroupDescription" : "Enable HTTP access via port 80 and SSH access",
|
256
|
+
"SecurityGroupIngress" : [
|
257
|
+
{"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"},
|
258
|
+
{"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}}
|
259
|
+
]
|
260
|
+
}
|
261
|
+
}
|
262
|
+
},
|
263
|
+
|
264
|
+
"Outputs" : {
|
265
|
+
"WebsiteURL" : {
|
266
|
+
"Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServer", "PublicDnsName" ]}]] },
|
267
|
+
"Description" : "Drupal Website"
|
268
|
+
}
|
269
|
+
}
|
270
|
+
}
|
@@ -0,0 +1,284 @@
|
|
1
|
+
AWSTemplateFormatVersion "2010-09-09"
|
2
|
+
|
3
|
+
Description (<<-EOS).undent
|
4
|
+
AWS CloudFormation Sample Template Drupal_Single_Instance.
|
5
|
+
Drupal is an open source content management platform powering millions of websites and applications.
|
6
|
+
This template installs a singe instance deployment with a local MySQL database for storage.
|
7
|
+
It uses the AWS CloudFormation bootstrap scripts to install packages and files at instance launch time.
|
8
|
+
|
9
|
+
**WARNING**
|
10
|
+
This template creates an Amazon EC2 instance.
|
11
|
+
You will be billed for the AWS resources used if you create a stack from this template.
|
12
|
+
EOS
|
13
|
+
|
14
|
+
Parameters do
|
15
|
+
KeyName do
|
16
|
+
Description "Name of an existing EC2 KeyPair to enable SSH access to the instances"
|
17
|
+
Type "String"
|
18
|
+
MinLength 1
|
19
|
+
MaxLength 255
|
20
|
+
AllowedPattern "[\\x20-\\x7E]*"
|
21
|
+
ConstraintDescription "can contain only ASCII characters."
|
22
|
+
end
|
23
|
+
InstanceType do
|
24
|
+
Description "WebServer EC2 instance type"
|
25
|
+
Type "String"
|
26
|
+
Default "m1.small"
|
27
|
+
AllowedValues "t1.micro", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.xlarge", "m3.2xlarge", "c1.medium", "c1.xlarge", "cc1.4xlarge", "cc2.8xlarge", "cg1.4xlarge"
|
28
|
+
ConstraintDescription "must be a valid EC2 instance type."
|
29
|
+
end
|
30
|
+
SiteName do
|
31
|
+
Default "My Site"
|
32
|
+
Description "The name of the Drupal Site"
|
33
|
+
Type "String"
|
34
|
+
end
|
35
|
+
SiteEMail do
|
36
|
+
Description "EMail for site adminitrator"
|
37
|
+
Type "String"
|
38
|
+
end
|
39
|
+
SiteAdmin do
|
40
|
+
Description "The Drupal site admin account username"
|
41
|
+
Type "String"
|
42
|
+
MinLength 1
|
43
|
+
MaxLength 16
|
44
|
+
AllowedPattern "[a-zA-Z][a-zA-Z0-9]*"
|
45
|
+
ConstraintDescription "must begin with a letter and contain only alphanumeric characters."
|
46
|
+
end
|
47
|
+
SitePassword do
|
48
|
+
NoEcho "true"
|
49
|
+
Description "The Drupal site admin account password"
|
50
|
+
Type "String"
|
51
|
+
MinLength 1
|
52
|
+
MaxLength 41
|
53
|
+
AllowedPattern "[a-zA-Z0-9]*"
|
54
|
+
ConstraintDescription "must contain only alphanumeric characters."
|
55
|
+
end
|
56
|
+
DBName do
|
57
|
+
Default "drupaldb"
|
58
|
+
Description "The Drupal database name"
|
59
|
+
Type "String"
|
60
|
+
MinLength 1
|
61
|
+
MaxLength 64
|
62
|
+
AllowedPattern "[a-zA-Z][a-zA-Z0-9]*"
|
63
|
+
ConstraintDescription "must begin with a letter and contain only alphanumeric characters."
|
64
|
+
end
|
65
|
+
DBUsername do
|
66
|
+
Default "admin"
|
67
|
+
NoEcho "true"
|
68
|
+
Description "The Drupal database admin account username"
|
69
|
+
Type "String"
|
70
|
+
MinLength 1
|
71
|
+
MaxLength 16
|
72
|
+
AllowedPattern "[a-zA-Z][a-zA-Z0-9]*"
|
73
|
+
ConstraintDescription "must begin with a letter and contain only alphanumeric characters."
|
74
|
+
end
|
75
|
+
DBPassword do
|
76
|
+
Default "admin"
|
77
|
+
NoEcho "true"
|
78
|
+
Description "The Drupal database admin account password"
|
79
|
+
Type "String"
|
80
|
+
MinLength 1
|
81
|
+
MaxLength 41
|
82
|
+
AllowedPattern "[a-zA-Z0-9]*"
|
83
|
+
ConstraintDescription "must contain only alphanumeric characters."
|
84
|
+
end
|
85
|
+
DBRootPassword do
|
86
|
+
NoEcho "true"
|
87
|
+
Description "Root password for MySQL"
|
88
|
+
Type "String"
|
89
|
+
MinLength 1
|
90
|
+
MaxLength 41
|
91
|
+
AllowedPattern "[a-zA-Z0-9]*"
|
92
|
+
ConstraintDescription "must contain only alphanumeric characters."
|
93
|
+
end
|
94
|
+
SSHLocation do
|
95
|
+
Description "The IP address range that can be used to SSH to the EC2 instances"
|
96
|
+
Type "String"
|
97
|
+
MinLength 9
|
98
|
+
MaxLength 18
|
99
|
+
Default "0.0.0.0/0"
|
100
|
+
AllowedPattern "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
|
101
|
+
ConstraintDescription "must be a valid IP CIDR range of the form x.x.x.x/x."
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
Mappings do
|
106
|
+
AWSInstanceType2Arch(
|
107
|
+
{"t1.micro"=>{"Arch"=>"64"},
|
108
|
+
"m1.small"=>{"Arch"=>"64"},
|
109
|
+
"m1.medium"=>{"Arch"=>"64"},
|
110
|
+
"m1.large"=>{"Arch"=>"64"},
|
111
|
+
"m1.xlarge"=>{"Arch"=>"64"},
|
112
|
+
"m2.xlarge"=>{"Arch"=>"64"},
|
113
|
+
"m2.2xlarge"=>{"Arch"=>"64"},
|
114
|
+
"m2.4xlarge"=>{"Arch"=>"64"},
|
115
|
+
"m3.xlarge"=>{"Arch"=>"64"},
|
116
|
+
"m3.2xlarge"=>{"Arch"=>"64"},
|
117
|
+
"c1.medium"=>{"Arch"=>"64"},
|
118
|
+
"c1.xlarge"=>{"Arch"=>"64"},
|
119
|
+
"cc1.4xlarge"=>{"Arch"=>"64HVM"},
|
120
|
+
"cc2.8xlarge"=>{"Arch"=>"64HVM"},
|
121
|
+
"cg1.4xlarge"=>{"Arch"=>"64HVM"}})
|
122
|
+
AWSRegionArch2AMI(
|
123
|
+
{"us-east-1"=>
|
124
|
+
{"32"=>"ami-a0cd60c9", "64"=>"ami-aecd60c7", "64HVM"=>"ami-a8cd60c1"},
|
125
|
+
"us-west-2"=>
|
126
|
+
{"32"=>"ami-46da5576", "64"=>"ami-48da5578", "64HVM"=>"NOT_YET_SUPPORTED"},
|
127
|
+
"us-west-1"=>
|
128
|
+
{"32"=>"ami-7d4c6938", "64"=>"ami-734c6936", "64HVM"=>"NOT_YET_SUPPORTED"},
|
129
|
+
"eu-west-1"=>
|
130
|
+
{"32"=>"ami-61555115", "64"=>"ami-6d555119", "64HVM"=>"ami-67555113"},
|
131
|
+
"ap-southeast-1"=>
|
132
|
+
{"32"=>"ami-220b4a70", "64"=>"ami-3c0b4a6e", "64HVM"=>"NOT_YET_SUPPORTED"},
|
133
|
+
"ap-southeast-2"=>
|
134
|
+
{"32"=>"ami-b3990e89", "64"=>"ami-bd990e87", "64HVM"=>"NOT_YET_SUPPORTED"},
|
135
|
+
"ap-northeast-1"=>
|
136
|
+
{"32"=>"ami-2a19aa2b", "64"=>"ami-2819aa29", "64HVM"=>"NOT_YET_SUPPORTED"},
|
137
|
+
"sa-east-1"=>
|
138
|
+
{"32"=>"ami-f836e8e5", "64"=>"ami-fe36e8e3", "64HVM"=>"NOT_YET_SUPPORTED"}})
|
139
|
+
end
|
140
|
+
|
141
|
+
Resources do
|
142
|
+
WebServer do
|
143
|
+
Type "AWS::EC2::Instance"
|
144
|
+
Metadata do
|
145
|
+
AWS__CloudFormation__Init do
|
146
|
+
config do
|
147
|
+
packages do
|
148
|
+
yum(
|
149
|
+
{"httpd"=>[],
|
150
|
+
"php"=>[],
|
151
|
+
"php-mysql"=>[],
|
152
|
+
"php-gd"=>[],
|
153
|
+
"php-xml"=>[],
|
154
|
+
"php-mbstring"=>[],
|
155
|
+
"mysql"=>[],
|
156
|
+
"mysql-server"=>[],
|
157
|
+
"mysql-devel"=>[],
|
158
|
+
"mysql-libs"=>[]})
|
159
|
+
end
|
160
|
+
sources do
|
161
|
+
_path "/var/www/html", "http://ftp.drupal.org/files/projects/drupal-7.8.tar.gz"
|
162
|
+
_path "/home/ec2-user", "http://ftp.drupal.org/files/projects/drush-7.x-4.5.tar.gz"
|
163
|
+
end
|
164
|
+
files do
|
165
|
+
_path("/tmp/setup.mysql") do
|
166
|
+
content (<<-EOS).fn_join
|
167
|
+
CREATE DATABASE <%= Ref "DBName" %>;
|
168
|
+
CREATE USER '<%= Ref "DBUsername" %>'@'localhost' IDENTIFIED BY '<%= Ref "DBPassword" %>';
|
169
|
+
GRANT ALL ON <%= Ref "DBName" %>.* TO '<%= Ref "DBUsername" %>'@'localhost';
|
170
|
+
FLUSH PRIVILEGES;
|
171
|
+
EOS
|
172
|
+
mode "000644"
|
173
|
+
owner "root"
|
174
|
+
group "root"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
services do
|
178
|
+
sysvinit do
|
179
|
+
httpd do
|
180
|
+
enabled "true"
|
181
|
+
ensureRunning "true"
|
182
|
+
end
|
183
|
+
mysqld do
|
184
|
+
enabled "true"
|
185
|
+
ensureRunning "true"
|
186
|
+
end
|
187
|
+
sendmail do
|
188
|
+
enabled "false"
|
189
|
+
ensureRunning "false"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
Properties do
|
198
|
+
ImageId do
|
199
|
+
Fn__FindInMap "AWSRegionArch2AMI", _{ Ref "AWS::Region" }, _{
|
200
|
+
Fn__FindInMap "AWSInstanceType2Arch", _{ Ref "InstanceType" }, "Arch"
|
201
|
+
}
|
202
|
+
end
|
203
|
+
InstanceType do
|
204
|
+
Ref "InstanceType"
|
205
|
+
end
|
206
|
+
SecurityGroups [
|
207
|
+
_{ Ref "WebServerSecurityGroup" }
|
208
|
+
]
|
209
|
+
KeyName do
|
210
|
+
Ref "KeyName"
|
211
|
+
end
|
212
|
+
UserData do
|
213
|
+
Fn__Base64 (<<-EOS).fn_join
|
214
|
+
#!/bin/bash -v
|
215
|
+
yum update -y aws-cfn-bootstrap
|
216
|
+
# Helper function
|
217
|
+
function error_exit
|
218
|
+
{
|
219
|
+
/opt/aws/bin/cfn-signal -e 0 -r "$1" '<%= Ref "WaitHandle" %>'
|
220
|
+
exit 1
|
221
|
+
}
|
222
|
+
# Install Apache Web Server, MySQL, PHP and Drupal
|
223
|
+
/opt/aws/bin/cfn-init -s <%= Ref "AWS::StackId" %> -r WebServer --region <%= Ref "AWS::Region" %> || error_exit 'Failed to run cfn-init'
|
224
|
+
# Setup MySQL root password and create a user
|
225
|
+
mysqladmin -u root password '<%= Ref "DBRootPassword" %>' || error_exit 'Failed to initialize root password'
|
226
|
+
mysql -u root --password='<%= Ref "DBRootPassword" %>' < /tmp/setup.mysql || error_exit 'Failed to create database user'
|
227
|
+
# Make changes to Apache Web Server configuration
|
228
|
+
mv /var/www/html/drupal-7.8/* /var/www/html
|
229
|
+
mv /var/www/html/drupal-7.8/.* /var/www/html
|
230
|
+
rmdir /var/www/html/drupal-7.8
|
231
|
+
sed -i 's/AllowOverride None/AllowOverride All/g' /etc/httpd/conf/httpd.conf
|
232
|
+
service httpd restart
|
233
|
+
# Create the site in Drupal
|
234
|
+
cd /var/www/html
|
235
|
+
~ec2-user/drush/drush site-install standard --yes --site-name='<%= Ref "SiteName" %>' --site-mail=<%= Ref "SiteEMail" %> --account-name=<%= Ref "SiteAdmin" %> --account-pass=<%= Ref "SitePassword" %> --db-url=mysql://<%= Ref "DBUsername" %>:<%= Ref "DBPassword" %>@localhost/<%= Ref "DBName" %> --db-prefix=drupal_
|
236
|
+
chown apache:apache sites/default/files
|
237
|
+
# All is well so signal success
|
238
|
+
/opt/aws/bin/cfn-signal -e 0 -r "Drupal setup complete" '<%= Ref "WaitHandle" %>'
|
239
|
+
EOS
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
WaitHandle do
|
244
|
+
Type "AWS::CloudFormation::WaitConditionHandle"
|
245
|
+
end
|
246
|
+
WaitCondition do
|
247
|
+
Type "AWS::CloudFormation::WaitCondition"
|
248
|
+
DependsOn "WebServer"
|
249
|
+
Properties do
|
250
|
+
Handle do
|
251
|
+
Ref "WaitHandle"
|
252
|
+
end
|
253
|
+
Timeout 300
|
254
|
+
end
|
255
|
+
end
|
256
|
+
WebServerSecurityGroup do
|
257
|
+
Type "AWS::EC2::SecurityGroup"
|
258
|
+
Properties do
|
259
|
+
GroupDescription "Enable HTTP access via port 80 and SSH access"
|
260
|
+
SecurityGroupIngress [
|
261
|
+
_{
|
262
|
+
IpProtocol "tcp"
|
263
|
+
FromPort 80
|
264
|
+
ToPort 80
|
265
|
+
CidrIp "0.0.0.0/0"
|
266
|
+
},
|
267
|
+
_{
|
268
|
+
IpProtocol "tcp"
|
269
|
+
FromPort 22
|
270
|
+
ToPort 22
|
271
|
+
CidrIp do
|
272
|
+
Ref "SSHLocation"
|
273
|
+
end
|
274
|
+
}
|
275
|
+
]
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
Outputs do
|
280
|
+
WebsiteURL do
|
281
|
+
Value 'http://<%= Fn__GetAtt "WebServer", "PublicDnsName" %>'.fn_join
|
282
|
+
Description "Drupal Website"
|
283
|
+
end
|
284
|
+
end
|
@@ -621,4 +621,79 @@ end
|
|
621
621
|
}
|
622
622
|
EOS
|
623
623
|
end
|
624
|
+
|
625
|
+
|
626
|
+
it 'convert splitted Ruby template to JSON template' do
|
627
|
+
json_template = nil
|
628
|
+
|
629
|
+
part_of_template = <<-EOS
|
630
|
+
myEC2Instance do
|
631
|
+
Type "AWS::EC2::Instance"
|
632
|
+
Properties do
|
633
|
+
ImageId "ami-XXXXXXXX"
|
634
|
+
InstanceType "t1.micro"
|
635
|
+
end
|
636
|
+
end
|
637
|
+
EOS
|
638
|
+
|
639
|
+
tempfile(part_of_template, '.rb') do |f|
|
640
|
+
template = <<-EOS
|
641
|
+
Resources do
|
642
|
+
_include #{f.path.inspect}
|
643
|
+
end
|
644
|
+
|
645
|
+
Outputs do
|
646
|
+
AZ do
|
647
|
+
Value do
|
648
|
+
Fn__GetAtt "myEC2Instance", "AvailabilityZone"
|
649
|
+
end
|
650
|
+
end
|
651
|
+
end
|
652
|
+
EOS
|
653
|
+
|
654
|
+
json_template = run_client(:convert, :template => template)
|
655
|
+
end
|
656
|
+
|
657
|
+
expect(json_template).to eq((<<-EOS).chomp)
|
658
|
+
{
|
659
|
+
"Resources": {
|
660
|
+
"myEC2Instance": {
|
661
|
+
"Type": "AWS::EC2::Instance",
|
662
|
+
"Properties": {
|
663
|
+
"ImageId": "ami-XXXXXXXX",
|
664
|
+
"InstanceType": "t1.micro"
|
665
|
+
}
|
666
|
+
}
|
667
|
+
},
|
668
|
+
"Outputs": {
|
669
|
+
"AZ": {
|
670
|
+
"Value": {
|
671
|
+
"Fn::GetAtt": [
|
672
|
+
"myEC2Instance",
|
673
|
+
"AvailabilityZone"
|
674
|
+
]
|
675
|
+
}
|
676
|
+
}
|
677
|
+
}
|
678
|
+
}
|
679
|
+
EOS
|
680
|
+
end
|
681
|
+
|
682
|
+
let(:drupal_single_instance_template) do
|
683
|
+
path = File.expand_path('../Drupal_Single_Instance.template', __FILE__)
|
684
|
+
open(path) {|f| f.read }
|
685
|
+
end
|
686
|
+
|
687
|
+
let(:drupal_single_instance_template_rb) do
|
688
|
+
path = File.expand_path('../Drupal_Single_Instance.template.rb', __FILE__)
|
689
|
+
open(path) {|f| f.read }
|
690
|
+
end
|
691
|
+
|
692
|
+
it 'Ruby templates and JSON template should be same' do
|
693
|
+
json_template = JSON.parse(drupal_single_instance_template)
|
694
|
+
ruby_template = run_client(:convert, :template => drupal_single_instance_template_rb)
|
695
|
+
ruby_template = JSON.parse(ruby_template)
|
696
|
+
|
697
|
+
expect(ruby_template).to eq(json_template)
|
698
|
+
end
|
624
699
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
describe 'Kumogata::Client#diff' do
|
2
|
+
let(:drupal_single_instance_template) do
|
3
|
+
path = File.expand_path('../Drupal_Single_Instance.template', __FILE__)
|
4
|
+
open(path) {|f| f.read }
|
5
|
+
end
|
6
|
+
|
7
|
+
let(:drupal_single_instance_template_rb) do
|
8
|
+
path = File.expand_path('../Drupal_Single_Instance.template.rb', __FILE__)
|
9
|
+
open(path) {|f| f.read }
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'compare templates logically' do
|
13
|
+
json_template = drupal_single_instance_template
|
14
|
+
json_template.sub!('localhost', '127.0.0.1')
|
15
|
+
json_template.sub!('"ToPort": "80"', '"ToPort": "8080"')
|
16
|
+
|
17
|
+
tempfile(json_template, '.templates') do |js|
|
18
|
+
tempfile(drupal_single_instance_template_rb, '.rb') do |rb|
|
19
|
+
diff = ruby_template = run_client(:diff, :arguments => [js.path, rb.path], :options => {:color => false})
|
20
|
+
diff = diff.split(/\n/).slice(2..-1).join("\n")
|
21
|
+
|
22
|
+
expect(diff).to eq((<<-EOS).chomp)
|
23
|
+
@@ -257,7 +257,7 @@
|
24
|
+
{
|
25
|
+
"Ref": "DBUsername"
|
26
|
+
},
|
27
|
+
- "'@'127.0.0.1' IDENTIFIED BY '",
|
28
|
+
+ "'@'localhost' IDENTIFIED BY '",
|
29
|
+
{
|
30
|
+
"Ref": "DBPassword"
|
31
|
+
},
|
32
|
+
EOS
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kumogata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Genki Sugawara
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: diffy
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: dslh
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -175,9 +189,12 @@ files:
|
|
175
189
|
- lib/kumogata/version.rb
|
176
190
|
- packer/CentOS-6.4-x86_64-with_Updates-Asia_Pacific.json
|
177
191
|
- packer/Ubuntu-12.04.4-LTS-x86_64-ebs-Asia_Pacific.json
|
192
|
+
- spec/Drupal_Single_Instance.template
|
193
|
+
- spec/Drupal_Single_Instance.template.rb
|
178
194
|
- spec/kumogata_convert_spec.rb
|
179
195
|
- spec/kumogata_create_spec.rb
|
180
196
|
- spec/kumogata_delete_spec.rb
|
197
|
+
- spec/kumogata_diff_spec.rb
|
181
198
|
- spec/kumogata_export_spec.rb
|
182
199
|
- spec/kumogata_list_spec.rb
|
183
200
|
- spec/kumogata_show_outputs_spec.rb
|
@@ -210,9 +227,12 @@ signing_key:
|
|
210
227
|
specification_version: 4
|
211
228
|
summary: A tool for AWS CloudFormation.
|
212
229
|
test_files:
|
230
|
+
- spec/Drupal_Single_Instance.template
|
231
|
+
- spec/Drupal_Single_Instance.template.rb
|
213
232
|
- spec/kumogata_convert_spec.rb
|
214
233
|
- spec/kumogata_create_spec.rb
|
215
234
|
- spec/kumogata_delete_spec.rb
|
235
|
+
- spec/kumogata_diff_spec.rb
|
216
236
|
- spec/kumogata_export_spec.rb
|
217
237
|
- spec/kumogata_list_spec.rb
|
218
238
|
- spec/kumogata_show_outputs_spec.rb
|