Skip to content

Commit

Permalink
add --working-dir option to replace --connection-file
Browse files Browse the repository at this point in the history
Signed-off-by: Jericho Tolentino <[email protected]>
  • Loading branch information
jericht committed May 1, 2024
1 parent 77cce05 commit 7371685
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 170 deletions.
31 changes: 26 additions & 5 deletions src/openjd/adaptor_runtime/_background/backend_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .server_response import ServerResponseGenerator
from .._osname import OSName
from ..adaptors import AdaptorRunner
from .._http import SocketDirectories
from .._http import SocketPaths
from .._utils import secure_open

if OSName.is_posix():
Expand All @@ -33,15 +33,34 @@ class BackendRunner:
Class that runs the backend logic in background mode.
"""

_connection_file_path: str
_working_dir: str | None

def __init__(
self,
adaptor_runner: AdaptorRunner,
connection_file_path: str,
*,
# TODO: Deprecate connection_file_path
connection_file_path: str | None = None,
working_dir: str | None = None,
log_buffer: LogBuffer | None = None,
) -> None:
self._adaptor_runner = adaptor_runner
self._connection_file_path = connection_file_path

if (connection_file_path and working_dir) or not (connection_file_path or working_dir):
raise RuntimeError(
"Exactly one of 'connection_file_path' or 'working_dir' must be provided, but got:"
f" connection_file_path={connection_file_path} working_dir={working_dir}"
)

if working_dir:
self._working_dir = working_dir
self._connection_file_path = os.path.join(working_dir, "connection.json")
else:
assert connection_file_path # for mypy
self._working_dir = None
self._connection_file_path = connection_file_path

self._log_buffer = log_buffer
self._server: Optional[Union[BackgroundHTTPServer, WinBackgroundNamedPipeServer]] = None
signal.signal(signal.SIGINT, self._sigint_handler)
Expand Down Expand Up @@ -79,8 +98,10 @@ def run(self) -> None:
shutdown_event: Event = Event()

if OSName.is_posix(): # pragma: is-windows
server_path = SocketDirectories.for_os().get_process_socket_path(
"runtime", create_dir=True
server_path = SocketPaths.for_os().get_process_socket_path(
"runtime",
base_dir=self._working_dir,
create_dir=True,
)
else: # pragma: is-posix
server_path = NamedPipeHelper.generate_pipe_name("AdaptorNamedPipe")
Expand Down
42 changes: 37 additions & 5 deletions src/openjd/adaptor_runtime/_background/frontend_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,43 @@ class FrontendRunner:
Class that runs the frontend logic in background mode.
"""

_connection_file_path: str
_working_dir: str | None

def __init__(
self,
connection_file_path: str,
*,
# TODO: Deprecate this option, replace with working_dir
connection_file_path: str | None = None,
working_dir: str | None = None,
timeout_s: float = 5.0,
heartbeat_interval: float = 1.0,
) -> None:
"""
Args:
connection_file_path (str): Absolute path to the connection file.
connection_file_path (Optional[str]): DEPRECATED. Please use 'working_dir' instead. Absolute path to the connection file.
working_dir (Optional[str]): Working directory for the runtime. A connection.json file must exist in this directory.
timeout_s (float, optional): Timeout for HTTP requests, in seconds. Defaults to 5.
heartbeat_interval (float, optional): Interval between heartbeats, in seconds.
Defaults to 1.
"""
self._timeout_s = timeout_s
self._heartbeat_interval = heartbeat_interval
self._connection_file_path = connection_file_path

if (connection_file_path and working_dir) or not (connection_file_path or working_dir):
raise RuntimeError(
"Expected exactly one of 'connection_file_path' or 'working_dir', but got: "
f"connection_file_path={connection_file_path} working_dir={working_dir}"
)

if working_dir:
self._working_dir = working_dir
self._connection_file_path = os.path.join(working_dir, "connection.json")
else:
assert connection_file_path # for mypy
self._working_dir = None
self._connection_file_path = connection_file_path

self._canceled = Event()
signal.signal(signal.SIGINT, self._sigint_handler)
if OSName.is_posix(): # pragma: is-windows
Expand Down Expand Up @@ -111,14 +131,26 @@ def init(
[
"daemon",
"_serve",
"--connection-file",
self._connection_file_path,
"--init-data",
json.dumps(init_data),
"--path-mapping-rules",
json.dumps(path_mapping_data),
]
)
if self._working_dir:
args.extend(
[
"--working-dir",
self._working_dir,
]
)
else:
args.extend(
[
"--connection-file",
self._connection_file_path,
]
)
try:
process = subprocess.Popen(
args,
Expand Down
57 changes: 45 additions & 12 deletions src/openjd/adaptor_runtime/_entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@
"file://path/to/file.json"
),
"show_config": "Prints the adaptor runtime configuration, then the program exits.",
"connection_file": "The file path to the connection file for use in background mode.",
"connection_file": "DEPRECATED. Please use 'working_dir' instead.\n\nThe file path to the connection file for use in background mode.",
"working_dir": "The path to the directory to use for runtime files. This directory must not already exist.",
}

