Skip to content

Commit

Permalink
Introduce new --strict-mode option. (#410)
Browse files Browse the repository at this point in the history
This also adds a new `HAPROXY_{n}_ENABLED` option, which lets you
enabled/disable individual backends for an app.

This resolves issues #402 and #403.
  • Loading branch information
brndnmtthws authored Jan 24, 2017
1 parent 5d6447b commit b46ace4
Show file tree
Hide file tree
Showing 5 changed files with 331 additions and 57 deletions.
22 changes: 19 additions & 3 deletions Longhelp.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ Marathon-lb just needs to know where to find Marathon.
```
usage: marathon_lb.py [-h] [--longhelp] [--marathon MARATHON [MARATHON ...]]
[--haproxy-config HAPROXY_CONFIG] [--group GROUP]
[--command COMMAND] [--sse] [--health-check]
[--command COMMAND] [--strict-mode] [--sse]
[--health-check]
[--lru-cache-capacity LRU_CACHE_CAPACITY]
[--haproxy-map] [--dont-bind-http-https]
[--ssl-certs SSL_CERTS] [--skip-validation] [--dry]
Expand All @@ -44,11 +45,15 @@ optional arguments:
Location of haproxy configuration (default:
/etc/haproxy/haproxy.cfg)
--group GROUP [required] Only generate config for apps which list
the specified names. Use '*' to match all groups
(default: [])
the specified names. Use '*' to match all groups,
including those without a group specified. (default:
[])
--command COMMAND, -c COMMAND
If set, run this command to reload haproxy. (default:
None)
--strict-mode If set, backends are only advertised if
HAPROXY_{n}_ENABLED=true. Strict mode will be enabled
by default in a future release. (default: False)
--sse, -s Use Server Sent Events (default: False)
--health-check, -H If set, respect Marathon's health check statuses
before adding the app instance into the backend pool.
Expand Down Expand Up @@ -1052,6 +1057,17 @@ generally do not need to modify this unless you implement your
own deployment orchestrator.


## `HAPROXY_{n}_ENABLED`
*per service port*

Specified as `HAPROXY_{n}_ENABLED`.

Enable this backend. By default, all backends are enabled. To disable
backends by default, specify the `--strict-mode` flag.

Ex: `HAPROXY_0_ENABLED = true`


## `HAPROXY_{n}_GROUP`
*per service port*

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ You can also run the update script directly.
To generate an HAProxy configuration from Marathon running at `localhost:8080` with the `marathon_lb.py` script, run:

```console
$ ./marathon_lb.py --marathon http://localhost:8080 --group external
$ ./marathon_lb.py --marathon http://localhost:8080 --group external --strict-mode --health-check
```

It is possible to pass `--auth-credentials=` option if your Marathon requires authentication:
Expand All @@ -123,7 +123,7 @@ $ ./marathon_lb.py --help
You can provide your SSL certificate paths to be placed in frontend marathon_https_in section with `--ssl-certs`.

``` console
$ ./marathon_lb.py --marathon http://localhost:8080 --group external --ssl-certs /etc/ssl/site1.co,/etc/ssl/site2.co
$ ./marathon_lb.py --marathon http://localhost:8080 --group external --ssl-certs /etc/ssl/site1.co,/etc/ssl/site2.co --health-check --strict-mode
```

If you are using the script directly, you have two options:
Expand Down
12 changes: 12 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,10 @@ def set_sticky(x, k, v):
x.sticky = string_to_bool(v)


def set_enabled(x, k, v):
x.enabled = string_to_bool(v)


def set_redirect_http_to_https(x, k, v):
x.redirectHttpToHttps = string_to_bool(v)

Expand Down Expand Up @@ -1309,6 +1313,14 @@ def __init__(self, name, func, description, perServicePort=True):
Ex: `HAPROXY_0_STICKY = true`
'''))
labels.append(Label(name='ENABLED',
func=set_enabled,
description='''\
Enable this backend. By default, all backends are enabled. To disable
backends by default, specify the `--strict-mode` flag.
Ex: `HAPROXY_0_ENABLED = true`
'''))
labels.append(Label(name='REDIRECT_TO_HTTPS',
func=set_redirect_http_to_https,
description='''\
Expand Down
25 changes: 20 additions & 5 deletions marathon_lb.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def __repr__(self):

class MarathonService(object):

def __init__(self, appId, servicePort, healthCheck):
def __init__(self, appId, servicePort, healthCheck, strictMode):
self.appId = appId
self.servicePort = servicePort
self.backends = set()
Expand All @@ -105,6 +105,7 @@ def __init__(self, appId, servicePort, healthCheck):
self.authUser = None
self.authPasswd = None
self.sticky = False
self.enabled = not strictMode
self.redirectHttpToHttps = False
self.useHsts = False
self.sslCert = None
Expand Down Expand Up @@ -153,10 +154,11 @@ def __eq__(self, other):


class Marathon(object):
def __init__(self, hosts, health_check, auth, ca_cert=None):
def __init__(self, hosts, health_check, strict_mode, auth, ca_cert=None):
# TODO(cmaloney): Support getting master list from zookeeper
self.__hosts = hosts
self.__health_check = health_check
self.__strict_mode = strict_mode
self.__auth = auth
self.__cycle_hosts = cycle(self.__hosts)
self.__verify = False
Expand Down Expand Up @@ -215,6 +217,9 @@ def list(self):
def health_check(self):
return self.__health_check

def strict_mode(self):
return self.__strict_mode

def tasks(self):
logger.info('fetching tasks')
return self.api_req('GET', ['tasks'])["tasks"]
Expand Down Expand Up @@ -360,6 +365,9 @@ def config(apps, groups, bind_http_https, ssl_certs, templater,
else:
if not has_group(groups, app.groups):
continue
# Skip if it's not actually enabled
if not app.enabled:
continue

logger.debug("configuring app %s", app.appId)
if len(app.backends) < 1:
Expand Down Expand Up @@ -1333,8 +1341,9 @@ def get_apps(marathon):
logger.warning("Skipping undefined service port")
continue

service = MarathonService(
appId, servicePort, get_health_check(app, i))
service = MarathonService(appId, servicePort,
get_health_check(app, i),
marathon.strict_mode())

for key_unformatted in label_keys:
key = key_unformatted.format(i)
Expand Down Expand Up @@ -1580,12 +1589,17 @@ def get_arg_parser():
parser.add_argument("--group",
help="[required] Only generate config for apps which"
" list the specified names. Use '*' to match all"
" groups",
" groups, including those without a group specified.",
action="append",
default=list())
parser.add_argument("--command", "-c",
help="If set, run this command to reload haproxy.",
default=None)
parser.add_argument("--strict-mode",
help="If set, backends are only advertised if"
" HAPROXY_{n}_ENABLED=true. Strict mode will be"
" enabled by default in a future release.",
action="store_true")
parser.add_argument("--sse", "-s",
help="Use Server Sent Events",
action="store_true")
Expand Down Expand Up @@ -1710,6 +1724,7 @@ def process_sse_events(marathon, processor):
# Marathon API connector
marathon = Marathon(args.marathon,
args.health_check,
args.strict_mode,
get_marathon_auth_params(args),
args.marathon_ca_cert)

Expand Down
Loading

0 comments on commit b46ace4

Please sign in to comment.