cloudster 2.17.0 → 2.18.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.17.0
1
+ 2.18.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "cloudster"
8
- s.version = "2.17.0"
8
+ s.version = "2.18.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Emil Soman"]
12
- s.date = "2013-01-07"
12
+ s.date = "2013-01-08"
13
13
  s.description = "Cloudster is a Ruby gem that was born to cut the learning curve involved \n in writing your own CloudFormation templates. If you don't know what a CloudFormation template is, \n but know about the AWS Cloud offerings, you can still use cloudster to provision your stack. \n Still in infancy , cloudster can create a very basic stack like a breeze. All kinds of contribution welcome !"
14
14
  s.email = "emil.soman@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -37,15 +37,18 @@ Gem::Specification.new do |s|
37
37
  "lib/cloudster/elasticache.rb",
38
38
  "lib/cloudster/elb.rb",
39
39
  "lib/cloudster/options_manager.rb",
40
+ "lib/cloudster/output.rb",
40
41
  "lib/cloudster/rds.rb",
41
42
  "lib/cloudster/s3.rb",
42
43
  "spec/chef_client_spec.rb",
43
44
  "spec/cloud_front_spec.rb",
44
45
  "spec/cloud_spec.rb",
46
+ "spec/deep_merge_spec.rb",
45
47
  "spec/ec2_spec.rb",
46
48
  "spec/elastic_ip_spec.rb",
47
49
  "spec/elasticache_spec.rb",
48
50
  "spec/elb_spec.rb",
51
+ "spec/output_spec.rb",
49
52
  "spec/rds_spec.rb",
50
53
  "spec/s3_spec.rb",
51
54
  "spec/spec_helper.rb"
@@ -2,6 +2,7 @@
2
2
  #This file requires all dependencies
3
3
  require 'json'
4
4
  require 'fog'
5
+ require 'cloudster/output'
5
6
  require 'cloudster/options_manager'
6
7
  require 'cloudster/deep_merge'
7
8
  include OptionsManager
@@ -59,14 +59,17 @@ module Cloudster
59
59
  resources = options[:resources]
60
60
  description = options[:description] || 'This stack is created by Cloudster'
61
61
  resource_template = {}
62
+ output_template = {}
62
63
  resources.each do |resource|
63
64
  resource_template.merge!(resource.template['Resources'])
65
+ output_template.merge!(resource.template['Outputs']) unless resource.template['Outputs'].nil?
64
66
  end
65
67
 
66
68
  cloud_template = {'AWSTemplateFormatVersion' => '2010-09-09',
67
- 'Description' => description,
68
- 'Resources' => resource_template
69
+ 'Description' => description
69
70
  }
71
+ cloud_template['Resources'] = resource_template if !resource_template.empty?
72
+ cloud_template['Outputs'] = output_template if !output_template.empty?
70
73
  return cloud_template.to_json
71
74
  end
72
75
 
@@ -257,7 +260,7 @@ module Cloudster
257
260
  ec2_resource_ids.each do |key, value|
258
261
  ec2_instance_details = ec2.describe_instances('instance-id' => value)
259
262
  ec2_details[key] = ec2_instance_details.body["reservationSet"][0]["instancesSet"][0] rescue nil
260
- end
263
+ end
261
264
  return ec2_details
262
265
  end
263
266
 
@@ -1,4 +1,4 @@
1
- # Stolen shamelessly from here http://apidock.com/rails/Hash/deep_merge!
1
+ # Stolen shamelessly from Rails : http://apidock.com/rails/Hash/deep_merge!
2
2
  class Hash
3
3
  def deep_merge(other_hash)
4
4
  other_hash.each_pair do |k,v|
@@ -6,4 +6,9 @@ module OptionsManager
6
6
  end
7
7
  raise ArgumentError, "Missing required argument: #{missing_args.join(',')}" unless missing_args.empty?
8
8
  end
9
+
10
+ def validate_option_in_list(option, list)
11
+ raise ArgumentError, "Option: #{option} should be one of #{list.inspect}" unless list.include?(option)
12
+ end
13
+
9
14
  end
@@ -0,0 +1,17 @@
1
+ module Cloudster
2
+ module Output
3
+ # Returns the Output template for resources
4
+ #
5
+ # ==== Parameters
6
+ # * output: Hash containing the valid outputs and their cloudformation translations
7
+ def output_template(outputs)
8
+ resource_name = outputs.keys[0]
9
+ outputs_array = outputs.values[0].collect
10
+ each_output_join = outputs_array.collect {|output| {"Fn::Join" => [":", output]}}
11
+ return resource_name => {
12
+ 'Value' => { "Fn::Join" => [ ",", each_output_join] }
13
+ }
14
+ end
15
+
16
+ end
17
+ end
@@ -1,6 +1,8 @@
1
1
  module Cloudster
2
2
  #S3 Resource
3
+ #Output values : bucket_name, dns_name, website_url
3
4
  class S3
5
+ extend Cloudster::Output
4
6
 
5
7
  attr_accessor :name, :template
6
8
  # Initialize a s3 bucket
