Permalink
Browse files

Initial commit of gem files

  • Loading branch information...
0 parents commit 8509cad0dff14f8bf459aae54f49053c0282446b @JordanHatch committed Mar 16, 2012
@@ -0,0 +1,2 @@
+.DS_Store
+pkg/*
@@ -0,0 +1,3 @@
+source "http://rubygems.org"
+
+gemspec
@@ -0,0 +1,32 @@
+PATH
+ remote: .
+ specs:
+ bowler (0.0.1)
+ foreman
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ diff-lcs (1.1.3)
+ foreman (0.27.0)
+ term-ansicolor (~> 1.0.5)
+ thor (>= 0.13.6)
+ rake (0.9.2.2)
+ rspec (2.8.0)
+ rspec-core (~> 2.8.0)
+ rspec-expectations (~> 2.8.0)
+ rspec-mocks (~> 2.8.0)
+ rspec-core (2.8.0)
+ rspec-expectations (2.8.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.8.0)
+ term-ansicolor (1.0.7)
+ thor (0.14.6)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ bowler!
+ rake (~> 0.9.2.2)
+ rspec (~> 2.8.0)
@@ -0,0 +1,3 @@
+# Bowler
+
+Bowler is a gem to manage process dependencies in Foreman.
@@ -0,0 +1,18 @@
+# -*- encoding: utf-8 -*-
+
+require "bundler/gem_tasks"
+require "rdoc/task"
+require 'rspec/core/rake_task'
+
+RDoc::Task.new do |rd|
+ rd.rdoc_files.include("lib/**/*.rb")
+ rd.rdoc_dir = "rdoc"
+end
+
+desc "Run specs"
+RSpec::Core::RakeTask.new do |t|
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
+ # Put spec opts in a file named .rspec in root
+end
+
+task :default => :spec
@@ -0,0 +1,5 @@
+#!/usr/bin/env ruby
+require 'bowler'
+require 'bowler/cli'
+
+Bowler::CLI.start(ARGV)
@@ -0,0 +1,27 @@
+# -*- encoding: utf-8 -*-
+lib = File.expand_path('../lib/', __FILE__)
+$:.unshift lib unless $:.include?(lib)
+
+require 'bowler/version'
+
+Gem::Specification.new do |s|
+ s.name = "bowler"
+ s.version = Bowler::VERSION
+ s.platform = Gem::Platform::RUBY
+ s.authors = ["Jordan Hatch"]
+ s.email = ["jordan@jordanh.net"]
+ s.summary = %q{A wrapper for large Foreman-managed apps with dependent processes}
+
+ s.files = Dir.glob("lib/**/*") + %w(README.md Rakefile)
+ s.test_files = Dir['test/**/*']
+ s.require_path = 'lib'
+
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ s.executables = %w(bowl)
+ s.require_paths = ["lib"]
+
+ s.add_dependency 'foreman'
+
+ s.add_development_dependency 'rake', '~> 0.9.2.2'
+ s.add_development_dependency 'rspec', '~> 2.8.0'
+end
@@ -0,0 +1,11 @@
+require 'ostruct'
+
+module Bowler
+
+ autoload :DependencyTree, 'bowler/dependency_tree'
+ autoload :DSL, 'bowler/dsl'
+
+ class PinfileNotFound < Exception; end
+ class PinfileError < Exception; end
+
+end
@@ -0,0 +1,28 @@
+require 'logger'
+
+module Bowler
+ class CLI
+
+ def self.start(processes)
+ tree = Bowler::DependencyTree.load
+ process_list = processes.map(&:to_sym)
+
+ launch_string = tree.process_list_for(process_list)
+
+ logger.info "Starting #{tree.dependencies_for(process_list).join(', ')}.."
+
+ exec( self.build_command launch_string )
+ rescue PinfileNotFound
+ logger.error "Bowler could not find a Pinfile in the current directory."
+ end
+
+ def self.logger
+ @logger ||= Logger.new(STDOUT)
+ end
+
+ def self.build_command(launch_string)
+ "foreman start -c #{launch_string}"
+ end
+
+ end
+end
@@ -0,0 +1,30 @@
+module Bowler
+
+ class DependencyTree
+
+ # Load the Pinfile
+ def self.load(absolute_path = nil)
+ absolute_path ||= File.join( Dir.pwd, 'Pinfile' )
+ definition = DSL.evaluate(absolute_path)
+ self.new(definition)
+ end
+
+ def initialize(definition)
+ @definition = definition
+ end
+
+ def dependencies_for(processes)
+ processes.inject([]) do |array, p|
+ array += [ (@definition.tree[p] || []), p ].flatten
+ end.uniq
+ end
+
+ def process_list_for(processes)
+ on = dependencies_for(processes)
+ off = @definition.processes.reject {|i| on.include? i }
+
+ [ on.map {|x| "#{x}=1" }.join(','), off.map {|x| "#{x}=0" }.join(',') ].flatten.join(',')
+ end
+
+ end
+end
@@ -0,0 +1,48 @@
+module Bowler
+ class DSL
+ def self.evaluate(pinfile)
+ dsl = new
+ dsl.eval_pinfile(pinfile)
+ dsl.to_definition
+ end
+
+ def eval_pinfile(pinfile)
+ raise PinfileNotFound unless File.exists?(pinfile)
+ file = File.read(pinfile)
+ instance_eval( file )
+ rescue SyntaxError => e
+ raise PinfileError, e
+ end
+
+ def initialize
+ @processes = []
+ @global_dependencies = []
+ end
+
+ def dependency(*dependencies)
+ @global_dependencies += [dependencies].flatten
+ end
+
+ def process(params)
+ if params.is_a? Hash
+ parent = params.keys.first
+ dependencies = [params.values.first]
+
+ @processes << { :process => parent, :dependencies => [dependencies].flatten }
+ else
+ @processes << { :process => params, :dependencies => [ ] }
+ end
+ end
+
+ def to_definition
+ definition = {
+ :tree => @processes.each_with_object({}) {|p, hash|
+ hash[p[:process]] = (p[:dependencies] + @global_dependencies).uniq
+ },
+ :processes => (@processes.map {|x| x[:process]} + @global_dependencies).uniq
+ }
+ OpenStruct.new(definition)
+ end
+
+ end
+end
@@ -0,0 +1,3 @@
+module Bowler
+ VERSION = '0.0.1'
+end
@@ -0,0 +1,50 @@
+require 'bowler'
+require_relative 'helpers/definition_helper'
+
+module Bowler
+
+ describe DependencyTree do
+
+ include DefinitionHelper
+
+ context "given a Pinfile" do
+ it "should load a dependency tree" do
+ tree = DependencyTree.load File.join( File.dirname(__FILE__), 'fixtures', 'dependency_tree_pinfile' )
+
+ tree.should be_instance_of DependencyTree
+ tree.dependencies_for([:foo]).should == [:bar, :required, :foo]
+ tree.dependencies_for([:nyan]).should == [:foo, :bar, :required, :nyan]
+ end
+ end
+
+ context "given an array of one process" do
+ before do
+ @tree = DependencyTree.new stub_definition
+ end
+
+ it "should find the correct dependencies" do
+ @tree.dependencies_for([:app1]).should == [:app2, :app3, :app1]
+ end
+
+ it "should give a correct process list" do
+ @tree.process_list_for([:app2]).should == "app3=1,app2=1,app1=0"
+ end
+ end
+
+ context "given an array of multiple processes" do
+ before do
+ @tree = DependencyTree.new stub_definition
+ end
+
+ it "should find the correct dependencies" do
+ @tree.dependencies_for([:app1, :other]).should == [:app2, :app3, :app1, :a, :b, :c, :other]
+ end
+
+ it "should give a correct process list" do
+ @tree.process_list_for([:app2, :other]).should == "app3=1,app2=1,a=1,b=1,c=1,other=1,app1=0"
+ end
+ end
+
+ end
+
+end
@@ -0,0 +1,5 @@
+dependency :required
+
+process :foo => :bar
+process :nyan => [:foo, :bar]
+process :rick
@@ -0,0 +1,19 @@
+module Bowler
+ module DefinitionHelper
+
+ require 'ostruct'
+
+ def stub_definition
+ OpenStruct.new ({
+ :processes => [ :app1, :app2, :app3 ],
+ :tree => {
+ :app1 => [ :app2, :app3 ],
+ :app2 => [ :app3 ],
+ :app3 => [ ],
+ :other => [ :a, :b, :c ]
+ }
+ })
+ end
+
+ end
+end

0 comments on commit 8509cad

Please sign in to comment.