Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding flags to enable dev mode; flags for custom path to localnet config #569

Merged
merged 15 commits into from
Sep 19, 2024
15 changes: 15 additions & 0 deletions docs/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,12 @@
- [reset](#reset)
- [Options](#options-16)
- [--update, --no-update](#--update---no-update)
- [-P, --config-dir ](#-p---config-dir-)
- [start](#start)
- [Options](#options-17)
- [-n, --name ](#-n---name--1)
- [-P, --config-dir ](#-p---config-dir--1)
- [-d, --dev, --no-dev](#-d---dev---no-dev)
- [status](#status)
- [stop](#stop)
- [project](#project)
Expand Down Expand Up @@ -799,6 +802,10 @@ algokit localnet reset [OPTIONS]
### --update, --no-update
Enable or disable updating to the latest available LocalNet version, default: don't update


### -P, --config-dir <config_path>
Specify the custom localnet configuration directory.

### start

Start the AlgoKit LocalNet.
Expand All @@ -813,6 +820,14 @@ algokit localnet start [OPTIONS]
### -n, --name <name>
Specify a name for a custom LocalNet instance. AlgoKit will not manage the configuration of named LocalNet instances, allowing developers to configure it in any way they need.


### -P, --config-dir <config_path>
Specify the custom localnet configuration directory.


### -d, --dev, --no-dev
Control whether to launch 'algod' in developer mode or not. Defaults to 'yes'.

### status

Check the status of the AlgoKit LocalNet.
Expand Down
49 changes: 44 additions & 5 deletions src/algokit/cli/localnet.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import logging
import os
from pathlib import Path

import click
import questionary
Expand Down Expand Up @@ -126,7 +128,26 @@ def config_command(*, engine: str | None, force: bool) -> None:
"AlgoKit will not manage the configuration of named LocalNet instances, "
"allowing developers to configure it in any way they need.",
)
def start_localnet(name: str | None) -> None:
@click.option(
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved
"--config-dir",
"-P",
"config_path",
type=click.Path(exists=True, readable=True, file_okay=False, resolve_path=True, path_type=Path),
default=lambda: os.environ.get("ALGOKIT_LOCALNET_CONFIG_DIR", None),
required=False,
help="Specify the custom localnet configuration directory.",
)
@click.option(
"--dev/--no-dev",
"-d",
"algod_dev_mode",
is_flag=True,
required=False,
default=True,
type=click.BOOL,
help=("Control whether to launch 'algod' in developer mode or not. Defaults to 'yes'."),
)
def start_localnet(*, name: str | None, config_path: Path | None, algod_dev_mode: bool) -> None:
sandbox = ComposeSandbox.from_environment()
full_name = f"{SANDBOX_BASE_NAME}_{name}" if name is not None else SANDBOX_BASE_NAME
if sandbox is not None and full_name != sandbox.name:
Expand All @@ -135,7 +156,7 @@ def start_localnet(name: str | None) -> None:
sandbox.stop()
else:
raise click.ClickException("LocalNet is already running. Please stop it first")
sandbox = ComposeSandbox() if name is None else ComposeSandbox(name)
sandbox = ComposeSandbox(SANDBOX_BASE_NAME, config_path) if name is None else ComposeSandbox(name, config_path)
compose_file_status = sandbox.compose_file_status()
sandbox.check_docker_compose_for_new_image_versions()
if compose_file_status is ComposeFileStatus.MISSING:
Expand All @@ -156,7 +177,16 @@ def start_localnet(name: str | None) -> None:
"A named LocalNet is running, update checks are disabled. If you wish to synchronize with the latest "
"version, run `algokit localnet reset --update`"
)
sandbox.up()
if sandbox.is_algod_dev_mode() != algod_dev_mode:
sandbox.set_algod_dev_mode(dev_mode=algod_dev_mode)
if click.confirm(
f"Would you like to recreate 'algod' container to apply 'DevMode' flag set to '{algod_dev_mode}'? "
"Otherwise, the next `algokit localnet reset` will restart with the new flag",
default=True,
):
sandbox.recreate_container("algod")
else:
sandbox.up()


@localnet_group.command("stop", short_help="Stop the AlgoKit LocalNet.")
Expand All @@ -176,10 +206,19 @@ def stop_localnet() -> None:
default=False,
help="Enable or disable updating to the latest available LocalNet version, default: don't update",
)
def reset_localnet(*, update: bool) -> None:
@click.option(
"--config-dir",
"-P",
"config_path",
type=click.Path(exists=True, readable=True, file_okay=False, resolve_path=True, path_type=Path),
default=lambda: os.environ.get("ALGOKIT_LOCALNET_CONFIG_DIR", None),
required=False,
help="Specify the custom localnet configuration directory.",
)
def reset_localnet(*, update: bool, config_path: Path | None) -> None:
sandbox = ComposeSandbox.from_environment()
if sandbox is None:
sandbox = ComposeSandbox()
sandbox = ComposeSandbox(config_path=config_path)
compose_file_status = sandbox.compose_file_status()
if compose_file_status is ComposeFileStatus.MISSING:
logger.debug("Existing LocalNet not found; creating from scratch...")
Expand Down
30 changes: 28 additions & 2 deletions src/algokit/core/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ def get_min_compose_version() -> str:


class ComposeSandbox:
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved
def __init__(self, name: str = SANDBOX_BASE_NAME) -> None:
def __init__(self, name: str = SANDBOX_BASE_NAME, config_path: Path | None = None) -> None:
self.name = SANDBOX_BASE_NAME if name == SANDBOX_BASE_NAME else f"{SANDBOX_BASE_NAME}_{name}"
self.directory = get_app_config_dir() / self.name
self.directory = (config_path or get_app_config_dir()) / self.name
if not self.directory.exists():
logger.debug(f"The {self.name} directory does not exist yet; creating it")
self.directory.mkdir()
Expand Down Expand Up @@ -128,6 +128,17 @@ def _create_instance_from_data(cls, data: list[dict[str, Any]]) -> ComposeSandbo
return cls(name)
return None

def set_algod_dev_mode(self, *, dev_mode: bool) -> None:
content = self.algod_network_template_file_path.read_text()
new_value = "true" if dev_mode else "false"
new_content = re.sub(r'"DevMode":\s*(true|false)', f'"DevMode": {new_value}', content)
self.algod_network_template_file_path.write_text(new_content)

def is_algod_dev_mode(self) -> bool:
content = self.algod_network_template_file_path.read_text()
search = re.search(r'"DevMode":\s*(true|false)', content)
return search is not None and search.group(1) == "true"

def compose_file_status(self) -> ComposeFileStatus:
try:
compose_content = self.compose_file_path.read_text()
Expand Down Expand Up @@ -184,6 +195,21 @@ def up(self) -> None:
else:
logger.warning("AlgoKit LocalNet failed to return a successful health check")

def recreate_container(self, container_name: str) -> None:
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved
logger.info("Recreating the algod container to apply configuration changes...")
self._run_compose_command(
f"stop {container_name}",
bad_return_code_error_message=f"Failed to remove {container_name} container.",
)
self._run_compose_command(
f"rm -f -v {container_name}",
bad_return_code_error_message=f"Failed to remove {container_name} container.",
)
self._run_compose_command(
f"up -d {container_name}",
bad_return_code_error_message=f"Failed to recreate {container_name} container.",
)

def stop(self) -> None:
logger.info("Stopping AlgoKit LocalNet now...")
self._run_compose_command("stop", bad_return_code_error_message="Failed to stop LocalNet")
Expand Down
Loading