Skip to content
This repository has been archived by the owner on Jul 15, 2022. It is now read-only.

Commit

Permalink
config_generator module
Browse files Browse the repository at this point in the history
  • Loading branch information
IKrukov-HORIS committed Dec 24, 2020
1 parent 50dcadf commit 89df0e1
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 145 deletions.
10 changes: 6 additions & 4 deletions projector_installer/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@
find_apps, edit_config, list_apps, select_installed_app, select_run_config, make_run_config, \
get_user_install_input, make_config_from_input

from .global_config import get_download_cache_dir, RunConfig
from .global_config import get_download_cache_dir

from .ide_configuration import forbid_updates_for
from .run_config import get_run_configs, get_run_script_path, validate_run_config, \
save_config, delete_config, rename_config, make_config_name, get_configs_with_app, \
check_config, lock_config, release_config
from .run_config import RunConfig, get_run_configs, get_run_script_path, validate_run_config, \
delete_config, rename_config, make_config_name, get_configs_with_app, \
lock_config, release_config

from .config_generator import save_config, check_config


def do_list_config(pattern: Optional[str] = None) -> None:
Expand Down
61 changes: 4 additions & 57 deletions projector_installer/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,18 @@


"""Application management functions."""
import io
from os import listdir, chmod, stat, rename
from os import listdir, rename
from os.path import join, expanduser, dirname, isfile, isdir
from distutils.version import LooseVersion
from typing import Optional, List, TextIO
from typing import Optional, List
import json

from . import global_config
from .global_config import get_apps_dir, get_projector_server_dir, \
InstallableApp, RunConfig, init_compatible_apps, get_ssl_properties_file

from .global_config import get_apps_dir, init_compatible_apps
from .installable_app import InstallableApp
from .utils import unpack_tar_file

IDEA_RUN_CLASS = 'com.intellij.idea.Main'
PROJECTOR_RUN_CLASS = 'org.jetbrains.projector.server.ProjectorLauncher'
IDEA_PLATFORM_PREFIX = 'idea.platform.prefix'
IDEA_PATH_SELECTOR = 'idea.paths.selector'
TOKEN_ENV_NAME = 'ORG_JETBRAINS_PROJECTOR_SERVER_HANDSHAKE_TOKEN'
RO_TOKEN_ENV_NAME = 'ORG_JETBRAINS_PROJECTOR_SERVER_RO_HANDSHAKE_TOKEN'
SSL_ENV_NAME = 'ORG_JETBRAINS_PROJECTOR_SERVER_SSL_PROPERTIES_PATH'


def get_installed_apps(pattern: Optional[str] = None) -> List[str]:
Expand Down Expand Up @@ -62,51 +54,6 @@ def get_app_path(app_name: str) -> str:
return join(get_apps_dir(), app_name)


def write_run_script(run_config: RunConfig, src: TextIO, dst: TextIO) -> None:
"""Writes run script from src to dst"""

for line in src:
if line.startswith("IDE_BIN_HOME"):
line = f'IDE_BIN_HOME={join(run_config.path_to_app, "bin")}\n'
elif line.find("classpath") != -1:
line = f' -classpath "$CLASSPATH:{get_projector_server_dir()}/*" \\\n'
elif line.find(IDEA_RUN_CLASS) != -1:
line = f' -Dorg.jetbrains.projector.server.port={run_config.projector_port} \\\n'
line += f' -Dorg.jetbrains.projector.server.classToLaunch={IDEA_RUN_CLASS} \\\n'

if run_config.is_secure():
line += f' -D{SSL_ENV_NAME}=\"{get_ssl_properties_file(run_config.name)}\" \\\n'

if run_config.is_password_protected():
line += f' -D{TOKEN_ENV_NAME}=\"{run_config.password}\" \\\n'
line += f' -D{RO_TOKEN_ENV_NAME}=\"{run_config.ro_password}\" \\\n'

line += f' {PROJECTOR_RUN_CLASS}\\\n'

dst.write(line)


def make_run_script(run_config: RunConfig, run_script: str) -> None:
"""Creates run script from ide launch script."""
idea_script = get_launch_script(run_config.path_to_app)

with open(idea_script, 'r') as src, open(run_script, 'w') as dst:
write_run_script(run_config, src, dst)

stats = stat(run_script)
chmod(run_script, stats.st_mode | 0o0111)


def check_run_script(run_config: RunConfig, run_script_name: str) -> bool:
"""Check if run script corresponds to given config"""
idea_script = get_launch_script(run_config.path_to_app)
with open(idea_script, 'r') as src, open(run_script_name, 'r') as run_script:
dst = io.StringIO()
write_run_script(run_config, src, dst)
dst.seek(0)
return dst.read() == run_script.read()


class ProductInfo:
"""Ide product info"""

Expand Down
123 changes: 123 additions & 0 deletions projector_installer/config_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Copyright 2000-2020 JetBrains s.r.o.
# Use of this source code is governed by the Apache 2.0 license that can be found
# in the LICENSE file.

"""Run config generation stuff"""

import configparser
import io
from os import mkdir, stat, chmod
from os.path import join, isdir
from typing import TextIO

