Skip to content

Commit

Permalink
[CLI] New CLI tool for node operators
Browse files Browse the repository at this point in the history
We now provide a CLI tool that integrates all the operations
commonly performed by node operators. Currently, this CLI
allows to:

* generate private keys for the node, replacing a functionality
  that was implemented in the CCN main app directly.
* run migrations, replacing the config updater script.
  • Loading branch information
odesenfans committed Jun 14, 2022
1 parent d10cdd0 commit fdf844f
Show file tree
Hide file tree
Showing 16 changed files with 371 additions and 215 deletions.
1 change: 0 additions & 1 deletion deployment/docker-build/pyaleph.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ RUN /opt/venv/bin/pip install --no-cache-dir -r /opt/build/requirements.txt
RUN rm /opt/build/requirements.txt

# === Install the CCN itself ===
COPY deployment/migrations /opt/pyaleph/migrations
COPY setup.py /opt/pyaleph/
COPY src /opt/pyaleph/src
# Git data is used to determine the version of the CCN
Expand Down
164 changes: 0 additions & 164 deletions deployment/migrations/config_updater.py

This file was deleted.

3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ install_requires =
sentry-sdk==1.5.11
setproctitle==1.2.2
substrate-interface==1.1.7
typer==0.4.1
ujson==5.1.0 # required by aiocache
urllib3==1.26.8
uvloop==0.16.0
Expand Down Expand Up @@ -95,6 +96,7 @@ testing =
pytest-aiohttp
pytest-asyncio
pytest-mock
types-pyyaml
types-requests
types-setuptools
nuls2 =
Expand All @@ -110,6 +112,7 @@ docs =
# Add here console scripts like:
console_scripts =
pyaleph = aleph.commands:run
ccn_cli = aleph.ccn_cli.main:app
# For example:
# console_scripts =
# fibonacci = pyaleph.skeleton:run
Expand Down
File renamed without changes.
14 changes: 14 additions & 0 deletions src/aleph/ccn_cli/cli_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""
Global configuration object for the CLI. Use the `get_cli_config()` method
to access and modify the configuration.
"""

from dataclasses import dataclass
from pathlib import Path


@dataclass
class CliConfig:
config_file_path: Path
key_dir: Path
verbose: bool
Empty file.
46 changes: 46 additions & 0 deletions src/aleph/ccn_cli/commands/keys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import typer

from aleph.ccn_cli.cli_config import CliConfig
from typing import cast
from aleph.ccn_cli.services.keys import generate_keypair, save_keys

keys_ns = typer.Typer()


@keys_ns.command()
def generate(ctx: typer.Context):
"""
Generates a new set of private/public keys for the Core Channel Node.
The keys will be created in the key directory. You can modify the destination
by using the --key-dir option.
"""
cli_config = cast(CliConfig, ctx.obj)
print(cli_config)

typer.echo(f"Generating a key pair in {cli_config.key_dir.absolute()}...")
key_pair = generate_keypair()
save_keys(key_pair, str(cli_config.key_dir))
typer.echo("Done.")


@keys_ns.command()
def show(ctx: typer.Context):
"""
Prints the private key of the node.
"""
cli_config = cast(CliConfig, ctx.obj)

key_path = cli_config.key_dir / "node-secret.key"
if not key_path.exists():
typer.echo(
f"'{key_path.absolute()}' does not exist. Did you run 'keys generate'?",
err=True,
)
raise typer.Exit(code=1)

if not key_path.is_file():
typer.echo(f"'{key_path}' is not a file.", err=True)
raise typer.Exit(code=1)

with key_path.open() as f:
typer.echo(f.read())
87 changes: 87 additions & 0 deletions src/aleph/ccn_cli/commands/migrations/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import asyncio
from pathlib import Path
from traceback import format_exc
from typing import Optional
from typing import cast

import typer

from aleph.ccn_cli.cli_config import CliConfig
from .migration_runner import run_migrations

migrations_ns = typer.Typer()


FILTER_SCRIPTS_HELP = (
"A filter for migration scripts. If specified, only the files "
"matching the provided glob expression will be run."
)

KEY_FILE_HELP = (
"Path to the private key file, if any. "
"Only used to upgrade the key to the latest format."
)


def run_migration_command(
cli_config: CliConfig,
command: str,
filter_scripts: Optional[str],
key_file: Optional[Path],
):
try:
asyncio.run(
run_migrations(
cli_config=cli_config,
command=command,
filter_scripts=filter_scripts,
key_file=key_file,
)
)
except Exception as e:
typer.echo(f"{command} failed: {e}.", err=True)
if cli_config.verbose:
typer.echo(format_exc())
raise typer.Exit(code=1)


@migrations_ns.command()
def upgrade(
ctx: typer.Context,
filter_scripts: Optional[str] = typer.Option(
None,
help=FILTER_SCRIPTS_HELP,
),
key_file: Optional[Path] = typer.Option(
None,
help=KEY_FILE_HELP,
),
):
cli_config = cast(CliConfig, ctx.obj)
run_migration_command(
cli_config=cli_config,
command="upgrade",
filter_scripts=filter_scripts,
key_file=key_file,
)


@migrations_ns.command()
def downgrade(
ctx: typer.Context,
filter_scripts: Optional[str] = typer.Option(
None,
help=FILTER_SCRIPTS_HELP,
),
key_file: Optional[Path] = typer.Option(
None,
help=KEY_FILE_HELP,
),
):
cli_config = cast(CliConfig, ctx.obj)
run_migration_command(
cli_config=cli_config,
command="downgrade",
filter_scripts=filter_scripts,
key_file=key_file,
)
Loading

0 comments on commit fdf844f

Please sign in to comment.