clouds 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +97 -0
- data/bin/clouds +162 -0
- data/clouds.rdoc +5 -0
- data/lib/clouds/version.rb +3 -0
- data/lib/clouds.rb +227 -0
- metadata +188 -0
data/README.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# clouds
|
2
|
+
|
3
|
+
This is a simple tool that aims to ease the handling of [AWS CloudFormation](https://aws.amazon.com/cloudformation/) stacks, following the [infrastructure as code](http://sdarchitect.wordpress.com/2012/12/13/infrastructure-as-code/) philosophy in ways that are not possible with the AWS console. Even though you can achieve pretty much the same using the AWS command line tools, `clouds` aims to be much easier to use, cleaner and more specialized in handling CloudFormation stacks as code.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
- Upload templates and parameters from the current directory into AWS with a single intuitive command. They need to be located in stacks/stack_name/{template.json,parameters.yaml}
|
7
|
+
- List existing stacks defined in AWS and also those only defined locally
|
8
|
+
- Dump one or all of the stacks from your currently selected AWS account into the current directory (preferably stored in a version control system) under the 'stacks' directory, including both the template JSON code and the parameters that were used for launching it, which will then be saved in a human-friendly YAML file.
|
9
|
+
- Perform updates on the AWS stacks once you modified the dumped data (template or parameters)
|
10
|
+
- Validate templates for JSON correctness when uploading or updating a stack. The error messages should help you debug syntax errors.
|
11
|
+
- Clone existing stacks to create new ones. It defaults to local clone, which then needs another update call to get in effect. This is an easy way to migrate infrastructure code and later to promote changes between environments, and can also be used easily with projects running in different AWS accounts, especially if using a simple AWS profile switcher shell alias like implemented on oh-my-zsh.
|
12
|
+
- Perform cost calculations when creating a new stack.
|
13
|
+
- Delete existing stacks with a simple command
|
14
|
+
- For authentication it can use AWS account credentials defined using either the AWS_ACCESS_KEY_ID&AWS_SECRET_ACCESS_KEY combination, or the AWS_DEFAULT_PROFILE environment variables
|
15
|
+
- Able to use temporary credentials, if the AWS_SECURITY_TOKEN variable is defined in the environment.
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
gem install clouds
|
20
|
+
|
21
|
+
or using a [bundler](http://bundler.io/) Gemfile:
|
22
|
+
|
23
|
+
gem 'clouds'
|
24
|
+
|
25
|
+
Note: On systems running Ruby 1.8.x such as RHEL5 and clones, you need to be aware of the incompatibility between the more recent versions of `nokogiri`(a dependency of the `aws-sdk`, that `clouds` indirectly depends on) and Ruby 1.8. This is pretty well-documented [here](http://ruby.awsblog.com/post/Tx2T9MFQJK7U74N/AWS-SDK-for-Ruby-and-Nokogiri). **You will need to manually install the latest compatible version of nokogiri and the AWS SDK for Ruby as documented on that page.**
|
26
|
+
|
27
|
+
## Running
|
28
|
+
Execute this in your shell:
|
29
|
+
|
30
|
+
clouds -h
|
31
|
+
|
32
|
+
In order to do real stuff you need a profile to be defined in .aws/config for the aws command line tool, and to have it referenced by the AWS_DEFAULT_PROFILE environment variable. The AWS_ACCESS_KEY_ID&AWS_SECRET_ACCESS_KEY combination are also supported. You can also use temporary credentials, if the AWS_SECURITY_TOKEN variable is properly defined in the environment when using the temporary access key and secret.
|
33
|
+
|
34
|
+
export AWS_DEFAULT_PROFILE=my_aws_profile
|
35
|
+
or
|
36
|
+
|
37
|
+
export AWS_ACCESS_KEY_ID=my_key_id
|
38
|
+
export AWS_SECRET_ACCESS_KEY=my_key_secret
|
39
|
+
|
40
|
+
The oh-my-zsh users can also use the `asp` command implemented in the [AWS zsh plugin](https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins#aws), which makes it very easy to switch between different profiles defined in .aws/config.
|
41
|
+
|
42
|
+
## Use cases
|
43
|
+
|
44
|
+
Dump all the stacks from your account into the current directory
|
45
|
+
|
46
|
+
clouds dump --all
|
47
|
+
|
48
|
+
Once you edit a stack source code, this command would update it on AWS
|
49
|
+
|
50
|
+
clouds update stack_name
|
51
|
+
|
52
|
+
Clone a stack (locally only, so you can perform some changes)
|
53
|
+
|
54
|
+
clouds clone stack new_stack
|
55
|
+
|
56
|
+
Upload the cloned stack to AWS CloudFormation
|
57
|
+
|
58
|
+
clouds update new_stack -c
|
59
|
+
|
60
|
+
Delete the new stack (needs --force)
|
61
|
+
|
62
|
+
clouds delete new_stack
|
63
|
+
|
64
|
+
|
65
|
+
## Development
|
66
|
+
|
67
|
+
### Build requirements
|
68
|
+
- Ruby, rubygems and rake (some might already be there on Ruby > 1.9)
|
69
|
+
- Development headers for libxml2 and libxslt (-devel packages)
|
70
|
+
- Bundler
|
71
|
+
|
72
|
+
gem install bundler
|
73
|
+
|
74
|
+
### Install dependencies
|
75
|
+
Only in case you didn't do it before
|
76
|
+
|
77
|
+
bundle install
|
78
|
+
|
79
|
+
### Running for development
|
80
|
+
|
81
|
+
bundle exec bin/clouds
|
82
|
+
|
83
|
+
### Updating the installed gem
|
84
|
+
|
85
|
+
rake repackage
|
86
|
+
sudo gem install pkg/clouds-0.1.0.gem
|
87
|
+
|
88
|
+
### Build instructions
|
89
|
+
|
90
|
+
Simply run (once you have the stated requirements satisfied)
|
91
|
+
|
92
|
+
rake package
|
93
|
+
|
94
|
+
### Installing your own gem
|
95
|
+
|
96
|
+
sudo gem install pkg/clouds-0.1.0.gem
|
97
|
+
|
data/bin/clouds
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# For development, you need to use `bundle exec bin/clouds` to run this code
|
3
|
+
# At install-time, RubyGems will make sure the lib, etc. are in the load path
|
4
|
+
|
5
|
+
require 'gli'
|
6
|
+
require 'clouds'
|
7
|
+
|
8
|
+
include GLI::App
|
9
|
+
|
10
|
+
program_desc 'Tool that eases handling of AWS Cloudformation stacks as code'
|
11
|
+
|
12
|
+
version Clouds::VERSION
|
13
|
+
|
14
|
+
desc 'Dry run, nothing would be done NOT IMPLEMENTED YET'
|
15
|
+
switch [:d,:dry], :negatable => false
|
16
|
+
|
17
|
+
|
18
|
+
desc 'Force overwrites of existing data'
|
19
|
+
switch [:f,:force], :negatable => false
|
20
|
+
|
21
|
+
desc 'List CloudFormation stacks from your account'
|
22
|
+
arg_name 'Arguments to list'
|
23
|
+
command :list do |c|
|
24
|
+
|
25
|
+
c.desc 'List all the stacks available within your account'
|
26
|
+
|
27
|
+
c.action do |global_options,options,args|
|
28
|
+
|
29
|
+
raise 'This command takes no arguments.' unless args.empty?
|
30
|
+
list_stacks()
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc 'Dump CloudFormation stacks from your account into the current directory'
|
35
|
+
arg_name 'Arguments to dump'
|
36
|
+
command :dump do |c|
|
37
|
+
|
38
|
+
c.desc 'Dump all the stacks available within your account into the current directory'
|
39
|
+
c.switch [:a,:all], :negatable => false
|
40
|
+
c.desc 'Force overwrites of existing data'
|
41
|
+
c.switch [:f,:force], :negatable => false
|
42
|
+
|
43
|
+
c.action do |global_options,options,args|
|
44
|
+
if args.empty? && options[:all]
|
45
|
+
puts 'dumping all stacks'
|
46
|
+
dump_all_stacks(global_options[:force] || options[:force])
|
47
|
+
elsif args.length >= 1
|
48
|
+
puts "dumping the following stacks: #{args.inspect}"
|
49
|
+
dump_stacks(args, global_options[:force] || options[:force])
|
50
|
+
else # no arguments and --all flag
|
51
|
+
raise 'This command needs a list of stacks, or the --all flag in order to dump all the stacks.'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'Edit a CloudFormation stack locally'
|
57
|
+
arg_name 'Arguments to edit'
|
58
|
+
command :edit do |c|
|
59
|
+
|
60
|
+
c.desc 'Force overwrites of existing data'
|
61
|
+
c.switch [:p,:parameters], :negatable => false
|
62
|
+
c.switch [:t,:template], :negatable => false
|
63
|
+
|
64
|
+
c.action do |global_options,options,args|
|
65
|
+
if args.length == 1
|
66
|
+
stack = args[0]
|
67
|
+
if options[:parameters]
|
68
|
+
puts 'editing parameters'
|
69
|
+
system("#{ENV['EDITOR']} #{get_parameters_path(stack)}")
|
70
|
+
elsif options[:template]
|
71
|
+
puts 'editing template'
|
72
|
+
system("#{ENV['EDITOR']} #{get_template_path(stack)}")
|
73
|
+
else
|
74
|
+
puts options.inspect
|
75
|
+
puts 'editing both the template and the parameters'
|
76
|
+
system("#{ENV['EDITOR']} #{get_template_path(stack)} #{get_parameters_path(stack)}")
|
77
|
+
end
|
78
|
+
else
|
79
|
+
raise 'This command needs a single stack as an argument.'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
desc 'Clones an existing stack into a new one'
|
86
|
+
arg_name 'Arguments: stack new_stack'
|
87
|
+
command :clone do |c|
|
88
|
+
c.desc 'Force overwrites of existing data'
|
89
|
+
c.switch [:f,:force], :negatable => false
|
90
|
+
|
91
|
+
c.desc 'Commit changes to AWS, otherwise just copy the stack locally'
|
92
|
+
c.switch [:c,:commit], :negatable => false
|
93
|
+
|
94
|
+
c.action do |global_options,options,args|
|
95
|
+
if args.length == 2
|
96
|
+
clone_stack(args.first, args.last, global_options[:force] || options[:force], options['commit'])
|
97
|
+
else
|
98
|
+
raise 'Needed arguments: source_stack destination_stack'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
desc 'Updated a list of CloudFormation stacks based on information from the current directory'
|
104
|
+
arg_name 'Arguments to update'
|
105
|
+
command :update do |c|
|
106
|
+
|
107
|
+
c.desc 'Update all the stacks within the current directory'
|
108
|
+
c.switch [:a,:all], :negatable => false
|
109
|
+
c.desc 'Create AWS stacks if the required sources exist locally'
|
110
|
+
c.switch [:c,:create_missing], :negatable => false
|
111
|
+
|
112
|
+
c.action do |global_options,options,args|
|
113
|
+
if args.empty? && options[:all]
|
114
|
+
puts 'dumping all stacks'
|
115
|
+
update_all_stacks(options[:create_missing])
|
116
|
+
elsif args.length >= 1
|
117
|
+
puts "updating the following stacks: #{args.inspect}"
|
118
|
+
update_stacks(args,options[:create_missing])
|
119
|
+
else # no arguments and --all flag
|
120
|
+
raise 'This command needs a list of stacks, or the --all flag in order to update all the stacks.'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
#TODO: support deletion of multiple stacks, and of all stacks.
|
126
|
+
desc 'Deletes a stack'
|
127
|
+
arg_name 'Arguments: stack'
|
128
|
+
command :delete do |c|
|
129
|
+
c.desc 'Force deletion of the running stack'
|
130
|
+
c.switch [:f,:force], :negatable => false
|
131
|
+
c.action do |global_options,options,args|
|
132
|
+
raise "This command might impact running environments and it needs the --force flag, hopefully you know what you are doing" unless global_options[:force] || options[:force]
|
133
|
+
if args.length == 1
|
134
|
+
delete_stack(args.first)
|
135
|
+
else
|
136
|
+
raise 'Needed arguments: stack'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
pre do |global,command,options,args|
|
142
|
+
# Pre logic here
|
143
|
+
# Return true to proceed; false to abort and not call the
|
144
|
+
# chosen command
|
145
|
+
# Use skips_pre before a command to skip this block
|
146
|
+
# on that command only
|
147
|
+
true
|
148
|
+
end
|
149
|
+
|
150
|
+
post do |global,command,options,args|
|
151
|
+
# Post logic here
|
152
|
+
# Use skips_post before a command to skip this
|
153
|
+
# block on that command only
|
154
|
+
end
|
155
|
+
|
156
|
+
on_error do |exception|
|
157
|
+
# Error logic here
|
158
|
+
# return false to skip default error handling
|
159
|
+
true
|
160
|
+
end
|
161
|
+
|
162
|
+
exit run(ARGV)
|
data/clouds.rdoc
ADDED
data/lib/clouds.rb
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'clouds/version.rb'
|
2
|
+
|
3
|
+
require 'aws-sdk'
|
4
|
+
|
5
|
+
require 'inifile'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
def configure(profile=nil)
|
10
|
+
if profile.nil? && ENV['AWS_ACCESS_KEY_ID'] && ENV['AWS_SECRET_ACCESS_KEY']
|
11
|
+
@aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
|
12
|
+
@aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
|
13
|
+
@aws_session_token = ENV['AWS_SECURITY_TOKEN']
|
14
|
+
@region = ENV['AWS_DEFAULT_REGION'] || 'us-east-1'
|
15
|
+
else
|
16
|
+
profile = profile || ENV['AWS_DEFAULT_PROFILE']
|
17
|
+
aws_config_file = File.join(File.expand_path('~'), '.aws', 'config')
|
18
|
+
|
19
|
+
if profile.nil?
|
20
|
+
profile = "default"
|
21
|
+
puts "Using the default profile"
|
22
|
+
else
|
23
|
+
profile = "profile #{profile}"
|
24
|
+
puts "Using the profile '#{profile}'"
|
25
|
+
end
|
26
|
+
aws_config = IniFile.load(aws_config_file)[profile]
|
27
|
+
|
28
|
+
@aws_access_key_id = aws_config['aws_access_key_id']
|
29
|
+
@aws_secret_access_key = aws_config['aws_secret_access_key']
|
30
|
+
@region = aws_config['region']
|
31
|
+
end
|
32
|
+
|
33
|
+
proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
34
|
+
|
35
|
+
AWS.config({:access_key_id => @aws_access_key_id,
|
36
|
+
:secret_access_key => @aws_secret_access_key,
|
37
|
+
:session_token => @aws_session_token,
|
38
|
+
:region => @region,
|
39
|
+
:proxy_uri => proxy,
|
40
|
+
})
|
41
|
+
|
42
|
+
@cfn = AWS::CloudFormation.new
|
43
|
+
end
|
44
|
+
|
45
|
+
def write_file(file_name, content, force)
|
46
|
+
puts "Creating #{file_name}"
|
47
|
+
if File.exist?(file_name) and force == false
|
48
|
+
raise 'The file already exists, use --force to override'
|
49
|
+
end
|
50
|
+
File.open(file_name, 'w') {|f| f.write(content)}
|
51
|
+
puts "Created #{file_name}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def read_file(file_name)
|
55
|
+
begin
|
56
|
+
File.open(file_name,'rb').read
|
57
|
+
rescue => e
|
58
|
+
puts e
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_stack_directory(stack_name)
|
63
|
+
File.join(File.expand_path('.'),'stacks', stack_name)
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_stack_directory(stack_name)
|
67
|
+
FileUtils.mkdir_p(get_stack_directory(stack_name))
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def get_template_path(stack_name)
|
72
|
+
File.join(get_stack_directory(stack_name), 'template.json')
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_parameters_path(stack_name)
|
76
|
+
File.join(get_stack_directory(stack_name), 'parameters.yaml')
|
77
|
+
end
|
78
|
+
|
79
|
+
def list_stacks()
|
80
|
+
configure()
|
81
|
+
max_stack_length = 0
|
82
|
+
stacks = Hash.new()
|
83
|
+
|
84
|
+
local_stacks = list_local_stacks()
|
85
|
+
local_stacks.each do |s|
|
86
|
+
max_stack_length = s.length if s.length > max_stack_length
|
87
|
+
stacks[s] = 'LOCAL-ONLY'
|
88
|
+
end
|
89
|
+
|
90
|
+
begin
|
91
|
+
@cfn.stacks.each do |stack|
|
92
|
+
stacks[stack.name] = stack.status
|
93
|
+
max_stack_length = stack.name.length if stack.name.length > max_stack_length
|
94
|
+
end
|
95
|
+
rescue => e
|
96
|
+
puts e
|
97
|
+
end
|
98
|
+
puts 'Stack list and stack status:'
|
99
|
+
stacks.keys.sort.each do |key|
|
100
|
+
printf("%#{max_stack_length}s %s\n",key, stacks[key])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def list_local_stacks()
|
105
|
+
list = []
|
106
|
+
return [] unless File.directory?('stacks')
|
107
|
+
Dir.foreach('stacks') do |item|
|
108
|
+
next if item == '.' or item == '..'
|
109
|
+
list << item
|
110
|
+
end
|
111
|
+
list
|
112
|
+
end
|
113
|
+
|
114
|
+
def dump_stacks(stack_list, force=false)
|
115
|
+
stack_list.each do |stack_name|
|
116
|
+
configure()
|
117
|
+
begin
|
118
|
+
stack = @cfn.stacks[stack_name]
|
119
|
+
puts "Dumping stack #{stack.name}"
|
120
|
+
|
121
|
+
template_content = stack.template
|
122
|
+
parameters = stack.parameters
|
123
|
+
create_stack_directory(stack_name)
|
124
|
+
write_file(get_template_path(stack_name), template_content, force)
|
125
|
+
write_file(get_parameters_path(stack_name), parameters.to_yaml, force)
|
126
|
+
rescue => e
|
127
|
+
puts "dump failed: #{e}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def dump_all_stacks(force=false)
|
133
|
+
configure()
|
134
|
+
begin
|
135
|
+
@cfn.stacks.each do |stack|
|
136
|
+
dump_stacks([stack.name],force)
|
137
|
+
end
|
138
|
+
rescue => e
|
139
|
+
puts e
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def update_stack(stack_name, create_if_missing=false)
|
144
|
+
configure()
|
145
|
+
stack=nil
|
146
|
+
|
147
|
+
template_content = read_file(get_template_path(stack_name))
|
148
|
+
parameters_content = read_file(get_parameters_path(stack_name))
|
149
|
+
|
150
|
+
begin
|
151
|
+
parameters_hash = YAML.load(parameters_content)
|
152
|
+
rescue => e
|
153
|
+
puts e
|
154
|
+
raise e
|
155
|
+
end
|
156
|
+
|
157
|
+
raise 'Empty stack template' if template_content.nil? || template_content.empty?
|
158
|
+
|
159
|
+
template_validation = @cfn.validate_template(template_content)
|
160
|
+
raise template_validation[:message] unless template_validation[:message].nil?
|
161
|
+
|
162
|
+
begin
|
163
|
+
if @cfn.stacks[stack_name].exists?
|
164
|
+
puts "Updating stack #{stack_name}"
|
165
|
+
stack = @cfn.stacks[stack_name]
|
166
|
+
stack_capabilities = stack.capabilities
|
167
|
+
stack.update(:template => template_content,
|
168
|
+
:parameters => parameters_hash,
|
169
|
+
:capabilities => stack_capabilities)
|
170
|
+
elsif create_if_missing
|
171
|
+
puts "Creating stack #{stack_name}"
|
172
|
+
stack = @cfn.stacks.create(stack_name,
|
173
|
+
template_content,
|
174
|
+
{ :parameters => parameters_hash,
|
175
|
+
:capabilities => ['CAPABILITY_IAM']})
|
176
|
+
else
|
177
|
+
puts "Skipping stack #{stack_name} since it's not defined in this AWS account, if the stack exists locally you might use the -c flag"
|
178
|
+
end
|
179
|
+
unless stack.nil?
|
180
|
+
estimated_cost = stack.estimate_template_cost()
|
181
|
+
puts "Estimated costs for the stack #{stack_name} is #{estimated_cost}"
|
182
|
+
end
|
183
|
+
rescue => e
|
184
|
+
puts e
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def update_stacks(stack_list, create_if_missing=false)
|
189
|
+
stack_list.each do |stack|
|
190
|
+
update_stack(stack, create_if_missing)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def update_all_stacks()
|
195
|
+
Dir.foreach('stacks') do |stack|
|
196
|
+
next if item == '.' or item == '..'
|
197
|
+
update_stack(stack)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
def clone_stack(stack, new_stack, force=false, commit=false)
|
203
|
+
if File.exist?(get_stack_directory(new_stack)) and force == false
|
204
|
+
raise 'The stack already exists, use --force to override'
|
205
|
+
elsif force == true
|
206
|
+
FileUtils.rm_rf(get_stack_directory(new_stack))
|
207
|
+
end
|
208
|
+
FileUtils.cp_r(get_stack_directory(stack), get_stack_directory(new_stack))
|
209
|
+
if commit
|
210
|
+
puts 'Committing changes to AWS'
|
211
|
+
update_stack(new_stack, true)
|
212
|
+
else
|
213
|
+
puts 'Only copied the stack template and parameters locally, use the --commit flag in order to do commit the changes to AWS'
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def delete_stack(stack_name)
|
218
|
+
configure()
|
219
|
+
FileUtils.rm_rf(get_stack_directory(stack_name))
|
220
|
+
if @cfn.stacks[stack_name].exists?
|
221
|
+
puts "Deleting stack #{stack_name}"
|
222
|
+
@cfn.stacks[stack_name].delete
|
223
|
+
else
|
224
|
+
puts "Stack #{stack_name} does not exist, nothing to delete here..."
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
metadata
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: clouds
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Cristian Magherusan-Stanciu
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-05-22 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 10.2.2
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 10.2.2
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rdoc
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 4.1.1
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 4.1.1
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: aruba
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.5.4
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.5.4
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: nokogiri
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.6.1
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.6.1
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: gli
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 2.9.0
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.9.0
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: aws-sdk
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.38.0
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 1.38.0
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: inifile
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 2.0.2
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 2.0.2
|
142
|
+
description: A layer of syntax sugar around the AWS Cloudformation API that allows
|
143
|
+
you to handle Cloudformation-defined infrastructure as code with a simple tool
|
144
|
+
email: cristian.magherusan-stanciu@here.com
|
145
|
+
executables:
|
146
|
+
- clouds
|
147
|
+
extensions: []
|
148
|
+
extra_rdoc_files:
|
149
|
+
- README.md
|
150
|
+
- clouds.rdoc
|
151
|
+
files:
|
152
|
+
- bin/clouds
|
153
|
+
- lib/clouds/version.rb
|
154
|
+
- lib/clouds.rb
|
155
|
+
- README.md
|
156
|
+
- clouds.rdoc
|
157
|
+
homepage: http://here.com
|
158
|
+
licenses:
|
159
|
+
- GPL-2
|
160
|
+
post_install_message:
|
161
|
+
rdoc_options:
|
162
|
+
- --title
|
163
|
+
- clouds
|
164
|
+
- --main
|
165
|
+
- README.md
|
166
|
+
- -ri
|
167
|
+
require_paths:
|
168
|
+
- lib
|
169
|
+
- lib
|
170
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
171
|
+
none: false
|
172
|
+
requirements:
|
173
|
+
- - ! '>='
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
requirements: []
|
183
|
+
rubyforge_project:
|
184
|
+
rubygems_version: 1.8.23
|
185
|
+
signing_key:
|
186
|
+
specification_version: 3
|
187
|
+
summary: AWS Cloudformation API
|
188
|
+
test_files: []
|