cumuli 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5e3ea3081971fb3671f1b98e50f1d7140bb23587
4
+ data.tar.gz: 9eb5f33068ba05c2dfc927d8b0e0b320acbe28e9
5
+ SHA512:
6
+ metadata.gz: 570630e93591b54fdb115244de8969f3b2a739f470c74133f8e4b72bfe7ca14892a6b060ea3a316a704b2b9502c179aced952c5e0d04ff0fd02259eca57adf42
7
+ data.tar.gz: 556f8513559a6d74c80a46813c13d27b15b17b4a23c631082d140d5132ffa73517270840c60496f716d42209b0159c19adc10d925a57cf6f4286cf9359d378f0
data/.gitignore ADDED
@@ -0,0 +1,18 @@
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
18
+ Procfile
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.rvmrc ADDED
@@ -0,0 +1,6 @@
1
+ rvm_install_on_use_flag=1
2
+ rvm_trust_rvmrcs_flag=1
3
+ rvm_gemset_create_on_use_flag=1
4
+
5
+ rvm use 2.0.0@strawboss --create
6
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in strawboss.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 SocialChorus, Inc.
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.
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # Cumuli
2
+
3
+ In the land of Service Oriented Architecture, knowing whether everything
4
+ is communicating properly is hard. Strawboss is a tool for running many
5
+ foreman runnable applications, in different directories, from a single
6
+ process. This is a great way to see if the services that are distributed
7
+ over Heroku apps, actually are working together as expected.
8
+
9
+ We use strawboss as a way to reality check in a full development
10
+ sandbox; to write integration specs; and as a staging ground for broad
11
+ ranging deploy scripts or data migrations.
12
+
13
+ See usage for more details.
14
+
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ gem 'cumuli'
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install cumuli
29
+
30
+ ## Usage
31
+
32
+ ### Command line interface for Procfiles
33
+
34
+ Strawboss has a command-line interface that can be used via
35
+ a parent Procfile. This allows procfiles to point to other
36
+ applications, with their own Procfiles. This is what the parent
37
+ Procfile might look like:
38
+
39
+ rails_app_1: cumuli ../rails_app_1 -p 3000
40
+ rails_app_2: cumuli ../rails_app_2 -p 4000
41
+ node_app: cumuli ../node_app -p 5000
42
+
43
+ Currently, cumuli works via .rvmrc files. Ruby version files are not
44
+ yet implemented, but cumuli will use the rvm environment described in
45
+ the .rvmrc file.
46
+
47
+ ### App for intergration testing
48
+
49
+ Running a set of applications in tandem is great for sandboxing, but
50
+ ultimately we need to do integration testing across services and apps.
51
+ Cumuli comes with an application component that can be run in test
52
+ framework.
53
+
54
+ # Both initialization argument are optional
55
+ # first argument: environment
56
+ # second argument: whether to try to establish a connection to
57
+ # each of the apps with a port before continuing in the thread
58
+ app = Cumuli::App.new('test', false)
59
+
60
+ app.start # starts all the applications and services in the Procfile
61
+
62
+ app.pid # pid of top level foreman process
63
+
64
+ app.wait_for_app(5000) # wait for app on port 5000
65
+ # alternately app.wait_for_apps will wait for every app in the
66
+ # Procfile that has a port
67
+ #
68
+ # or just don't pass false into the initializer!
69
+
70
+ app.stop # gracefully kills all the related processes
71
+
72
+ ## Contributing
73
+
74
+ 1. Fork it
75
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
76
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
77
+ 4. Push to the branch (`git push origin my-new-feature`)
78
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ desc "kill the ruby stuff, debugging script"
4
+ task :kill_rubies do
5
+ ps_list = `ps axo pid,comm | grep ruby`
6
+ pids = ps_list.lines.map(&:split).map(&:first).map(&:to_i) - [Process.pid]
7
+ pids.each do |pid|
8
+ Process.kill("SIGINT", pid)
9
+ end
10
+ end
11
+
12
+ task :ps do
13
+ ps = `ps axo pid,ppid,comm,args,user`
14
+ puts ps.lines.select{|l| l.match(/ruby|resque|foreman|rvm/)}
15
+ end
data/bin/cumuli ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "cumuli"
4
+
5
+ Cumuli::CLI.new.run
data/cumuli.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cumuli/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cumuli"
8
+ spec.version = Cumuli::VERSION
9
+ spec.authors = ["SocialChorus", "Kane Baccigalupi", "Fito von Zastrow"]
10
+ spec.email = ["developers@socialchorus.com"]
11
+ spec.description = %q{Cumuli runs several foreman processes in different directories}
12
+ spec.summary = %q{Cumuli makes SOA on Heroku easier by delegating to Foreman in a Procfile}
13
+ spec.homepage = "http://github.com/socialchorus/cumuli"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "rspec"
22
+ spec.add_development_dependency "foreman"
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
@@ -0,0 +1,18 @@
1
+ module Cumuli
2
+ class Args
3
+ attr_reader :argv, :dir
4
+
5
+ def initialize(argv)
6
+ @argv = argv
7
+ @dir ||= argv.shift
8
+ end
9
+
10
+ def name
11
+ @name ||= dir.match(/([a-z_]+)$/i)[0]
12
+ end
13
+
14
+ def foreman_options
15
+ argv.join(' ')
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,43 @@
1
+ module Cumuli
2
+ class CLI
3
+ def run
4
+ spawn_app
5
+ end
6
+
7
+ def args
8
+ @args ||= Args.new(ARGV.dup)
9
+ end
10
+
11
+ def spawn_app
12
+ listen_for_signals
13
+
14
+ Dir.chdir(args.dir) do
15
+ command = Commander.new(args).build
16
+ puts "starting ... #{command}"
17
+ spawn_terminal(command)
18
+ end
19
+ end
20
+
21
+ def signals
22
+ # these are the signals used by Foreman
23
+ ['TERM', 'INT', 'HUP']
24
+ end
25
+
26
+ def listen_for_signals
27
+ signals.each do |signal|
28
+ Signal.trap(signal) do
29
+ kill_process
30
+ end
31
+ end
32
+ end
33
+
34
+ def kill_process
35
+ Process.kill('INT', Process.pid)
36
+ end
37
+
38
+ def spawn_terminal(command)
39
+ Terminal.new(command).spawn
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,29 @@
1
+ module Cumuli
2
+ class Commander
3
+ attr_reader :args
4
+
5
+ def initialize(args)
6
+ @args = args
7
+ end
8
+
9
+ def build
10
+ "#{rvm_preface} foreman start #{args.foreman_options}"
11
+ end
12
+
13
+ def rvm_preface
14
+ "rvm ruby-#{rvm_version} exec" if rvmrc?
15
+ end
16
+
17
+ def rvmrc_descriptor
18
+ './.rvmrc'
19
+ end
20
+
21
+ def rvmrc?
22
+ File.exist?(rvmrc_descriptor)
23
+ end
24
+
25
+ def rvm_version
26
+ File.read(rvmrc_descriptor).match(/(\d\.\d\.\d@\w+)/)[0]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ module Cumuli
2
+ class Terminal
3
+ VARS = ['GEM_HOME', 'GEM_PATH', 'RUBYOPT', 'RBENV_DIR']
4
+
5
+ attr_reader :command
6
+
7
+ def initialize(command)
8
+ @command = command
9
+ end
10
+
11
+ def bundled?
12
+ Object.const_defined?('Bundler')
13
+ end
14
+
15
+ def spawn
16
+ bundled? ? call_bundled : execute_command
17
+ end
18
+
19
+ def call_bundled
20
+ Bundler.with_clean_env do
21
+ clear_env
22
+ execute_command
23
+ end
24
+ end
25
+
26
+ def execute_command
27
+ exec(command)
28
+ end
29
+
30
+ def clear_env
31
+ VARS.each { |e| ENV.delete(e) }
32
+ end
33
+ end
34
+ end
35
+
data/lib/cumuli/cli.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "cumuli/cli/args"
2
+ require "cumuli/cli/cli"
3
+ require "cumuli/cli/commander"
4
+ require "cumuli/cli/terminal"
@@ -0,0 +1,3 @@
1
+ module Cumuli
2
+ VERSION = "0.1.0"
3
+ end
data/lib/cumuli.rb ADDED
@@ -0,0 +1,7 @@
1
+ $stdout.sync = true
2
+
3
+ lib = File.expand_path(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require "cumuli/cli"
7
+ require "cumuli/version"
data/spec/args_spec.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cumuli::Args do
4
+ let(:argv) { ["../mactivator", "-p", "4000"] }
5
+ let(:args) { Cumuli::Args.new(argv) }
6
+
7
+ it "#dir will return the first element passed in" do
8
+ args.dir.should == "../mactivator"
9
+ end
10
+
11
+ it "#name is correctly determined from the directory" do
12
+ args.name.should == 'mactivator'
13
+ end
14
+
15
+ it "#foreman_options should be a string representation of the rest of the arguments" do
16
+ args.foreman_options.should == '-p 4000'
17
+ end
18
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cumuli::Commander do
4
+ describe "#build" do
5
+ let(:args) { mock({foreman_options: 'foreman-options-here'}) }
6
+ let(:commander) { Cumuli::Commander.new(args) }
7
+
8
+ context "application directory has no .rvmrc" do
9
+ before do
10
+ commander.stub(:rvmrc?).and_return(false)
11
+ end
12
+
13
+ it "has not rvm preface" do
14
+ commander.build.should_not include('rvm')
15
+ end
16
+ end
17
+
18
+ context "application directory has an .rvmrc" do
19
+ before do
20
+ commander.stub(:rvm_version).and_return('1.9.3')
21
+ commander.stub(:rvmrc?).and_return(true)
22
+ end
23
+
24
+ it "has an rvm preface" do
25
+ commander.build.should include('rvm ruby-1.9.3 exec')
26
+ end
27
+ end
28
+
29
+ it "ends with a call to foreman" do
30
+ commander.build.should match(/foreman start foreman-options-here$/)
31
+ end
32
+
33
+ describe "reading from the file system" do
34
+ it "prefaces with the right rvm information" do
35
+ Dir.chdir(File.dirname(__FILE__) + "/fixtures/app_set/loopy") do
36
+ commander.build.should include('rvm ruby-2.0.0')
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1 @@
1
+ loopy: ../../bin/strawboss ./loopy
@@ -0,0 +1,5 @@
1
+ rvm_install_on_use_flag=1
2
+ rvm_trust_rvmrcs_flag=1
3
+ rvm_gemset_create_on_use_flag=1
4
+
5
+ rvm use 1.9.3@strawboss --create
@@ -0,0 +1,5 @@
1
+ while (true)
2
+ puts "Loop it when you can!"
3
+ sleep 4
4
+ end
5
+
@@ -0,0 +1,5 @@
1
+ while (true)
2
+ puts "Loop it if you can"
3
+ sleep 4
4
+ end
5
+
@@ -0,0 +1,5 @@
1
+ rvm_install_on_use_flag=1
2
+ rvm_trust_rvmrcs_flag=1
3
+ rvm_gemset_create_on_use_flag=1
4
+
5
+ rvm use 2.0.0@strawboss --create
@@ -0,0 +1,2 @@
1
+ loop_it_real_good: ruby loop.rb
2
+ loop_it_half_ass: ruby half_loop.rb
@@ -0,0 +1,5 @@
1
+ while (true)
2
+ puts "Loop it half good!"
3
+ sleep 2
4
+ end
5
+
@@ -0,0 +1,5 @@
1
+ while (true)
2
+ puts "Loop it real good!"
3
+ sleep 1
4
+ end
5
+
@@ -0,0 +1,9 @@
1
+ here = File.dirname(__FILE__)
2
+
3
+ require "#{here}/../lib/cumuli"
4
+ Dir["#{here}/support/**/*.rb"].each {|f| require f}
5
+
6
+ require 'pty'
7
+
8
+ RSpec.configure do |config|
9
+ end
@@ -0,0 +1,20 @@
1
+ def preserving_env
2
+ old_env = ENV.to_hash
3
+ begin
4
+ yield
5
+ ensure
6
+ ENV.clear
7
+ ENV.update(old_env)
8
+ end
9
+ end
10
+
11
+ def capture_stdout
12
+ old_stdout = $stdout.dup
13
+ rd, wr = IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe("BINARY")
14
+ $stdout = wr
15
+ yield
16
+ wr.close
17
+ rd.read
18
+ ensure
19
+ $stdout = old_stdout
20
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cumuli::Terminal do
4
+ it "clears environmental variables" do
5
+ preserving_env do
6
+ ENV['GEM_HOME'] = 'somewhere-over-the-rainbow'
7
+
8
+ terminal = Cumuli::Terminal.new('$GEM_HOME')
9
+ terminal.clear_env
10
+
11
+ ENV['GEM_HOME'].should == nil
12
+ end
13
+ end
14
+
15
+ it "spawns a new thread that runs the command" do
16
+ preserving_env do
17
+ pid = fork do
18
+ Cumuli::Terminal.new('STRAWBOSSED=true').spawn
19
+ ENV['STRAWBOSSED'].should == true
20
+ end
21
+ Process.kill('INT', pid)
22
+ end
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cumuli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - SocialChorus
8
+ - Kane Baccigalupi
9
+ - Fito von Zastrow
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-07-09 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: foreman
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: bundler
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ version: '1.3'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: '1.3'
57
+ - !ruby/object:Gem::Dependency
58
+ name: rake
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ description: Cumuli runs several foreman processes in different directories
72
+ email:
73
+ - developers@socialchorus.com
74
+ executables:
75
+ - cumuli
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - .gitignore
80
+ - .rspec
81
+ - .rvmrc
82
+ - Gemfile
83
+ - LICENSE.txt
84
+ - README.md
85
+ - Rakefile
86
+ - bin/cumuli
87
+ - cumuli.gemspec
88
+ - lib/cumuli.rb
89
+ - lib/cumuli/cli.rb
90
+ - lib/cumuli/cli/args.rb
91
+ - lib/cumuli/cli/cli.rb
92
+ - lib/cumuli/cli/commander.rb
93
+ - lib/cumuli/cli/terminal.rb
94
+ - lib/cumuli/version.rb
95
+ - spec/args_spec.rb
96
+ - spec/commander_spec.rb
97
+ - spec/fixtures/app_set/Procfile
98
+ - spec/fixtures/app_set/legacied/.rvmrc
99
+ - spec/fixtures/app_set/legacied/half_loop.rb
100
+ - spec/fixtures/app_set/legacied/quarter_loop.rb
101
+ - spec/fixtures/app_set/loopy/.rvmrc
102
+ - spec/fixtures/app_set/loopy/Procfile
103
+ - spec/fixtures/app_set/loopy/half_loop.rb
104
+ - spec/fixtures/app_set/loopy/loop.rb
105
+ - spec/spec_helper.rb
106
+ - spec/support/functional_helpers.rb
107
+ - spec/terminal_spec.rb
108
+ homepage: http://github.com/socialchorus/cumuli
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.0.3
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Cumuli makes SOA on Heroku easier by delegating to Foreman in a Procfile
132
+ test_files:
133
+ - spec/args_spec.rb
134
+ - spec/commander_spec.rb
135
+ - spec/fixtures/app_set/Procfile
136
+ - spec/fixtures/app_set/legacied/.rvmrc
137
+ - spec/fixtures/app_set/legacied/half_loop.rb
138
+ - spec/fixtures/app_set/legacied/quarter_loop.rb
139
+ - spec/fixtures/app_set/loopy/.rvmrc
140
+ - spec/fixtures/app_set/loopy/Procfile
141
+ - spec/fixtures/app_set/loopy/half_loop.rb
142
+ - spec/fixtures/app_set/loopy/loop.rb
143
+ - spec/spec_helper.rb
144
+ - spec/support/functional_helpers.rb
145
+ - spec/terminal_spec.rb