_DIR = os.path.dirname(os.path.realpath(__file__))
Expand Down Expand Up @@ -300,9 +301,25 @@ def _handle_daemon(
integration_data: _IntegrationData,
reentry_exe: Optional[Path] = None,
):
connection_file = parsed_args.connection_file
if not os.path.isabs(connection_file):
# Validate args
connection_file = None
if hasattr(parsed_args, "connection_file"):
connection_file = parsed_args.connection_file

working_dir = None
if hasattr(parsed_args, "working_dir"):
working_dir = parsed_args.working_dir

if (connection_file and working_dir) or not (connection_file or working_dir):
raise RuntimeError(
"Expected exactly one of 'connection_file' or 'working_dir' to be provided, "
f"but got args: {parsed_args}"
)

if connection_file and not os.path.isabs(connection_file):
connection_file = os.path.abspath(connection_file)
if working_dir and not os.path.isabs(working_dir):
working_dir = os.path.abspath(working_dir)
subcommand = parsed_args.subcommand if hasattr(parsed_args, "subcommand") else None

if subcommand == "_serve":
Expand All @@ -318,14 +335,18 @@ def _handle_daemon(
# forever until a shutdown is requested
backend = BackendRunner(
AdaptorRunner(adaptor=adaptor),
connection_file,
connection_file_path=connection_file,
working_dir=working_dir,
log_buffer=log_buffer,
)
backend.run()
else:
# This process is running in frontend mode. Create the frontend runner and send
# the appropriate request to the backend.
frontend = FrontendRunner(connection_file)
frontend = FrontendRunner(
connection_file_path=connection_file,
working_dir=working_dir,
)
if subcommand == "start":
adaptor_module = sys.modules.get(self.adaptor_class.__module__)
if adaptor_module is None:
Expand All @@ -349,10 +370,12 @@ def _handle_daemon(
def _parse_args(self) -> Tuple[ArgumentParser, Namespace]:
parser = self._build_argparser()
try:
return parser, parser.parse_args(sys.argv[1:])
parsed_args = parser.parse_args(sys.argv[1:])
except Exception as e:
_logger.error(f"Error parsing command line arguments: {e}")
raise
else:
return parser, parsed_args

def _build_argparser(self) -> ArgumentParser:
parser = ArgumentParser(
Expand Down Expand Up @@ -412,9 +435,15 @@ def _build_argparser(self) -> ArgumentParser:
connection_file = ArgumentParser(add_help=False)
connection_file.add_argument(
"--connection-file",
default="",
help=_CLI_HELP_TEXT["connection_file"],
required=True,
required=False,
)

working_dir = ArgumentParser(add_help=False)
working_dir.add_argument(
"--working-dir",
help=_CLI_HELP_TEXT["working_dir"],
required=False,
)

bg_parser = subparser.add_parser("daemon", help="Runs the adaptor in a daemon mode.")
Expand All @@ -427,11 +456,15 @@ def _build_argparser(self) -> ArgumentParser:
)

# "Hidden" command that actually runs the adaptor runtime in background mode
bg_subparser.add_parser("_serve", parents=[init_data, path_mapping_rules, connection_file])
bg_subparser.add_parser(
"_serve", parents=[init_data, path_mapping_rules, connection_file, working_dir]
)

bg_subparser.add_parser("start", parents=[init_data, path_mapping_rules, connection_file])
bg_subparser.add_parser("run", parents=[run_data, connection_file])
bg_subparser.add_parser("stop", parents=[connection_file])
bg_subparser.add_parser(
"start", parents=[init_data, path_mapping_rules, connection_file, working_dir]
)
bg_subparser.add_parser("run", parents=[run_data, connection_file, working_dir])
bg_subparser.add_parser("stop", parents=[connection_file, working_dir])

return parser

Expand Down
4 changes: 2 additions & 2 deletions src/openjd/adaptor_runtime/_http/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

from .request_handler import HTTPResponse, RequestHandler, ResourceRequestHandler
from .sockets import SocketDirectories
from .sockets import SocketPaths

__all__ = ["HTTPResponse", "RequestHandler", "ResourceRequestHandler", "SocketDirectories"]
__all__ = ["HTTPResponse", "RequestHandler", "ResourceRequestHandler", "SocketPaths"]
Loading

0 comments on commit 7371685

Please sign in to comment.