blimpy 0.0.1

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.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in blimpy.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'rake'
8
+ gem 'rspec'
9
+ gem 'cucumber'
10
+ gem 'aruba'
11
+ gem 'tempdir'
12
+ gem 'pry'
13
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 R. Tyler Croy
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,45 @@
1
+ # Blimpy
2
+
3
+ ![Excelsior!](http://strongspace.com/rtyler/public/excelsior.png)
4
+
5
+
6
+ ### About
7
+ Notes and other bits are being stored in [this public Evernote
8
+ notebook](https://www.evernote.com/pub/agentdero/blimpy).
9
+
10
+ The current concept/design document is captured in [this
11
+ note](https://www.evernote.com/pub/agentdero/blimpy#b=58a228bb-8910-4cd1-a7f5-995d775b81a2&n=06def701-7e25-425b-81d4-5811e7987c7e)
12
+
13
+
14
+ ### The Blimpfile
15
+
16
+ Here's an example Blimpfile:
17
+
18
+ ```ruby
19
+ Blimpy.fleet do |fleet|
20
+ fleet.add do |ship|
21
+ ship.image_id = 'ami-349b495d'
22
+ ship.livery = 'rails'
23
+ ship.group = 'Simple' # [Required] The name of the desired Security Group
24
+ ship.region = 'us-west-1'
25
+ ship.name = 'Rails App Server'
26
+ end
27
+ end
28
+ ```
29
+
30
+
31
+ ### What is Livery?
32
+
33
+ In aviation, livery is the insignia or "look" an aircraft typically has. For
34
+ example, Alaskan Airlines has a distinctive "[creepy mountain
35
+ man](http://farm1.static.flickr.com/135/333644732_4f797d3c22.jpg)" livery on
36
+ every plane.
37
+
38
+ With Blimpy, "livery" is a similar concept, a means of describing the "look" of
39
+ a specific machine in the cloud. Currently the concept is still on the drawing
40
+ board, but if you would imagine a tarball containing a `bootstrap.sh` script
41
+ and Chef cookbooks or Puppet manifests to provision the entirety of the machine
42
+ from start-to-finish.
43
+
44
+ When the machine comes online, the specified livery would be downloaded from S3
45
+ (for example) and bootstrap.sh would be invoked as root.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'thor'
5
+
6
+ begin
7
+ require 'blimpy'
8
+ rescue LoadError
9
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib/')
10
+ require 'blimpy'
11
+ end
12
+
13
+ module Blimpy
14
+ class CLI < Thor
15
+ BLIMPFILE = File.join(Dir.pwd, 'Blimpfile')
16
+
17
+ no_tasks do
18
+ def ensure_blimpfile
19
+ unless File.exists? Blimpy::CLI::BLIMPFILE
20
+ puts 'Please create a Blimpfile in your current directory'
21
+ exit 1
22
+ end
23
+ end
24
+ end
25
+
26
+ desc 'start', 'Start up a fleet of blimps'
27
+ method_options :"dry-run" => :boolean
28
+ def start
29
+ ensure_blimpfile
30
+ engine = Blimpy::Engine.new
31
+ engine.load_file(File.open(BLIMPFILE).read)
32
+ puts 'Up, up and away!'
33
+
34
+ if options[:'dry-run']
35
+ puts 'skipping actually starting the fleet'
36
+ exit 0
37
+ end
38
+
39
+ engine.fleet.start
40
+ end
41
+
42
+ desc 'list', 'List running blimps'
43
+ def list
44
+ ensure_blimpfile
45
+ blimps = Dir["#{Dir.pwd}/.blimpy.d/*.blimp"]
46
+ if blimps.empty?
47
+ puts 'No currently running VMs'
48
+ exit 0
49
+ end
50
+
51
+ blimps.each do |blimp|
52
+ data = YAML.load_file(blimp)
53
+ instance_id = File.basename(blimp)
54
+ instance_id = instance_id.split('.blimp').first
55
+ puts "#{data['name']} (#{instance_id}) is: online at #{data['dns']}"
56
+ end
57
+ end
58
+
59
+ desc 'destroy', 'Destroy all running blimps'
60
+ def destroy
61
+ ensure_blimpfile
62
+ fleet = Blimpy::Fleet.new
63
+ fleet.destroy
64
+ end
65
+
66
+
67
+ desc 'init', 'Create a skeleton Blimpfile in the current directory'
68
+ def init
69
+ File.open(File.join(Dir.pwd, 'Blimpfile'), 'w') do |f|
70
+ f.write(
71
+ """# vim: ft=ruby
72
+ # Blimpfile created on #{Time.now}
73
+
74
+ Blimpy.fleet do |fleet|
75
+ fleet.add do |ship|
76
+ ship.name = 'Excelsior'
77
+ ship.group = 'default'
78
+ end
79
+ end
80
+ """)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ Blimpy::CLI.start
87
+
88
+ exit 0
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/blimpy/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["R. Tyler Croy"]
6
+ gem.email = ["tyler@monkeypox.org"]
7
+ gem.description = %q{Blimpy is a tool for managing a fleet of machines in the CLOUD!}
8
+ gem.summary = %q{Ruby + CLOUD = Blimpy}
9
+ gem.homepage = "https://github.com/rtyler/blimpy"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "blimpy"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Blimpy::VERSION
17
+
18
+ gem.add_dependency 'fog'
19
+ gem.add_dependency 'thor'
20
+ end
@@ -0,0 +1,10 @@
1
+ Feature: Create a Blimpfile in the current working directory
2
+ As a Blimpy user
3
+ In order to get started as quickly as possible
4
+ The 'init' command should create a skeleton Blimpfile in the current directroy
5
+
6
+
7
+ Scenario: Clean working directory
8
+ Given I have no Blimpfile in my current directory
9
+ When I run `blimpy init`
10
+ Then a file named "Blimpfile" should exist
@@ -0,0 +1,19 @@
1
+ Feature: List running VMs
2
+
3
+ Scenario: With no running VMs
4
+ Given I have the Blimpfile:
5
+ """
6
+ # Empty!
7
+ """
8
+ When I run `blimpy list`
9
+ Then the exit status should be 0
10
+ And the output should contain:
11
+ """
12
+ No currently running VMs
13
+ """
14
+
15
+ Scenario: With a running VM
16
+ Given I have a single VM running
17
+ When I run `blimpy list`
18
+ Then the exit status should be 0
19
+ And the output should list the VM
@@ -0,0 +1,27 @@
1
+ Feature: Start a VM or cluster of VMs in the cloud
2
+
3
+ Scenario: Without a Blimpfile
4
+ Given I have no Blimpfile in my current directory
5
+ When I run `blimpy start`
6
+ Then the output should contain:
7
+ """
8
+ Please create a Blimpfile in your current directory
9
+ """
10
+ And the exit status should be 1
11
+
12
+ Scenario: With a simple Blimpfile
13
+ Given I have the Blimpfile:
14
+ """
15
+ Blimpy.fleet do |f|
16
+ f.add do |host|
17
+ host.group = 'Simple'
18
+ host.name = 'Cucumber Host'
19
+ end
20
+ end
21
+ """
22
+ When I run `blimpy start --dry-run`
23
+ Then the exit status should be 0
24
+ And the output should contain:
25
+ """
26
+ Up, up and away!
27
+ """
@@ -0,0 +1,32 @@
1
+
2
+ Given /^I have no Blimpfile in my current directory$/ do
3
+ # no-op: default state of the world is to not have a Blimpfile!
4
+ end
5
+
6
+ Given /^I have the Blimpfile:$/ do |string|
7
+ create_blimpfile(string)
8
+ end
9
+
10
+ Given /^I have a single VM running$/ do
11
+ create_blimpfile(
12
+ """
13
+ Blimpy.fleet do |f|
14
+ f.add do |host|
15
+ host.name = 'Failboat'
16
+ end
17
+ end
18
+ """)
19
+ d = File.join(@tempdir, '.blimpy.d')
20
+ Dir.mkdir(d)
21
+ @name = 'Cucumber host'
22
+ @server_id = '0xdeadbeef'
23
+ File.open(File.join(d, "#{@server_id}.blimp"), 'w') do |f|
24
+ f.write("name: #{@name}\n")
25
+ f.write("dns: foo.bar\n")
26
+ end
27
+ end
28
+
29
+ Then /^the output should list the VM$/ do
30
+ expected = 'Cucumber host (0xdeadbeef) is: online at foo.bar'
31
+ assert_partial_output(expected, all_output)
32
+ end
@@ -0,0 +1,19 @@
1
+ require 'aruba/cucumber'
2
+ require 'fileutils'
3
+ require 'temp_dir'
4
+
5
+
6
+ # Pull in my gem working directory bin directory
7
+ ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
8
+
9
+
10
+ module BlimpyWorld
11
+ def create_blimpfile(string)
12
+ path = File.join(@tempdir, 'Blimpfile')
13
+ File.open(path, 'w') do |f|
14
+ f.write(string)
15
+ end
16
+ end
17
+ end
18
+
19
+ World(BlimpyWorld)
@@ -0,0 +1,18 @@
1
+ Before do
2
+ @cwd = Dir.pwd
3
+ @tempdir = TempDir.create(:basename => 'blimpy_test')
4
+ puts "Using tempdir: #{@tempdir}"
5
+ Dir.chdir(@tempdir)
6
+ @dirs = [@tempdir]
7
+ end
8
+
9
+ After do |scenario|
10
+ Dir.chdir(@cwd)
11
+
12
+ unless scenario.failed?
13
+ # NOTE: just having this line here makes me apprehensive
14
+ #FileUtils.rm_rf(@tempdir) unless @tempdir.nil?
15
+ else
16
+ puts "Leaving the tempdir in tact: #{@tempdir}"
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ require 'blimpy/box'
2
+ require 'blimpy/engine'
3
+ require 'blimpy/fleet'
4
+ require 'blimpy/version'
5
+
6
+ module Blimpy
7
+ def self.fleet(&block)
8
+ if block.nil?
9
+ return false
10
+ end
11
+ fleet = Blimpy::Fleet.new
12
+ block.call fleet
13
+ fleet
14
+ end
15
+
16
+ class InvalidBlimpFileError < Exception
17
+ end
18
+ class InvalidRegionError < Exception
19
+ end
20
+ class BoxValidationError < Exception
21
+ end
22
+ end
@@ -0,0 +1,92 @@
1
+
2
+ module Blimpy
3
+ class Box
4
+ attr_reader :allowed_regions, :region, :server
5
+ attr_accessor :image_id, :livery, :group, :name, :tags, :fleet_id
6
+
7
+ def self.from_instance_id(an_id)
8
+ server = Fog::Compute[:aws].servers.get(an_id)
9
+ if server.nil?
10
+ return nil
11
+ end
12
+ self.new(server)
13
+ end
14
+
15
+ def initialize(server=nil)
16
+ @allowed_regions = ['us-west-1', 'us-west-2', 'us-east-1']
17
+ @region = 'us-west-2' # Default to US West (Oregon) for now
18
+ @image_id = 'ami-349b495d' # Default to Ubuntu 10.04 LTS (64bit)
19
+ @livery = nil
20
+ @group = nil
21
+ @name = 'Unnamed Box'
22
+ @tags = {}
23
+ @server = server
24
+ @fleet_id = 0
25
+ end
26
+
27
+ def region=(newRegion)
28
+ unless @allowed_regions.include? newRegion
29
+ raise InvalidRegionError
30
+ end
31
+ @region = newRegion
32
+ end
33
+
34
+ def validate!
35
+ if Fog::Compute[:aws].security_groups.get(@group).nil?
36
+ raise BoxValidationError
37
+ end
38
+ end
39
+
40
+ def online!
41
+ File.open(File.join(state_dir, state_file), 'a') do |f|
42
+ f.write("dns: #{@server.dns_name}\n")
43
+ end
44
+ end
45
+
46
+ def start
47
+ ensure_state_dir
48
+ @server = create_host
49
+
50
+ File.open(File.join(state_dir, state_file), 'w') do |f|
51
+ f.write("name: #{@name}\n")
52
+ end
53
+ end
54
+
55
+ def stop
56
+ unless @server.nil?
57
+ @server.stop
58
+ end
59
+ end
60
+
61
+ def destroy
62
+ unless @server.nil?
63
+ @server.destroy
64
+ File.unlink(File.join(state_dir, state_file))
65
+ end
66
+ end
67
+
68
+ def state_dir
69
+ File.join(Dir.pwd, '.blimpy.d')
70
+ end
71
+
72
+ def state_file
73
+ if @server.nil?
74
+ raise Exception, "I can't make a state file without a @server!"
75
+ end
76
+ "#{@server.id}.blimp"
77
+ end
78
+
79
+ def ensure_state_dir
80
+ unless File.exist? state_dir
81
+ Dir.mkdir(state_dir)
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def create_host
88
+ tags = @tags.merge({:Name => @name, :CreatedBy => 'Blimpy', :BlimpyFleetId => @fleet_id})
89
+ Fog::Compute[:aws].servers.create(:image_id => @image_id, :region => @region, :tags => tags)
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,29 @@
1
+
2
+ require 'rubygems'
3
+ require 'fog'
4
+
5
+ module Blimpy
6
+ class Engine
7
+ attr_reader :fleet
8
+
9
+ def initialize
10
+ @fleet = nil
11
+ end
12
+
13
+ def load_file(file_content)
14
+ if file_content.nil? || file_content.empty?
15
+ raise InvalidBlimpFileError, 'File appears empty'
16
+ end
17
+
18
+ begin
19
+ @fleet = eval(file_content)
20
+ if @fleet and !(@fleet.instance_of? Blimpy::Fleet)
21
+ raise Exception, 'File does not create a Fleet'
22
+ end
23
+ rescue Exception => e
24
+ raise InvalidBlimpFileError, e.to_s
25
+ end
26
+ @fleet
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,67 @@
1
+
2
+ module Blimpy
3
+ class Fleet
4
+ attr_reader :hosts
5
+
6
+ def initialize
7
+ @hosts = []
8
+ @servers = []
9
+ @id = Time.now.utc.to_i
10
+ end
11
+
12
+ def add(&block)
13
+ if block.nil?
14
+ return false
15
+ end
16
+ box = Blimpy::Box.new
17
+ box.fleet_id = @id
18
+ @hosts << box
19
+ block.call(box)
20
+ end
21
+
22
+ def start
23
+ # Make sure all our hosts are valid first!
24
+ @hosts.each do |host|
25
+ host.validate!
26
+ end
27
+
28
+ @hosts.each do |host|
29
+ @servers << host.start
30
+ end
31
+
32
+ @hosts.each do |host|
33
+ print ">> #{host.name} "
34
+ host.server.wait_for do
35
+ print '.'
36
+ ready?
37
+ end
38
+ print ".. online at: #{host.server.dns_name}"
39
+ host.online!
40
+ puts
41
+ end
42
+ end
43
+
44
+ def members
45
+ instance_ids = []
46
+ Dir["#{Dir.pwd}/.blimpy.d/*.blimp"].each do |d|
47
+ filename = File.basename(d)
48
+ instance_ids << filename.split('.blimp').first
49
+ end
50
+ instance_ids
51
+ end
52
+
53
+ def stop
54
+ members.each do |instance_id|
55
+ box = Blimpy::Box.from_instance_id(instance_id)
56
+ box.stop
57
+ end
58
+ end
59
+
60
+ def destroy
61
+ members.each do |instance_id|
62
+ box = Blimpy::Box.from_instance_id(instance_id)
63
+ box.destroy
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,3 @@
1
+ module Blimpy
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Blimpy do
4
+ describe '#fleet' do
5
+ context 'without a block' do
6
+ it 'should not create a new Fleet' do
7
+ Blimpy::Fleet.should_receive(:new).never
8
+ subject.fleet
9
+ end
10
+ end
11
+
12
+ context 'with a block' do
13
+ it 'should create a new Fleet' do
14
+ result = subject.fleet do |f|
15
+ end
16
+ result.should be_instance_of Blimpy::Fleet
17
+ end
18
+
19
+ it 'should invoke the block with a Fleet' do
20
+ invoked_block = false
21
+ subject.fleet do |f|
22
+ invoked_block = true
23
+ end
24
+ invoked_block.should be true
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe Blimpy::Box do
4
+ describe '#image_id' do
5
+ it 'should be the Ubuntu 10.04 AMI ID by default' do
6
+ subject.image_id.should == 'ami-349b495d'
7
+ end
8
+ end
9
+
10
+ describe '#livery' do
11
+ it 'should be unset by default' do
12
+ subject.livery.should be nil
13
+ end
14
+ end
15
+
16
+ describe '#group' do
17
+ it 'should be unset by default' do
18
+ subject.group.should be nil
19
+ end
20
+ end
21
+
22
+ describe '#name' do
23
+ it 'should be "Unnamed Box" by default' do
24
+ subject.name.should == 'Unnamed Box'
25
+ end
26
+ end
27
+
28
+ describe '#allowed_regions' do
29
+ it 'should be an Array' do
30
+ subject.allowed_regions.should be_instance_of Array
31
+ end
32
+ it 'should not be empty' do
33
+ subject.allowed_regions.should_not be_empty
34
+ end
35
+ end
36
+
37
+ describe '#region' do
38
+ it 'should return the default region' do
39
+ subject.region.should == 'us-west-2'
40
+ end
41
+ end
42
+
43
+ describe '#region=' do
44
+ it 'should raise an InvalidRegionError if the region is not allowed' do
45
+ expect {
46
+ subject.region = :elbonia
47
+ }.to raise_error(Blimpy::InvalidRegionError)
48
+ end
49
+
50
+ it 'should change the value of @region' do
51
+ subject.region = 'us-east-1'
52
+ subject.region.should == 'us-east-1'
53
+ end
54
+ end
55
+
56
+ describe '#validate!' do
57
+ let(:security_group) do
58
+ group = double('Fog::Compute::AWS::SecurityGroup')
59
+ group.stub(:name).and_return('MockedGroup')
60
+ group
61
+ end
62
+ let(:groups) { double('Fog::Compute::AWS::SecurityGroups') }
63
+
64
+ before :each do
65
+ # Fog::Compute[:aws] will return a *new* instance of
66
+ # Fog::Compute::Aws::Real every time (apparently) it is invoked
67
+ Fog::Compute::AWS::Real.any_instance.should_receive(:security_groups).and_return(groups)
68
+ end
69
+
70
+ context 'with invalid settings' do
71
+ it 'should raise with a bad security group' do
72
+ groups.should_receive(:get).and_return(nil)
73
+ expect {
74
+ subject.validate!
75
+ }.to raise_error(Blimpy::BoxValidationError)
76
+ end
77
+ end
78
+
79
+ context 'with valid settings' do
80
+ it 'should validate with a good security group' do
81
+ groups.should_receive(:get).with('MockedGroup').and_return(security_group)
82
+ expect {
83
+ subject.group = 'MockedGroup'
84
+ subject.validate!
85
+ }.not_to raise_error(Blimpy::BoxValidationError)
86
+ end
87
+ end
88
+ end
89
+
90
+ context 'with a mocked server' do
91
+ let(:server_id) { 'id-0xdeadbeef' }
92
+ let(:server) do
93
+ server = double('Fog::Compute::AWS::Server')
94
+ server.stub(:id).and_return(server_id)
95
+ server
96
+ end
97
+
98
+ describe '#start' do
99
+ before :each do
100
+ # Mocking out #create_host so we don't actually create EC2 instance
101
+ Blimpy::Box.any_instance.should_receive(:create_host).and_return(server)
102
+ Blimpy::Box.any_instance.should_receive(:ensure_state_dir).and_return(true)
103
+ end
104
+
105
+ it 'should create a state file' do
106
+ path = File.join(subject.state_dir, "#{server_id}.blimp")
107
+ File.should_receive(:open).with(path, 'w')
108
+ subject.start
109
+ end
110
+ end
111
+
112
+
113
+ describe '#stop' do
114
+ before :each do
115
+ server.should_receive(:stop)
116
+ end
117
+
118
+ subject { Blimpy::Box.new(server) }
119
+
120
+ it 'should stop the Box' do
121
+ subject.stop
122
+ end
123
+ end
124
+ describe '#destroy' do
125
+ before :each do
126
+ server.should_receive(:destroy)
127
+ end
128
+ subject { Blimpy::Box.new(server) }
129
+
130
+ it 'should remove its state file' do
131
+ subject.should_receive(:state_file).and_return('foo')
132
+ File.should_receive(:unlink).with(File.join(subject.state_dir, 'foo'))
133
+ subject.destroy
134
+ end
135
+ end
136
+ end
137
+
138
+ describe '#ensure_state_dir' do
139
+ let(:path) { File.join(Dir.pwd, '.blimpy.d') }
140
+
141
+ context 'if ./.blimpy.d does not exist' do
142
+ before :each do
143
+ File.should_receive(:exist?).with(path).and_return(false)
144
+ end
145
+
146
+ it 'should create directory' do
147
+ Dir.should_receive(:mkdir).with(path)
148
+ subject.ensure_state_dir
149
+ end
150
+ end
151
+
152
+ context 'if ./blimpy.d does exist' do
153
+ before :each do
154
+ File.should_receive(:exist?).with(path).and_return(true)
155
+ end
156
+
157
+ it 'should create directory' do
158
+ Dir.should_receive(:mkdir).with(path).never
159
+ subject.ensure_state_dir
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe Blimpy::Engine do
4
+
5
+ describe '#load_file' do
6
+ context 'no contents' do
7
+ let(:content) { '' }
8
+
9
+ it 'should raise InvalidBlimpFileError' do
10
+ expect {
11
+ subject.load_file(content)
12
+ }.to raise_error(Blimpy::InvalidBlimpFileError)
13
+ end
14
+
15
+ end
16
+
17
+ context 'invalid content' do
18
+ let(:content) do
19
+ """
20
+ this is totally invalid Ruby
21
+ """
22
+ end
23
+
24
+ it 'should raise InvalidBlimpFileError' do
25
+ expect {
26
+ subject.load_file(content)
27
+ }.to raise_error(Blimpy::InvalidBlimpFileError)
28
+ end
29
+ end
30
+
31
+ context 'valid content' do
32
+ let(:content) do
33
+ """
34
+ Blimpy.fleet do |fleet|
35
+ fleet.add do |host|
36
+ host.image_id = 'ami-349b495d'
37
+ host.livery = 'rails'
38
+ host.group = 'Simple'
39
+ host.region = 'us-west-1'
40
+ host.name = 'Rails App Server'
41
+ end
42
+ end
43
+ """
44
+ end
45
+
46
+ it 'should create the appropriate Fleet object' do
47
+ result = subject.load_file(content)
48
+ result.should be_instance_of Blimpy::Fleet
49
+ result.hosts.should be_instance_of Array
50
+ result.hosts.size.should == 1
51
+
52
+ host = result.hosts.first
53
+ host.group.should == 'Simple'
54
+ host.name.should == 'Rails App Server'
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe Blimpy::Fleet do
4
+ describe '#hosts' do
5
+ it 'should be an Array' do
6
+ subject.hosts.should be_instance_of Array
7
+ subject.hosts.size.should == 0
8
+ end
9
+ end
10
+
11
+ describe '#add' do
12
+ it 'should return false if no Box was properly added' do
13
+ subject.add.should == false
14
+ end
15
+
16
+ it 'should pass a Box instance to the block' do
17
+ invoked_block = false
18
+ subject.add do |box|
19
+ invoked_block = true
20
+ box.should be_instance_of Blimpy::Box
21
+ end
22
+ invoked_block.should be true
23
+ end
24
+
25
+ context 'with a block' do
26
+ before :each do
27
+ subject.add do |b|
28
+ @box = b
29
+ end
30
+ end
31
+
32
+ it 'should add the box the fleet' do
33
+ @box.should_not be nil
34
+ subject.hosts.should include(@box)
35
+ end
36
+ end
37
+ end
38
+
39
+
40
+ context 'group operations' do
41
+ before :each do
42
+ subject.should_receive(:members).and_return([])
43
+ end
44
+ describe '#stop' do
45
+ it 'should run stop' do
46
+ subject.stop
47
+ end
48
+ end
49
+
50
+ describe '#destroy' do
51
+ it 'should run destroy' do
52
+ subject.destroy
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,15 @@
1
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'blimpy'
4
+
5
+ RSpec.configure do |config|
6
+ # RSpec automatically cleans stuff out of backtraces;
7
+ # sometimes this is annoying when trying to debug something e.g. a gem
8
+ config.backtrace_clean_patterns = [
9
+ /\/lib\d*\/ruby\//,
10
+ /bin\//,
11
+ /gems/,
12
+ /spec\/spec_helper\.rb/,
13
+ /lib\/rspec\/(core|expectations|matchers|mocks)/
14
+ ]
15
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: blimpy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - R. Tyler Croy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-23 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fog
16
+ requirement: &6750880 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *6750880
25
+ - !ruby/object:Gem::Dependency
26
+ name: thor
27
+ requirement: &6747240 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *6747240
36
+ description: Blimpy is a tool for managing a fleet of machines in the CLOUD!
37
+ email:
38
+ - tyler@monkeypox.org
39
+ executables:
40
+ - blimpy
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - .gitignore
45
+ - Gemfile
46
+ - LICENSE
47
+ - README.md
48
+ - Rakefile
49
+ - bin/blimpy
50
+ - blimpy.gemspec
51
+ - features/cli/init.feature
52
+ - features/cli/list.feature
53
+ - features/cli/start.feature
54
+ - features/step_definitions/cli_steps.rb
55
+ - features/support/env.rb
56
+ - features/support/hooks.rb
57
+ - lib/blimpy.rb
58
+ - lib/blimpy/box.rb
59
+ - lib/blimpy/engine.rb
60
+ - lib/blimpy/fleet.rb
61
+ - lib/blimpy/version.rb
62
+ - spec/blimpy_spec.rb
63
+ - spec/box_spec.rb
64
+ - spec/engine_spec.rb
65
+ - spec/fleet_spec.rb
66
+ - spec/spec_helper.rb
67
+ homepage: https://github.com/rtyler/blimpy
68
+ licenses: []
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 1.8.10
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Ruby + CLOUD = Blimpy
91
+ test_files:
92
+ - features/cli/init.feature
93
+ - features/cli/list.feature
94
+ - features/cli/start.feature
95
+ - features/step_definitions/cli_steps.rb
96
+ - features/support/env.rb
97
+ - features/support/hooks.rb
98
+ - spec/blimpy_spec.rb
99
+ - spec/box_spec.rb
100
+ - spec/engine_spec.rb
101
+ - spec/fleet_spec.rb
102
+ - spec/spec_helper.rb