commit
b4af1e2213
16 changed files with 319 additions and 120 deletions
12
.gitpod.yml
Normal file
12
.gitpod.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# This configuration file was automatically generated by Gitpod.
|
||||||
|
# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
|
||||||
|
# and commit this file to your remote git repository to share the goodness with others.
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- init:
|
||||||
|
make
|
||||||
|
|
||||||
|
- command: |
|
||||||
|
virtualenv -p /usr/bin/python3 venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
19
.vscode/launch.json
vendored
Normal file
19
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Python: Current File",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${file}",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"env": {
|
||||||
|
"PYTHONPATH": "${cwd}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
FROM alpine:3.14
|
FROM alpine:3.16
|
||||||
|
|
||||||
WORKDIR /scripts
|
WORKDIR /scripts
|
||||||
|
|
||||||
|
|
|
||||||
100
README.md
100
README.md
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
[](http://opensource.byjg.com)
|
[](http://opensource.byjg.com)
|
||||||
[](https://github.com/byjg/docker-easy-haproxy/actions/workflows/build.yml)
|
[](https://github.com/byjg/docker-easy-haproxy/actions/workflows/build.yml)
|
||||||
|
[](https://github.com/byjg/docker-easy-haproxy/)
|
||||||
|
[](https://opensource.byjg.com/opensource/licensing.html)
|
||||||
|
[](https://github.com/byjg/docker-easy-haproxy/releases/)
|
||||||
|
|
||||||
|
Service discovery for HAProxy.
|
||||||
|
|
||||||
This Docker image will create dynamically the `haproxy.cfg` based on the labels defined in docker containers or from
|
This Docker image will create dynamically the `haproxy.cfg` based on the labels defined in docker containers or from
|
||||||
a simple Yaml instead docker
|
a simple Yaml instead docker
|
||||||
|
|
@ -13,7 +18,6 @@ a simple Yaml instead docker
|
||||||
- Discover and setup haproxy redirect from Docker Tag
|
- Discover and setup haproxy redirect from Docker Tag
|
||||||
- Setup HAProxy CFG from a Yaml file.
|
- Setup HAProxy CFG from a Yaml file.
|
||||||
|
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
|
|
||||||
The Easy HAProxy will create the `haproxy.cfg` automatically based on the containers or from a YAML provided.
|
The Easy HAProxy will create the `haproxy.cfg` automatically based on the containers or from a YAML provided.
|
||||||
|
|
@ -24,7 +28,7 @@ The basic command line to run is:
|
||||||
docker run -d \
|
docker run -d \
|
||||||
--name easy-haproxy-container \
|
--name easy-haproxy-container \
|
||||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||||
-e DISCOVER="swarm|docker|static" \
|
-e EASYHAPROXY_DISCOVER="swarm|docker|static" \
|
||||||
# + Environment Variables \
|
# + Environment Variables \
|
||||||
# + ports mapped to the host \
|
# + ports mapped to the host \
|
||||||
byjg/easy-haproxy
|
byjg/easy-haproxy
|
||||||
|
|
@ -34,17 +38,17 @@ The mapping to `/var/run/docker.sock` is necessary to discover the docker contai
|
||||||
|
|
||||||
The environment variables will setup the HAProxy.
|
The environment variables will setup the HAProxy.
|
||||||
|
|
||||||
| Environment Variable | Description |
|
| Environment Variable | Description |
|
||||||
|----------------------|-------------------------------------------------------------------------------|
|
|--------------------------|-------------------------------------------------------------------------------|
|
||||||
| DISCOVER | How `haproxy.cfg` will be created: `static`, `docker` or `swarm` |
|
| EASYHAPROXY_DISCOVER | How `haproxy.cfg` will be created: `static`, `docker` or `swarm` |
|
||||||
| HAPROXY_USERNAME | (Optional) The HAProxy username to the statistics. Default: `admin` |
|
| EASYHAPROXY_LABEL_PREFIX | (Optional) The key will search to match resources. Default: `easyhaproxy`. |
|
||||||
| HAPROXY_PASSWORD | The HAProxy password to the statistics. If not set disable stats. |
|
| HAPROXY_USERNAME | (Optional) The HAProxy username to the statistics. Default: `admin` |
|
||||||
| HAPROXY_STATS_PORT | (Optional) The HAProxy port to the statistics. Default: `1936` |
|
| HAPROXY_PASSWORD | The HAProxy password to the statistics. If not set disable stats. |
|
||||||
| HAPROXY_CUSTOMERRORS | (Optional) If HAProxy will use custom HTML errors. true/false. Default: false |
|
| HAPROXY_STATS_PORT | (Optional) The HAProxy port to the statistics. Default: `1936` |
|
||||||
|
| HAPROXY_CUSTOMERRORS. | (Optional) If HAProxy will use custom HTML errors. true/false. Default: false |
|
||||||
|
|
||||||
|
The environment variable `EASYHAPROXY_DISCOVER` will define where is located your containers (see below more details):
|
||||||
|
|
||||||
|
|
||||||
The environment variable `DISCOVER` will define where is located your containers (see below more details):
|
|
||||||
- docker
|
- docker
|
||||||
- swarm
|
- swarm
|
||||||
- static
|
- static
|
||||||
|
|
@ -53,7 +57,7 @@ The environment variable `DISCOVER` will define where is located your containers
|
||||||
|
|
||||||
Easy HAProxy can discover automatically the container services running in the same network of Docker or in a Docker Swarm cluster.
|
Easy HAProxy can discover automatically the container services running in the same network of Docker or in a Docker Swarm cluster.
|
||||||
|
|
||||||
### DISCOVER: docker
|
### EASYHAPROXY_DISCOVER: docker
|
||||||
|
|
||||||
This method will use a regular docker installation to discover the containers and configure the HAProxy.
|
This method will use a regular docker installation to discover the containers and configure the HAProxy.
|
||||||
|
|
||||||
|
|
@ -71,7 +75,7 @@ docker run --network easyhaproxy byjg/easyhaproxy
|
||||||
docker run --network easyhaproxy myimage
|
docker run --network easyhaproxy myimage
|
||||||
```
|
```
|
||||||
|
|
||||||
### DISCOVER: swarm
|
### EASYHAPROXY_DISCOVER: swarm
|
||||||
|
|
||||||
This method requires a functional Docker Swarm Cluster. The system will search for the labels in all containers on all
|
This method requires a functional Docker Swarm Cluster. The system will search for the labels in all containers on all
|
||||||
swarm nodes.
|
swarm nodes.
|
||||||
|
|
@ -82,16 +86,15 @@ Important: easyhaproxy needs to be in the same network of the containers or othe
|
||||||
|
|
||||||
### Tags to be attached in the Docker Container (Swarm or Docker)
|
### Tags to be attached in the Docker Container (Swarm or Docker)
|
||||||
|
|
||||||
| Tag | Description | Example |
|
| Tag | Description | Example |
|
||||||
|------------------------------------|---------------------------------------------------------------------------------------------------------|--------------|
|
|---------------------------------------|---------------------------------------------------------------------------------------------------------|--------------|
|
||||||
| easyhaproxy.definitions | A Comma delimited list with the definitions. Each name requires the definition of the parameters below. | service,service2 |
|
| easyhaproxy.[definition].mode | (Optional) Is this `http` or `tcp` mode in HAProxy. (Defaults to http) | http |
|
||||||
| easyhaproxy.mode.[definition] | (Optional) Is this `http` or `tcp` mode in HAProxy. (Defaults to http) | http |
|
| easyhaproxy.[definition].port | (Optional) What is the port that the HAProxy will listen to. (Defaults to 80) | 80 |
|
||||||
| easyhaproxy.port.[definition] | (Optional) What is the port that the HAProxy will listen to. (Defaults to 80) | 80 |
|
| easyhaproxy.[definition].localport. | (Optional) What is the port that the container is listening. (Defaults to 80) | 8080 |
|
||||||
| easyhaproxy.localport.[definition] | (Optional) What is the port that the container is listening. (Defaults to 80) | 8080 |
|
| easyhaproxy.[definition].host | What is the host that the HAProxy will listen to. | somehost.com |
|
||||||
| easyhaproxy.host.[definition] | What is the host that the HAProxy will listen to. | somehost.com |
|
| easyhaproxy.[definition].redirect | (Optional) Host redirects from connections in the port defined above. | foo.com--https://bla.com,bar.com--https://bar.org |
|
||||||
| easyhaproxy.redirect.[definition] | (Optional) Host redirects from connections in the port defined above. | foo.com--https://bla.com,bar.com--https://bar.org |
|
| easyhaproxy.[definition].sslcert | (Optional) Cert PEM Base64 encoded. | |
|
||||||
| easyhaproxy.sslcert.[definition] | (Optional) Cert PEM Base64 encoded. | |
|
| easyhaproxy.[definition].health-check | (Optional) `ssl`, enable health check via SSL in `mode tcp` (Defaults to "empty") | |
|
||||||
| easyhaproxy.health-check.[definition] | (Optional) `ssl`, enable health check via SSL in `mode tcp` (Defaults to "empty") | |
|
|
||||||
|
|
||||||
### Defining the labels in Docker Swarm
|
### Defining the labels in Docker Swarm
|
||||||
|
|
||||||
|
|
@ -102,62 +105,56 @@ services:
|
||||||
foo:
|
foo:
|
||||||
deploy:
|
deploy:
|
||||||
labels:
|
labels:
|
||||||
easyhaproxy.definitions: "service1,service2"
|
easyhaproxy.my.host: "www.example.org"
|
||||||
|
easyhaproxy.my.localport: 8080
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Single Definition
|
||||||
### Single Definition:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run \
|
docker run \
|
||||||
-l easyhaproxy.definitions=webapi \
|
-l easyhaproxy.webapi.port=80\
|
||||||
-l easyhaproxy.port.webapi=80\
|
-l easyhaproxy.webapi.host=byjg.com.br \
|
||||||
-l easyhaproxy.host.webapi=byjg.com.br \
|
|
||||||
....
|
....
|
||||||
```
|
```
|
||||||
|
|
||||||
### Multiples Definitions on the same container:
|
### Multiples Definitions on the same container
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run \
|
docker run \
|
||||||
-l easyhaproxy.definitions=express,admin \
|
-l easyhaproxy.express.port=80 \
|
||||||
|
-l easyhaproxy.express.localport=3000 \
|
||||||
|
-l easyhaproxy.express.host=express.byjg.com.br \
|
||||||
|
|
||||||
-l easyhaproxy.port.express=80 \
|
-l easyhaproxy.admin.port=80 \
|
||||||
-l easyhaproxy.localport.express=3000 \
|
-l easyhaproxy.admin.localport=3001 \
|
||||||
-l easyhaproxy.host.express=express.byjg.com.br \
|
-l easyhaproxy.admin.host=admin.byjg.com.br \
|
||||||
|
|
||||||
-l easyhaproxy.port.admin=80 \
|
|
||||||
-l easyhaproxy.localport.admin=3001 \
|
|
||||||
-l easyhaproxy.host.admin=admin.byjg.com.br \
|
|
||||||
.... \
|
.... \
|
||||||
some/myimage
|
some/myimage
|
||||||
```
|
```
|
||||||
|
|
||||||
### TLS passthrough
|
### TLS passthrough
|
||||||
|
|
||||||
Used to pass on SSL-termination to a backend:
|
Used to pass on SSL-termination to a backend. Alternatively, you can enable health-check via SSL on the backend with the optional `health-check` label:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run \
|
docker run \
|
||||||
-l easyhaproxy.defintions=example \
|
-l easyhaproxy.example.mode=tcp \
|
||||||
-l easyhaproxy.mode.example=tcp \
|
-l easyhaproxy.example.health-check=ssl \
|
||||||
-l easyhaproxy.health-check.example=ssl \
|
-l easyhaproxy.example.port=443
|
||||||
-l easyhaproxy.port.example=443
|
|
||||||
.... \
|
.... \
|
||||||
some/tcp-service
|
some/tcp-service
|
||||||
```
|
```
|
||||||
|
|
||||||
- enable health-check via SSL on the backend with the optional `health-check` label
|
### Redirect Example
|
||||||
|
|
||||||
### Redirect Example:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run \
|
docker run \
|
||||||
-l easyhaproxy.redirect.<defintion>=www.byjg.com.br--http://byjg.com.br,byjg.com--http://byjg.com.br
|
-l easyhaproxy.[definition].redirect=www.byjg.com.br--http://byjg.com.br,byjg.com--http://byjg.com.br
|
||||||
```
|
```
|
||||||
|
|
||||||
## DISCOVER: static
|
## EASYHAPROXY_DISCOVER: static
|
||||||
|
|
||||||
This method expects a YAML file to setup the `haproxy.cfg`
|
This method expects a YAML file to setup the `haproxy.cfg`
|
||||||
|
|
||||||
|
|
@ -206,7 +203,6 @@ docker run \
|
||||||
-d byjg/easy-haproxy
|
-d byjg/easy-haproxy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Handling SSL
|
## Handling SSL
|
||||||
|
|
||||||
You can attach a valid SSL certificate to the request.
|
You can attach a valid SSL certificate to the request.
|
||||||
|
|
@ -235,7 +231,7 @@ MIIEojCCA4qgAwIBAgIUegW2BimwuL4RzRZ2WYkHA6U5nkAwDQYJKoZIhvcNAQEL
|
||||||
cat single.pem | base64 -w0
|
cat single.pem | base64 -w0
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Use this string to define the label `easyhaproxy.sslcert.[definition]`
|
3. Use this string to define the label `easyhaproxy.[definition].sslcert`
|
||||||
|
|
||||||
## Setting Custom Errors
|
## Setting Custom Errors
|
||||||
|
|
||||||
|
|
@ -244,10 +240,10 @@ where ERROR_NUMBER is the http error code (e.g. 503.http)
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
```
|
|
||||||
|
```bash
|
||||||
docker build -t byjg/easy-haproxy .
|
docker build -t byjg/easy-haproxy .
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
[Open source ByJG](http://opensource.byjg.com)
|
[Open source ByJG](http://opensource.byjg.com)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ cd /scripts
|
||||||
|
|
||||||
RELOAD="true"
|
RELOAD="true"
|
||||||
|
|
||||||
if [[ "$DISCOVER" == "static" ]]; then
|
if [[ "$EASYHAPROXY_DISCOVER" == "static" ]]; then
|
||||||
CONTROL_FILE="/etc/haproxy/haproxy.cfg"
|
CONTROL_FILE="/etc/haproxy/haproxy.cfg"
|
||||||
touch ${CONTROL_FILE}
|
touch ${CONTROL_FILE}
|
||||||
cp ${CONTROL_FILE} ${CONTROL_FILE}.old
|
cp ${CONTROL_FILE} ${CONTROL_FILE}.old
|
||||||
|
|
@ -15,7 +15,7 @@ else
|
||||||
mv ${CONTROL_FILE} ${CONTROL_FILE}.old
|
mv ${CONTROL_FILE} ${CONTROL_FILE}.old
|
||||||
touch ${CONTROL_FILE}
|
touch ${CONTROL_FILE}
|
||||||
|
|
||||||
if [[ "$DISCOVER" == "docker" ]]; then
|
if [[ "$EASYHAPROXY_DISCOVER" == "docker" ]]; then
|
||||||
CONTAINERS=$(docker ps -q)
|
CONTAINERS=$(docker ps -q)
|
||||||
LABEL_PATH=".Config.Labels"
|
LABEL_PATH=".Config.Labels"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ if os.getenv("HAPROXY_PASSWORD"):
|
||||||
"port": os.getenv("HAPROXY_STATS_PORT") if os.getenv("HAPROXY_STATS_PORT") else "1936",
|
"port": os.getenv("HAPROXY_STATS_PORT") if os.getenv("HAPROXY_STATS_PORT") else "1936",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result["lookup_label"] = os.getenv("EASYHAPROXY_LABEL_PREFIX") if os.getenv("EASYHAPROXY_LABEL_PREFIX") else "easyhaproxy"
|
||||||
|
|
||||||
cfg = HaproxyConfigGenerator(result)
|
cfg = HaproxyConfigGenerator(result)
|
||||||
print(cfg.generate(lineList))
|
print(cfg.generate(lineList))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,14 @@ import hashlib
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
class DockerLabelHandler:
|
class DockerLabelHandler:
|
||||||
def __init__(self, label):
|
def __init__(self, label):
|
||||||
self.__label_base = label
|
self.__label_base = label
|
||||||
|
|
||||||
|
def get_lookup_label(self):
|
||||||
|
return self.__label_base
|
||||||
|
|
||||||
def create(self, key):
|
def create(self, key):
|
||||||
if isinstance(key, str):
|
if isinstance(key, str):
|
||||||
|
|
@ -35,16 +38,16 @@ class DockerLabelHandler:
|
||||||
class HaproxyConfigGenerator:
|
class HaproxyConfigGenerator:
|
||||||
def __init__(self, mapping, ssl_cert_folder="/etc/haproxy/certs"):
|
def __init__(self, mapping, ssl_cert_folder="/etc/haproxy/certs"):
|
||||||
self.mapping = mapping
|
self.mapping = mapping
|
||||||
self.label = DockerLabelHandler("easyhaproxy")
|
self.label = DockerLabelHandler(mapping['lookup_label'] if 'lookup_label' in mapping else "easyhaproxy")
|
||||||
self.ssl_cert_folder = ssl_cert_folder
|
self.ssl_cert_folder = ssl_cert_folder
|
||||||
self.ssl_cert_increment = 0
|
self.ssl_cert_increment = 0
|
||||||
os.makedirs(self.ssl_cert_folder, exist_ok=True)
|
os.makedirs(self.ssl_cert_folder, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
def generate(self, lineList = []):
|
def generate(self, line_list = []):
|
||||||
# static?
|
# static?
|
||||||
if len(lineList) > 0:
|
if len(line_list) > 0:
|
||||||
self.mapping["easymapping"] = self.__parse(lineList)
|
self.mapping["easymapping"] = self.parse(line_list)
|
||||||
else:
|
else:
|
||||||
for d in self.mapping["easymapping"]:
|
for d in self.mapping["easymapping"]:
|
||||||
for name, hosts in d.get('hosts', {}).items():
|
for name, hosts in d.get('hosts', {}).items():
|
||||||
|
|
@ -63,42 +66,49 @@ class HaproxyConfigGenerator:
|
||||||
return template.render(data=self.mapping)
|
return template.render(data=self.mapping)
|
||||||
|
|
||||||
|
|
||||||
def __parse(self, lineList):
|
def parse(self, line_list):
|
||||||
easymapping = dict()
|
easymapping = dict()
|
||||||
|
|
||||||
for line in lineList:
|
for line in line_list:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
i = line.find("=")
|
i = line.find("=")
|
||||||
container = line[:i]
|
container = line[:i]
|
||||||
jsonStr = line[i+1:]
|
json_str = line[i+1:]
|
||||||
d = json.loads(jsonStr)
|
d = json.loads(json_str)
|
||||||
|
|
||||||
if self.label.create("definitions") not in d.keys():
|
# Extract the definitions dynamically
|
||||||
|
definitions = {}
|
||||||
|
r = re.compile(self.label.get_lookup_label() + r"\.(.*)\..*")
|
||||||
|
for key in d.keys():
|
||||||
|
if r.match(key):
|
||||||
|
definitions[r.search(key).group(1)] = 1
|
||||||
|
|
||||||
|
if len(definitions.keys()) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.label.set_data(d)
|
self.label.set_data(d)
|
||||||
|
|
||||||
definitions = d[self.label.create("definitions")].split(",")
|
# Parse each definition found.
|
||||||
for definition in definitions:
|
for definition in definitions.keys():
|
||||||
mode = self.label.get(
|
mode = self.label.get(
|
||||||
self.label.create(["mode", definition]),
|
self.label.create([definition, "mode"]),
|
||||||
"http"
|
"http"
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO: we can ignore "host" in TCP, but it would break the template
|
# TODO: we can ignore "host" in TCP, but it would break the template
|
||||||
host_label = self.label.create(["host", definition])
|
host_label = self.label.create([definition, "host"])
|
||||||
if not self.label.has_label(host_label):
|
if not self.label.has_label(host_label):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
port = self.label.get(
|
port = self.label.get(
|
||||||
self.label.create(["port", definition]),
|
self.label.create([definition, "port"]),
|
||||||
"80"
|
"80"
|
||||||
)
|
)
|
||||||
|
|
||||||
hash = ""
|
hash = ""
|
||||||
if self.label.create(["sslcert", definition]) in d:
|
if self.label.create([definition, "sslcert"]) in d:
|
||||||
hash = hashlib.md5(
|
hash = hashlib.md5(
|
||||||
d[self.label.create(["sslcert", definition])].encode('utf-8')
|
d[self.label.create([definition, "sslcert"])].encode('utf-8')
|
||||||
).hexdigest()
|
).hexdigest()
|
||||||
|
|
||||||
key = port if not hash else port + "_" + hash
|
key = port if not hash else port + "_" + hash
|
||||||
|
|
@ -114,12 +124,12 @@ class HaproxyConfigGenerator:
|
||||||
|
|
||||||
# TODO: this could use `EXPOSE` from `Dockerfile`?
|
# TODO: this could use `EXPOSE` from `Dockerfile`?
|
||||||
ct_port = self.label.get(
|
ct_port = self.label.get(
|
||||||
self.label.create(["localport", definition]),
|
self.label.create([definition, "localport"]),
|
||||||
"80"
|
"80"
|
||||||
)
|
)
|
||||||
|
|
||||||
easymapping[key]["health-check"] = self.label.get(
|
easymapping[key]["health-check"] = self.label.get(
|
||||||
self.label.create(["health-check", definition]),
|
self.label.create([definition, "health-check"]),
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -127,7 +137,7 @@ class HaproxyConfigGenerator:
|
||||||
easymapping[key]["hosts"][d[host_label]] += ["{}:{}".format(container, ct_port)]
|
easymapping[key]["hosts"][d[host_label]] += ["{}:{}".format(container, ct_port)]
|
||||||
|
|
||||||
# handle SSL
|
# handle SSL
|
||||||
ssl_label = self.label.create(["sslcert", definition])
|
ssl_label = self.label.create([definition, "sslcert"])
|
||||||
if self.label.has_label(ssl_label):
|
if self.label.has_label(ssl_label):
|
||||||
self.ssl_cert_increment += 1
|
self.ssl_cert_increment += 1
|
||||||
filename = "{}/{}.{}.pem".format(
|
filename = "{}/{}.{}.pem".format(
|
||||||
|
|
@ -141,7 +151,7 @@ class HaproxyConfigGenerator:
|
||||||
|
|
||||||
# handle redirects
|
# handle redirects
|
||||||
redirect = self.label.get(
|
redirect = self.label.get(
|
||||||
self.label.create(["redirect", definition])
|
self.label.create([definition, "redirect"])
|
||||||
)
|
)
|
||||||
if len(redirect) > 0:
|
if len(redirect) > 0:
|
||||||
for r in redirect.split(","):
|
for r in redirect.split(","):
|
||||||
|
|
|
||||||
37
examples/docker/docker-compose-changed-label.yml
Normal file
37
examples/docker/docker-compose-changed-label.yml
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,12 +1,21 @@
|
||||||
|
# curl -H Host:www.helloworld.com localhost:19901
|
||||||
|
# f6d8d45b7411
|
||||||
|
# 59b213cb8592
|
||||||
|
|
||||||
|
# curl -I -H Host:google.helloworld.com localhost:19901
|
||||||
|
# HTTP/1.1 301 Moved Permanently
|
||||||
|
# content-length: 0
|
||||||
|
# location: www.google.com/
|
||||||
|
|
||||||
version: "3"
|
version: "3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
haproxy:
|
haproxy:
|
||||||
image: 0x0400/easy-haproxy
|
image: byjg/easy-haproxy
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
environment:
|
environment:
|
||||||
DISCOVER: docker
|
EASYHAPROXY_DISCOVER: docker
|
||||||
HAPROXY_CUSTOMERRORS: "true"
|
HAPROXY_CUSTOMERRORS: "true"
|
||||||
HAPROXY_USERNAME: admin
|
HAPROXY_USERNAME: admin
|
||||||
HAPROXY_PASSWORD: password
|
HAPROXY_PASSWORD: password
|
||||||
|
|
@ -21,18 +30,8 @@ services:
|
||||||
deploy:
|
deploy:
|
||||||
replicas: 2
|
replicas: 2
|
||||||
labels:
|
labels:
|
||||||
easyhaproxy.definitions: "http"
|
easyhaproxy.http.redirect: google.helloworld.com--www.google.com
|
||||||
|
easyhaproxy.http.host: www.helloworld.com
|
||||||
|
easyhaproxy.http.port: 19901
|
||||||
|
easyhaproxy.http.localport: 80
|
||||||
|
|
||||||
easyhaproxy.redirect.http: google.helloworld.com--www.google.com
|
|
||||||
easyhaproxy.host.http: www.helloworld.com
|
|
||||||
easyhaproxy.port.http: 19901
|
|
||||||
easyhaproxy.localport.http: 80
|
|
||||||
|
|
||||||
# curl -H Host:www.helloworld.com localhost:19901
|
|
||||||
# f6d8d45b7411
|
|
||||||
# 59b213cb8592
|
|
||||||
|
|
||||||
# curl -I -H Host:google.helloworld.com localhost:19901
|
|
||||||
# HTTP/1.1 301 Moved Permanently
|
|
||||||
# content-length: 0
|
|
||||||
# location: www.google.com/
|
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,3 +1,6 @@
|
||||||
|
# To test:
|
||||||
|
# curl -k -H "Host: host1.local" https://127.0.0.1/
|
||||||
|
|
||||||
version: "3"
|
version: "3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
@ -8,7 +11,7 @@ services:
|
||||||
- ./host1.local.pem:/etc/certs/host1.local.pem
|
- ./host1.local.pem:/etc/certs/host1.local.pem
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
environment:
|
environment:
|
||||||
DISCOVER: static
|
EASYHAPROXY_DISCOVER: static
|
||||||
ports:
|
ports:
|
||||||
- "80:80/tcp"
|
- "80:80/tcp"
|
||||||
- "443:443/tcp"
|
- "443:443/tcp"
|
||||||
|
|
|
||||||
8
tests/fixtures/services
vendored
8
tests/fixtures/services
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
portainer-agent_agent={"com.docker.stack.image":"portainer/agent:1.5.1","com.docker.stack.namespace":"portainer-agent"}
|
portainer-agent_agent={"com.docker.stack.image":"portainer/agent:1.5.1","com.docker.stack.namespace":"portainer-agent"}
|
||||||
my-stack_agent={"easyhaproxy.definitions":"agent","easyhaproxy.host.agent":"agent.quantum.example.org","easyhaproxy.localport.agent":"9001","easyhaproxy.mode.agent":"tcp","easyhaproxy.port.agent":"31339","com.docker.stack.image":"portainer/agent:1.5.1","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
my-stack_agent={"easyhaproxy.agent.host":"agent.quantum.example.org","easyhaproxy.agent.localport":"9001","easyhaproxy.agent.mode":"tcp","easyhaproxy.agent.port":"31339","com.docker.stack.image":"portainer/agent:1.5.1","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
||||||
my-stack_cadvisor={"easyhaproxy.definitions":"cadvisor","easyhaproxy.host.cadvisor":"cadvisor.quantum.example.org","easyhaproxy.localport.cadvisor":"8080","easyhaproxy.port.cadvisor":"31337","com.docker.stack.image":"gcr.io/google-containers/cadvisor:v0.34.0","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
my-stack_cadvisor={"easyhaproxy.cadvisor.host":"cadvisor.quantum.example.org","easyhaproxy.cadvisor.localport":"8080","easyhaproxy.cadvisor.port":"31337","com.docker.stack.image":"gcr.io/google-containers/cadvisor:v0.34.0","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
||||||
my-stack_node-exporter={"easyhaproxy.definitions":"exp","easyhaproxy.host.exp":"node-exporter.quantum.example.org","easyhaproxy.localport.exp":"9100","easyhaproxy.port.exp":"31337","com.docker.stack.image":"stefanprodan/swarmprom-node-exporter:v0.16.0","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
my-stack_node-exporter={"easyhaproxy.exp.host":"node-exporter.quantum.example.org","easyhaproxy.exp.localport":"9100","easyhaproxy.exp.port":"31337","com.docker.stack.image":"stefanprodan/swarmprom-node-exporter:v0.16.0","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
||||||
my-stack_reverse-proxy={"com.docker.stack.image":"quay.io/pngmbh/easy-haproxy:tcp-mode","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
my-stack_reverse-proxy={"com.docker.stack.image":"quay.io/pngmbh/easy-haproxy:tcp-mode","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
||||||
some-service={"easyhaproxy.definitions":"http,https","easyhaproxy.port.http":"80","easyhaproxy.host.http":"www.somehost.com.br","easyhaproxy.localport.http":"80","easyhaproxy.redirect.http":"somehost.com.br--https://www.somehost.com.br,somehost.com--https://www.somehost.com.br,www.somehost.com--https://www.somehost.com.br,byjg.ca--https://www.somehost.com.br,www.byjg.ca--https://www.somehost.com.br","easyhaproxy.port.https":"443","easyhaproxy.host.https":"www.somehost.com.br","easyhaproxy.localport.https":"80","easyhaproxy.redirect.https":"somehost.com.br--https://www.somehost.com.br,somehost.com--https://www.somehost.com.br,www.somehost.com--https://www.somehost.com.br,byjg.ca--https://www.somehost.com.br,www.byjg.ca--https://www.somehost.com.br","easyhaproxy.sslcert.https":"U29tZSBQRU0gQ2VydGlmaWNhdGU="}
|
some-service={"easyhaproxy.http.port":"80","easyhaproxy.http.host":"www.somehost.com.br","easyhaproxy.http.localport":"80","easyhaproxy.http.redirect":"somehost.com.br--https://www.somehost.com.br,somehost.com--https://www.somehost.com.br,www.somehost.com--https://www.somehost.com.br,byjg.ca--https://www.somehost.com.br,www.byjg.ca--https://www.somehost.com.br","easyhaproxy.https.port":"443","easyhaproxy.https.host":"www.somehost.com.br","easyhaproxy.https.localport":"80","easyhaproxy.https.redirect":"somehost.com.br--https://www.somehost.com.br,somehost.com--https://www.somehost.com.br,www.somehost.com--https://www.somehost.com.br,byjg.ca--https://www.somehost.com.br,www.byjg.ca--https://www.somehost.com.br","easyhaproxy.https.sslcert":"U29tZSBQRU0gQ2VydGlmaWNhdGU="}
|
||||||
6
tests/fixtures/services-changed-label
vendored
Normal file
6
tests/fixtures/services-changed-label
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
portainer-agent_agent={"com.docker.stack.image":"portainer/agent:1.5.1","com.docker.stack.namespace":"portainer-agent"}
|
||||||
|
my-stack_agent={"haproxy.agent.host":"agent.quantum.example.org","haproxy.agent.localport":"9001","haproxy.agent.mode":"tcp","haproxy.agent.port":"31339","com.docker.stack.image":"portainer/agent:1.5.1","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
||||||
|
my-stack_cadvisor={"haproxy.cadvisor.host":"cadvisor.quantum.example.org","haproxy.cadvisor.localport":"8080","haproxy.cadvisor.port":"31337","com.docker.stack.image":"gcr.io/google-containers/cadvisor:v0.34.0","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
||||||
|
my-stack_node-exporter={"haproxy.exp.host":"node-exporter.quantum.example.org","haproxy.exp.localport":"9100","haproxy.exp.port":"31337","com.docker.stack.image":"stefanprodan/swarmprom-node-exporter:v0.16.0","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
||||||
|
my-stack_reverse-proxy={"com.docker.stack.image":"quay.io/pngmbh/easy-haproxy:tcp-mode","com.docker.stack.namespace":"my-stack","com.planetary-quantum":"monitoring"}
|
||||||
|
some-service={"haproxy.http.port":"80","haproxy.http.host":"www.somehost.com.br","haproxy.http.localport":"80","haproxy.http.redirect":"somehost.com.br--https://www.somehost.com.br,somehost.com--https://www.somehost.com.br,www.somehost.com--https://www.somehost.com.br,byjg.ca--https://www.somehost.com.br,www.byjg.ca--https://www.somehost.com.br","haproxy.https.port":"443","haproxy.https.host":"www.somehost.com.br","haproxy.https.localport":"80","haproxy.https.redirect":"somehost.com.br--https://www.somehost.com.br,somehost.com--https://www.somehost.com.br,www.somehost.com--https://www.somehost.com.br,byjg.ca--https://www.somehost.com.br,www.byjg.ca--https://www.somehost.com.br","haproxy.https.sslcert":"U29tZSBQRU0gQ2VydGlmaWNhdGU="}
|
||||||
4
tests/fixtures/services-multi-containers
vendored
4
tests/fixtures/services-multi-containers
vendored
|
|
@ -1,2 +1,2 @@
|
||||||
test_nginx.2.t5r94mjlced7m3t5orfjbowmm={"easyhaproxy.definitions":"http","easyhaproxy.host.http":"www.helloworld.com","easyhaproxy.localport.http":"80","easyhaproxy.port.http":"19901","com.docker.stack.image":"stenote/nginx-hostname","com.docker.stack.namespace":"test"}
|
test_nginx.2.t5r94mjlced7m3t5orfjbowmm={"easyhaproxy.http.host":"www.helloworld.com","easyhaproxy.http.localport":"80","easyhaproxy.http.port":"19901","com.docker.stack.image":"stenote/nginx-hostname","com.docker.stack.namespace":"test"}
|
||||||
test_nginx.1.p552hqxkdx88narjrp5kouwb2={"easyhaproxy.definitions":"http","easyhaproxy.host.http":"www.helloworld.com","easyhaproxy.localport.http":"80","easyhaproxy.port.http":"19901","com.docker.stack.image":"stenote/nginx-hostname","com.docker.stack.namespace":"test"}
|
test_nginx.1.p552hqxkdx88narjrp5kouwb2={"easyhaproxy.http.host":"www.helloworld.com","easyhaproxy.http.localport":"80","easyhaproxy.http.port":"19901","com.docker.stack.image":"stenote/nginx-hostname","com.docker.stack.namespace":"test"}
|
||||||
2
tests/fixtures/services-tcp
vendored
2
tests/fixtures/services-tcp
vendored
|
|
@ -1,2 +1,2 @@
|
||||||
test_agent={"easyhaproxy.definitions":"agent","easyhaproxy.host.agent":"agent.quantum.local","easyhaproxy.localport.agent":"9001","easyhaproxy.mode.agent":"tcp","easyhaproxy.port.agent":"31339","com.docker.stack.image":"portainer/agent:1.5.1","com.docker.stack.namespace":"test", "easyhaproxy.health-check.agent":"ssl"}
|
test_agent={"easyhaproxy.agent.host":"agent.quantum.local","easyhaproxy.agent.localport":"9001","easyhaproxy.agent.mode":"tcp","easyhaproxy.agent.port":"31339","com.docker.stack.image":"portainer/agent:1.5.1","com.docker.stack.namespace":"test", "easyhaproxy.agent.health-check":"ssl"}
|
||||||
test_proxy={"com.docker.stack.image":"byjg/easy-haproxy:local","com.docker.stack.namespace":"test"}
|
test_proxy={"com.docker.stack.image":"byjg/easy-haproxy:local","com.docker.stack.namespace":"test"}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from .context import easymapping
|
import easymapping
|
||||||
import pytest
|
import pytest
|
||||||
import os
|
import os
|
||||||
import yaml
|
import yaml
|
||||||
|
|
@ -7,20 +7,20 @@ import yaml
|
||||||
def load_fixture(file):
|
def load_fixture(file):
|
||||||
path = os.path.dirname(os.path.realpath(__file__))
|
path = os.path.dirname(os.path.realpath(__file__))
|
||||||
with open(path + "/fixtures/" + file, 'r') as content_file:
|
with open(path + "/fixtures/" + file, 'r') as content_file:
|
||||||
lineList = content_file.readlines()
|
line_list = content_file.readlines()
|
||||||
|
|
||||||
return lineList
|
return line_list
|
||||||
|
|
||||||
|
|
||||||
def test_parser_doesnt_crash():
|
def test_parser_doesnt_crash():
|
||||||
lineList = load_fixture("no-services")
|
line_list = load_fixture("no-services")
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"customerrors": False
|
"customerrors": False
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg = easymapping.HaproxyConfigGenerator(result, "/tmp")
|
cfg = easymapping.HaproxyConfigGenerator(result, "/tmp")
|
||||||
haproxy_config = cfg.generate(lineList)
|
haproxy_config = cfg.generate(line_list)
|
||||||
|
|
||||||
assert len(haproxy_config) > 0
|
assert len(haproxy_config) > 0
|
||||||
path = os.path.dirname(os.path.realpath(__file__))
|
path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
@ -29,7 +29,7 @@ def test_parser_doesnt_crash():
|
||||||
|
|
||||||
|
|
||||||
def test_parser_finds_services():
|
def test_parser_finds_services():
|
||||||
lineList = load_fixture("services")
|
line_list = load_fixture("services")
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"customerrors": False
|
"customerrors": False
|
||||||
|
|
@ -40,7 +40,7 @@ def test_parser_finds_services():
|
||||||
os.remove(cert_file)
|
os.remove(cert_file)
|
||||||
|
|
||||||
cfg = easymapping.HaproxyConfigGenerator(result, "/tmp")
|
cfg = easymapping.HaproxyConfigGenerator(result, "/tmp")
|
||||||
haproxy_config = cfg.generate(lineList)
|
haproxy_config = cfg.generate(line_list)
|
||||||
|
|
||||||
assert len(haproxy_config) > 0
|
assert len(haproxy_config) > 0
|
||||||
path = os.path.dirname(os.path.realpath(__file__))
|
path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
@ -50,6 +50,114 @@ def test_parser_finds_services():
|
||||||
with open(cert_file, 'r') as expected_file:
|
with open(cert_file, 'r') as expected_file:
|
||||||
assert expected_file.read() == "Some PEM Certificate"
|
assert expected_file.read() == "Some PEM Certificate"
|
||||||
|
|
||||||
|
def test_parser_finds_services_changed_label():
|
||||||
|
line_list = load_fixture("services-changed-label")
|
||||||
|
|
||||||
|
result = {
|
||||||
|
"customerrors": False,
|
||||||
|
"lookup_label": "haproxy"
|
||||||
|
}
|
||||||
|
|
||||||
|
cert_file = "/tmp/www.somehost.com.br.1.pem"
|
||||||
|
if os.path.exists(cert_file):
|
||||||
|
os.remove(cert_file)
|
||||||
|
|
||||||
|
cfg = easymapping.HaproxyConfigGenerator(result, "/tmp")
|
||||||
|
haproxy_config = cfg.generate(line_list)
|
||||||
|
|
||||||
|
assert len(haproxy_config) > 0
|
||||||
|
path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
with open(path + "/expected/services.txt", 'r') as expected_file:
|
||||||
|
assert expected_file.read() == haproxy_config
|
||||||
|
|
||||||
|
with open(cert_file, 'r') as expected_file:
|
||||||
|
assert expected_file.read() == "Some PEM Certificate"
|
||||||
|
|
||||||
|
def test_parser_finds_services_raw():
|
||||||
|
line_list = load_fixture("services")
|
||||||
|
|
||||||
|
result = {
|
||||||
|
"customerrors": False
|
||||||
|
}
|
||||||
|
|
||||||
|
cert_file = "/tmp/www.somehost.com.br.1.pem"
|
||||||
|
if os.path.exists(cert_file):
|
||||||
|
os.remove(cert_file)
|
||||||
|
|
||||||
|
cfg = easymapping.HaproxyConfigGenerator(result, "/tmp")
|
||||||
|
|
||||||
|
parsed_object = [
|
||||||
|
{
|
||||||
|
"mode":"tcp",
|
||||||
|
"health-check":"",
|
||||||
|
"port":"31339",
|
||||||
|
"hosts":{
|
||||||
|
"agent.quantum.example.org":[
|
||||||
|
"my-stack_agent:9001"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"redirect":{
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mode":"http",
|
||||||
|
"health-check":"",
|
||||||
|
"port":"31337",
|
||||||
|
"hosts":{
|
||||||
|
"cadvisor.quantum.example.org":[
|
||||||
|
"my-stack_cadvisor:8080"
|
||||||
|
],
|
||||||
|
"node-exporter.quantum.example.org":[
|
||||||
|
"my-stack_node-exporter:9100"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"redirect":{
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mode":"http",
|
||||||
|
"health-check":"",
|
||||||
|
"port":"80",
|
||||||
|
"hosts":{
|
||||||
|
"www.somehost.com.br":[
|
||||||
|
"some-service:80"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"redirect":{
|
||||||
|
"somehost.com.br":"https://www.somehost.com.br",
|
||||||
|
"somehost.com":"https://www.somehost.com.br",
|
||||||
|
"www.somehost.com":"https://www.somehost.com.br",
|
||||||
|
"byjg.ca":"https://www.somehost.com.br",
|
||||||
|
"www.byjg.ca":"https://www.somehost.com.br"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mode":"http",
|
||||||
|
"health-check":"",
|
||||||
|
"port":"443",
|
||||||
|
"hosts":{
|
||||||
|
"www.somehost.com.br":[
|
||||||
|
"some-service:80"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"redirect":{
|
||||||
|
"somehost.com.br":"https://www.somehost.com.br",
|
||||||
|
"somehost.com":"https://www.somehost.com.br",
|
||||||
|
"www.somehost.com":"https://www.somehost.com.br",
|
||||||
|
"byjg.ca":"https://www.somehost.com.br",
|
||||||
|
"www.byjg.ca":"https://www.somehost.com.br"
|
||||||
|
},
|
||||||
|
"ssl_cert":"/tmp/www.somehost.com.br.1.pem"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
processed = list(cfg.parse(line_list))
|
||||||
|
|
||||||
|
assert parsed_object == processed
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_parser_static():
|
def test_parser_static():
|
||||||
path = os.path.dirname(os.path.realpath(__file__))
|
path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
@ -65,14 +173,14 @@ def test_parser_static():
|
||||||
|
|
||||||
|
|
||||||
def test_parser_tcp():
|
def test_parser_tcp():
|
||||||
lineList = load_fixture("services-tcp")
|
line_list = load_fixture("services-tcp")
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"customerrors": False
|
"customerrors": False
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg = easymapping.HaproxyConfigGenerator(result, "/tmp")
|
cfg = easymapping.HaproxyConfigGenerator(result, "/tmp")
|
||||||
haproxy_config = cfg.generate(lineList)
|
haproxy_config = cfg.generate(line_list)
|
||||||
# print(haproxy_config)
|
# print(haproxy_config)
|
||||||
|
|
||||||
assert len(haproxy_config) > 0
|
assert len(haproxy_config) > 0
|
||||||
|
|
@ -81,17 +189,20 @@ def test_parser_tcp():
|
||||||
assert expected_file.read() == haproxy_config
|
assert expected_file.read() == haproxy_config
|
||||||
|
|
||||||
def test_parser_multi_containers():
|
def test_parser_multi_containers():
|
||||||
lineList = load_fixture("services-multi-containers")
|
line_list = load_fixture("services-multi-containers")
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"customerrors": False
|
"customerrors": False
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg = easymapping.HaproxyConfigGenerator(result, "/tmp")
|
cfg = easymapping.HaproxyConfigGenerator(result, "/tmp")
|
||||||
haproxy_config = cfg.generate(lineList)
|
haproxy_config = cfg.generate(line_list)
|
||||||
|
|
||||||
assert len(haproxy_config) > 0
|
assert len(haproxy_config) > 0
|
||||||
path = os.path.dirname(os.path.realpath(__file__))
|
path = os.path.dirname(os.path.realpath(__file__))
|
||||||
with open(path + "/expected/services-multi-containers.txt", 'r') as expected_file:
|
with open(path + "/expected/services-multi-containers.txt", 'r') as expected_file:
|
||||||
assert expected_file.read() == haproxy_config
|
assert expected_file.read() == haproxy_config
|
||||||
|
|
||||||
|
|
||||||
|
#test_parser_finds_services_raw()
|
||||||
|
#test_parser_tcp()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue