Merge pull request #31 from memory/listen_option

allow override of listening address
The base service watcher uses the logging mixin

This fixes the docker and DNS service watchers
Make the one test there is actually pass
Fix exception handling
Add some tests so that I understand what the hell I'm changing
Allow us to discover docker containers against the newer API
Fix mock data for what actually comes out of the API, and fix code to still work
Merge pull request #40 from bobtfish/extend_docker_watcher_for_new_api

Extend docker watcher for new api
don't require backends to have names

but still make the stats socket readable if a name exists
don't set names for dns watchers

they don't add any additional information
zookeeper: look for the backend name in the node data

this is instead of looking for it in the node name, which is properly metadata.
this allows us to always generate ephemeral sequence ids for nerve node names
and still have readable information in haproxy
allow leader election by controlling backends returned

this is an alternate approach to airbnb/synapse#29 which is not tied to particular
service watchers. as long as the watcher ads a numeric ID field to each backend hash,
a leader can be elected.

if a leader cannot be elected, we fail hard by returning no backends
Merge pull request #43 from airbnb/allow_master_selection

Allow master selection
Merge pull request #26 from memory/yaml-conf

use YAML rather than JSON for configuration files
fix yaml parsing

always return a ruby object from the parsing function
bump version to 0.9.0
shared frontend stanzas in haproxy sections

For HTTP-only services, there is no need to dedicate a port to each service:
services which need to be co-located on a single IP address can, for instance,
share some sort of app container and route based on host or path names.

While haproxy can route on host headers, synapse currently assumes a 1:1
frontend:backend ratio.  But what we want here is a single frontend mapping
to multiple backends based on acl rules.  So herein, a simple stab at it:
if there is a "shared_frontend" key in the root haproxy config, we create
a "shared-frontend" frontend, read in any configuration lines, and then as
we iterate over the services, pluck out any shared_frontend lines like so:

  { "haproxy": {
      "shared_frontend": [
        "bind 127.0.0.1:8081"
      ],
      "global": [
        "daemon",
        "stats socket /var/run/haproxy.sock"
      ],
      "defaults": [
        "log      global",
      ],
    },
    "services": {
      "service1": {
        "haproxy": {
          "server_options": "check inter 2s rise 3 fall 2",
          "backend": [
            "mode http"
          ],
          "shared_frontend": [
            "acl is_service1 hdr_dom(host) -i service1.lb",
            "use_backend service1 if is_service1"
          ]
        }
      },
      "service2": {
        "haproxy": {
          "server_options": "check inter 2s rise 3 fall 2",
          "backend": [
            "mode http"
          ],
          "shared_frontend": [
            "acl is_service2 hdr_dom(host) -i service2.lb",
            "use_backend service2 if is_service2"
          ]
        }
      }
    }
  }

...produces a FE/BE config like this:

  frontend service1
        bind localhost:8086
        default_backend service1

  backend service1
        mode http
        server host1_service1:8101_20d8a0f6 10.73.132.39:8101 check inter 2s rise 3 fall 2
        server host1_service1:8101_4f48153f 10.181.203.244:8101 check inter 2s rise 3 fall 2

  backend service2
        mode http
        server host1_service2:8101_6f0a9d02 10.60.12.9:8101 check inter 2s rise 3 fall 2
        server host2_service2:8101_f3518f4f 10.81.23.44:8101 check inter 2s rise 3 fall 2

  frontend shared-frontend
        bind 127.0.0.1:8081
        acl is_service1 hdr_dom(host) -i service1.lb
        use_backend service1 if is_service1
        acl is_service2 hdr_dom(host) -i service2.lb
        use_backend service2 if is_service2