Skip to content
This repository has been archived by the owner on Dec 4, 2024. It is now read-only.

Commit

Permalink
Use a separate HAProxy map file for mapping Marathon app IDs to backe…
Browse files Browse the repository at this point in the history
…nds (#303)

* Use a separate HAProxy map file to map app IDs to backends

* Use os.path functions to generate map file paths

* Implement /_haproxy_getappmap endpoint to get app ID -> backend map

* Generalize getvhostmap.lua to fetch other map files

* Rework validation to check new map files

* Write map files before main config file
* Edit temporary config file to include temporary map files so that
  new map files are validated
* Small refactor - generalize some functions that work with temp files

* Clean up and hopefully fix getmaps.lua

* Hopefully fix map file reading

* Hopefully actually fix map file reading

* Run build-docs.sh
  • Loading branch information
JayH5 authored and brndnmtthws committed Sep 8, 2016
1 parent dbb9f87 commit 75d9b08
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 185 deletions.
18 changes: 14 additions & 4 deletions Longhelp.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ usage: marathon_lb.py [-h] [--longhelp] [--marathon MARATHON [MARATHON ...]]
[--command COMMAND] [--sse] [--health-check]
[--lru-cache-capacity LRU_CACHE_CAPACITY]
[--haproxy-map] [--dont-bind-http-https]
[--ssl-certs SSL_CERTS] [--skip-validation] [--dry]
[--ssl-certs SSL_CERTS]
[--marathon-ca-cert MARATHON_CA_CERT]
[--skip-validation] [--dry]
[--min-serv-port-ip-per-task MIN_SERV_PORT_IP_PER_TASK]
[--max-serv-port-ip-per-task MAX_SERV_PORT_IP_PER_TASK]
[--syslog-socket SYSLOG_SOCKET]
[--log-format LOG_FORMAT] [--log-level LOG_LEVEL]
[--marathon-auth-credential-file MARATHON_AUTH_CREDENTIAL_FILE]
[--auth-credentials AUTH_CREDENTIALS]
[--dcos-auth-credentials DCOS_AUTH_CREDENTIALS]
Marathon HAProxy Load Balancer
Expand All @@ -40,7 +43,7 @@ optional arguments:
--marathon MARATHON [MARATHON ...], -m MARATHON [MARATHON ...]
[required] Marathon endpoint, eg. -m
http://marathon1:8080 http://marathon2:8080 (default:
None)
['http://master.mesos:8080'])
--listening LISTENING, -l LISTENING
(deprecated) The address this script listens on for
marathon events (e.g., http://0.0.0.0:8080) (default:
Expand Down Expand Up @@ -76,6 +79,9 @@ optional arguments:
frontend marathon_https_inEx:
/etc/ssl/site1.co.pem,/etc/ssl/site2.co.pem (default:
/etc/ssl/mesosphere.com.pem)
--marathon-ca-cert MARATHON_CA_CERT
CA certificate for Marathon HTTPS connections
(default: None)
--skip-validation Skip haproxy config file validation (default: False)
--dry, -d Only print configuration to console (default: False)
--min-serv-port-ip-per-task MIN_SERV_PORT_IP_PER_TASK
Expand All @@ -98,6 +104,8 @@ optional arguments:
--auth-credentials AUTH_CREDENTIALS
user/pass for the Marathon HTTP API in the format of
'user:pass'. (default: None)
--dcos-auth-credentials DCOS_AUTH_CREDENTIALS
DC/OS service account credentials (default: None)
```
## Templates

Expand Down Expand Up @@ -373,7 +381,7 @@ global
server-state-base /var/state/haproxy/
lua-load /marathon-lb/getpids.lua
lua-load /marathon-lb/getconfig.lua
lua-load /marathon-lb/getvhostmap.lua
lua-load /marathon-lb/getmaps.lua
defaults
load-server-state-from-file global
log global
Expand Down Expand Up @@ -401,6 +409,8 @@ listen stats
http-request use-service lua.getpids if getpid
acl getvhostmap path /_haproxy_getvhostmap
http-request use-service lua.getvhostmap if getvhostmap
acl getappmap path /_haproxy_getappmap
http-request use-service lua.getappmap if getappmap
acl getconfig path /_haproxy_getconfig
http-request use-service lua.getconfig if getconfig
```
Expand Down Expand Up @@ -859,7 +869,7 @@ of the `HAPROXY_HTTP_FRONTEND_APPID_HEAD` using haproxy maps.

**Default template for `HAPROXY_MAP_HTTP_FRONTEND_APPID_ACL`:**
```
use_backend %[req.hdr(x-marathon-app-id),lower,map({haproxy_dir}/domain2backend.map)]
use_backend %[req.hdr(x-marathon-app-id),lower,map({haproxy_dir}/app2backend.map)]
```
## `HAPROXY_TCP_BACKEND_ACL_ALLOW_DENY`
*Global*
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ Marathon-lb exposes a few endpoints on port 9090 (by default). They are:
| `:9090/haproxy?stats;csv` | This is a CSV version of the stats above, which can be consumed by other tools. For example, it's used in the [`zdd.py`](zdd.py) script. |
| `:9090/_haproxy_health_check` | HAProxy health check endpoint. Returns `200 OK` if HAProxy is healthy. |
| `:9090/_haproxy_getconfig` | Returns the HAProxy config file as it was when HAProxy was started. Implemented in [`getconfig.lua`](getconfig.lua). |
| `:9090/_haproxy_getvhostmap` | Returns the HAProxy vhost to backend map. This endpoint returns HAProxy map file only when `--haproxy-map` flag is enabled, it returns a empty string otherwise. Implemented in [`getvhostmap.lua`](getvhostmap.lua). |
| `:9090/_haproxy_getvhostmap` | Returns the HAProxy vhost to backend map. This endpoint returns HAProxy map file only when the `--haproxy-map` flag is enabled, it returns an empty string otherwise. Implemented in [`getmaps.lua`](getmaps.lua). |
| `:9090/_haproxy_getappmap` | Returns the HAProxy app ID to backend map. Like `_haproxy_getvhostmap`, this requires the `--haproxy-map` flag to be enabled and returns an empty string otherwise. Also implemented in `getmaps.lua`. |
| `:9090/_haproxy_getpids` | Returns the PIDs for all HAProxy instances within the current process namespace. This literally returns `$(pidof haproxy)`. Implemented in [`getpids.lua`](getpids.lua). This is also used by the [`zdd.py`](zdd.py) script to determine if connections have finished draining during a deploy. |


Expand Down
6 changes: 4 additions & 2 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def load(self):
server-state-base /var/state/haproxy/
lua-load /marathon-lb/getpids.lua
lua-load /marathon-lb/getconfig.lua
lua-load /marathon-lb/getvhostmap.lua
lua-load /marathon-lb/getmaps.lua
defaults
load-server-state-from-file global
log global
Expand Down Expand Up @@ -87,6 +87,8 @@ def load(self):
http-request use-service lua.getpids if getpid
acl getvhostmap path /_haproxy_getvhostmap
http-request use-service lua.getvhostmap if getvhostmap
acl getappmap path /_haproxy_getappmap
http-request use-service lua.getappmap if getappmap
acl getconfig path /_haproxy_getconfig
http-request use-service lua.getconfig if getconfig
''',
Expand Down Expand Up @@ -422,7 +424,7 @@ def load(self):
ConfigTemplate(name='MAP_HTTP_FRONTEND_APPID_ACL',
value='''\
use_backend %[req.hdr(x-marathon-app-id),lower,\
map({haproxy_dir}/domain2backend.map)]
map({haproxy_dir}/app2backend.map)]
''',
overridable=True,
description='''\
Expand Down
59 changes: 59 additions & 0 deletions getmaps.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
-- A simple Lua script which serves up the HAProxy
-- vhost to backend map file.
function check_file_exists(name)
local f = io.open(name, "r")
if f ~= nil then io.close(f) return true else return false end
end

