Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Ability to turn off the auto-restart functionality of the monitor with `--no-restart`

### Changed
- Refactored the `main.py` module so that it's broken into smaller, more-manageable pieces

## [1.13.0b1]
### Added
- API documentation for Merlin's core codebase
Expand Down
25 changes: 25 additions & 0 deletions merlin/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
##############################################################################
# Copyright (c) Lawrence Livermore National Security, LLC and other Merlin
# Project developers. See top-level LICENSE and COPYRIGHT files for dates and
# other details. No copyright assignment is required to contribute to Merlin.
##############################################################################

"""
Merlin CLI Package.

This package defines the core components and supporting utilities for the
Merlin command-line interface (CLI). It provides the entry point parser for
the `merlin` CLI tool, a suite of modular subcommands for workflow and
infrastructure management, and shared helper functions used across CLI
handlers.

Subpackages:
commands: Contains all command implementations for the Merlin CLI, including
workflow execution, monitoring, database interaction, and more.

Modules:
argparse_main: Sets up the top-level argument parser and integrates all
registered CLI subcommands into the `merlin` CLI interface.
utils: Provides shared utility functions for parsing arguments, loading
YAML specifications, and handling configuration logic across commands.
"""
72 changes: 72 additions & 0 deletions merlin/cli/argparse_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
##############################################################################
# Copyright (c) Lawrence Livermore National Security, LLC and other Merlin
# Project developers. See top-level LICENSE and COPYRIGHT files for dates and
# other details. No copyright assignment is required to contribute to Merlin.
##############################################################################

"""
Main CLI parser setup for the Merlin command-line interface.

This module defines the primary argument parser for the `merlin` CLI tool,
including custom error handling and integration of all available subcommands.
"""

import sys
from argparse import ArgumentParser, RawDescriptionHelpFormatter

from merlin import VERSION
from merlin.ascii_art import banner_small
from merlin.cli.commands import ALL_COMMANDS


DEFAULT_LOG_LEVEL = "INFO"


class HelpParser(ArgumentParser):
"""
This class overrides the error message of the argument parser to
print the help message when an error happens.

Methods:
error: Override the error message of the `ArgumentParser` class.
"""

def error(self, message: str):
"""
Override the error message of the `ArgumentParser` class.

Args:
message: The error message to log.
"""
sys.stderr.write(f"error: {message}\n")
self.print_help()
sys.exit(2)


def build_main_parser() -> ArgumentParser:
"""
Set up the command-line argument parser for the Merlin package.

Returns:
An `ArgumentParser` object with every parser defined in Merlin's codebase.
"""
parser = HelpParser(
prog="merlin",
description=banner_small,
formatter_class=RawDescriptionHelpFormatter,
epilog="See merlin <command> --help for more info",
)
parser.add_argument("-v", "--version", action="version", version=VERSION)
parser.add_argument(
"-lvl",
"--level",
type=str,
default=DEFAULT_LOG_LEVEL,
help="Set log level: DEBUG, INFO, WARNING, ERROR [Default: %(default)s]",
)
subparsers = parser.add_subparsers(dest="subparsers", required=True)

for command in ALL_COMMANDS:
command.add_parser(subparsers)

return parser
66 changes: 66 additions & 0 deletions merlin/cli/commands/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
##############################################################################
# Copyright (c) Lawrence Livermore National Security, LLC and other Merlin
# Project developers. See top-level LICENSE and COPYRIGHT files for dates and
# other details. No copyright assignment is required to contribute to Merlin.
##############################################################################

"""
Merlin CLI Commands Package.

This package defines all top-level and subcommand implementations for the Merlin
command-line interface. Each module encapsulates the logic and argument parsing
for a distinct Merlin command, following a consistent structure built around the
`CommandEntryPoint` interface.

Modules:
command_entry_point: Defines the abstract base class `CommandEntryPoint` for all CLI commands.
config: Implements the `config` command for managing Merlin configuration files.
database: Implements the `database` command for interacting with the underlying database (view, delete, inspect).
example: Implements the `example` command to download and set up example workflows.
info: Implements the `info` command for displaying configuration and environment diagnostics.
monitor: Implements the `monitor` command to keep workflow allocations alive.
purge: Implements the `purge` command for removing tasks from queues.
query_workers: Implements the `query-workers` command for inspecting active task server workers.
queue_info: Implements the `queue-info` command for querying task server queue statistics.
restart: Implements the `restart` command to resume a workflow from a previous state.
run_workers: Implements the `run-workers` command to launch task-executing workers.
run: Implements the `run` command to execute Merlin or Maestro workflows.
server: Implements the `server` command to manage containerized Redis server components.
status: Implements the `status` and `detailed-status` commands for workflow state inspection.
stop_workers: Implements the `stop-workers` command for terminating active workers.
"""

from merlin.cli.commands.config import ConfigCommand
from merlin.cli.commands.database import DatabaseCommand
from merlin.cli.commands.example import ExampleCommand
from merlin.cli.commands.info import InfoCommand
from merlin.cli.commands.monitor import MonitorCommand
from merlin.cli.commands.purge import PurgeCommand
from merlin.cli.commands.query_workers import QueryWorkersCommand
from merlin.cli.commands.queue_info import QueueInfoCommand
from merlin.cli.commands.restart import RestartCommand
from merlin.cli.commands.run import RunCommand
from merlin.cli.commands.run_workers import RunWorkersCommand
from merlin.cli.commands.server import ServerCommand
from merlin.cli.commands.status import DetailedStatusCommand, StatusCommand
from merlin.cli.commands.stop_workers import StopWorkersCommand


# Keep these in alphabetical order
ALL_COMMANDS = [
ConfigCommand(),
DatabaseCommand(),
DetailedStatusCommand(),
ExampleCommand(),
InfoCommand(),
MonitorCommand(),
PurgeCommand(),
QueryWorkersCommand(),
QueueInfoCommand(),
RestartCommand(),
RunCommand(),
RunWorkersCommand(),
ServerCommand(),
StatusCommand(),
StopWorkersCommand(),
]
36 changes: 36 additions & 0 deletions merlin/cli/commands/command_entry_point.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
##############################################################################
# Copyright (c) Lawrence Livermore National Security, LLC and other Merlin
# Project developers. See top-level LICENSE and COPYRIGHT files for dates and
# other details. No copyright assignment is required to contribute to Merlin.
##############################################################################

"""
Defines the abstract base class for Merlin CLI commands.

This module provides the `CommandEntryPoint` abstract base class that all
Merlin command implementations must inherit from. It standardizes the interface
for adding command-specific argument parsers and processing CLI command logic.
"""

from abc import ABC, abstractmethod
from argparse import ArgumentParser, Namespace


class CommandEntryPoint(ABC):
"""
Abstract base class for a Merlin CLI command entry point.

Methods:
add_parser: Adds the parser for a specific command to the main `ArgumentParser`.
process_command: Executes the logic for this CLI command.
"""

@abstractmethod
def add_parser(self, subparsers: ArgumentParser):
"""Add the parser for this command to the main `ArgumentParser`."""
raise NotImplementedError("Subclasses of `CommandEntryPoint` must implement an `add_parser` method.")

@abstractmethod
def process_command(self, args: Namespace):
"""Execute the logic for this CLI command."""
raise NotImplementedError("Subclasses of `CommandEntryPoint` must implement an `process_command` method.")
Loading