Skip to content

Commit 32c4c98

Browse files
committed
Support reading apply configurations from stdin
1 parent b23fae8 commit 32c4c98

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

src/dstack/_internal/cli/commands/apply.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import argparse
2-
from pathlib import Path
32

43
from argcomplete import FilesCompleter
54

65
from dstack._internal.cli.commands import APIBaseCommand
76
from dstack._internal.cli.services.configurators import (
7+
APPLY_STDIN_NAME,
88
get_apply_configurator_class,
99
load_apply_configuration,
1010
)
@@ -40,9 +40,12 @@ def _register(self):
4040
self._parser.add_argument(
4141
"-f",
4242
"--file",
43-
type=Path,
4443
metavar="FILE",
45-
help="The path to the configuration file. Defaults to [code]$PWD/.dstack.yml[/]",
44+
help=(
45+
"The path to the configuration file."
46+
" Specify [code]-[/] to read configuration from stdin."
47+
" Defaults to [code]$PWD/.dstack.yml[/]"
48+
),
4649
dest="configuration_file",
4750
).completer = FilesCompleter(allowednames=["*.yml", "*.yaml"])
4851
self._parser.add_argument(
@@ -104,6 +107,10 @@ def _command(self, args: argparse.Namespace):
104107
return
105108

106109
super()._command(args)
110+
if not args.yes and args.configuration_file == APPLY_STDIN_NAME:
111+
# FIXME: probably does not work since dstack apply can ask questions futher,
112+
# e.g. whether to terminate a resource on ctrl+c or not
113+
raise CLIError("Cannot read configuration from stdin if -y/--yes is not specified")
107114
if args.repo and args.no_repo:
108115
raise CLIError("Either --repo or --no-repo can be specified")
109116
repo = None

src/dstack/_internal/cli/services/configurators/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import sys
12
from pathlib import Path
23
from typing import Dict, Optional, Tuple, Type
34

@@ -20,6 +21,9 @@
2021
parse_apply_configuration,
2122
)
2223

24+
APPLY_STDIN_NAME = "-"
25+
26+
2327
apply_configurators_mapping: Dict[ApplyConfigurationType, Type[BaseApplyConfigurator]] = {
2428
cls.TYPE: cls
2529
for cls in [
@@ -62,6 +66,8 @@ def load_apply_configuration(
6266
raise ConfigurationError(
6367
"No configuration file specified via `-f` and no default .dstack.yml configuration found"
6468
)
69+
elif configuration_file == APPLY_STDIN_NAME:
70+
configuration_path = sys.stdin.fileno()
6571
else:
6672
configuration_path = Path(configuration_file)
6773
if not configuration_path.exists():
@@ -71,4 +77,6 @@ def load_apply_configuration(
7177
conf = parse_apply_configuration(yaml.safe_load(f))
7278
except OSError:
7379
raise ConfigurationError(f"Failed to load configuration from {configuration_path}")
80+
if isinstance(configuration_path, int):
81+
return APPLY_STDIN_NAME, conf
7482
return str(configuration_path.absolute().relative_to(Path.cwd())), conf

0 commit comments

Comments
 (0)