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 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