Skip to content

Commit

Permalink
feat(command): install or upgrade application using CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
maugde committed May 3, 2024
1 parent e5adb9a commit 1b6d038
Show file tree
Hide file tree
Showing 49 changed files with 198 additions and 9 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ coverage.xml
.pytest_cache/
cover/

# test data
tests/samples/results/nt!/Program Files/
tests/samples/results/nt/Program Files/*
tests/samples/results/posix/opt/*

# Translations
*.mo
*.pot
Expand Down Expand Up @@ -158,3 +163,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/

2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
docs_dir: docs
site_name: Antares Web Installer Documentation
repo_url: https://github.com/AntaresSimulatorTeam/antares-web-installer
edit_uri: edit/doc/docs/
edit_uri: edit/docs/docs/

theme:
name: mkdocs # material
Expand Down
1 change: 1 addition & 0 deletions src/antares_web_installer/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DEBUG = True
3 changes: 1 addition & 2 deletions src/antares_web_installer/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
Main entrypoint for the CLI application.
"""
import sys

from antares_web_installer.cli import install_cli
from cli import install_cli


def main():
Expand Down
57 changes: 52 additions & 5 deletions src/antares_web_installer/cli.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,61 @@
import time

import os
import click
from antares_web_installer import DEBUG
from pathlib import Path
from installer import install


# SETTINGS WHEN DEBUGGING
if DEBUG:
BASE_DIR = Path().resolve().parent.parent

SRC_DIR = "tests/samples/initial/"
TARGET_DIR = "tests/samples/results/"
if os.name.lower() == "posix":
suffix = "posix/opt/antares-web/"
else:
suffix = "nt/Program Files/AntaresWeb/"
TARGET_DIR += suffix
SRC_DIR += suffix

# REAL SETTINGS
else:
if os.name.lower() == "posix":
TARGET_DIR = "/opt/antares-web/"
else:
TARGET_DIR = "C:/Program Files/AntaresWeb/"

SRC_DIR = ""


@click.group()
def cli():
pass


@click.command()
@click.argument("target_dir", type=click.Path())
@click.option("-t", "--target-dir",
default=TARGET_DIR,
show_default=True,
type=click.Path(),
help="where to install your application")
def install_cli(target_dir):
"""
Install Antares Web.
Install Antares Web at the right file locations.
"""
target_dir = Path(target_dir)
src_dir = Path(SRC_DIR)

if DEBUG:
target_dir = BASE_DIR.joinpath(Path(target_dir))
src_dir = BASE_DIR.joinpath(Path(src_dir))
target_dir = target_dir.expanduser()

# TODO: check whether the server is running
# in case it is, stop it

print(f"Starting installation in directory: '{target_dir}'...")
time.sleep(1)

install(src_dir, target_dir)

print("Installation complete!")
5 changes: 5 additions & 0 deletions src/antares_web_installer/config/config_2_15.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ def update_to_2_15(config: t.MutableMapping[str, t.Any]) -> None:
nb_cores_max = os.cpu_count() or nb_cores_min
nb_cores_default = max(nb_cores_min, nb_cores_max - 2)

# WIP
if not config:
config = {}
# end of WIP

config.setdefault("launcher", {})
config["launcher"].setdefault("local", {})
config["launcher"].setdefault("slurm", {})
Expand Down
107 changes: 107 additions & 0 deletions src/antares_web_installer/installer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import subprocess
import textwrap
import os
from pathlib import Path
from antares_web_installer import DEBUG
from shutil import copytree, copy2, rmtree
from config import update_config

# List of files and directories to exclude during installation
COMMON_EXCLUDED_FILES = {"config.prod.yaml", "config.yaml", "examples", "logs", "matrices", "tmp", }
POSIX_EXCLUDED_FILES = COMMON_EXCLUDED_FILES | {"AntaresWebWorker"}
WINDOWS_EXCLUDED_FILES = COMMON_EXCLUDED_FILES | {"AntaresWebWorker.exe"}
EXCLUDED_FILES = POSIX_EXCLUDED_FILES if os.name == "posix" else WINDOWS_EXCLUDED_FILES


class InstallError(Exception):
"""
Exception that handles installation error
"""
pass


def install(src_dir: Path, target_dir: Path) -> None:
"""
"""
# if "AntaresWeb/" directory already exists
if target_dir.joinpath("AntaresWeb").is_dir():
# check app version
version = check_version(target_dir)

# update config file
config_path = target_dir.joinpath("config.yaml")
update_config(config_path, config_path, version)

# copy binaries
copy_files(src_dir, target_dir)

else:
# copy all files from package
copytree(src_dir, target_dir)


def check_version(target_dir: Path) -> str:
"""
Execute command to get the current version of the server.
:param target_dir: path of target directory
"""
# debug mode
if DEBUG:
exe_path = target_dir.joinpath("AntaresWeb/AntaresWebServer.py")
args = ["python", exe_path, "--version"]
else:
exe_path = target_dir.joinpath("AntaresWeb/AntaresWebServer.exe")
# check user's os
if os.name.lower() == "posix": # if os is linux, remove ".exe"
exe_path.with_suffix("")
args = [exe_path, "--version"]

try:
version = subprocess.check_output(args, text=True, stderr=subprocess.PIPE).strip()
except FileNotFoundError as e:
raise InstallError(f"Can't check version: {e}") from e
except subprocess.CalledProcessError as e:
reason = textwrap.indent(e.stderr, " | ", predicate=lambda line: True)
raise InstallError(f"Can't check version: {reason}")

return version


def copy_files(src_dir: Path, target_dir: Path):
"""
Copy all files from src_dir to target_dir
Override existing files and directories that have the same name
Raise an InstallError if an error occurs while overriding a directory, if the user hasn't the permission to write or
if target_dir already exists.
:param src_dir: location of directory to copy files from
:param target_dir: location of directory to copy files to
"""
for elt_path in src_dir.iterdir():
if elt_path.name not in EXCLUDED_FILES:
# verbose action
print(f"copy {elt_path.name} to {target_dir.name}")

try:
if elt_path.is_file():
copy2(elt_path, target_dir)
else:
# copytree() cannot natively override directory
# the target must be deleted first
rmtree(target_dir.joinpath(elt_path.name))

# check if the old directory is completely erased
if target_dir.joinpath(elt_path.name).exists():
raise InstallError(f"Erreur : Impossible de mettre à jour le répertoire {elt_path}")

# copy new directory
copytree(elt_path, target_dir.joinpath(elt_path.name))
# handle permission errors
except PermissionError:
raise InstallError(f"Erreur : Impossible d'écrire dans {target_dir}")
# handle other errors
except BaseException as e:
raise InstallError(f"{e}")
else:
print(f"ignoring {elt_path.name}")
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import click
import time


@click.version_option(version="2.15.0", message="%(version)s")
@click.group()
def cli():
pass


if __name__ == "__main__":
cli()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "2.14.4"
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import click
from tests.samples import version


@click.command()
def get_version():
return version


if __name__ == "__main__":
get_version()
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file.
2 changes: 1 addition & 1 deletion tests/test_about.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import re

from antares_web_installer.__about__ import __version__
from src.antares_web_installer.__about__ import __version__


def test_version():
Expand Down

0 comments on commit 1b6d038

Please sign in to comment.