zombees 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/.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
|