Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F9348374
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Subscribers
None
View Options
diff --git a/swh/core/cli/__init__.py b/swh/core/cli/__init__.py
index bcaf77c..a840d55 100644
--- a/swh/core/cli/__init__.py
+++ b/swh/core/cli/__init__.py
@@ -1,126 +1,126 @@
# Copyright (C) 2019 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
import logging
import logging.config
-import signal
import click
import pkg_resources
-import yaml
-
-from ..sentry import init_sentry
LOG_LEVEL_NAMES = ["NOTSET", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
logger = logging.getLogger(__name__)
class AliasedGroup(click.Group):
"""A simple Group that supports command aliases, as well as notes related to
options"""
def __init__(self, name=None, commands=None, **attrs):
self.option_notes = attrs.pop("option_notes", None)
self.aliases = {}
super().__init__(name, commands, **attrs)
def get_command(self, ctx, cmd_name):
return super().get_command(ctx, self.aliases.get(cmd_name, cmd_name))
def add_alias(self, name, alias):
if not isinstance(name, str):
name = name.name
self.aliases[alias] = name
def format_options(self, ctx, formatter):
click.Command.format_options(self, ctx, formatter)
if self.option_notes:
with formatter.section("Notes"):
formatter.write_text(self.option_notes)
self.format_commands(ctx, formatter)
def clean_exit_on_signal(signal, frame):
"""Raise a SystemExit exception to let command-line clients wind themselves
down on exit"""
raise SystemExit(0)
@click.group(
context_settings=CONTEXT_SETTINGS,
cls=AliasedGroup,
option_notes="""\
If both options are present, --log-level will override the root logger
configuration set in --log-config.
The --log-config YAML must conform to the logging.config.dictConfig schema
documented at https://docs.python.org/3/library/logging.config.html.
""",
)
@click.option(
"--log-level",
"-l",
default=None,
type=click.Choice(LOG_LEVEL_NAMES),
help="Log level (defaults to INFO).",
)
@click.option(
"--log-config",
default=None,
type=click.File("r"),
help="Python yaml logging configuration file.",
)
@click.option(
"--sentry-dsn", default=None, help="DSN of the Sentry instance to report to"
)
@click.option(
"--sentry-debug/--no-sentry-debug",
default=False,
hidden=True,
help="Enable debugging of sentry",
)
@click.pass_context
def swh(ctx, log_level, log_config, sentry_dsn, sentry_debug):
"""Command line interface for Software Heritage.
"""
+ import signal
+ import yaml
+ from ..sentry import init_sentry
+
signal.signal(signal.SIGTERM, clean_exit_on_signal)
signal.signal(signal.SIGINT, clean_exit_on_signal)
init_sentry(sentry_dsn, debug=sentry_debug)
if log_level is None and log_config is None:
log_level = "INFO"
if log_config:
logging.config.dictConfig(yaml.safe_load(log_config.read()))
if log_level:
log_level = logging.getLevelName(log_level)
logging.root.setLevel(log_level)
ctx.ensure_object(dict)
ctx.obj["log_level"] = log_level
def main():
# Even though swh() sets up logging, we need an earlier basic logging setup
# for the next few logging statements
logging.basicConfig()
# load plugins that define cli sub commands
for entry_point in pkg_resources.iter_entry_points("swh.cli.subcommands"):
try:
cmd = entry_point.load()
swh.add_command(cmd, name=entry_point.name)
except Exception as e:
logger.warning("Could not load subcommand %s: %s", entry_point.name, str(e))
return swh(auto_envvar_prefix="SWH")
if __name__ == "__main__":
main()
diff --git a/swh/core/cli/db.py b/swh/core/cli/db.py
index 78d3c81..2c89ca9 100755
--- a/swh/core/cli/db.py
+++ b/swh/core/cli/db.py
@@ -1,190 +1,191 @@
#!/usr/bin/env python3
# Copyright (C) 2018-2020 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
-import glob
import logging
from os import path, environ
-import subprocess
import warnings
import click
from swh.core.cli import CONTEXT_SETTINGS
-from swh.core.config import read as config_read
warnings.filterwarnings("ignore") # noqa prevent psycopg from telling us sh*t
logger = logging.getLogger(__name__)
@click.group(name="db", context_settings=CONTEXT_SETTINGS)
@click.option(
"--config-file",
"-C",
default=None,
type=click.Path(exists=True, dir_okay=False),
help="Configuration file.",
)
@click.pass_context
def db(ctx, config_file):
"""Software Heritage database generic tools.
"""
+ from swh.core.config import read as config_read
+
ctx.ensure_object(dict)
if config_file is None:
config_file = environ.get("SWH_CONFIG_FILENAME")
cfg = config_read(config_file)
ctx.obj["config"] = cfg
@db.command(name="init", context_settings=CONTEXT_SETTINGS)
@click.pass_context
def init(ctx):
"""Initialize the database for every Software Heritage module found in the
configuration file. For every configuration section in the config file
that:
1. has the name of an existing swh package,
2. has credentials for a local db access,
it will run the initialization scripts from the swh package against the
given database.
Example for the config file::
\b
storage:
cls: local
args:
db: postgresql:///?service=swh-storage
objstorage:
cls: remote
args:
url: http://swh-objstorage:5003/
the command:
swh db -C /path/to/config.yml init
will initialize the database for the `storage` section using initialization
scripts from the `swh.storage` package.
"""
+ import subprocess
for modname, cfg in ctx.obj["config"].items():
if cfg.get("cls") == "local" and cfg.get("args"):
try:
sqlfiles = get_sql_for_package(modname)
except click.BadParameter:
logger.info(
"Failed to load/find sql initialization files for %s", modname
)
if sqlfiles:
conninfo = cfg["args"]["db"]
for sqlfile in sqlfiles:
subprocess.check_call(
[
"psql",
"--quiet",
"--no-psqlrc",
"-v",
"ON_ERROR_STOP=1",
"-d",
conninfo,
"-f",
sqlfile,
]
)
@click.command(context_settings=CONTEXT_SETTINGS)
@click.argument("module", nargs=-1, required=True)
@click.option(
"--db-name",
"-d",
help="Database name.",
default="softwareheritage-dev",
show_default=True,
)
@click.option(
"--create-db/--no-create-db",
"-C",
help="Attempt to create the database.",
default=False,
)
def db_init(module, db_name, create_db):
"""Initialise a database for the Software Heritage <module>. By
default, does not attempt to create the database.
Example:
swh db-init -d swh-test storage
If you want to specify non-default postgresql connection parameters,
please provide them using standard environment variables.
See psql(1) man page (section ENVIRONMENTS) for details.
Example:
PGPORT=5434 swh db-init indexer
"""
# put import statements here so we can keep startup time of the main swh
# command as short as possible
from swh.core.db.tests.db_testing import (
pg_createdb,
pg_restore,
DB_DUMP_TYPES,
swh_db_version,
)
logger.debug("db_init %s dn_name=%s", module, db_name)
dump_files = []
for modname in module:
dump_files.extend(get_sql_for_package(modname))
if create_db:
# Create the db (or fail silently if already existing)
pg_createdb(db_name, check=False)
# Try to retrieve the db version if any
db_version = swh_db_version(db_name)
if not db_version: # Initialize the db
dump_files = [(x, DB_DUMP_TYPES[path.splitext(x)[1]]) for x in dump_files]
for dump, dtype in dump_files:
click.secho("Loading {}".format(dump), fg="yellow")
pg_restore(db_name, dump, dtype)
db_version = swh_db_version(db_name)
# TODO: Ideally migrate the version from db_version to the latest
# db version
click.secho(
"DONE database is {} version {}".format(db_name, db_version),
fg="green",
bold=True,
)
def get_sql_for_package(modname):
+ import glob
from importlib import import_module
from swh.core.utils import numfile_sortkey as sortkey
if not modname.startswith("swh."):
modname = "swh.{}".format(modname)
try:
m = import_module(modname)
except ImportError:
raise click.BadParameter("Unable to load module {}".format(modname))
sqldir = path.join(path.dirname(m.__file__), "sql")
if not path.isdir(sqldir):
raise click.BadParameter(
"Module {} does not provide a db schema " "(no sql/ dir)".format(modname)
)
return list(sorted(glob.glob(path.join(sqldir, "*.sql")), key=sortkey))
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Jul 4 2025, 6:27 PM (5 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3268529
Attached To
rDCORE Foundations and core functionalities
Event Timeline
Log In to Comment