2018-08-01 17:06:52 +02:00
|
|
|
"""Test traefik configuration"""
|
|
|
|
|
import os
|
|
|
|
|
|
2020-06-08 12:36:26 +03:00
|
|
|
import pytest
|
2023-05-15 08:51:35 +00:00
|
|
|
import toml
|
2018-08-01 17:06:52 +02:00
|
|
|
|
2023-05-15 08:51:35 +00:00
|
|
|
from tljh import config, traefik
|
2018-08-01 17:06:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_download_traefik(tmpdir):
|
|
|
|
|
traefik_bin = tmpdir.mkdir("bin").join("traefik")
|
|
|
|
|
traefik.ensure_traefik_binary(str(tmpdir))
|
|
|
|
|
assert traefik_bin.exists()
|
2018-08-03 16:11:49 +02:00
|
|
|
# ignore higher-order permission bits, only verify ugo permissions
|
|
|
|
|
assert (traefik_bin.stat().mode & 0o777) == 0o755
|
2018-08-01 17:06:52 +02:00
|
|
|
|
|
|
|
|
|
2023-05-15 10:53:53 +02:00
|
|
|
def _read_toml(path):
|
|
|
|
|
"""Read a toml file
|
|
|
|
|
|
|
|
|
|
print config for debugging on failure
|
|
|
|
|
"""
|
|
|
|
|
print(path)
|
|
|
|
|
with open(path) as f:
|
|
|
|
|
toml_cfg = f.read()
|
|
|
|
|
print(toml_cfg)
|
|
|
|
|
return toml.loads(toml_cfg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _read_static_config(state_dir):
|
|
|
|
|
return _read_toml(os.path.join(state_dir, "traefik.toml"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _read_dynamic_config(state_dir):
|
|
|
|
|
return _read_toml(os.path.join(state_dir, "rules", "dynamic.toml"))
|
|
|
|
|
|
|
|
|
|
|
2018-08-01 17:06:52 +02:00
|
|
|
def test_default_config(tmpdir, tljh_dir):
|
|
|
|
|
state_dir = tmpdir.mkdir("state")
|
2019-02-22 11:39:40 +01:00
|
|
|
traefik.ensure_traefik_config(str(state_dir))
|
2018-08-01 17:06:52 +02:00
|
|
|
assert state_dir.join("traefik.toml").exists()
|
2023-05-15 10:53:53 +02:00
|
|
|
os.path.join(state_dir, "traefik.toml")
|
|
|
|
|
rules_dir = os.path.join(state_dir, "rules")
|
2019-02-11 11:13:22 +02:00
|
|
|
|
2023-05-15 10:53:53 +02:00
|
|
|
cfg = _read_static_config(state_dir)
|
|
|
|
|
assert cfg["api"] == {}
|
2019-01-22 16:24:38 +02:00
|
|
|
assert cfg["entryPoints"] == {
|
2023-05-15 10:53:53 +02:00
|
|
|
"http": {
|
|
|
|
|
"address": ":80",
|
|
|
|
|
"transport": {"respondingTimeouts": {"idleTimeout": "10m"}},
|
|
|
|
|
},
|
2019-01-22 16:24:38 +02:00
|
|
|
"auth_api": {
|
2023-05-15 10:53:53 +02:00
|
|
|
"address": "localhost:8099",
|
2019-01-22 16:24:38 +02:00
|
|
|
},
|
2018-08-01 17:06:52 +02:00
|
|
|
}
|
2023-05-15 10:53:53 +02:00
|
|
|
assert cfg["providers"] == {
|
|
|
|
|
"providersThrottleDuration": "0s",
|
|
|
|
|
"file": {"directory": rules_dir, "watch": True},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dynamic_config = _read_dynamic_config(state_dir)
|
|
|
|
|
assert dynamic_config == {}
|
2018-08-01 17:06:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_letsencrypt_config(tljh_dir):
|
|
|
|
|
state_dir = config.STATE_DIR
|
|
|
|
|
config.set_config_value(config.CONFIG_FILE, "https.enabled", True)
|
|
|
|
|
config.set_config_value(
|
|
|
|
|
config.CONFIG_FILE, "https.letsencrypt.email", "fake@jupyter.org"
|
|
|
|
|
)
|
|
|
|
|
config.set_config_value(
|
|
|
|
|
config.CONFIG_FILE, "https.letsencrypt.domains", ["testing.jovyan.org"]
|
|
|
|
|
)
|
2019-02-22 11:39:40 +01:00
|
|
|
traefik.ensure_traefik_config(str(state_dir))
|
2019-02-11 11:13:22 +02:00
|
|
|
|
2023-05-15 10:53:53 +02:00
|
|
|
cfg = _read_static_config(state_dir)
|
2018-08-01 17:06:52 +02:00
|
|
|
assert cfg["entryPoints"] == {
|
2023-05-15 10:53:53 +02:00
|
|
|
"http": {
|
|
|
|
|
"address": ":80",
|
|
|
|
|
"http": {
|
|
|
|
|
"redirections": {
|
|
|
|
|
"entryPoint": {
|
|
|
|
|
"scheme": "https",
|
|
|
|
|
"to": "https",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"transport": {"respondingTimeouts": {"idleTimeout": "10m"}},
|
|
|
|
|
},
|
|
|
|
|
"https": {
|
|
|
|
|
"address": ":443",
|
|
|
|
|
"http": {"tls": {"options": "default"}},
|
|
|
|
|
"transport": {"respondingTimeouts": {"idleTimeout": "10m"}},
|
|
|
|
|
},
|
2019-01-22 16:24:38 +02:00
|
|
|
"auth_api": {
|
2023-05-15 10:53:53 +02:00
|
|
|
"address": "localhost:8099",
|
2019-01-22 16:24:38 +02:00
|
|
|
},
|
2018-08-01 17:06:52 +02:00
|
|
|
}
|
2023-05-15 10:53:53 +02:00
|
|
|
assert "tls" not in cfg
|
|
|
|
|
|
|
|
|
|
dynamic_config = _read_dynamic_config(state_dir)
|
|
|
|
|
|
|
|
|
|
assert dynamic_config["tls"] == {
|
|
|
|
|
"options": {"default": {"minVersion": "VersionTLS12"}},
|
|
|
|
|
"stores": {
|
|
|
|
|
"default": {
|
|
|
|
|
"defaultGeneratedCert": {
|
|
|
|
|
"resolver": "letsencrypt",
|
|
|
|
|
"domain": {
|
|
|
|
|
"main": "testing.jovyan.org",
|
|
|
|
|
"sans": [],
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
2023-05-16 13:05:34 +02:00
|
|
|
assert "certificatesResolvers" in cfg
|
|
|
|
|
assert "letsencrypt" in cfg["certificatesResolvers"]
|
2023-05-15 10:53:53 +02:00
|
|
|
|
2023-05-16 13:05:34 +02:00
|
|
|
assert cfg["certificatesResolvers"]["letsencrypt"]["acme"] == {
|
2018-08-01 17:06:52 +02:00
|
|
|
"email": "fake@jupyter.org",
|
|
|
|
|
"storage": "acme.json",
|
2023-05-16 13:05:34 +02:00
|
|
|
"tlsChallenge": {},
|
2018-08-01 17:06:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_manual_ssl_config(tljh_dir):
|
|
|
|
|
state_dir = config.STATE_DIR
|
|
|
|
|
config.set_config_value(config.CONFIG_FILE, "https.enabled", True)
|
|
|
|
|
config.set_config_value(config.CONFIG_FILE, "https.tls.key", "/path/to/ssl.key")
|
|
|
|
|
config.set_config_value(config.CONFIG_FILE, "https.tls.cert", "/path/to/ssl.cert")
|
2019-02-22 11:39:40 +01:00
|
|
|
traefik.ensure_traefik_config(str(state_dir))
|
2023-05-15 10:53:53 +02:00
|
|
|
|
|
|
|
|
cfg = _read_static_config(state_dir)
|
|
|
|
|
|
2018-08-01 17:06:52 +02:00
|
|
|
assert cfg["entryPoints"] == {
|
2023-05-15 10:53:53 +02:00
|
|
|
"http": {
|
|
|
|
|
"address": ":80",
|
|
|
|
|
"http": {
|
|
|
|
|
"redirections": {
|
|
|
|
|
"entryPoint": {
|
|
|
|
|
"scheme": "https",
|
|
|
|
|
"to": "https",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"transport": {
|
|
|
|
|
"respondingTimeouts": {
|
|
|
|
|
"idleTimeout": "10m",
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
2018-08-01 17:06:52 +02:00
|
|
|
"https": {
|
|
|
|
|
"address": ":443",
|
2023-05-15 10:53:53 +02:00
|
|
|
"http": {"tls": {"options": "default"}},
|
|
|
|
|
"transport": {"respondingTimeouts": {"idleTimeout": "10m"}},
|
2018-08-01 17:06:52 +02:00
|
|
|
},
|
2019-01-22 16:24:38 +02:00
|
|
|
"auth_api": {
|
2023-05-15 10:53:53 +02:00
|
|
|
"address": "localhost:8099",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
assert "tls" not in cfg
|
|
|
|
|
|
|
|
|
|
dynamic_config = _read_dynamic_config(state_dir)
|
|
|
|
|
|
|
|
|
|
assert "tls" in dynamic_config
|
|
|
|
|
|
|
|
|
|
assert dynamic_config["tls"] == {
|
|
|
|
|
"options": {"default": {"minVersion": "VersionTLS12"}},
|
|
|
|
|
"stores": {
|
|
|
|
|
"default": {
|
|
|
|
|
"defaultCertificate": {
|
|
|
|
|
"certFile": "/path/to/ssl.cert",
|
|
|
|
|
"keyFile": "/path/to/ssl.key",
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-22 16:24:38 +02:00
|
|
|
},
|
2018-08-01 17:06:52 +02:00
|
|
|
}
|
2020-06-02 18:20:28 +03:00
|
|
|
|
2021-11-01 09:42:45 +01:00
|
|
|
|
2020-06-02 18:20:28 +03:00
|
|
|
def test_extra_config(tmpdir, tljh_dir):
|
|
|
|
|
extra_config_dir = os.path.join(tljh_dir, config.CONFIG_DIR, "traefik_config.d")
|
|
|
|
|
state_dir = tmpdir.mkdir("state")
|
2020-06-08 12:36:26 +03:00
|
|
|
traefik_toml = os.path.join(state_dir, "traefik.toml")
|
|
|
|
|
|
|
|
|
|
# Generate default config
|
|
|
|
|
traefik.ensure_traefik_config(str(state_dir))
|
|
|
|
|
|
|
|
|
|
# Read the default config
|
|
|
|
|
toml_cfg = toml.load(traefik_toml)
|
|
|
|
|
|
|
|
|
|
# Make sure the defaults are what we expect
|
2023-05-15 10:53:53 +02:00
|
|
|
assert toml_cfg["log"]["level"] == "INFO"
|
2020-06-08 12:36:26 +03:00
|
|
|
with pytest.raises(KeyError):
|
2023-05-15 10:53:53 +02:00
|
|
|
toml_cfg["api"]["dashboard"]
|
|
|
|
|
assert toml_cfg["entryPoints"]["auth_api"]["address"] == "localhost:8099"
|
2020-06-02 18:20:28 +03:00
|
|
|
|
|
|
|
|
extra_config = {
|
|
|
|
|
# modify existing value
|
2023-05-15 10:53:53 +02:00
|
|
|
"log": {
|
|
|
|
|
"level": "ERROR",
|
|
|
|
|
},
|
2020-06-02 18:20:28 +03:00
|
|
|
# add new setting
|
2023-05-15 10:53:53 +02:00
|
|
|
"api": {"dashboard": True},
|
2020-06-02 18:20:28 +03:00
|
|
|
}
|
|
|
|
|
|
2020-06-02 19:09:19 +03:00
|
|
|
with open(os.path.join(extra_config_dir, "extra.toml"), "w+") as extra_config_file:
|
2020-06-02 18:20:28 +03:00
|
|
|
toml.dump(extra_config, extra_config_file)
|
|
|
|
|
|
2020-06-08 12:36:26 +03:00
|
|
|
# Merge the extra config with the defaults
|
2020-06-02 18:20:28 +03:00
|
|
|
traefik.ensure_traefik_config(str(state_dir))
|
|
|
|
|
|
|
|
|
|
# Read back the merged config
|
|
|
|
|
toml_cfg = toml.load(traefik_toml)
|
|
|
|
|
|
2020-06-08 12:36:26 +03:00
|
|
|
# Check that the defaults were updated by the extra config
|
2023-05-15 10:53:53 +02:00
|
|
|
assert toml_cfg["log"]["level"] == "ERROR"
|
|
|
|
|
assert toml_cfg["api"]["dashboard"] == True
|