@@ -38,7 +40,12 @@ module Cloudster
38
40
  # ==== Returns
39
41
  # * Ruby hash version of the Cloud Formation template for the s3 resource
40
42
  def template
41
- @template ||= S3.template({:name => @name, :access_control => @access_control, :website_configuration => @website_configuration})
43
+ @template ||= S3.template({
44
+ :name => @name,
45
+ :access_control => @access_control,
46
+ :website_configuration => @website_configuration,
47
+ :outputs => @outputs
48
+ })
42
49
  end
43
50
 
44
51
  # Class method that returns a Ruby hash version of the Cloud Formation template
@@ -63,13 +70,22 @@ module Cloudster
63
70
  unless options[:website_configuration].nil?
64
71
  properties.merge!({"WebsiteConfiguration" => {"IndexDocument" => options[:website_configuration]["index_document"], "ErrorDocument" => options[:website_configuration]["error_document"]}})
65
72
  end
66
- template = {'Resources' => {
67
- options[:name] => {
68
- 'Type' => 'AWS::S3::Bucket',
69
- 'Properties' => properties
70
- }
71
- }
73
+ outputs = {
74
+ options[:name] => {
75
+ 'bucket_name' => { 'Ref' => options[:name] },
76
+ 'dns_name' => {'Fn::GetAtt' => [options[:name], 'DomainName']},
77
+ 'website_url' => {'Fn::GetAtt' => [options[:name], 'WebsiteURL']}
78
+ }
72
79
  }
80
+ template = {
81
+ 'Resources' => {
82
+ options[:name] => {
83
+ 'Type' => 'AWS::S3::Bucket',
84
+ 'Properties' => properties
85
+ }
86
+ }
87
+ }
88
+ template['Outputs'] = output_template(outputs)
73
89
  return template
74
90
  end
75
91
  end
@@ -33,6 +33,19 @@ describe Cloudster::ChefClient do
33
33
  "Enabled"=>"true"
34
34
  }
35
35
  }
36
+ },
37
+ },
38
+ "Outputs" => {
39
+ "S3ResourceName"=>{
40
+ "Value"=>{
41
+ "Fn::Join"=>[",",
42
+ [
43
+ {"Fn::Join"=>[":", ["bucket_name", {"Ref"=>"S3ResourceName"}]]},
44
+ {"Fn::Join"=>[":", ["dns_name", {"Fn::GetAtt"=>["S3ResourceName", "DomainName"]}]]},
45
+ {"Fn::Join"=>[":", ["website_url", {"Fn::GetAtt"=>["S3ResourceName", "WebsiteURL"]}]]}
46
+ ]
47
+ ]
48
+ }
36
49
  }
37
50
  }
38
51
  }
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Hash" do
4
+ describe "#deep_merge" do
5
+ it "should do a deep merge for new keys and deep override for existing keys" do
6
+ hash1 = {
7
+ 'key1' => 'value1',
8
+ 'key2' => {
9
+ 'inner_key1' =>'inner_value1',
10
+ 'inner_key2' =>'inner_value2'
11
+ }
12
+ }
13
+ hash2 = {
14
+ 'key_to_merge' => 'value_to_merge',
15
+ 'key2' => {
16
+ 'inner_key_to_be_merged' =>'inner_value_to_be_merged',
17
+ 'inner_key2' =>'inner_value_to_override'
18
+ }
19
+ }
20
+ hash1.deep_merge(hash2).should == {
21
+ "key1"=>"value1",
22
+ "key2"=>{
23
+ "inner_key1"=>"inner_value1",
24
+ "inner_key2"=>"inner_value_to_override",
25
+ "inner_key_to_be_merged"=>"inner_value_to_be_merged"
26
+ },
27
+ "key_to_merge"=>"value_to_merge"
28
+ }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cloudster::Output do
4
+ describe "output_template" do
5
+ it "should return the cloudformation template for the Outputs" do
6
+ resource_name = "S3ResourceName"
7
+ outputs = {
8
+ resource_name => {
9
+ 'bucket_name' => {"Ref" => resource_name },
10
+ 'dns_name' => {'Fn::GetAtt' => [resource_name, 'DomainName']}
11
+ }
12
+ }
13
+ class Resource;end
14
+ Resource.extend(Cloudster::Output)
15
+ Resource.output_template(outputs).should == {
16
+ resource_name => {
17
+ "Value" => {
18
+ "Fn::Join" => [ ",",[
19
+ {"Fn::Join" => [":", ['bucket_name', {"Ref" => resource_name } ] ]},
20
+ {"Fn::Join" => [":", ['dns_name', {'Fn::GetAtt' => [resource_name, 'DomainName']} ] ]}
21
+ ]]
22
+ }
23
+ }
24
+ }
25
+ end
26
+ end
27
+ end
@@ -13,11 +13,17 @@ describe Cloudster::S3 do
13
13
  describe '#template' do
14
14
  it "should return a ruby hash for the resource cloudformation template with only mandatory fields" do
15
15
  s3 = Cloudster::S3.new(:name => 'bucket_name')
16
- s3.template.should == {'Resources' => {'bucket_name' => {'Type' => 'AWS::S3::Bucket', 'Properties' => {}}}}
16
+ s3.template.should == {
17
+ 'Resources' => {'bucket_name' => {'Type' => 'AWS::S3::Bucket', 'Properties' => {}}},
18
+ "Outputs" => {"bucket_name"=>{"Value"=>{"Fn::Join"=>[",", [{"Fn::Join"=>[":", ["bucket_name", {"Ref"=>"bucket_name"}]]}, {"Fn::Join"=>[":", ["dns_name", {"Fn::GetAtt"=>["bucket_name", "DomainName"]}]]}, {"Fn::Join"=>[":", ["website_url", {"Fn::GetAtt"=>["bucket_name", "WebsiteURL"]}]]}]]}}}
19
+ }
17
20
  end
18
21
  it "should return a ruby hash for the resource cloudformation template" do
19
22
  s3 = Cloudster::S3.new(:name => 'bucket_name', :access_control => "PublicRead", :website_configuration => {"index_document" => "index.html", "error_document" => "error.html"} )
20
- s3.template.should == {'Resources' => {'bucket_name' => {'Type' => 'AWS::S3::Bucket', 'Properties' => {"AccessControl" => "PublicRead", "WebsiteConfiguration" => { "IndexDocument" => "index.html", "ErrorDocument" => "error.html" } }}}}
23
+ s3.template.should == {
24
+ 'Resources' => {'bucket_name' => {'Type' => 'AWS::S3::Bucket', 'Properties' => {"AccessControl" => "PublicRead", "WebsiteConfiguration" => { "IndexDocument" => "index.html", "ErrorDocument" => "error.html" } }}},
25
+ "Outputs" => {"bucket_name"=>{"Value"=>{"Fn::Join"=>[",", [{"Fn::Join"=>[":", ["bucket_name", {"Ref"=>"bucket_name"}]]}, {"Fn::Join"=>[":", ["dns_name", {"Fn::GetAtt"=>["bucket_name", "DomainName"]}]]}, {"Fn::Join"=>[":", ["website_url", {"Fn::GetAtt"=>["bucket_name", "WebsiteURL"]}]]}]]}}}
26
+ }
21
27
  end
22
28
  end
23
29
 
@@ -27,7 +33,10 @@ describe Cloudster::S3 do
27
33
  end
28
34
  it "should return a ruby hash for the resource cloudformation template" do
29
35
  hash = Cloudster::S3.template(:name => 'bucket_name', :access_control => "PublicRead", :website_configuration => {"index_document" => "index.html", "error_document" => "error.html"} )
30
- hash.should == {'Resources' => {'bucket_name' => {'Type' => 'AWS::S3::Bucket', 'Properties' => {"AccessControl" => "PublicRead", "WebsiteConfiguration" => { "IndexDocument" => "index.html", "ErrorDocument" => "error.html" } }}}}
36
+ hash.should == {
37
+ 'Resources' => {'bucket_name' => {'Type' => 'AWS::S3::Bucket', 'Properties' => {"AccessControl" => "PublicRead", "WebsiteConfiguration" => { "IndexDocument" => "index.html", "ErrorDocument" => "error.html" } }}},
38
+ "Outputs" => {"bucket_name"=>{"Value"=>{"Fn::Join"=>[",", [{"Fn::Join"=>[":", ["bucket_name", {"Ref"=>"bucket_name"}]]}, {"Fn::Join"=>[":", ["dns_name", {"Fn::GetAtt"=>["bucket_name", "DomainName"]}]]}, {"Fn::Join"=>[":", ["website_url", {"Fn::GetAtt"=>["bucket_name", "WebsiteURL"]}]]}]]}}}
39
+ }
31
40
  end
32
41
  end
33
42
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudster
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.17.0
4
+ version: 2.18.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-07 00:00:00.000000000 Z
12
+ date: 2013-01-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog
@@ -139,15 +139,18 @@ files:
139
139
  - lib/cloudster/elasticache.rb
140
140
  - lib/cloudster/elb.rb
141
141
  - lib/cloudster/options_manager.rb
142
+ - lib/cloudster/output.rb
142
143
  - lib/cloudster/rds.rb
143
144
  - lib/cloudster/s3.rb
144
145
  - spec/chef_client_spec.rb
145
146
  - spec/cloud_front_spec.rb
146
147
  - spec/cloud_spec.rb
148
+ - spec/deep_merge_spec.rb
147
149
  - spec/ec2_spec.rb
148
150
  - spec/elastic_ip_spec.rb
149
151
  - spec/elasticache_spec.rb
150
152
  - spec/elb_spec.rb
153
+ - spec/output_spec.rb
151
154
  - spec/rds_spec.rb
152
155
  - spec/s3_spec.rb
153
156
  - spec/spec_helper.rb
@@ -166,7 +169,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
166
169
  version: '0'
167
170
  segments:
168
171
  - 0
169
- hash: 500109
172
+ hash: 571049873
170
173
  required_rubygems_version: !ruby/object:Gem::Requirement
171
174
  none: false
172
175
  requirements: