bora 0.1.0 → 0.2.0

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