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") traefik.ensure_traefik_config(str(state_dir)) traefik_toml = os.path.join(state_dir, "traefik.toml") with open(traefik_toml) as f: toml_cfg = f.read() # print config for debugging on failure print(config.CONFIG_FILE) print(toml_cfg) cfg = toml.loads(toml_cfg) assert cfg["defaultEntryPoints"] == ["http", "https"] assert "acme" not in cfg assert cfg["entryPoints"] == { "http": { "address": ":80", "redirect": { "entryPoint": "https" } }, "https": { "address": ":443", "backend": "jupyterhub", "tls": { "certificates": [{ "certFile": "/path/to/ssl.cert", "keyFile": "/path/to/ssl.key" }] }, }, }
def test_default_config(tmpdir, tljh_dir): state_dir = tmpdir.mkdir("state") traefik.ensure_traefik_config(str(state_dir)) assert state_dir.join("traefik.toml").exists() traefik_toml = os.path.join(state_dir, "traefik.toml") with open(traefik_toml) as f: toml_cfg = f.read() # print config for debugging on failure print(config.CONFIG_FILE) print(toml_cfg) cfg = toml.loads(toml_cfg) assert cfg["defaultEntryPoints"] == ["http"] assert len(cfg["entryPoints"]["auth_api"]["auth"]["basic"]["users"]) == 1 # runtime generated entry, value not testable cfg["entryPoints"]["auth_api"]["auth"]["basic"]["users"] = [""] assert cfg["entryPoints"] == { "http": { "address": ":80" }, "auth_api": { "address": "127.0.0.1:8099", "auth": { "basic": { "users": [""] } }, "whiteList": { "sourceRange": ["127.0.0.1"] }, }, }
def test_default_config(tmpdir, tljh_dir): state_dir = tmpdir.mkdir("state") traefik.ensure_traefik_config(str(state_dir)) assert state_dir.join("traefik.toml").exists() traefik_toml = os.path.join(state_dir, "traefik.toml") with open(traefik_toml) as f: toml_cfg = f.read() # print config for debugging on failure print(config.CONFIG_FILE) print(toml_cfg) cfg = toml.loads(toml_cfg) assert cfg["defaultEntryPoints"] == ["http"] assert cfg["entryPoints"] == {"http": {"address": ":80"}} assert cfg["frontends"] == { "jupyterhub": { "backend": "jupyterhub", "passHostHeader": True } } assert cfg["backends"] == { "jupyterhub": { "servers": { "chp": { "url": "http://127.0.0.1:15003" } } } }
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", "*****@*****.**") config.set_config_value(config.CONFIG_FILE, "https.letsencrypt.domains", ["testing.jovyan.org"]) traefik.ensure_traefik_config(str(state_dir)) traefik_toml = os.path.join(state_dir, "traefik.toml") with open(traefik_toml) as f: toml_cfg = f.read() # print config for debugging on failure print(config.CONFIG_FILE) print(toml_cfg) cfg = toml.loads(toml_cfg) assert cfg["defaultEntryPoints"] == ["http", "https"] assert "acme" in cfg assert len(cfg["entryPoints"]["auth_api"]["auth"]["basic"]["users"]) == 1 # runtime generated entry, value not testable cfg["entryPoints"]["auth_api"]["auth"]["basic"]["users"] = [""] assert cfg["entryPoints"] == { "http": { "address": ":80", "redirect": { "entryPoint": "https" } }, "https": { "address": ":443", "tls": { "minVersion": "VersionTLS12" } }, "auth_api": { "address": "127.0.0.1:8099", "auth": { "basic": { "users": [""] } }, "whiteList": { "sourceRange": ["127.0.0.1"] }, }, } assert cfg["acme"] == { "email": "*****@*****.**", "storage": "acme.json", "entryPoint": "https", "httpChallenge": { "entryPoint": "http" }, "domains": [{ "main": "testing.jovyan.org" }], }
def ensure_jupyterhub_service(prefix): """ Ensure JupyterHub Services are set up properly """ os.makedirs(STATE_DIR, mode=0o700, exist_ok=True) with open(os.path.join(HERE, 'systemd-units', 'jupyterhub.service')) as f: hub_unit_template = f.read() with open( os.path.join(HERE, 'systemd-units', 'configurable-http-proxy.service')) as f: proxy_unit_template = f.read() with open(os.path.join(HERE, 'systemd-units', 'traefik.service')) as f: traefik_unit_template = f.read() traefik.ensure_traefik_config(STATE_DIR) unit_params = dict( python_interpreter_path=sys.executable, jupyterhub_config_path=os.path.join(HERE, 'jupyterhub_config.py'), install_prefix=INSTALL_PREFIX, ) systemd.install_unit('configurable-http-proxy.service', proxy_unit_template.format(**unit_params)) systemd.install_unit('jupyterhub.service', hub_unit_template.format(**unit_params)) systemd.install_unit('traefik.service', traefik_unit_template.format(**unit_params)) systemd.reload_daemon() # Set up proxy / hub secret oken if it is not already setup proxy_secret_path = os.path.join(STATE_DIR, 'configurable-http-proxy.secret') if not os.path.exists(proxy_secret_path): with open(proxy_secret_path, 'w') as f: f.write('CONFIGPROXY_AUTH_TOKEN=' + '0123456789abcdef0123456789abcdef') # f.write('CONFIGPROXY_AUTH_TOKEN=' + secrets.token_hex(32)) # If we are changing CONFIGPROXY_AUTH_TOKEN, restart configurable-http-proxy! systemd.restart_service('configurable-http-proxy') # Start CHP if it has already not been started systemd.start_service('configurable-http-proxy') # If JupyterHub is running, we want to restart it. systemd.restart_service('jupyterhub') systemd.restart_service('traefik') # Mark JupyterHub & CHP to start at boot time systemd.enable_service('jupyterhub') systemd.enable_service('configurable-http-proxy') systemd.enable_service('traefik')
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") traefik.ensure_traefik_config(str(state_dir)) traefik_toml = os.path.join(state_dir, "traefik.toml") with open(traefik_toml) as f: toml_cfg = f.read() # print config for debugging on failure print(config.CONFIG_FILE) print(toml_cfg) cfg = toml.loads(toml_cfg) assert cfg["defaultEntryPoints"] == ["http", "https"] assert "acme" not in cfg assert len(cfg["entryPoints"]["auth_api"]["auth"]["basic"]["users"]) == 1 # runtime generated entry, value not testable cfg["entryPoints"]["auth_api"]["auth"]["basic"]["users"] = [""] assert cfg["entryPoints"] == { "http": { "address": ":80", "redirect": { "entryPoint": "https" } }, "https": { "address": ":443", "tls": { "minVersion": "VersionTLS12", "certificates": [{ "certFile": "/path/to/ssl.cert", "keyFile": "/path/to/ssl.key" }], }, }, "auth_api": { "address": "127.0.0.1:8099", "auth": { "basic": { "users": [""] } }, "whiteList": { "sourceRange": ["127.0.0.1"] }, }, }
def reload_component(component): """ Reload a TLJH component. component can be 'hub' or 'proxy'. """ # import here to avoid circular imports from tljh import systemd, traefik if component == 'hub': systemd.restart_service('jupyterhub') # FIXME: Verify hub is back up? print('Hub reload with new configuration complete') elif component == 'proxy': traefik.ensure_traefik_config(STATE_DIR) systemd.restart_service('configurable-http-proxy') systemd.restart_service('traefik') print('Proxy reload with new configuration complete')
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") 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 assert toml_cfg["logLevel"] == "INFO" with pytest.raises(KeyError): toml_cfg["checkNewVersion"] assert toml_cfg["entryPoints"]["auth_api"]["address"] == "127.0.0.1:8099" extra_config = { # modify existing value "logLevel": "ERROR", # modify existing value with multiple levels "entryPoints": { "auth_api": { "address": "127.0.0.1:9999" } }, # add new setting "checkNewVersion": False, } with open(os.path.join(extra_config_dir, "extra.toml"), "w+") as extra_config_file: toml.dump(extra_config, extra_config_file) # Merge the extra config with the defaults traefik.ensure_traefik_config(str(state_dir)) # Read back the merged config toml_cfg = toml.load(traefik_toml) # Check that the defaults were updated by the extra config assert toml_cfg["logLevel"] == "ERROR" assert toml_cfg["checkNewVersion"] == False assert toml_cfg["entryPoints"]["auth_api"]["address"] == "127.0.0.1:9999"
def ensure_jupyterhub_service(prefix): """ Ensure JupyterHub Services are set up properly """ os.makedirs(STATE_DIR, mode=0o700, exist_ok=True) remove_chp() systemd.reload_daemon() with open(os.path.join(HERE, 'systemd-units', 'jupyterhub.service')) as f: hub_unit_template = f.read() with open(os.path.join(HERE, 'systemd-units', 'traefik.service')) as f: traefik_unit_template = f.read() #Set up proxy / hub secret token if it is not already setup proxy_secret_path = os.path.join(STATE_DIR, 'traefik-api.secret') if not os.path.exists(proxy_secret_path): with open(proxy_secret_path, 'w') as f: f.write(secrets.token_hex(32)) traefik.ensure_traefik_config(STATE_DIR) unit_params = dict( python_interpreter_path=sys.executable, jupyterhub_config_path=os.path.join(HERE, 'jupyterhub_config.py'), install_prefix=INSTALL_PREFIX, ) systemd.install_unit('jupyterhub.service', hub_unit_template.format(**unit_params)) systemd.install_unit('traefik.service', traefik_unit_template.format(**unit_params)) systemd.reload_daemon() # If JupyterHub is running, we want to restart it. systemd.restart_service('jupyterhub') systemd.restart_service('traefik') # Mark JupyterHub & traefik to start at boot time systemd.enable_service('jupyterhub') systemd.enable_service('traefik')
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", "*****@*****.**") config.set_config_value(config.CONFIG_FILE, "https.letsencrypt.domains", ["testing.jovyan.org"]) traefik.ensure_traefik_config(str(state_dir)) traefik_toml = os.path.join(state_dir, "traefik.toml") with open(traefik_toml) as f: toml_cfg = f.read() # print config for debugging on failure print(config.CONFIG_FILE) print(toml_cfg) cfg = toml.loads(toml_cfg) assert cfg["defaultEntryPoints"] == ["http", "https"] assert "acme" in cfg assert cfg["entryPoints"] == { "http": { "address": ":80", "redirect": { "entryPoint": "https" } }, "https": { "address": ":443", "backend": "jupyterhub", "tls": {} }, } assert cfg["acme"] == { "email": "*****@*****.**", "storage": "acme.json", "entryPoint": "https", "httpChallenge": { "entryPoint": "http" }, "domains": [{ "main": "testing.jovyan.org" }], }
def ensure_jupyterhub_service(prefix): """ Ensure JupyterHub Services are set up properly """ remove_chp() systemd.reload_daemon() with open(os.path.join(HERE, "systemd-units", "jupyterhub.service")) as f: hub_unit_template = f.read() with open(os.path.join(HERE, "systemd-units", "traefik.service")) as f: traefik_unit_template = f.read() # Set up proxy / hub secret token if it is not already setup proxy_secret_path = os.path.join(STATE_DIR, "traefik-api.secret") if not os.path.exists(proxy_secret_path): with open(proxy_secret_path, "w") as f: f.write(secrets.token_hex(32)) traefik.ensure_traefik_config(STATE_DIR) unit_params = dict( python_interpreter_path=sys.executable, jupyterhub_config_path=os.path.join(HERE, "jupyterhub_config.py"), install_prefix=INSTALL_PREFIX, ) systemd.install_unit("jupyterhub.service", hub_unit_template.format(**unit_params)) systemd.install_unit("traefik.service", traefik_unit_template.format(**unit_params)) systemd.reload_daemon() # If JupyterHub is running, we want to restart it. systemd.restart_service("jupyterhub") systemd.restart_service("traefik") # Mark JupyterHub & traefik to start at boot time systemd.enable_service("jupyterhub") systemd.enable_service("traefik")
def reload_component(component): """ Reload a TLJH component. component can be 'hub' or 'proxy'. """ # import here to avoid circular imports from tljh import systemd, traefik if component == 'hub': systemd.restart_service('jupyterhub') # Ensure hub is back up while not systemd.check_service_active('jupyterhub'): time.sleep(1) while not check_hub_ready(): time.sleep(1) print('Hub reload with new configuration complete') elif component == 'proxy': traefik.ensure_traefik_config(STATE_DIR) systemd.restart_service('traefik') while not systemd.check_service_active('traefik'): time.sleep(1) print('Proxy reload with new configuration complete')