from .apps import get_launch_script
from .global_config import get_run_configs_dir, get_projector_server_dir, \
get_ssl_properties_file
from .run_config import RunConfig, get_run_script_path, CONFIG_INI_NAME
from .secure_config import generate_server_secrets

IDEA_RUN_CLASS = 'com.intellij.idea.Main'
PROJECTOR_RUN_CLASS = 'org.jetbrains.projector.server.ProjectorLauncher'
IDEA_PLATFORM_PREFIX = 'idea.platform.prefix'
TOKEN_ENV_NAME = 'ORG_JETBRAINS_PROJECTOR_SERVER_HANDSHAKE_TOKEN'
RO_TOKEN_ENV_NAME = 'ORG_JETBRAINS_PROJECTOR_SERVER_RO_HANDSHAKE_TOKEN'
SSL_ENV_NAME = 'ORG_JETBRAINS_PROJECTOR_SERVER_SSL_PROPERTIES_PATH'


def write_run_script(run_config: RunConfig, src: TextIO, dst: TextIO) -> None:
"""Writes run script from src to dst"""

for line in src:
if line.startswith("IDE_BIN_HOME"):
line = f'IDE_BIN_HOME={join(run_config.path_to_app, "bin")}\n'
elif line.find("classpath") != -1:
line = f' -classpath "$CLASSPATH:{get_projector_server_dir()}/*" \\\n'
elif line.find(IDEA_RUN_CLASS) != -1:
line = f' -Dorg.jetbrains.projector.server.port={run_config.projector_port} \\\n'
line += f' -Dorg.jetbrains.projector.server.classToLaunch={IDEA_RUN_CLASS} \\\n'

if run_config.is_secure():
line += f' -D{SSL_ENV_NAME}=\"{get_ssl_properties_file(run_config.name)}\" \\\n'

if run_config.is_password_protected():
line += f' -D{TOKEN_ENV_NAME}=\"{run_config.password}\" \\\n'
line += f' -D{RO_TOKEN_ENV_NAME}=\"{run_config.ro_password}\" \\\n'

line += f' {PROJECTOR_RUN_CLASS}\\\n'

dst.write(line)


def make_run_script(run_config: RunConfig, run_script: str) -> None:
"""Creates run script from ide launch script."""
idea_script = get_launch_script(run_config.path_to_app)

with open(idea_script, 'r') as src, open(run_script, 'w') as dst:
write_run_script(run_config, src, dst)

stats = stat(run_script)
chmod(run_script, stats.st_mode | 0o0111)


def check_run_script(run_config: RunConfig, run_script_name: str) -> bool:
"""Check if run script corresponds to given config"""
idea_script = get_launch_script(run_config.path_to_app)
with open(idea_script, 'r') as src, open(run_script_name, 'r') as run_script:
dst = io.StringIO()
write_run_script(run_config, src, dst)
dst.seek(0)
return dst.read() == run_script.read()


def generate_run_script(run_config: RunConfig) -> None:
"""Generates projector run script"""
run_script = get_run_script_path(run_config.name)
make_run_script(run_config, run_script)


def save_config(run_config: RunConfig) -> None:
"""Saves given run config."""
config = configparser.ConfigParser()
config['IDE'] = {}
config['IDE']['PATH'] = run_config.path_to_app

config['PROJECTOR'] = {}
config['PROJECTOR']['PORT'] = str(run_config.projector_port)

if run_config.is_secure():
config['SSL'] = {}
config['SSL']['TOKEN'] = run_config.token

if run_config.is_password_protected():
config['PASSWORDS'] = {}
config['PASSWORDS']['PASSWORD'] = run_config.password # type: ignore
config['PASSWORDS']['RO_PASSWORD'] = run_config.ro_password # type: ignore

if run_config.toolbox:
config['TOOLBOX'] = {}
config['TOOLBOX']['TOOLBOX'] = 'True' # type: ignore

if run_config.fqdns:
config['FQDNS'] = {}
config['FQDNS']['FQDNS'] = run_config.fqdns # type: ignore

config_path = join(get_run_configs_dir(), run_config.name)

if not isdir(config_path):
mkdir(config_path)

config_path = join(config_path, CONFIG_INI_NAME)

with open(config_path, 'w') as configfile:
config.write(configfile)

generate_run_script(run_config)

if run_config.is_secure():
generate_server_secrets(run_config)


def check_config(run_config: RunConfig) -> bool:
"""Check if all run config files corresponds to given configuration"""
run_script = get_run_script_path(run_config.name)
return check_run_script(run_config, run_script)
25 changes: 0 additions & 25 deletions projector_installer/global_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,31 +71,6 @@ def get_ssl_dir() -> str:
COMPATIBLE_APPS: List[InstallableApp] = []


class RunConfig:
"""Run config dataclass"""

# pylint: disable=too-many-instance-attributes
def __init__(self, own_name: str, path_to_app: str, projector_port: int,
token: str, password: str, ro_password: str, toolbox: bool,
custom_fqdns: str) -> None:
self.name: str = own_name
self.path_to_app: str = path_to_app
self.projector_port: int = projector_port
self.token: str = token
self.password: str = password
self.ro_password: str = ro_password
self.toolbox = toolbox
self.fqdns = custom_fqdns