function read_file(filepath)
-- Read all of the given file, returning an empty string if the file doesn't
-- exist.
local content = ""
if check_file_exists(filepath) then
local f = io.open(filepath, "rb")
content = f:read("*all")
f:close()
end
return content
end

function detect_config_dir()
-- Read the process's (HAProxy's) cmdline proc and parse the path to the
-- config file so that we can determine the config directory.
local f = io.open("/proc/self/cmdline", "rb")
local cmdline = f:read("*all")
f:close()

local found = false
local sep = package.config:sub(1, 1)
for opt in string.gmatch(cmdline, "%g+") do
if opt == "-f" then
found = true
elseif found then
return opt:match("(.*"..sep..")")
end
end
end

function load_map(filename)
local config_dir = detect_config_dir()
return read_file(config_dir..filename)
end

function send_map(applet, map)
applet:set_status(200)
applet:add_header("content-length", string.len(map))
applet:add_header("content-type", "text/plain")
applet:start_response()
applet:send(map)
end

core.register_service("getvhostmap", "http", function(applet)
local haproxy_vhostmap = load_map("domain2backend.map")
send_map(applet, haproxy_vhostmap)
end)

core.register_service("getappmap", "http", function(applet)
local haproxy_appmap = load_map("app2backend.map")
send_map(applet, haproxy_appmap)
end)
48 changes: 0 additions & 48 deletions getvhostmap.lua

This file was deleted.

Loading

0 comments on commit 75d9b08

Please sign in to comment.