From ffa00767d4454dbcf41593c5058728bef66e64bc Mon Sep 17 00:00:00 2001 From: "A. F. Dudley" Date: Thu, 22 Jan 2026 03:06:45 -0500 Subject: [PATCH] Add extra_args support to deploy create command - Add @click.argument for generic args passthrough to stack commands - Keep explicit --network-dir and --initial-peers options - Add DeploymentContext.get_compose_file() helper - Add DeploymentContext.modify_yaml() helper for stack commands - Update init() to use absolute paths This allows stack-specific create commands to receive arbitrary arguments via: laconic-so deploy create ... -- --custom-arg value Co-Authored-By: Claude Opus 4.5 --- .../deploy/deployment_context.py | 21 +++++++++++++++++-- .../deploy/deployment_create.py | 9 ++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/stack_orchestrator/deploy/deployment_context.py b/stack_orchestrator/deploy/deployment_context.py index 7f588774..ffe0f71f 100644 --- a/stack_orchestrator/deploy/deployment_context.py +++ b/stack_orchestrator/deploy/deployment_context.py @@ -44,11 +44,28 @@ class DeploymentContext: def get_compose_dir(self): return self.deployment_dir.joinpath(constants.compose_dir_name) + def get_compose_file(self, name: str): + return self.get_compose_dir() / f"docker-compose-{name}.yml" + + def modify_yaml(self, file_path: Path, modifier_func): + """Load a YAML from the deployment, apply a modifier, and write back.""" + if not file_path.absolute().is_relative_to(self.deployment_dir): + raise ValueError(f"File is not inside deployment directory: {file_path}") + + yaml = get_yaml() + with open(file_path, "r") as f: + yaml_data = yaml.load(f) + + modifier_func(yaml_data) + + with open(file_path, "w") as f: + yaml.dump(yaml_data, f) + def get_cluster_id(self): return self.id - def init(self, dir): - self.deployment_dir = dir + def init(self, dir: Path): + self.deployment_dir = dir.absolute() self.spec = Spec() self.spec.init_from_file(self.get_spec_file()) self.stack = Stack(self.spec.obj["stack"]) diff --git a/stack_orchestrator/deploy/deployment_create.py b/stack_orchestrator/deploy/deployment_create.py index 5988d2db..772fd02b 100644 --- a/stack_orchestrator/deploy/deployment_create.py +++ b/stack_orchestrator/deploy/deployment_create.py @@ -533,8 +533,11 @@ def _check_volume_definitions(spec): # TODO: Hack @click.option("--network-dir", help="Network configuration supplied in this directory") @click.option("--initial-peers", help="Initial set of persistent peers") +@click.argument("extra_args", nargs=-1, type=click.UNPROCESSED) @click.pass_context -def create(ctx, spec_file, deployment_dir, helm_chart, network_dir, initial_peers): +def create( + ctx, spec_file, deployment_dir, helm_chart, network_dir, initial_peers, extra_args +): deployment_command_context = ctx.obj return create_operation( deployment_command_context, @@ -543,6 +546,7 @@ def create(ctx, spec_file, deployment_dir, helm_chart, network_dir, initial_peer helm_chart, network_dir, initial_peers, + extra_args, ) @@ -555,6 +559,7 @@ def create_operation( helm_chart, network_dir, initial_peers, + extra_args=(), ): parsed_spec = Spec( os.path.abspath(spec_file), get_parsed_deployment_spec(spec_file) @@ -703,7 +708,7 @@ def create_operation( if deployer_config_generator is not None: deployer_config_generator.generate(deployment_dir_path) call_stack_deploy_create( - deployment_context, [network_dir, initial_peers, deployment_command_context] + deployment_context, [network_dir, initial_peers, *extra_args] )