bowler 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.
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Bowler
2
+
3
+ Bowler is a gem to manage process dependencies in Foreman.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rdoc/task"
5
+ require 'rspec/core/rake_task'
6
+
7
+ RDoc::Task.new do |rd|
8
+ rd.rdoc_files.include("lib/**/*.rb")
9
+ rd.rdoc_dir = "rdoc"
10
+ end
11
+
12
+ desc "Run specs"
13
+ RSpec::Core::RakeTask.new do |t|
14
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
15
+ # Put spec opts in a file named .rspec in root
16
+ end
17
+
18
+ task :default => :spec
data/bin/bowl ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bowler'
3
+ require 'bowler/cli'
4
+
5
+ Bowler::CLI.start(ARGV)
data/lib/bowler/cli.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'logger'
2
+
3
+ module Bowler
4
+ class CLI
5
+
6
+ def self.start(processes)
7
+ tree = Bowler::DependencyTree.load
8
+ process_list = processes.map(&:to_sym)
9
+
10
+ launch_string = tree.process_list_for(process_list)
11
+
12
+ logger.info "Starting #{tree.dependencies_for(process_list).join(', ')}.."
13
+
14
+ start_foreman_with launch_string
15
+ rescue PinfileNotFound
16
+ logger.error "Bowler could not find a Pinfile in the current directory."
17
+ rescue PinfileError => e
18
+ logger.error "Bowler could not load the Pinfile due to an error: #{e}"
19
+ end
20
+
21
+ def self.logger
22
+ @logger ||= Logger.new(STDOUT)
23
+ end
24
+
25
+ def self.build_command(launch_string)
26
+ "foreman start -c #{launch_string}"
27
+ end
28
+
29
+ private
30
+ def self.start_foreman_with(launch_string)
31
+ exec ( self.build_command launch_string )
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,30 @@
1
+ module Bowler
2
+
3
+ class DependencyTree
4
+
5
+ # Load the Pinfile
6
+ def self.load(absolute_path = nil)
7
+ absolute_path ||= File.join( Dir.pwd, 'Pinfile' )
8
+ definition = DSL.evaluate(absolute_path)
9
+ self.new(definition)
10
+ end
11
+
12
+ def initialize(definition)
13
+ @definition = definition
14
+ end
15
+
16
+ def dependencies_for(processes)
17
+ processes.inject([]) do |array, p|
18
+ array += [ (@definition.tree[p] || []), p ].flatten
19
+ end.uniq
20
+ end
21
+
22
+ def process_list_for(processes)
23
+ on = dependencies_for(processes)
24
+ off = @definition.processes.reject {|i| on.include? i }
25
+
26
+ [ on.map {|x| "#{x}=1" }, off.map {|x| "#{x}=0" } ].flatten.sort.join(',')
27
+ end
28
+
29
+ end
30
+ end
data/lib/bowler/dsl.rb ADDED
@@ -0,0 +1,52 @@
1
+ module Bowler
2
+ class DSL
3
+ attr_reader :processes, :global_dependencies
4
+
5
+ def self.evaluate(pinfile)
6
+ dsl = new
7
+ dsl.eval_pinfile(pinfile)
8
+ dsl.to_definition
9
+ end
10
+
11
+ def eval_pinfile(pinfile)
12
+ raise PinfileNotFound unless File.exists?(pinfile)
13
+ file = File.read(pinfile)
14
+ instance_eval( file )
15
+ rescue SyntaxError => e
16
+ raise PinfileError, e
17
+ end
18
+
19
+ def initialize
20
+ @processes = []
21
+ @global_dependencies = []
22
+ @specified_dependencies = []
23
+ end
24
+
25
+ def dependency(*dependencies)
26
+ @global_dependencies += [dependencies].flatten
27
+ end
28
+
29
+ def process(params)
30
+ if params.is_a? Hash
31
+ parent = params.keys.first
32
+ dependencies = [params.values.first]
33
+
34
+ @processes << { :process => parent, :dependencies => [dependencies].flatten }
35
+ @specified_dependencies += dependencies.flatten
36
+ else
37
+ @processes << { :process => params, :dependencies => [ ] }
38
+ end
39
+ end
40
+
41
+ def to_definition
42
+ definition = {
43
+ :tree => @processes.each_with_object({}) {|p, hash|
44
+ hash[p[:process]] = (p[:dependencies] + @global_dependencies).uniq
45
+ },
46
+ :processes => (@processes.map {|x| x[:process]} + @global_dependencies + @specified_dependencies).uniq
47
+ }
48
+ OpenStruct.new(definition)
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module Bowler
2
+ VERSION = '0.0.1'
3
+ end
data/lib/bowler.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'ostruct'
2
+
3
+ module Bowler
4
+
5
+ autoload :DependencyTree, 'bowler/dependency_tree'
6
+ autoload :DSL, 'bowler/dsl'
7
+
8
+ class PinfileNotFound < Exception; end
9
+ class PinfileError < Exception; end
10
+
11
+ end
@@ -0,0 +1,50 @@
1
+ require 'bowler'
2
+ require_relative 'helpers/definition_helper'
3
+
4
+ module Bowler
5
+
6
+ describe DependencyTree do
7
+
8
+ include DefinitionHelper
9
+
10
+ context "given a Pinfile" do
11
+ it "should load a dependency tree" do
12
+ tree = DependencyTree.load File.join( File.dirname(__FILE__), 'fixtures', 'dependency_tree_pinfile' )
13
+
14
+ tree.should be_instance_of DependencyTree
15
+ tree.dependencies_for([:foo]).should =~ [:bar, :foo, :required]
16
+ tree.dependencies_for([:nyan]).should =~ [:bar, :foo, :nyan, :required]
17
+ end
18
+ end
19
+
20
+ context "given an array of one process" do
21
+ before do
22
+ @tree = DependencyTree.new stub_definition
23
+ end
24
+
25
+ it "should find the correct dependencies" do
26
+ @tree.dependencies_for([:app1]).should =~ [:app2, :app3, :app1]
27
+ end
28
+
29
+ it "should give a correct process list" do
30
+ @tree.process_list_for([:app2]).should == "a=0,app1=0,app2=1,app3=1,b=0,c=0,other=0"
31
+ end
32
+ end
33
+
34
+ context "given an array of multiple processes" do
35
+ before do
36
+ @tree = DependencyTree.new stub_definition
37
+ end
38
+
39
+ it "should find the correct dependencies" do
40
+ @tree.dependencies_for([:app1, :other]).should =~ [:app2, :app3, :app1, :a, :b, :c, :other]
41
+ end
42
+
43
+ it "should give a correct process list" do
44
+ @tree.process_list_for([:app2, :other]).should == "a=1,app1=0,app2=1,app3=1,b=1,c=1,other=1"
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ end
data/spec/dsl_spec.rb ADDED
@@ -0,0 +1,71 @@
1
+ require 'bowler'
2
+
3
+ module Bowler
4
+
5
+ describe DSL do
6
+
7
+ include DefinitionHelper
8
+
9
+ context "given a valid pinfile" do
10
+ it "should return a valid definition" do
11
+ path_to_pinfile = File.join( File.dirname(__FILE__), 'fixtures', 'dsl_valid_pinfile' )
12
+ definition = DSL.evaluate path_to_pinfile
13
+
14
+ definition.should be_instance_of OpenStruct
15
+ definition.tree.should == {
16
+ :app => [ :database, :tiles, :templates ],
17
+ :tiles => [ :database, :templates ]
18
+ }
19
+ definition.processes.should =~ [ :app, :database, :templates, :tiles ]
20
+ end
21
+ end
22
+
23
+ context "given an invalid pinfile" do
24
+ it "should raise a gem-defined exception" do
25
+ path_to_pinfile = File.join( File.dirname(__FILE__), 'fixtures', 'dsl_invalid_pinfile' )
26
+ expect do
27
+ DSL.evaluate path_to_pinfile
28
+ end.to raise_error(PinfileError)
29
+ end
30
+ end
31
+
32
+ context "given a process" do
33
+ before do
34
+ @dsl = DSL.new
35
+ @dsl.process :test
36
+ end
37
+
38
+ it "should update the processes list with the specified process" do
39
+ @dsl.processes.should == [{ :process => :test, :dependencies => [] }]
40
+ @dsl.to_definition.processes.should == [ :test ]
41
+ end
42
+ end
43
+
44
+ context "given a process with dependencies" do
45
+ before do
46
+ @dsl = DSL.new
47
+ @dsl.process :test => [ :dependency1, :dependency2 ]
48
+ end
49
+
50
+ it "should update the processes list with all specified processes" do
51
+ @dsl.processes.should == [{ :process => :test, :dependencies => [:dependency1, :dependency2] }]
52
+ @dsl.to_definition.processes.should =~ [ :dependency1, :dependency2, :test ]
53
+ end
54
+ end
55
+
56
+ context "given global dependencies" do
57
+ before do
58
+ @dsl = DSL.new
59
+ @dsl.dependency :global1, :global2
60
+ @dsl.dependency :global3
61
+ end
62
+
63
+ it "should update the processes list with all specified processes" do
64
+ @dsl.global_dependencies.should =~ [:global1, :global2, :global3]
65
+ @dsl.to_definition.processes.should =~ [ :global1, :global2, :global3 ]
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,5 @@
1
+ dependency :required
2
+
3
+ process :foo => :bar
4
+ process :nyan => [:foo, :bar]
5
+ process :rick
@@ -0,0 +1,3 @@
1
+ dependey :templates
2
+
3
+ process :app => [:database,,,]
@@ -0,0 +1,4 @@
1
+ dependency :templates
2
+
3
+ process :app => [:database, :tiles]
4
+ process :tiles => :database
@@ -0,0 +1,19 @@
1
+ module Bowler
2
+ module DefinitionHelper
3
+
4
+ require 'ostruct'
5
+
6
+ def stub_definition
7
+ OpenStruct.new ({
8
+ :processes => [ :app1, :app2, :app3, :other, :a, :b, :c ],
9
+ :tree => {
10
+ :app1 => [ :app2, :app3 ],
11
+ :app2 => [ :app3 ],
12
+ :app3 => [ ],
13
+ :other => [ :a, :b, :c ]
14
+ }
15
+ })
16
+ end
17
+
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bowler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jordan Hatch
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-16 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: foreman
16
+ requirement: &70276368515620 !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: *70276368515620
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &70276368514980 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.2.2
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70276368514980
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70276368514300 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.8.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70276368514300
47
+ description:
48
+ email:
49
+ - jordan@jordanh.net
50
+ executables:
51
+ - bowl
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - lib/bowler/cli.rb
56
+ - lib/bowler/dependency_tree.rb
57
+ - lib/bowler/dsl.rb
58
+ - lib/bowler/version.rb
59
+ - lib/bowler.rb
60
+ - README.md
61
+ - Rakefile
62
+ - spec/dependency_tree_spec.rb
63
+ - spec/dsl_spec.rb
64
+ - spec/fixtures/dependency_tree_pinfile
65
+ - spec/fixtures/dsl_invalid_pinfile
66
+ - spec/fixtures/dsl_valid_pinfile
67
+ - spec/helpers/definition_helper.rb
68
+ - bin/bowl
69
+ homepage:
70
+ licenses: []
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ segments:
82
+ - 0
83
+ hash: 1393360155367898551
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ segments:
91
+ - 0
92
+ hash: 1393360155367898551
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 1.8.12
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: A wrapper for large Foreman-managed apps with dependent processes
99
+ test_files:
100
+ - spec/dependency_tree_spec.rb
101
+ - spec/dsl_spec.rb
102
+ - spec/fixtures/dependency_tree_pinfile
103
+ - spec/fixtures/dsl_invalid_pinfile
104
+ - spec/fixtures/dsl_valid_pinfile
105
+ - spec/helpers/definition_helper.rb