def is_secure(self) -> bool:
"""Checks if secure configuration"""
return self.token != ''

def is_password_protected(self) -> bool:
"""Checks if run config is password protected"""
return self.password != ''


def init_compatible_apps() -> List[InstallableApp]:
"""Initializes compatible apps list."""
try:
Expand Down
86 changes: 28 additions & 58 deletions projector_installer/run_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,47 @@

"""Run configurations related functions"""

from os import listdir, mkdir, path, rename
from os import listdir, rename
from os.path import join, isdir
from shutil import rmtree
from typing import Optional, Dict, List, TextIO
from fcntl import lockf, LOCK_EX, LOCK_NB

import configparser

from .apps import get_app_path, make_run_script, check_run_script
from .global_config import get_run_configs_dir, RunConfig
from .secure_config import generate_server_secrets
from .apps import get_app_path
from .global_config import get_run_configs_dir

CONFIG_INI_NAME = 'config.ini'
RUN_SCRIPT_NAME = 'run.sh'
LOCK_FILE_NAME: str = 'run.lock'


class RunConfig:
"""Run config dataclass"""

# pylint: disable=too-many-instance-attributes
def __init__(self, own_name: str, path_to_app: str, projector_port: int,
token: str, password: str, ro_password: str, toolbox: bool,
custom_fqdns: str) -> None:
self.name: str = own_name
self.path_to_app: str = path_to_app
self.projector_port: int = projector_port
self.token: str = token
self.password: str = password
self.ro_password: str = ro_password
self.toolbox = toolbox
self.fqdns = custom_fqdns

def is_secure(self) -> bool:
"""Checks if secure configuration"""
return self.token != ''

def is_password_protected(self) -> bool:
"""Checks if run config is password protected"""
return self.password != ''


def load_config(config_name: str) -> RunConfig:
"""Loads specified config from disk."""
config = configparser.ConfigParser()
Expand All @@ -43,54 +67,6 @@ def get_run_script_path(config_name: str) -> str:
return join(get_run_configs_dir(), config_name, RUN_SCRIPT_NAME)


def generate_run_script(run_config: RunConfig) -> None:
"""Generates projector run script"""
run_script = get_run_script_path(run_config.name)
make_run_script(run_config, run_script)


def save_config(run_config: RunConfig) -> None:
"""Saves given run config."""
config = configparser.ConfigParser()
config['IDE'] = {}
config['IDE']['PATH'] = run_config.path_to_app

config['PROJECTOR'] = {}
config['PROJECTOR']['PORT'] = str(run_config.projector_port)

if run_config.is_secure():
config['SSL'] = {}
config['SSL']['TOKEN'] = run_config.token

if run_config.is_password_protected():
config['PASSWORDS'] = {}
config['PASSWORDS']['PASSWORD'] = run_config.password # type: ignore
config['PASSWORDS']['RO_PASSWORD'] = run_config.ro_password # type: ignore

if run_config.toolbox:
config['TOOLBOX'] = {}
config['TOOLBOX']['TOOLBOX'] = 'True' # type: ignore

if run_config.fqdns:
config['FQDNS'] = {}
config['FQDNS']['FQDNS'] = run_config.fqdns # type: ignore

config_path = join(get_run_configs_dir(), run_config.name)

if not path.isdir(config_path):
mkdir(config_path)

config_path = join(config_path, CONFIG_INI_NAME)

with open(config_path, 'w') as configfile:
config.write(configfile)

generate_run_script(run_config)

if run_config.is_secure():
generate_server_secrets(run_config)


def get_run_configs(pattern: Optional[str] = None) -> Dict[str, RunConfig]:
"""Get run configs, matched given pattern."""
res = {}
Expand Down Expand Up @@ -156,12 +132,6 @@ def get_configs_with_app(app_name: str) -> List[str]:
return [k for k, v in get_run_configs().items() if v.path_to_app == app_path]


def check_config(run_config: RunConfig) -> bool:
"""Check if all run config files corresponds to given configuration"""
run_script = get_run_script_path(run_config.name)
return check_run_script(run_config, run_script)


def get_lock_file_name(config_name: str) -> str:
"""Return full path to lock file for given config name"""
return join(get_run_configs_dir(), config_name, LOCK_FILE_NAME)
Expand Down
3 changes: 2 additions & 1 deletion projector_installer/secure_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
import secrets
import string

from .global_config import get_ssl_dir, RunConfig, get_run_configs_dir, get_ssl_properties_file
from .global_config import get_ssl_dir, get_run_configs_dir, get_ssl_properties_file
from .log_utils import init_log, shutdown_log
from .utils import create_dir_if_not_exist, remove_file_if_exist, get_local_addresses
from .apps import get_jre_dir
from .run_config import RunConfig

PROJECTOR_JKS_NAME = 'projector'
DEF_TOKEN_LEN = 20
Expand Down

0 comments on commit 89df0e1

Please sign in to comment.