diff --git a/quetz/cli.py b/quetz/cli.py index 5cc2a82c..0358b45c 100644 --- a/quetz/cli.py +++ b/quetz/cli.py @@ -177,7 +177,6 @@ def _set_user_roles(db: Session, config: Config): ] default_role = config.users_default_role - for users, role in role_map: for username in users: try: @@ -186,8 +185,8 @@ def _set_user_roles(db: Session, config: Config): # use github as default provider raise ValueError( "could not parse the users setting, please provide users in" - "the format 'PROVIDER:USERNAME' where PROVIDER is one of" - "'google', 'github', 'dummy', etc." + " the format 'PROVIDER:USERNAME' where PROVIDER is one of" + " 'google', 'github', 'dummy', etc." ) logger.info(f"create user {username} with role {role}") user = ( @@ -462,6 +461,23 @@ def create( ) raise typer.Abort() + if copy_conf: + if not os.path.exists(copy_conf): + typer.echo(f'Config file to copy does not exist {copy_conf}.', err=True) + raise typer.Abort() + typer.echo(f"Copying config file from {copy_conf} to {config_file}") + shutil.copyfile(copy_conf, config_file) + + if not config_file.exists() and create_conf: + https = 'false' if dev else 'true' + conf = create_config(https=https) + with open(config_file, 'w') as f: + f.write(conf) + + os.environ[_env_prefix + _env_config_file] = str(config_file.resolve()) + config = Config(str(config_file)) + + # Overwrites the config variable if not config_file.exists() and not create_conf and not copy_conf: try: # If no config file is provided or created, try to get config @@ -480,23 +496,6 @@ def create( ) raise typer.Abort() - if copy_conf: - if not os.path.exists(copy_conf): - typer.echo(f'Config file to copy does not exist {copy_conf}.', err=True) - raise typer.Abort() - - typer.echo(f"Copying config file from {copy_conf} to {config_file}") - shutil.copyfile(copy_conf, config_file) - - if not config_file.exists() and create_conf: - https = 'false' if dev else 'true' - conf = create_config(https=https) - with open(config_file, 'w') as f: - f.write(conf) - - os.environ[_env_prefix + _env_config_file] = str(config_file.resolve()) - config = Config(str(config_file)) - deployment_folder.joinpath('channels').mkdir(exist_ok=True) with working_directory(db_path): diff --git a/quetz/config.py b/quetz/config.py index 82803877..79c9a019 100644 --- a/quetz/config.py +++ b/quetz/config.py @@ -1,6 +1,7 @@ # Copyright 2020 QuantStack # Distributed under the terms of the Modified BSD License. +import json import logging import logging.config import os @@ -383,6 +384,29 @@ def _find_first_level_config( return item return None + def _correct_environ_config_list_value(self, value: str) -> Union[str, List[str]]: + """Correct a value from environ that should be a list. + + Parameters + ---------- + value : str + The env variable value to correct. + + Returns + ------- + corrected_value : Union[str, List[str]] + Original value if no correction needed, else the corrected list of + strings value. + """ + corrected_value: Union[str, List[str]] = value + if isinstance(value, str): + if "[" in value: + corrected_value = json.loads(value) + elif "," in value and "[" not in value: + corrected_value = value.split(",") + + return corrected_value + def _get_environ_config(self) -> Dict[str, Any]: """Looks into environment variables if some matches with config_map. @@ -400,6 +424,7 @@ def _get_environ_config(self) -> Dict[str, Any]: if key.startswith(_env_prefix) } for var, value in quetz_var.items(): + parsed_value = self._correct_environ_config_list_value(value) splitted_key = var.split('_') config_key = splitted_key[1].lower() idx = 2 @@ -419,7 +444,7 @@ def _get_environ_config(self) -> Dict[str, Any]: continue # the first level is an entry, add it to the config. if isinstance(first_level, ConfigEntry): - config[first_level.name] = value + config[first_level.name] = parsed_value # the first level is a section. elif isinstance(first_level, ConfigSection): entry = "_".join(splitted_key[idx:]).lower() @@ -431,7 +456,9 @@ def _get_environ_config(self) -> Dict[str, Any]: # add the entry to the config. if first_level.name not in config: config[first_level.name]: Dict[str, Any] = {} - config[first_level.name]["_".join(splitted_key[idx:]).lower()] = value + config[first_level.name][ + "_".join(splitted_key[idx:]).lower() + ] = parsed_value return config diff --git a/quetz/tests/test_config.py b/quetz/tests/test_config.py index d6c72ad0..5c151e8c 100644 --- a/quetz/tests/test_config.py +++ b/quetz/tests/test_config.py @@ -111,6 +111,34 @@ def test_config_extend_require(config): config._config_map.pop() +@pytest.fixture() +def quetz_environ_config(database_url) -> None: + environ_values = { + "QUETZ_SESSION_HTTPS_ONLY": "False", + "QUETZ_LOGGING_LEVEL": "DEBUG", + "QUETZ_USERS_MEMBERS": '["dummy:happyuser"]', + "QUETZ_USERS_ADMINS": '["dummy:happyadmin"]', + "QUETZ_SESSION_SECRET": "test", + "QUETZ_SQLALCHEMY_DATABASE_URL": database_url, + } + for key, value in environ_values.items(): + os.environ[key] = value + yield + for key in environ_values.keys(): + if key in os.environ: + del os.environ[key] + + +def test_config_without_input( + quetz_environ_config, +): + c = Config() + assert c.session_https_only is False + assert c.logging_level == "DEBUG" + assert c.users_members == ["dummy:happyuser"] + assert c.users_admins == ["dummy:happyadmin"] + + @pytest.mark.parametrize( "config_extra", ["[extra_plugin]\nsome=\"testvalue\"\nconfig=\"othervalue\"\n"] )