zombees 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +104 -0
- data/Guardfile +24 -0
- data/README.md +51 -0
- data/Rakefile +20 -0
- data/ab_adapter_example.rb +10 -0
- data/lib/zombees/ab_adapter.rb +119 -0
- data/lib/zombees/connection.rb +16 -0
- data/lib/zombees/honey_comb.rb +22 -0
- data/lib/zombees/queen.rb +38 -0
- data/lib/zombees/swarm.rb +59 -0
- data/lib/zombees/swarm_options.rb +18 -0
- data/lib/zombees/version.rb +3 -0
- data/lib/zombees/worker.rb +45 -0
- data/lib/zombees.rb +3 -0
- data/spec/fixtures/ab.txt +45 -0
- data/spec/integration/running_a_server_swarm_spec.rb +24 -0
- data/spec/integration/worker_spec.rb +43 -0
- data/spec/integration_spec_helper.rb +3 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/zombees/ab_adapter_spec.rb +139 -0
- data/spec/zombees/command_role_spec.rb +9 -0
- data/spec/zombees/connection_spec.rb +47 -0
- data/spec/zombees/honey_comb_spec.rb +17 -0
- data/spec/zombees/queen_spec.rb +29 -0
- data/spec/zombees/swarm_spec.rb +90 -0
- data/tourfleet +27 -0
- data/tourfleet.pub +1 -0
- data/zombee.png +0 -0
- data/zombees.gemspec +34 -0
- metadata +286 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'integration_spec_helper'
|
2
|
+
require 'zombees'
|
3
|
+
require 'zombees/honey_comb'
|
4
|
+
|
5
|
+
module Zombees
|
6
|
+
describe Worker, integration: true do
|
7
|
+
before(:each) { Fog.mock! }
|
8
|
+
let(:config) {{
|
9
|
+
provider: 'AWS',
|
10
|
+
aws_access_key_id: 'asdf',
|
11
|
+
aws_secret_access_key: 'ghi'
|
12
|
+
}}
|
13
|
+
let(:worker) { HoneyComb.new(config).worker }
|
14
|
+
|
15
|
+
it 'creates a worker instance' do
|
16
|
+
expect(worker).to be_a(described_class)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'prepares a worker on bootstrap' do
|
20
|
+
worker.bootstrap
|
21
|
+
expect(worker).to be_ready
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should destroy the server if its ready', focus: true do
|
25
|
+
worker.bootstrap
|
26
|
+
worker.server.should_receive(:destroy)
|
27
|
+
worker.shutdown
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should not destroy the server if ts not ready to shutdown', focus: true do
|
31
|
+
worker.bootstrap
|
32
|
+
worker.server.stub(:ready?, false)
|
33
|
+
worker.server.should_not_receive(:destroy)
|
34
|
+
worker.shutdown
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'runs the command request on a worker' do
|
38
|
+
worker.bootstrap
|
39
|
+
stdout = worker.run_command('ls')
|
40
|
+
stdout.should_not be_nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'zombees'
|
2
|
+
require 'pry'
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
5
|
+
config.run_all_when_everything_filtered = true
|
6
|
+
config.filter_run :focus
|
7
|
+
|
8
|
+
config.order = 'random'
|
9
|
+
|
10
|
+
config.filter_run_excluding :integration
|
11
|
+
if ENV['CI']
|
12
|
+
config.filter_run_excluding :local
|
13
|
+
require 'coveralls'
|
14
|
+
Coveralls.wear!('test_frameworks')
|
15
|
+
elsif ENV['COVERAGE']
|
16
|
+
require 'simplecov'
|
17
|
+
SimpleCov.start('test_frameworks')
|
18
|
+
end
|
19
|
+
|
20
|
+
config.before(:each) do
|
21
|
+
#TODO Pull request to yell to expose level
|
22
|
+
require 'yell'
|
23
|
+
module Yell
|
24
|
+
class Logger
|
25
|
+
attr_accessor :level
|
26
|
+
end
|
27
|
+
end
|
28
|
+
Yell[Object].level = Yell.level.gt(:error)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fog'
|
3
|
+
require 'zombees/ab_adapter'
|
4
|
+
|
5
|
+
module Zombees
|
6
|
+
describe AbAdapter do
|
7
|
+
|
8
|
+
|
9
|
+
it 'prepares the worker supplied' do
|
10
|
+
worker = mock('worker')
|
11
|
+
worker.should_receive(:run_command).with(/apt-get -y update.*apt-get -y install/)
|
12
|
+
subject.prepare(worker)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'runs a command on a command object' do
|
16
|
+
worker = stub('worker')
|
17
|
+
mock_command = mock('command')
|
18
|
+
subject.command_source = ->(config) { mock_command }
|
19
|
+
|
20
|
+
mock_command.should_receive(:run).with(worker)
|
21
|
+
|
22
|
+
subject.run(worker)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'runs a command with specified config' do
|
26
|
+
expected_config = { hello: 'world' }
|
27
|
+
subject = described_class.new(expected_config)
|
28
|
+
worker = stub('worker')
|
29
|
+
|
30
|
+
subject.command_source = ->(config) {
|
31
|
+
config.should == expected_config
|
32
|
+
stub('command').as_null_object
|
33
|
+
}
|
34
|
+
|
35
|
+
subject.run(worker)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'parsers the command result' do
|
39
|
+
mock_parser = mock('parser')
|
40
|
+
AbAdapter::Parser.stub(:new).with(hello: 'world').and_return(mock_parser)
|
41
|
+
mock_parser.should_receive(:parse)
|
42
|
+
|
43
|
+
described_class.new.parse(hello: 'world')
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'parses and aggregates the result' do
|
47
|
+
mock_parser = mock('parser')
|
48
|
+
mock_aggregator = mock('aggregator')
|
49
|
+
AbAdapter::Parser.stub(:new).with(hello: 'world').and_return(mock_parser)
|
50
|
+
AbAdapter::Aggregator.stub(:new).with(command: 'results').and_return(mock_aggregator)
|
51
|
+
mock_parser.should_receive(:parse).and_return(command: 'results')
|
52
|
+
mock_aggregator.should_receive(:aggregate)
|
53
|
+
|
54
|
+
described_class.new.aggregate(hello: 'world')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe AbAdapter::Command do
|
59
|
+
context 'command generation' do
|
60
|
+
subject { described_class.new(requests: 1000, concurrency: 5, url: 'http://a.co', ab_options: '--foo').command }
|
61
|
+
it { should match '^ab' }
|
62
|
+
it("doesn't exit on socket receive") { should match '-r' }
|
63
|
+
it('should specify number of requests') { should match '-n 1000' }
|
64
|
+
it('should specify concurrency') { should match '-c 5' }
|
65
|
+
it('should set a dummy session id') { should match '-C "sessionid=fake"' }
|
66
|
+
it('should send extra options to ab') { should match '--foo' }
|
67
|
+
it('should pass the url') { should match '"http://a.co"$' }
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'generate a valid ab command', integration: true, local: true do
|
71
|
+
command = described_class.new(requests: 1, concurrency: 1, url: 'http://www.google.com/').command + "> /dev/null"
|
72
|
+
result = system(command)
|
73
|
+
result.should be_true
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'executes a command on a worker' do
|
77
|
+
subject.stub(:command).and_return('ab')
|
78
|
+
worker = mock('Worker')
|
79
|
+
worker.should_receive(:run_command).with('ab')
|
80
|
+
subject.run(worker)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe AbAdapter::Parser do
|
85
|
+
let(:output) { IO.read File.expand_path("../../fixtures/ab.txt", __FILE__) }
|
86
|
+
|
87
|
+
it 'transforms results of the ab command into a hash of data' do
|
88
|
+
data = described_class.parse(output)
|
89
|
+
data.should have_key(:requests_per_second)
|
90
|
+
data[:requests_per_second].should eq 120.06
|
91
|
+
data[:time_per_request].should eq 83.295
|
92
|
+
data[:time_per_request_concurrent].should eq 8.329
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'transforms results of the run command' do
|
96
|
+
command_results = 3.downto(1).map do |i|
|
97
|
+
[ stub(:command, stdout: output) ]
|
98
|
+
end
|
99
|
+
parser = described_class.new(command_results)
|
100
|
+
data = parser.parse
|
101
|
+
data.should have(3).results
|
102
|
+
end
|
103
|
+
end
|
104
|
+
describe AbAdapter::Aggregator do
|
105
|
+
it 'doesnt have any keys if input doesnt have any' do
|
106
|
+
input = [{foo: :bar},{baz: :bat}]
|
107
|
+
subject = described_class.new(input)
|
108
|
+
result = subject.aggregate
|
109
|
+
result.should_not have_key(:time_per_request)
|
110
|
+
result.should_not have_key(:complete_requests)
|
111
|
+
end
|
112
|
+
it 'totalize number of completed requests' do
|
113
|
+
input = [{complete_requests: 10}, {complete_requests: 15}]
|
114
|
+
subject = described_class.new(input)
|
115
|
+
result = subject.aggregate
|
116
|
+
result.should have_key(:complete_requests)
|
117
|
+
result[:complete_requests].should == 25
|
118
|
+
end
|
119
|
+
it 'totalize number of completed requests' do
|
120
|
+
input = [{failed_requests: 2}, {failed_requests: 1}]
|
121
|
+
subject = described_class.new(input)
|
122
|
+
result = subject.aggregate
|
123
|
+
result.should have_key(:failed_requests)
|
124
|
+
result[:failed_requests].should == 3
|
125
|
+
end
|
126
|
+
it 'averages time per request' do
|
127
|
+
input = [{time_per_request: 1.2}, {time_per_request: 1.6}]
|
128
|
+
subject = described_class.new(input)
|
129
|
+
result = subject.aggregate
|
130
|
+
result.should have_key(:time_per_request)
|
131
|
+
result[:time_per_request].should == 1.4
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
describe Fog::SSH::Result do
|
138
|
+
it { described_class.instance_methods.should include :stdout }
|
139
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'zombees/connection'
|
2
|
+
require 'celluloid/pmap'
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Zombees
|
6
|
+
describe Connection do
|
7
|
+
describe '#instance' do
|
8
|
+
before do
|
9
|
+
Fog::Compute.stub(:new).and_return(stub(key_pairs: stub(get: true)))
|
10
|
+
end
|
11
|
+
|
12
|
+
# it 'creates a single instance for the same config' do
|
13
|
+
# config = {foo: 'bar'}
|
14
|
+
# first_connection = Connection.instance(config)
|
15
|
+
# second_connection = Connection.instance(config)
|
16
|
+
#
|
17
|
+
# first_connection.should_not be_nil
|
18
|
+
# first_connection.object_id.should == second_connection.object_id
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# it 'creates a multiple instances for different config' do
|
22
|
+
# first_connection = Connection.instance(foo: :bar)
|
23
|
+
# second_connection = Connection.instance(baz: :bat)
|
24
|
+
#
|
25
|
+
# first_connection.should_not be_nil
|
26
|
+
# first_connection.object_id.should_not == second_connection.object_id
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# it 'creates a single instance for the same config when instantiated from multiple threads', focus: true do
|
30
|
+
# # Faking wait on fog instantiation
|
31
|
+
# Fog::Compute.stub(:new) do
|
32
|
+
# sleep(rand(0.1..0.3))
|
33
|
+
# stub(key_pairs: stub(get: true))
|
34
|
+
# end
|
35
|
+
# config = {some_key: rand(1..10)}
|
36
|
+
# connections = 10.downto(1).pmap do
|
37
|
+
# Connection.instance(config)
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# connections.each_cons(2) do |first, second|
|
41
|
+
# first.should_not be_nil
|
42
|
+
# first.object_id.should == second.object_id
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Zombees
|
4
|
+
describe HoneyComb do
|
5
|
+
before do
|
6
|
+
Connection.stub(:import_key_pair)
|
7
|
+
end
|
8
|
+
it 'stores a configuration' do
|
9
|
+
honeycomb = described_class.new(foo: :bar)
|
10
|
+
expect(honeycomb.config[:foo]).to eq :bar
|
11
|
+
end
|
12
|
+
it 'imports key pair' do
|
13
|
+
Connection.should_receive(:import_key_pair).with(foo: :bar)
|
14
|
+
honeycomb = described_class.new(foo: :bar)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'zombees/queen'
|
3
|
+
|
4
|
+
module Zombees
|
5
|
+
describe Queen do
|
6
|
+
let(:swarm) { mock('Swarm') }
|
7
|
+
let(:queen) {described_class.new(config: {}, worker_count: 3, command: "ls", swarm: swarm)}
|
8
|
+
|
9
|
+
before do
|
10
|
+
Connection.stub(:import_key_pair)
|
11
|
+
end
|
12
|
+
describe '#run' do
|
13
|
+
it 'runs the swarm' do
|
14
|
+
swarm.should_receive(:run)
|
15
|
+
queen.swarm_source = ->(options) { swarm }
|
16
|
+
queen.run
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'creates a swarm with default options' do
|
21
|
+
queen = described_class.new(config: {foo: :bar}, worker_count: 3, command: 'ls')
|
22
|
+
queen.swarm_source = ->(options) do
|
23
|
+
options.honey_comb.config[:foo].should eq :bar
|
24
|
+
stub(run: true)
|
25
|
+
end
|
26
|
+
queen.run
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'zombees/swarm'
|
3
|
+
require 'zombees/ab_adapter'
|
4
|
+
|
5
|
+
module Zombees
|
6
|
+
module NoopAdapter
|
7
|
+
def self.prepare(worker)
|
8
|
+
|
9
|
+
end
|
10
|
+
def self.run(worker)
|
11
|
+
|
12
|
+
end
|
13
|
+
def self.aggregate(whatever)
|
14
|
+
|
15
|
+
end
|
16
|
+
class Command
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
class NoopWorker
|
21
|
+
def bootstrap; self end
|
22
|
+
end
|
23
|
+
describe Swarm do
|
24
|
+
def generate_swarm(population)
|
25
|
+
described_class.new(options, population)
|
26
|
+
end
|
27
|
+
let(:swarm) { generate_swarm(nil) }
|
28
|
+
let(:options) { SwarmOptions.new(worker_count: 3, command: noop_adapter, honey_comb: honey_comb) }
|
29
|
+
let(:honey_comb) { stub(worker: worker) }
|
30
|
+
let(:worker) { NoopWorker.new }
|
31
|
+
let(:noop_adapter) { NoopAdapter }
|
32
|
+
|
33
|
+
it 'bootstraps requested number of servers' do
|
34
|
+
worker.should_receive(:bootstrap).exactly(3).times
|
35
|
+
|
36
|
+
swarm.breed
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'attempts shutdown if bootstrap fails' do
|
40
|
+
e = RuntimeError.new
|
41
|
+
worker.stub(:bootstrap).and_raise(e)
|
42
|
+
worker.should_receive(:shutdown).exactly(3).times.with(e)
|
43
|
+
|
44
|
+
swarm.breed
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'adds command-specific configuration to workers' do
|
48
|
+
noop_adapter.should_receive(:prepare).with(worker).exactly(3).times
|
49
|
+
|
50
|
+
swarm.breed
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'does not breed when already populated' do
|
54
|
+
worker.should_receive(:bootstrap).exactly(3).times.and_return(stub(run_command: true))
|
55
|
+
|
56
|
+
swarm.breed
|
57
|
+
swarm.breed
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
it 'distributes a command to the population of workers' do
|
62
|
+
workers = (1..3).map { |i| mock("Worker#{i}", shutdown: true) }
|
63
|
+
|
64
|
+
NoopAdapter.should_receive(:run).exactly(workers.size).times.and_return(true)
|
65
|
+
NoopAdapter.should_receive(:aggregate).with([true, true, true]).once.and_return(true)
|
66
|
+
swarm = generate_swarm(workers)
|
67
|
+
swarm.run
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'attempts to shutdown worker if run fails' do
|
71
|
+
worker = mock('Worker')
|
72
|
+
|
73
|
+
e = RuntimeError.new
|
74
|
+
NoopAdapter.stub(:run).and_raise(e)
|
75
|
+
swarm = generate_swarm([worker])
|
76
|
+
worker.should_receive(:shutdown)
|
77
|
+
swarm.run
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'attempts to shutdown worker if run fails' do
|
81
|
+
worker = mock('Worker')
|
82
|
+
|
83
|
+
e = RuntimeError.new
|
84
|
+
NoopAdapter.stub(:aggregate).and_return(true)
|
85
|
+
swarm = generate_swarm([worker])
|
86
|
+
worker.should_receive(:shutdown)
|
87
|
+
swarm.run
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/tourfleet
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIIEowIBAAKCAQEA2BRbCBTnbp++xa/VfI3cygPgBStFvqtKYatrq0BOjOwO/xMt
|
3
|
+
de1xf9z693ZZkpSb3arCeh/6eBU6dLDPMXLkYvRaOhbgFbwR78jUR5mZQYwOB6WY
|
4
|
+
SFc81YgKyrVGHHZQN+48xnaNHuYCR3RBdMnBSY/tRsKtMWSTgaCwSpVH5rTtEwYe
|
5
|
+
k0jy7cmIw6i/RecnmCkmhoEupW3780aj0uLEWML7w6/ID0JALVUyObemhjN1H/6q
|
6
|
+
3QoncfH1UvRqfEthMVSiQD8sp9ECK9JaMtCXEgPjXdlVatENsDHYCrHuHsACiGQm
|
7
|
+
W+j2JOdWrCXTE3FH7FHwNmraHH0EI4zj6kdK7QIDAQABAoIBACO9ejEkBAOwOIXK
|
8
|
+
R62KaXKgoXU5axfWjT8Kc4yn3lZA1VoreeF/nL5hdsFnufkcy4smq3Q3xd4G5NxY
|
9
|
+
Qm0Ta+NSN3pUPkxaBz16ImKVbVwCJm/tW/rbMxy+m8pboXUjvLEDntnU0hLCSK44
|
10
|
+
9Hq0xFu+iqihmrQIxr0yLvanKnVmOeEJLOeU8L/O/opxxG0uaaQSQzjJRw5WjhIc
|
11
|
+
ZMCJ+VYNqe3tZMHNHtXRaNqp2hlSgeoNEq0XubxRCO4MuW8iFi8SywevbWYdOCj4
|
12
|
+
yhgp6Q4wr92qgtonn2j2UBJTYFgn9i9cr1ryk2msnA2vkmrAeOOKyMO4jKTm7RY4
|
13
|
+
tLLAlgECgYEA7e9boFVEL+qwIAb1lAMezbjzZ5ElUBWK9sSlFz63PsSlUWUUexlW
|
14
|
+
NWuqvGTM+sA1E/Ei9FV5yahM8fGTmmP/94SJXGinbhg98i517qbi2O56SuPS23db
|
15
|
+
5dmJnyCZxu8MVoNqhGtJ+dM3aw+5ghj1QP5yoLJ4gjDFdt+sYX2gIPECgYEA6Hwz
|
16
|
+
tHJ/XpQDuJ7XeF58/vAfF049E9lv25oS7xVtmlw3XEG3Y0X75agnkC+KA+2/xHPX
|
17
|
+
ceWYI+EyBRo0/kqn3OUScyB2Lwg9I967YSIIir9dDddM71ruyh2PQliJcqzEJeUq
|
18
|
+
yN4/zb3xiF5eVUTayK0r6hhqHcphiq//PHBOib0CgYBd4dsSeXJtQbn6+SP/IfgO
|
19
|
+
jlKkY9YIMmfhlJfbgyiEwMzGQA8Dv2yPqYr1yQREUIDg/H2hUPS8CAdMU9i8y4Zd
|
20
|
+
INOePcEKpNAUdhaccwcBN5/TWu+BHyiImfw+aHukzf/dRv9Jfpfy1k+Ak/TLi5OB
|
21
|
+
8KREGgeIvzu6+uimkw4S0QKBgDSDEV652gEv56NE5aB/nzYqYKtv9aXNIFH2/D3a
|
22
|
+
ljYejDafdV/MB/i4wa70vfTjN8SU8d39IR9Bl33FjKC/lijz6PXuKCO5da3remGX
|
23
|
+
QVytmsQslGkgHf2zLY+r1ef8FBYHLGHQqZK8S5kkz6Ps+IoJa3jl6Novw1aDKGCr
|
24
|
+
cWH1AoGBAJz8/QJ+Dnmav70cX7faOlzTvzaNjqgWnZNAHXo/xxEG3MeIq5Oo6ae6
|
25
|
+
ADXnkU42kxs5FjnlTzpBZ/cYueHylDZydatUKsVngnnnm9drdnHinvatBctpQAbE
|
26
|
+
t2NOTCaWbsHRhRvZhUPCxYcrpEBAeOIrctf1hqnNFEWRN1vzpE58
|
27
|
+
-----END RSA PRIVATE KEY-----
|
data/tourfleet.pub
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYFFsIFOdun77Fr9V8jdzKA+AFK0W+q0phq2urQE6M7A7/Ey117XF/3Pr3dlmSlJvdqsJ6H/p4FTp0sM8xcuRi9Fo6FuAVvBHvyNRHmZlBjA4HpZhIVzzViArKtUYcdlA37jzGdo0e5gJHdEF0ycFJj+1Gwq0xZJOBoLBKlUfmtO0TBh6TSPLtyYjDqL9F5yeYKSaGgS6lbfvzRqPS4sRYwvvDr8gPQkAtVTI5t6aGM3Uf/qrdCidx8fVS9Gp8S2ExVKJAPyyn0QIr0loy0JcSA+Nd2VVq0Q2wMdgKse4ewAKIZCZb6PYk51asJdMTcUfsUfA2atocfQQjjOPqR0rt solomon@G10205.local
|
data/zombee.png
ADDED
Binary file
|
data/zombees.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'zombees/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "zombees"
|
8
|
+
spec.version = Zombees::VERSION
|
9
|
+
spec.authors = ["Maxim Filimonov","Solomon White"]
|
10
|
+
spec.email = ["tpaktopsp@gmail.com", "rubysolo@gmail.com"]
|
11
|
+
spec.description = %q{Zombees}
|
12
|
+
spec.summary = %q{Distributed load testing in Ruby}
|
13
|
+
spec.homepage = "http://github.com/zombees/zombees"
|
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_dependency 'celluloid-pmap'
|
22
|
+
spec.add_dependency 'celluloid', '~>0.13.0'
|
23
|
+
spec.add_dependency 'fog', '~>1.8.0'
|
24
|
+
spec.add_dependency 'net-ssh','~>2.5.0'
|
25
|
+
spec.add_dependency 'yell'
|
26
|
+
spec.add_dependency 'colorize'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'rspec'
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
30
|
+
spec.add_development_dependency "rake"
|
31
|
+
spec.add_development_dependency "guard-rspec"
|
32
|
+
spec.add_development_dependency 'emoji-rspec'
|
33
|
+
spec.add_development_dependency 'coveralls'
|
34
|
+
end
|