Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #51 get the plugin defintion from the label #52

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions docs/container-labels.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@

## Container (Docker or Swarm) labels

| Tag | Description | Default | Example |
|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|--------------|------------------------------------------------------------|
| easyhaproxy.[definition].host | Host(s) HAProxy is listening. More than one host use comma as delimiter | **required** | somehost.com OR host1.com,host2.com |
| easyhaproxy.[definition].mode | (Optional) Is this `http` or `tcp` mode in HAProxy. | http | http or tcp |
| easyhaproxy.[definition].port | (Optional) Port HAProxy will listen for the host. | 80 | 3000 |
| easyhaproxy.[definition].localport | (Optional) Port container is listening. | 80 | 8080 |
| easyhaproxy.[definition].redirect | (Optional) JSON containing key/value pair from host/to URL redirect. | *empty* | {"foo.com":"https://bla.com", "bar.com":"https://bar.org"} |
| easyhaproxy.[definition].sslcert | (Optional) Cert PEM Base64 encoded. Do not use this if `certbot` is enabled. | *empty* | base64 cert + key |
| easyhaproxy.[definition].ssl | (Optional) If `true` you need to provide certificate as a file. See below. Do not use with `sslcert`. | false | true or false |
| easyhaproxy.[definition].ssl-check | (Optional) `ssl`, enable health check via SSL in `mode tcp` | *empty* | ssl |
| easyhaproxy.[definition].certbot | (Optional) Generate certificate with certbot. Do not use with `sslcert` parameter. More info [here](acme.md). | false | true OR false |
| easyhaproxy.[definition].redirect_ssl | (Optional) Redirect all requests to https | false | true OR false |
| easyhaproxy.[definition].clone_to_ssl | (Optional) It copies the configuration to HTTPS(443) and disable SSL from the current config. **Do not use* this with `ssl` or `certbot` parameters | false | true OR false |
| easyhaproxy.[definition].balance | (Optional) HAProxy balance algorithm. See [HAProxy documentation](https://cbonte.github.io/haproxy-dconv/1.8/configuration.html#4.2-balance) | roundrobin | roundrobin, source, uri, url_param, hdr, rdp-cookie, leastconn, first, static-rr, rdp-cookie, hdr_dom, map-based |
| Tag | Description | Default | Example |
|----------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|--------------|------------------------------------------------------------------------------------------------------------------|
| easyhaproxy.[definition].host | Host(s) HAProxy is listening. More than one host use comma as delimiter | **required** | somehost.com OR host1.com,host2.com |
| easyhaproxy.[definition].mode | (Optional) Is this `http` or `tcp` mode in HAProxy. | http | http or tcp |
| easyhaproxy.[definition].port | (Optional) Port HAProxy will listen for the host. | 80 | 3000 |
| easyhaproxy.[definition].localport | (Optional) Port container is listening. | 80 | 8080 |
| easyhaproxy.[definition].redirect | (Optional) JSON containing key/value pair from host/to URL redirect. | *empty* | {"foo.com":"https://bla.com", "bar.com":"https://bar.org"} |
| easyhaproxy.[definition].sslcert | (Optional) Cert PEM Base64 encoded. Do not use this if `certbot` is enabled. | *empty* | base64 cert + key |
| easyhaproxy.[definition].ssl | (Optional) If `true` you need to provide certificate as a file. See below. Do not use with `sslcert`. | false | true or false |
| easyhaproxy.[definition].ssl-check | (Optional) `ssl`, enable health check via SSL in `mode tcp` | *empty* | ssl |
| easyhaproxy.[definition].certbot | (Optional) Generate certificate with certbot. Do not use with `sslcert` parameter. More info [here](acme.md). | false | true OR false |
| easyhaproxy.[definition].redirect_ssl | (Optional) Redirect all requests to https | false | true OR false |
| easyhaproxy.[definition].clone_to_ssl | (Optional) It copies the configuration to HTTPS(443) and disable SSL from the current config. **Do not use* this with `ssl` or `certbot` parameters | false | true OR false |
| easyhaproxy.[definition].balance | (Optional) HAProxy balance algorithm. See [HAProxy documentation](https://cbonte.github.io/haproxy-dconv/1.8/configuration.html#4.2-balance) | roundrobin | roundrobin, source, uri, url_param, hdr, rdp-cookie, leastconn, first, static-rr, rdp-cookie, hdr_dom, map-based |
| easyhaproxy.[definition].plugin.[name] | (Optional) EasyHAProxy plugin. | *empty* | Check the documentation of the plugin |

The `definition` is a string that will group all configurations togethers. Different `definition` will create different configurations.

Expand Down
4 changes: 4 additions & 0 deletions docs/static.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ easymapping:
- container:5000 # Endpoints of the hostname above (ip, dns, container, etc)
certbot: true # Optional. it will request a certbot certificate. Needs certbot.email set.
redirect_ssl: true # Optional. It will redirect this site to it SSL.
balance: roundrobin # Optional. Default `roundrobin`. Can be roundrobin, leastconn, source
plugin: # Optional. Default `none`.
- name1: args1
- name2: args2
ssl: true # Optional. Inform this port will listen to SSL, instead of HTTP
clone_to_ssl: true # Optional. Default False. You clone these hosts to its equivalent SSL.
redirect:
Expand Down
42 changes: 29 additions & 13 deletions src/easymapping/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def __init__(self, label):
def get_lookup_label(self):
return self.__label_base

def create(self, key):
def format(self, key):
if isinstance(key, str):
return "{}.{}".format(self.__label_base, key)

Expand All @@ -34,6 +34,17 @@ def get_json(self, label, default_value={}):
return json.loads(self.__data[label])
return default_value

def get_pattern(self, label):
label += "."
matching_elements = [element for element in self.__data if element.startswith(label)]
result_dict = {}

for element in matching_elements:
plugin_name = element[len(label):]
result_dict[plugin_name] = self.get(element)

return result_dict if result_dict else False

def set_data(self, data):
self.__data = data

Expand Down Expand Up @@ -89,26 +100,26 @@ def parse(self, container_metadata):
# Parse each definition found.
for definition in sorted(definitions.keys()):
mode = self.label.get(
self.label.create([definition, "mode"]),
self.label.format([definition, "mode"]),
"http"
)

# TODO: we can ignore "host" in TCP, but it would break the template
host_label = self.label.create([definition, "host"])
host_label = self.label.format([definition, "host"])
if not self.label.has_label(host_label):
continue

port = self.label.get(
self.label.create([definition, "port"]),
self.label.format([definition, "port"]),
"80"
)

certbot = self.label.get_bool(
self.label.create([definition, "certbot"]),
self.label.format([definition, "certbot"]),
False
) and self.mapping["certbot"]["email"] != ""
clone_to_ssl = self.label.get_bool(
self.label.create([definition, "clone_to_ssl"])
self.label.format([definition, "clone_to_ssl"])
)

if port not in easymapping:
Expand All @@ -122,15 +133,17 @@ def parse(self, container_metadata):

# TODO: this could use `EXPOSE` from `Dockerfile`?
ct_port = self.label.get(
self.label.create([definition, "localport"]),
self.label.format([definition, "localport"]),
"80"
)

easymapping[port]["ssl-check"] = self.label.get(
self.label.create([definition, "ssl-check"]),
self.label.format([definition, "ssl-check"]),
""
)

plugins = self.label.get_pattern(self.label.format([definition, "plugin"]))

for hostname in sorted(d[host_label].split(",")):
hostname = hostname.strip()
self.serving_hosts.append("%s:%s" % (hostname, port))
Expand All @@ -140,17 +153,20 @@ def parse(self, container_metadata):
easymapping[port]["hosts"][hostname]["containers"] += ["{}:{}".format(container, ct_port)]
easymapping[port]["hosts"][hostname]["certbot"] = certbot
easymapping[port]["hosts"][hostname]["redirect_ssl"] = self.label.get_bool(
self.label.create([definition, "redirect_ssl"])
self.label.format([definition, "redirect_ssl"])
)
easymapping[port]["hosts"][hostname]["balance"] = self.label.get(
self.label.create([definition, "balance"]),
self.label.format([definition, "balance"]),
"roundrobin"
)

easymapping[port]["redirect"] = self.label.get_json(
self.label.create([definition, "redirect"])
self.label.format([definition, "redirect"])
)

if (plugins):
easymapping[port]["hosts"][hostname]["plugins"] = plugins

if certbot or clone_to_ssl:
if "443" not in easymapping:
easymapping["443"] = {
Expand All @@ -168,13 +184,13 @@ def parse(self, container_metadata):
hostname) if certbot and hostname not in self.certbot_hosts else self.certbot_hosts

# handle SSL
ssl_label = self.label.create([definition, "sslcert"])
ssl_label = self.label.format([definition, "sslcert"])
if self.label.has_label(ssl_label):
filename = "{}.pem".format(d[host_label])
easymapping[port]["ssl"] = True if not clone_to_ssl else False
self.certs[filename] = base64.b64decode(d[ssl_label]).decode('ascii')

if self.label.get_bool(self.label.create([definition, "ssl"])):
if self.label.get_bool(self.label.format([definition, "ssl"])):
easymapping[port]["ssl"] = True if not clone_to_ssl else False

return easymapping.values()
2 changes: 2 additions & 0 deletions src/tests/test_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def test_processor_docker():
"easyhaproxy.http.port": "80",
"easyhaproxy.http.localport": "8080",
"easyhaproxy.http.host": "host1.local",
"easyhaproxy.http.plugin.xyz": "host1.local",

"easyhaproxy.http2.port": "90",
"easyhaproxy.http2.localport": "9000",
Expand Down Expand Up @@ -71,6 +72,7 @@ def test_processor_docker():
'easyhaproxy.http.host': 'host1.local',
'easyhaproxy.http.localport': '8080',
'easyhaproxy.http.port': '80',
'easyhaproxy.http.plugin.xyz': "host1.local",
'easyhaproxy.http2.host': 'host2.local',
'easyhaproxy.http2.localport': '9000',
'easyhaproxy.http2.port': '90',
Expand Down
10 changes: 5 additions & 5 deletions src/tests/test_labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
def test_label_generation():
label = DockerLabelHandler("foo")

assert label.create("bar") == "foo.bar"
assert label.create(["bar", "foobar"]) == "foo.bar.foobar"
assert label.format("bar") == "foo.bar"
assert label.format(["bar", "foobar"]) == "foo.bar.foobar"


def test_label_data():
label = DockerLabelHandler("base")
label.set_data(json.loads('{"base.definitions":"h2"}'))

label_name = label.create("definitions")
label_name = label.format("definitions")
assert label_name == "base.definitions"
assert label.has_label(label_name)
assert label.get(label_name) == "h2"
Expand All @@ -29,5 +29,5 @@ def test_label_complex_key():
data["till.mode.h2"] = "tcp"
label.set_data(json.loads(json.dumps(data)))

assert label.get(label.create(["host", "h2"])) == "fqdn.example.org"
assert label.get(label.create(["mode", "h2"])) == "tcp"
assert label.get(label.format(["host", "h2"])) == "fqdn.example.org"
assert label.get(label.format(["mode", "h2"])) == "tcp"
Loading