From 2bf23f0b28a3b55520773704cb71c5cb23f9c3fc Mon Sep 17 00:00:00 2001 From: Min RK Date: Tue, 28 Aug 2018 14:00:43 +0200 Subject: [PATCH] put config in a single `config` directory instead of top-level files - ensure directory is private - both tljh and jupyterhub config go in there - move old config.yaml to new location at install time --- tljh/config.py | 6 ++++- tljh/installer.py | 49 +++++++++++++++++++++++++++++++++------ tljh/jupyterhub_config.py | 4 ++-- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/tljh/config.py b/tljh/config.py index 7f6e3b4..a9855d0 100644 --- a/tljh/config.py +++ b/tljh/config.py @@ -27,7 +27,11 @@ INSTALL_PREFIX = os.environ.get('TLJH_INSTALL_PREFIX', '/opt/tljh') HUB_ENV_PREFIX = os.path.join(INSTALL_PREFIX, 'hub') USER_ENV_PREFIX = os.path.join(INSTALL_PREFIX, 'user') STATE_DIR = os.path.join(INSTALL_PREFIX, 'state') -CONFIG_FILE = os.path.join(INSTALL_PREFIX, 'config.yaml') +CONFIG_DIR = os.path.join(INSTALL_PREFIX, 'config') +CONFIG_FILE = os.path.join(CONFIG_DIR, 'config.yaml') + +# deprecated config file location +OLD_CONFIG_FILE = os.path.join(INSTALL_PREFIX, 'config.yaml') def set_item_in_config(config, property_path, value): diff --git a/tljh/installer.py b/tljh/installer.py index 6d5009a..f27af3e 100644 --- a/tljh/installer.py +++ b/tljh/installer.py @@ -1,19 +1,31 @@ +"""Installation logic for TLJH""" + import argparse +from datetime import date +import itertools +import logging import os import secrets +import shutil import subprocess -import itertools import sys import time -import logging from urllib.error import HTTPError from urllib.request import urlopen, URLError -import pluggy +import pluggy from ruamel.yaml import YAML from tljh import conda, systemd, traefik, user, apt, hooks -from tljh.config import INSTALL_PREFIX, HUB_ENV_PREFIX, USER_ENV_PREFIX, STATE_DIR, CONFIG_FILE +from tljh.config import ( + CONFIG_DIR, + CONFIG_FILE, + HUB_ENV_PREFIX, + INSTALL_PREFIX, + OLD_CONFIG_FILE, + STATE_DIR, + USER_ENV_PREFIX, +) HERE = os.path.abspath(os.path.dirname(__file__)) @@ -254,7 +266,7 @@ def ensure_admins(admins): if not admins: return logger.info("Setting up admin users") - config_path = os.path.join(INSTALL_PREFIX, 'config.yaml') + config_path = CONFIG_FILE if os.path.exists(config_path): with open(config_path, 'r') as f: config = rt_yaml.load(f) @@ -339,6 +351,7 @@ def setup_plugins(plugins): return pm + def run_plugin_actions(plugin_manager, plugins): """ Run installer hooks defined in plugins @@ -373,6 +386,29 @@ def ensure_config_yaml(plugin_manager): """ Ensure we have a config.yaml present """ + # ensure config dir exists and is private + for path in [CONFIG_DIR, os.path.join(CONFIG_DIR, 'jupyterhub_config.d')]: + os.makedirs(path, mode=0o700, exist_ok=True) + + # handle old TLJH_DIR/config.yaml location + if os.path.exists(OLD_CONFIG_FILE): + if os.path.exists(CONFIG_FILE): + # new config file already created! still move the config, + # but avoid collision + timestamp = date.today().isoformat() + dest = dest_base = f"{CONFIG_FILE}.old.{timestamp}" + i = 0 + while os.path.exists(dest): + # avoid collisions + dest = dest_base + f".{i}" + i += 1 + logger.warning(f"Found config in both old ({OLD_CONFIG_FILE}) and new ({CONFIG_FILE}).") + logger.warning(f"Moving {OLD_CONFIG_FILE} to {dest} to avoid clobbering. Its contents will be ignored.") + else: + logger.warning(f"Moving old config file to new location {OLD_CONFIG_FILE} -> {CONFIG_FILE}") + dest = CONFIG_FILE + shutil.move(OLD_CONFIG_FILE, dest) + if os.path.exists(CONFIG_FILE): with open(CONFIG_FILE, 'r') as f: config = rt_yaml.load(f) @@ -407,8 +443,8 @@ def main(): pm = setup_plugins(args.plugin) + ensure_config_yaml(pm) ensure_admins(args.admin) - ensure_usergroups() ensure_user_environment(args.user_requirements_txt_url) @@ -416,7 +452,6 @@ def main(): ensure_node() ensure_jupyterhub_package(HUB_ENV_PREFIX) ensure_chp_package(HUB_ENV_PREFIX) - ensure_config_yaml(pm) ensure_jupyterlab_extensions() ensure_jupyterhub_service(HUB_ENV_PREFIX) ensure_jupyterhub_running() diff --git a/tljh/jupyterhub_config.py b/tljh/jupyterhub_config.py index 4abb891..994e506 100644 --- a/tljh/jupyterhub_config.py +++ b/tljh/jupyterhub_config.py @@ -8,7 +8,7 @@ from glob import glob from systemdspawner import SystemdSpawner from tljh import user, configurer -from tljh.config import INSTALL_PREFIX, USER_ENV_PREFIX +from tljh.config import INSTALL_PREFIX, USER_ENV_PREFIX, CONFIG_DIR class CustomSpawner(SystemdSpawner): @@ -50,6 +50,6 @@ configurer.apply_config(config_overrides, c) # Load arbitrary .py config files if they exist. # This is our escape hatch -extra_configs = sorted(glob(os.path.join(INSTALL_PREFIX, 'jupyterhub_config.d', '*.py'))) +extra_configs = sorted(glob(os.path.join(CONFIG_DIR, 'jupyterhub_config.d', '*.py'))) for ec in extra_configs: load_subconfig(ec)