Skip to content

Commit 724993a

Browse files
[Feature]: Add JSON output option for CLI commands #3322 (WIP)
`dstack ps` support
1 parent 2c97fc1 commit 724993a

3 files changed

Lines changed: 47 additions & 1 deletion

File tree

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
LIVE_TABLE_REFRESH_RATE_PER_SEC,
1111
console,
1212
)
13+
from dstack._internal.core.errors import CLIError
1314

1415

1516
class PsCommand(APIBaseCommand):
@@ -43,12 +44,31 @@ def _register(self):
4344
type=int,
4445
default=None,
4546
)
47+
self._parser.add_argument(
48+
"--format",
49+
choices=["plain", "json"],
50+
default="plain",
51+
help="Output format (default: plain)",
52+
)
53+
self._parser.add_argument(
54+
"--json",
55+
action="store_const",
56+
const="json",
57+
dest="format",
58+
help="Output in JSON format (equivalent to --format json)",
59+
)
4660

4761
def _command(self, args: argparse.Namespace):
4862
super()._command(args)
63+
if args.watch and args.format == "json":
64+
raise CLIError("JSON output is not supported together with --watch")
65+
4966
runs = self.api.runs.list(all=args.all, limit=args.last)
5067
if not args.watch:
51-
console.print(run_utils.get_runs_table(runs, verbose=args.verbose))
68+
if args.format == "json":
69+
run_utils.print_runs_json(self.api.project, runs)
70+
else:
71+
console.print(run_utils.get_runs_table(runs, verbose=args.verbose))
5272
return
5373

5474
try:
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from typing import List
2+
3+
from dstack._internal.core.models.common import CoreConfig, generate_dual_core_model
4+
from dstack._internal.core.models.runs import Run
5+
from dstack._internal.utils.json_utils import pydantic_orjson_dumps_with_indent
6+
7+
8+
class PsCommandOutputConfig(CoreConfig):
9+
json_dumps = pydantic_orjson_dumps_with_indent
10+
11+
12+
class PsCommandOutput(generate_dual_core_model(PsCommandOutputConfig)):
13+
"""JSON output model for `dstack ps` command."""
14+
15+
project: str
16+
runs: List[Run]

src/dstack/_internal/cli/utils/run.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from rich.table import Table
66

77
from dstack._internal.cli.models.offers import OfferCommandOutput, OfferRequirements
8+
from dstack._internal.cli.models.runs import PsCommandOutput
89
from dstack._internal.cli.utils.common import NO_OFFERS_WARNING, add_row_from_dict, console
910
from dstack._internal.core.models.backends.base import BackendType
1011
from dstack._internal.core.models.configurations import DevEnvironmentConfiguration
@@ -64,6 +65,15 @@ def print_offers_json(run_plan: RunPlan, run_spec):
6465
print(output.json())
6566

6667

68+
def print_runs_json(project: str, runs: List[Run]) -> None:
69+
"""Print runs information in JSON format."""
70+
output = PsCommandOutput(
71+
project=project,
72+
runs=[r._run for r in runs],
73+
)
74+
print(output.json())
75+
76+
6777
def print_run_plan(
6878
run_plan: RunPlan, max_offers: Optional[int] = None, include_run_properties: bool = True
6979
):

0 commit comments

Comments
 (0)