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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b31c25198207adf1d56654843c7529fbd62f2ff6
4
- data.tar.gz: 7510a7e9a89a775a3869ab3d850f6ecaeb35a0e8
3
+ metadata.gz: db9de5e733c5ce3dbfb6cdcf818f7c6c8402f2e5
4
+ data.tar.gz: f6b43da8e971a28382d02450dc0666d50dfb270a
5
5
  SHA512:
6
- metadata.gz: a1bc043a32b8d8ab4d9439e56190d3ecbac5246c67a0f5c95996d585d8365d6b0553e265f517f94428241888fa441ec09eed28bc3be4caef07516a96dbca5cff
7
- data.tar.gz: 4fef527beb218337ff205adf84aa5ff149b3b2c41d3d13ef6e4b961210a1c510c362b37a9f062ce299f35c9cee388e2a074b6986e4c06f77ca9d9ea0bcbf9a01
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?201403061015)](http://badge.fury.io/rb/kumogata)
9
- [![Build Status](https://drone.io/github.com/winebarrel/kumogata/status.png?201403061015)](https://drone.io/github.com/winebarrel/kumogata/latest)
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] 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
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
 
@@ -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)
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'aws-sdk'
22
+ spec.add_dependency 'diffy'
22
23
  spec.add_dependency 'dslh', '>= 0.2.3'
23
24
  spec.add_dependency 'hashie'
24
25
  spec.add_dependency 'highline'
@@ -3,6 +3,7 @@ require 'kumogata/version'
3
3
 
4
4
  require 'aws-sdk'
5
5
  require 'base64'
6
+ require 'diffy'
6
7
  require 'dslh'
7
8
  require 'hashie'
8
9
  require 'highline/import'
@@ -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!
@@ -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
- gsub(/^[ \t]{,#{min_space_num}}/, '')
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 = {})
@@ -1,3 +1,3 @@
1
1
  module Kumogata
2
- VERSION = '0.2.6'
2
+ VERSION = '0.2.7'
3
3
  end
@@ -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.6
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