bora 0.1.0 → 0.2.0

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: 9d8bdb0f5c4ecf2bd52b21f4be37383916b33f11
4
- data.tar.gz: e0185553a1d9600dd9b4ff546e720b78fe006003
3
+ metadata.gz: a3bef88ac6bd7773175b02930da53efe7de03ec7
4
+ data.tar.gz: 450388c3e3ffc40c353ed09af8a79b8bf2223c13
5
5
  SHA512:
6
- metadata.gz: 64a03d50e228425644d439891c6f1272d12deae7d34cd0a43d6a8ef72ab2207ff5cee387413765ee24f347957851f7dc50bf8e86429c5bfcc6f7885351155292
7
- data.tar.gz: b992783319a0389b1bc7a57d6cdd862349d4b032072285a045e3d3aace2edb4253ad739833c9cfc577e5b11d8b44aaaf3288502da4fb7eafd126c6a7b8a84fcc
6
+ metadata.gz: 0b7cc4b0e82bf2eb5c9ba59e95600f890296b7dcb1409177dccff2373a7b99b74c5664b95bacc96a3d597ff1cdfa477164489b623a05d8a20972f9e9e9abe142
7
+ data.tar.gz: 770f772c1df360fc90dfe7bb1efa031e537aa110a11638fb3bda947dc3c08a45b48810e28f4598bcd7ea7efc169ed35a395530c6545fbfd0a0925706af01a285
data/README.md CHANGED
@@ -1,8 +1,12 @@
1
1
  # Bora
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/bora`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ > 1. A cold and often gusty katabatic wind in the Adriatic
4
+ > 2. A tool for pushing around your cloud formations
5
+
6
+ This gem contains Ruby [rake](https://github.com/ruby/rake) tasks that help you work with [CloudFormation](https://aws.amazon.com/cloudformation/) stacks.
7
+ You don't need to use it with rake though - you can use the underlaying classes
8
+ in any Ruby app.
4
9
 
5
- TODO: Delete this and the text above, and describe your gem
6
10
 
7
11
  ## Installation
8
12
 
@@ -22,15 +26,69 @@ Or install it yourself as:
22
26
 
23
27
  ## Usage
24
28
 
25
- TODO: Write usage instructions here
29
+ ### Quick Start
30
+
31
+ Add this to your `Rakefile`
32
+
33
+ ```ruby
34
+ require 'bora'
35
+
36
+ Bora::Tasks.new("example") do |t|
37
+ t.stack_options = {
38
+ template_body: File.read("example.json")
39
+ }
40
+ end
41
+ ```
42
+
43
+ This will give you the following rake tasks
44
+
45
+ ```shell
46
+ rake stack:example:apply # Creates (or updates) the example stack
47
+ rake stack:example:current_template # Shows the current template for example stack
48
+ rake stack:example:delete # Deletes the example stack
49
+ rake stack:example:diff # Diffs the new template with the example stack's current template
50
+ rake stack:example:events # Outputs the latest events from the example stack
51
+ rake stack:example:new_template # Shows the new template for example stack
52
+ ```
53
+
54
+ You can add as many templates as you like into your Rakefile, simply define an instance of `Bora::Tasks` for each one.
55
+
56
+ ### Task Options
57
+
58
+ When you define the Bora tasks, you can pass in a number of options that control how Bora works and what gets passed to CloudFormation.
59
+ The available options are shown below with their default values.
60
+
61
+ ```ruby
62
+ Bora::Tasks.new("example") do |t|
63
+ t.colorize = true
64
+ t.stack_options = {}
65
+ end
66
+ ```
67
+
68
+ * `colorize` - A boolean that controls whether console output is colored or not
69
+ * `stack_options` - A hash of options that are passed directly to the CloudFormation [create_stack](http://docs.aws.amazon.com/sdkforruby/api/Aws/CloudFormation/Client.html#create_stack-instance_method) and [update_stack](http://docs.aws.amazon.com/sdkforruby/api/Aws/CloudFormation/Client.html#update_stack-instance_method) APIs.
70
+ You must at a minimum specify either the `template_body` or `template_url` option.
71
+
72
+
73
+ ### API
74
+
75
+ You can use this gem without using Rake. Most of the logic is implemented in [stack.rb](https://github.com/ampedandwired/bora/blob/master/lib/bora/stack.rb) and is fairly self-explanatory.
76
+
77
+ ```ruby
78
+ require 'bora'
79
+
80
+ stack = Bora::Stack.new("my-stack")
81
+ result = stack.update({template_body: File.read("example.json")}) do |event|
82
+ puts event
83
+ end
84
+
85
+ puts "Update #{result ? "succeeded" : "failed"}"
86
+ ```
26
87
 
27
88
  ## Development
28
89
 
29
90
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
91
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
-
33
92
  ## Contributing
34
93
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/bora.
36
-
94
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ampedandwired/bora.
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.add_dependency "aws-sdk", "~> 2.0"
21
21
  spec.add_dependency "colorize", "~> 0.7"
22
+ spec.add_dependency "diffy", "~> 3.0"
22
23
  spec.add_dependency "rake", "~> 10.0"
23
24
 
24
25
  spec.add_development_dependency "bundler", "~> 1.11"
@@ -1,5 +1,6 @@
1
1
  require 'set'
2
2
  require 'aws-sdk'
3
+ require 'diffy'
3
4
 
4
5
  module Bora
5
6
  class Stack
@@ -9,22 +10,49 @@ module Bora
9
10
  @processed_events = Set.new
10
11
  end
11
12
 
12
- def create(params, &block)
13
- call_cfn_action(:create, params, &block)
13
+ def create(options, &block)
14
+ call_cfn_action(:create, options, &block)
14
15
  end
15
16
 
16
- def update(params, &block)
17
- call_cfn_action(:update, params, &block)
17
+ def update(options, &block)
18
+ call_cfn_action(:update, options, &block)
18
19
  end
19
20
 
20
- def create_or_update(params, &block)
21
- exists? ? update(params, &block) : create(params, &block)
21
+ def create_or_update(options, &block)
22
+ exists? ? update(options, &block) : create(options, &block)
22
23
  end
23
24
 
24
25
  def delete(&block)
25
26
  call_cfn_action(:delete, &block)
26
27
  end
27
28
 
29
+ def events
30
+ return [] if !underlying_stack
31
+ events = @cfn.describe_stack_events({stack_name: underlying_stack.stack_id}).stack_events
32
+ events.reverse.map { |e| Event.new(e) }
33
+ end
34
+
35
+ def template(pretty = true)
36
+ return if !exists?
37
+ template = @cfn.get_template({stack_name: @stack_name}).template_body
38
+ template = JSON.pretty_generate(JSON.parse(template)) if pretty
39
+ template
40
+ end
41
+
42
+ def new_template(options, pretty = true)
43
+ if options[:template_body]
44
+ template = options[:template_body]
45
+ template = JSON.pretty_generate(JSON.parse(template)) if pretty
46
+ template
47
+ else
48
+ raise Exception("new_template not yet implemented for template_url stack option")
49
+ end
50
+ end
51
+
52
+ def diff(options)
53
+ Diffy::Diff.new(template, new_template(options))
54
+ end
55
+
28
56
  def exists?
29
57
  underlying_stack && underlying_stack.stack_status != 'DELETE_COMPLETE'
30
58
  end
@@ -32,13 +60,13 @@ module Bora
32
60
 
33
61
  private
34
62
 
35
- def call_cfn_action(action, params = {}, &block)
63
+ def call_cfn_action(action, options = {}, &block)
36
64
  underlying_stack(refresh: true)
37
65
  return true if action == :delete && !exists?
38
66
  @previous_event_time = last_event_time
39
- params[:stack_name] = @stack_name
67
+ options[:stack_name] = @stack_name
40
68
  begin
41
- @cfn.method("#{action.to_s.downcase}_stack").call(params)
69
+ @cfn.method("#{action.to_s.downcase}_stack").call(options)
42
70
  wait_for_completion(&block)
43
71
  rescue Aws::CloudFormation::Errors::ValidationError => e
44
72
  raise e unless e.message.include?("No updates are to be performed")
@@ -11,20 +11,34 @@ module Bora
11
11
  define_tasks
12
12
  end
13
13
 
14
- attr_accessor :stack_params, :colorize
14
+ attr_accessor :stack_options, :colorize
15
15
 
16
16
  private
17
17
 
18
18
  def define_tasks
19
19
  define_apply_task
20
+ define_current_template_task
20
21
  define_delete_task
22
+ define_diff_task
23
+ define_events_task
24
+ define_new_template_task
21
25
  end
22
26
 
23
27
  def define_apply_task
24
28
  within_namespace do
25
29
  desc "Creates (or updates) the #{@stack_name} stack"
26
30
  task :apply do
27
- invoke_action(@stack.exists? ? "update" : "create", stack_params)
31
+ invoke_action(@stack.exists? ? "update" : "create", stack_options)
32
+ end
33
+ end
34
+ end
35
+
36
+ def define_current_template_task
37
+ within_namespace do
38
+ desc "Shows the current template for #{@stack_name} stack"
39
+ task :current_template do
40
+ template = @stack.template
41
+ puts template ? template : "Stack #{@stack_name} does not exist"
28
42
  end
29
43
  end
30
44
  end
@@ -38,6 +52,38 @@ module Bora
38
52
  end
39
53
  end
40
54
 
55
+ def define_diff_task
56
+ within_namespace do
57
+ desc "Diffs the new template with the #{@stack_name} stack's current template"
58
+ task :diff do
59
+ puts @stack.diff(@stack_options).to_s(@colorize ? :color : :text)
60
+ end
61
+ end
62
+ end
63
+
64
+ def define_events_task
65
+ within_namespace do
66
+ desc "Outputs the latest events from the #{@stack_name} stack"
67
+ task :events do
68
+ events = @stack.events
69
+ if events.length > 0
70
+ @stack.events.each { |e| puts e }
71
+ else
72
+ puts "No events for stack #{@stack_name}"
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ def define_new_template_task
79
+ within_namespace do
80
+ desc "Shows the new template for #{@stack_name} stack"
81
+ task :new_template do
82
+ puts @stack.new_template(@stack_options)
83
+ end
84
+ end
85
+ end
86
+
41
87
  def invoke_action(action, *args)
42
88
  puts "#{action.capitalize} stack #{@stack_name}"
43
89
  success = @stack.send(action, *args) { |event| puts event.to_s(colorize) }
@@ -1,3 +1,3 @@
1
1
  module Bora
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charles Blaxland
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-01-14 00:00:00.000000000 Z
11
+ date: 2016-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: diffy
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement