move config migration to its own file

This commit is contained in:
Min RK
2018-08-31 12:17:16 +02:00
parent 37ad207be9
commit 5df106fa82
5 changed files with 139 additions and 63 deletions

View File

@@ -2,12 +2,10 @@
Unit test functions in installer.py Unit test functions in installer.py
""" """
import os import os
from datetime import date
from tljh import installer from tljh import installer
def test_ensure_node(): def test_ensure_node():
installer.ensure_node() installer.ensure_node()
assert os.path.exists('/usr/bin/node') assert os.path.exists('/usr/bin/node')
@@ -19,39 +17,5 @@ def test_ensure_config_yaml(tljh_dir):
assert os.path.exists(installer.CONFIG_FILE) assert os.path.exists(installer.CONFIG_FILE)
assert os.path.isdir(installer.CONFIG_DIR) assert os.path.isdir(installer.CONFIG_DIR)
assert os.path.isdir(os.path.join(installer.CONFIG_DIR, 'jupyterhub_config.d')) assert os.path.isdir(os.path.join(installer.CONFIG_DIR, 'jupyterhub_config.d'))
assert not os.path.exists(installer.OLD_CONFIG_FILE) # verify that old config doesn't exist
assert not os.path.exists(os.path.join(tljh_dir, 'config.yaml'))
# run again, with old config in the way and no new config
upgraded_config = 'old: config\n'
with open(installer.OLD_CONFIG_FILE, 'w') as f:
f.write(upgraded_config)
os.remove(installer.CONFIG_FILE)
installer.ensure_config_yaml(pm)
assert os.path.exists(installer.CONFIG_FILE)
assert not os.path.exists(installer.OLD_CONFIG_FILE)
with open(installer.CONFIG_FILE) as f:
assert f.read() == upgraded_config
# run again, this time with both old and new config
duplicate_config = 'dupe: config\n'
with open(installer.OLD_CONFIG_FILE, 'w') as f:
f.write(duplicate_config)
installer.ensure_config_yaml(pm)
assert os.path.exists(installer.CONFIG_FILE)
assert not os.path.exists(installer.OLD_CONFIG_FILE)
# didn't clobber config:
with open(installer.CONFIG_FILE) as f:
assert f.read() == upgraded_config
# preserved old config
backup_config = installer.CONFIG_FILE + f".old.{date.today().isoformat()}"
assert os.path.exists(backup_config)
with open(backup_config) as f:
assert f.read() == duplicate_config

57
tests/test_migrator.py Normal file
View File

@@ -0,0 +1,57 @@
"""
Unit test functions in installer.py
"""
import os
from datetime import date
from tljh import migrator, config
def test_migrate_config(tljh_dir):
CONFIG_FILE = config.CONFIG_FILE
CONFIG_DIR = config.CONFIG_DIR
OLD_CONFIG_FILE = os.path.join(tljh_dir, "config.yaml")
OLD_CONFIG_D = os.path.join(tljh_dir, "jupyterhub_config.d")
CONFIG_D = os.path.join(config.CONFIG_DIR, "jupyterhub_config.d")
old_config_py = os.path.join(OLD_CONFIG_D, "upgrade.py")
new_config_py = os.path.join(CONFIG_D, "upgrade.py")
# initial condition: nothing exists
assert not os.path.exists(CONFIG_FILE)
assert not os.path.exists(OLD_CONFIG_FILE)
assert os.path.isdir(CONFIG_DIR)
# run migration with old config and no new config
upgraded_config = "old: config\n"
with open(OLD_CONFIG_FILE, "w") as f:
f.write(upgraded_config)
os.makedirs(OLD_CONFIG_D, exist_ok=True)
with open(old_config_py, "w") as f:
f.write("c.JupyterHub.log_level = 10")
migrator.migrate_config_files()
assert os.path.exists(CONFIG_FILE)
assert not os.path.exists(OLD_CONFIG_FILE)
with open(CONFIG_FILE) as f:
assert f.read() == upgraded_config
assert os.path.exists(new_config_py)
assert not os.path.exists(OLD_CONFIG_D)
# run again, this time with both old and new config
duplicate_config = "dupe: config\n"
with open(OLD_CONFIG_FILE, "w") as f:
f.write(duplicate_config)
migrator.migrate_config_files()
assert os.path.exists(CONFIG_FILE)
assert not os.path.exists(OLD_CONFIG_FILE)
# didn't clobber config:
with open(CONFIG_FILE) as f:
assert f.read() == upgraded_config
# preserved old config
backup_config = CONFIG_FILE + f".old.{date.today().isoformat()}"
assert os.path.exists(backup_config)
with open(backup_config) as f:
assert f.read() == duplicate_config
# migrate jupyterhub_con

View File

@@ -30,9 +30,6 @@ STATE_DIR = os.path.join(INSTALL_PREFIX, 'state')
CONFIG_DIR = os.path.join(INSTALL_PREFIX, 'config') CONFIG_DIR = os.path.join(INSTALL_PREFIX, 'config')
CONFIG_FILE = os.path.join(CONFIG_DIR, 'config.yaml') 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): def set_item_in_config(config, property_path, value):
""" """

View File

@@ -1,12 +1,10 @@
"""Installation logic for TLJH""" """Installation logic for TLJH"""
import argparse import argparse
from datetime import date
import itertools import itertools
import logging import logging
import os import os
import secrets import secrets
import shutil
import subprocess import subprocess
import sys import sys
import time import time
@@ -16,13 +14,21 @@ from urllib.request import urlopen, URLError
import pluggy import pluggy
from ruamel.yaml import YAML from ruamel.yaml import YAML
from tljh import conda, systemd, traefik, user, apt, hooks from tljh import (
apt,
conda,
hooks,
migrator,
systemd,
traefik,
user,
)
from tljh.config import ( from tljh.config import (
CONFIG_DIR, CONFIG_DIR,
CONFIG_FILE, CONFIG_FILE,
HUB_ENV_PREFIX, HUB_ENV_PREFIX,
INSTALL_PREFIX, INSTALL_PREFIX,
OLD_CONFIG_FILE,
STATE_DIR, STATE_DIR,
USER_ENV_PREFIX, USER_ENV_PREFIX,
) )
@@ -378,24 +384,7 @@ def ensure_config_yaml(plugin_manager):
for path in [CONFIG_DIR, os.path.join(CONFIG_DIR, 'jupyterhub_config.d')]: for path in [CONFIG_DIR, os.path.join(CONFIG_DIR, 'jupyterhub_config.d')]:
os.makedirs(path, mode=0o700, exist_ok=True) os.makedirs(path, mode=0o700, exist_ok=True)
# handle old TLJH_DIR/config.yaml location migrator.migrate_config_files()
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): if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, 'r') as f: with open(CONFIG_FILE, 'r') as f:

69
tljh/migrator.py Normal file
View File

@@ -0,0 +1,69 @@
"""Migration utilities for upgrading tljh"""
import os
from datetime import date
import logging
import shutil
from tljh.config import (
CONFIG_DIR,
CONFIG_FILE,
INSTALL_PREFIX,
)
logger = logging.getLogger(__name__)
def migrate_file(old_path, new_path):
"""Migrate one file from an old location to a new one
avoids collisions if the new file exists
"""
if not os.path.exists(old_path):
return
if os.path.exists(new_path):
# new config file already created! still move the config,
# but avoid collision
timestamp = date.today().isoformat()
dest = dest_base = f"{new_path}.old.{timestamp}"
i = 0
while os.path.exists(dest):
# avoid collisions
dest = dest_base + f".{i}"
i += 1
logger.warning(f"Found file in both old ({old_path}) and new ({new_path}).")
logger.warning(
f"Moving {old_path} to {dest} to avoid clobbering. Its contents will be ignored."
)
else:
dest = new_path
shutil.move(old_path, dest)
def migrate_directory(old_dir, new_dir):
"""Migrate a directory to a new location"""
if not os.path.exists(old_dir):
return
if os.path.exists(new_dir):
# both dirs exist
for f in os.listdir(old_dir):
src = os.path.join(old_dir, f)
dest = os.path.join(new_dir, f)
if os.path.isdir(src):
migrate_directory(src, dest)
else:
migrate_file(src, dest)
else:
logger.warning(f"Moving directory to new location {old_dir} -> {new_dir}")
shutil.move(old_dir, new_dir)
def migrate_config_files():
"""Migrate config files to their new locations"""
# handle old TLJH_DIR/config.yaml location
migrate_file(os.path.join(INSTALL_PREFIX, "config.yaml"), CONFIG_FILE)
migrate_directory(
os.path.join(INSTALL_PREFIX, "jupyterhub_config.d"),
os.path.join(CONFIG_DIR, "jupyterhub_config.d"),
)