kumogata 0.2.6 → 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Gem Version](https://badge.fury.io/rb/kumogata.png?
|
9
|
-
[![Build Status](https://drone.io/github.com/winebarrel/kumogata/status.png?
|
8
|
+
[![Gem Version](https://badge.fury.io/rb/kumogata.png?201403061208)](http://badge.fury.io/rb/kumogata)
|
9
|
+
[![Build Status](https://drone.io/github.com/winebarrel/kumogata/status.png?201403061208)](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
|