democracyworks-synapse 0.9.2

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.
@@ -0,0 +1,3 @@
1
+ module Synapse
2
+ VERSION = "0.9.2"
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ class MockWatcher; end;
4
+
5
+ describe Synapse::Haproxy do
6
+ subject { Synapse::Haproxy.new(config['haproxy']) }
7
+
8
+ it 'updating the config' do
9
+ mockWatcher = double(Synapse::ServiceWatcher)
10
+ subject.should_receive(:generate_config)
11
+ subject.update_config([mockWatcher])
12
+ end
13
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ class Synapse::BaseWatcher
4
+ attr_reader :should_exit, :default_servers
5
+ end
6
+
7
+ describe Synapse::BaseWatcher do
8
+ let(:mocksynapse) { double() }
9
+ subject { Synapse::BaseWatcher.new(args, mocksynapse) }
10
+ let(:testargs) { { 'name' => 'foo', 'discovery' => { 'method' => 'base' }, 'haproxy' => {} }}
11
+
12
+ def remove_arg(name)
13
+ args = testargs.clone
14
+ args.delete name
15
+ args
16
+ end
17
+
18
+ context "can construct normally" do
19
+ let(:args) { testargs }
20
+ it('can at least construct') { expect { subject }.not_to raise_error }
21
+ end
22
+
23
+ ['name', 'discovery', 'haproxy'].each do |to_remove|
24
+ context "without #{to_remove} argument" do
25
+ let(:args) { remove_arg to_remove }
26
+ it('gots bang') { expect { subject }.to raise_error(ArgumentError, "missing required option #{to_remove}") }
27
+ end
28
+ end
29
+
30
+ context "normal tests" do
31
+ let(:args) { testargs }
32
+ it('is running') { expect(subject.should_exit).to equal(false) }
33
+ it('can ping') { expect(subject.ping?).to equal(true) }
34
+ it('can be stopped') do
35
+ subject.stop
36
+ expect(subject.should_exit).to equal(true)
37
+ end
38
+ end
39
+
40
+ context "with default_servers" do
41
+ default_servers = ['server1', 'server2']
42
+ let(:args) { testargs.merge({'default_servers' => default_servers}) }
43
+ it('sets default backends to default_servers') { expect(subject.backends).to equal(default_servers) }
44
+
45
+ context "with keep_default_servers set" do
46
+ let(:args) { testargs.merge({'default_servers' => default_servers, 'keep_default_servers' => true}) }
47
+ let(:new_backends) { ['discovered1', 'discovered2'] }
48
+
49
+ it('keeps default_servers when setting backends') do
50
+ subject.send(:set_backends, new_backends)
51
+ expect(subject.backends).to eq(default_servers + new_backends)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+
3
+ class Synapse::DockerWatcher
4
+ attr_reader :check_interval, :watcher, :synapse
5
+ attr_accessor :default_servers
6
+ end
7
+
8
+ describe Synapse::DockerWatcher do
9
+ let(:mocksynapse) { double() }
10
+ subject { Synapse::DockerWatcher.new(testargs, mocksynapse) }
11
+ let(:testargs) { { 'name' => 'foo', 'discovery' => { 'method' => 'docker', 'servers' => [{'host' => 'server1.local', 'name' => 'mainserver'}], 'image_name' => 'mycool/image', 'container_port' => 6379 }, 'haproxy' => {} }}
12
+ before(:each) do
13
+ allow(subject.log).to receive(:warn)
14
+ allow(subject.log).to receive(:info)
15
+ end
16
+
17
+ def add_arg(name, value)
18
+ args = testargs.clone
19
+ args['discovery'][name] = value
20
+ args
21
+ end
22
+
23
+ context "can construct normally" do
24
+ it('can at least construct') { expect { subject }.not_to raise_error }
25
+ end
26
+
27
+ context "normal tests" do
28
+ it('starts a watcher thread') do
29
+ watcher_mock = double()
30
+ expect(Thread).to receive(:new).and_return(watcher_mock)
31
+ subject.start
32
+ expect(subject.watcher).to equal(watcher_mock)
33
+ end
34
+ it('sets default check interval') do
35
+ expect(Thread).to receive(:new).and_return(double)
36
+ subject.start
37
+ expect(subject.check_interval).to eq(15.0)
38
+ end
39
+ end
40
+
41
+ context "watch tests" do
42
+ before(:each) do
43
+ expect(subject).to receive(:sleep_until_next_check) do |arg|
44
+ subject.instance_variable_set('@should_exit', true)
45
+ end
46
+ end
47
+ it('has a happy first run path, configuring backends') do
48
+ expect(subject).to receive(:containers).and_return(['container1'])
49
+ expect(subject).to receive(:configure_backends).with(['container1'])
50
+ subject.send(:watch)
51
+ end
52
+ it('does not call configure_backends if there is no change') do
53
+ expect(subject).to receive(:containers).and_return([])
54
+ expect(subject).to_not receive(:configure_backends)
55
+ subject.send(:watch)
56
+ end
57
+ end
58
+ context "watch eats exceptions" do
59
+ it "blows up when finding containers" do
60
+ expect(subject).to receive(:containers) do |arg|
61
+ subject.instance_variable_set('@should_exit', true)
62
+ raise('throw exception inside watch')
63
+ end
64
+ expect { subject.send(:watch) }.not_to raise_error
65
+ end
66
+ end
67
+
68
+ context "configure_backends tests" do
69
+ before(:each) do
70
+ expect(subject.synapse).to receive(:'reconfigure!').at_least(:once)
71
+ end
72
+ it 'runs' do
73
+ expect { subject.send(:configure_backends, []) }.not_to raise_error
74
+ end
75
+ it 'sets backends right' do
76
+ subject.send(:configure_backends, ['foo'])
77
+ expect(subject.backends).to eq(['foo'])
78
+ end
79
+ it 'resets to default backends if no container found' do
80
+ subject.default_servers = ['fallback1']
81
+ subject.send(:configure_backends, ['foo'])
82
+ expect(subject.backends).to eq(['foo'])
83
+ subject.send(:configure_backends, [])
84
+ expect(subject.backends).to eq(['fallback1'])
85
+ end
86
+ it 'does not reset to default backends if there are no default backends' do
87
+ subject.default_servers = []
88
+ subject.send(:configure_backends, ['foo'])
89
+ expect(subject.backends).to eq(['foo'])
90
+ subject.send(:configure_backends, [])
91
+ expect(subject.backends).to eq(['foo'])
92
+ end
93
+ end
94
+
95
+ context "container discovery tests" do
96
+ before(:each) do
97
+ getter = double()
98
+ expect(getter).to receive(:get)
99
+ expect(Docker).to receive(:connection).and_return(getter)
100
+ end
101
+
102
+ it('has a sane uri') { subject.send(:containers); expect(Docker.url).to eql('http://server1.local:4243') }
103
+
104
+ context 'old style port mappings' do
105
+ context 'works for one container' do
106
+ let(:docker_data) { [{"Ports" => "0.0.0.0:49153->6379/tcp, 0.0.0.0:49154->6390/tcp", "Image" => "mycool/image:tagname"}] }
107
+ it do
108
+ expect(Docker::Util).to receive(:parse_json).and_return(docker_data)
109
+ expect(subject.send(:containers)).to eql([{"name"=>"mainserver", "host"=>"server1.local", "port"=>"49153"}])
110
+ end
111
+ end
112
+ context 'works for multiple containers' do
113
+ let(:docker_data) { [{"Ports" => "0.0.0.0:49153->6379/tcp, 0.0.0.0:49154->6390/tcp", "Image" => "mycool/image:tagname"}, {"Ports" => "0.0.0.0:49155->6379/tcp", "Image" => "mycool/image:tagname"}] }
114
+ it do
115
+ expect(Docker::Util).to receive(:parse_json).and_return(docker_data)
116
+ expect(subject.send(:containers)).to eql([{"name"=>"mainserver", "host"=>"server1.local", "port"=>"49153"},{"name"=>"mainserver", "host"=>"server1.local", "port"=>"49155"}])
117
+ end
118
+ end
119
+ end
120
+
121
+ context 'new style port mappings' do
122
+ let(:docker_data) { [{"Ports" => [{'PrivatePort' => 6379, 'PublicPort' => 49153}, {'PublicPort' => 49154, 'PrivatePort' => 6390}], "Image" => "mycool/image:tagname"}] }
123
+ it do
124
+ expect(Docker::Util).to receive(:parse_json).and_return(docker_data)
125
+ expect(subject.send(:containers)).to eql([{"name"=>"mainserver", "host"=>"server1.local", "port"=>"49153"}])
126
+ end
127
+ end
128
+
129
+ context 'filters out wrong images' do
130
+ let(:docker_data) { [{"Ports" => "0.0.0.0:49153->6379/tcp, 0.0.0.0:49154->6390/tcp", "Image" => "mycool/image:tagname"}, {"Ports" => "0.0.0.0:49155->6379/tcp", "Image" => "wrong/image:tagname"}] }
131
+ it do
132
+ expect(Docker::Util).to receive(:parse_json).and_return(docker_data)
133
+ expect(subject.send(:containers)).to eql([{"name"=>"mainserver", "host"=>"server1.local", "port"=>"49153"}])
134
+ end
135
+ end
136
+ end
137
+ end
138
+
@@ -0,0 +1,22 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ require "#{File.dirname(__FILE__)}/../lib/synapse"
8
+ require 'pry'
9
+ require 'support/config'
10
+
11
+ RSpec.configure do |config|
12
+ config.treat_symbols_as_metadata_keys_with_true_values = true
13
+ config.run_all_when_everything_filtered = true
14
+ config.filter_run :focus
15
+ config.include Config
16
+
17
+ # Run specs in random order to surface order dependencies. If you find an
18
+ # order dependency and want to debug it, you can fix the order by providing
19
+ # the seed, which is printed after each run.
20
+ # --seed 1234
21
+ config.order = 'random'
22
+ end
@@ -0,0 +1,9 @@
1
+ require "yaml"
2
+
3
+ module Config
4
+
5
+ def config
6
+ @config ||= YAML::load_file(File.join(File.dirname(File.expand_path(__FILE__)), 'minimum.conf.yaml'))
7
+ end
8
+
9
+ end
@@ -0,0 +1,27 @@
1
+ # list the services to connect
2
+ services:
3
+ - name: test
4
+ local_port: 3210
5
+ server_options: test_option
6
+ default_servers:
7
+ - { name: default1, host: localhost, port: 8080}
8
+ discovery:
9
+ method: zookeeper
10
+ path: /airbnb/service/logging/event_collector
11
+ hosts:
12
+ - localhost:2181
13
+ listen:
14
+ - test_option
15
+
16
+
17
+ # settings for haproxy including the global config
18
+ haproxy:
19
+ reload_command: "sudo service haproxy reload"
20
+ config_file_path: "/etc/haproxy/haproxy.cfg"
21
+ do_writes: false
22
+ do_reloads: false
23
+ global:
24
+ - global_test_option
25
+
26
+ defaults:
27
+ - default_test_option
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'synapse/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "democracyworks-synapse"
8
+ gem.version = Synapse::VERSION
9
+ gem.authors = ["Martin Rhoads", "Chris Shea"]
10
+ gem.email = ["martin.rhoads@airbnb.com", "chris@turbovote.org"]
11
+ gem.description = %q{: Write a gem description}
12
+ gem.summary = %q{: Write a gem summary}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+
19
+ gem.add_runtime_dependency "zk", "~> 1.9.2"
20
+ gem.add_runtime_dependency "docker-api", "~> 1.7.2"
21
+
22
+ gem.add_development_dependency "rspec"
23
+ gem.add_development_dependency "pry"
24
+ gem.add_development_dependency "pry-nav"
25
+ end
metadata ADDED
@@ -0,0 +1,155 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: democracyworks-synapse
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.2
5
+ platform: ruby
6
+ authors:
7
+ - Martin Rhoads
8
+ - Chris Shea
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: zk
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 1.9.2
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 1.9.2
28
+ - !ruby/object:Gem::Dependency
29
+ name: docker-api
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 1.7.2
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 1.7.2
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: pry
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: pry-nav
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ description: ": Write a gem description"
85
+ email:
86
+ - martin.rhoads@airbnb.com
87
+ - chris@turbovote.org
88
+ executables:
89
+ - synapse
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - ".mailmap"
95
+ - ".rspec"
96
+ - Gemfile
97
+ - Gemfile.lock
98
+ - LICENSE.txt
99
+ - Makefile
100
+ - README.md
101
+ - Rakefile
102
+ - bin/synapse
103
+ - config/hostheader_test.json
104
+ - config/svcdir_test.json
105
+ - config/synapse.conf.json
106
+ - config/synapse_services/service1.json
107
+ - config/synapse_services/service2.json
108
+ - lib/synapse.rb
109
+ - lib/synapse/base.rb
110
+ - lib/synapse/haproxy.rb
111
+ - lib/synapse/log.rb
112
+ - lib/synapse/service_watcher.rb
113
+ - lib/synapse/service_watcher/base.rb
114
+ - lib/synapse/service_watcher/dns.rb
115
+ - lib/synapse/service_watcher/docker.rb
116
+ - lib/synapse/service_watcher/ec2tag.rb
117
+ - lib/synapse/service_watcher/zookeeper.rb
118
+ - lib/synapse/version.rb
119
+ - spec/lib/synapse/haproxy_spec.rb
120
+ - spec/lib/synapse/service_watcher_base_spec.rb
121
+ - spec/lib/synapse/service_watcher_docker_spec.rb
122
+ - spec/spec_helper.rb
123
+ - spec/support/config.rb
124
+ - spec/support/minimum.conf.yaml
125
+ - synapse.gemspec
126
+ homepage: ''
127
+ licenses: []
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 2.2.0
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: ": Write a gem summary"
149
+ test_files:
150
+ - spec/lib/synapse/haproxy_spec.rb
151
+ - spec/lib/synapse/service_watcher_base_spec.rb
152
+ - spec/lib/synapse/service_watcher_docker_spec.rb
153
+ - spec/spec_helper.rb
154
+ - spec/support/config.rb
155
+ - spec/support/minimum.conf.yaml