blimpy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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