machine: Add a new command dvc machine status (#6649)

* machine: Add a new command `dvc machine status`

fix#6482
1. add a new command `dvc machien status`
2. add a unit test for the cli call.
3. add a unit test for the shown result.

* Update dvc/command/machine.py

Co-authored-by: Saugat Pachhai <[email protected]>

* Update dvc/command/machine.py

Co-authored-by: Saugat Pachhai <[email protected]>

* Update machine.py

* Remove sensitive fields

* Update dvc/machine/__init__.py

Co-authored-by: Casper da Costa-Luis <[email protected]>

* Update tests/func/machine/__init__.py

Co-authored-by: Casper da Costa-Luis <[email protected]>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Use white list to limit shown fields

Co-authored-by: Saugat Pachhai <[email protected]>
Co-authored-by: Casper da Costa-Luis <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Gao
2021-10-19 17:38:11 +09:00
committed by GitHub
co-authored by Saugat Pachhai Casper da Costa-Luis pre-commit-ci[bot]
parent 6d96ecb376
commit 966dc8a1ca
6 changed files with 103 additions and 8 deletions
+29
View File
@@ -143,6 +143,22 @@ class CmdMachineCreate(CmdBase):
return 0
class CmdMachineStatus(CmdBase):
SHOWN_FIELD = ["name", "cloud", "instance_hdd_size", "instance_ip"]
def run(self):
if self.repo.machine is None:
raise MachineDisabledError
all_status = self.repo.machine.status(self.args.name)
for i, status in enumerate(all_status, start=1):
ui.write(f"instance_num_{i}:")
for field in self.SHOWN_FIELD:
value = status.get(field, None)
ui.write(f"\t{field:20}: {value}")
return 0
class CmdMachineDestroy(CmdBase):
def run(self):
if self.repo.machine is None:
@@ -306,6 +322,19 @@ def add_parser(subparsers, parent_parser):
)
machine_create_parser.set_defaults(func=CmdMachineCreate)
machine_STATUS_HELP = "List the status of a running machine."
machine_status_parser = machine_subparsers.add_parser(
"status",
parents=[parent_config_parser, parent_parser],
description=append_doc_link(machine_STATUS_HELP, "machine/status"),
help=machine_STATUS_HELP,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
machine_status_parser.add_argument(
"name", help="Name of the running machine."
)
machine_status_parser.set_defaults(func=CmdMachineStatus)
machine_DESTROY_HELP = "Destroy an machine instance."
machine_destroy_parser = machine_subparsers.add_parser(
"destroy",
+6
View File
@@ -2,8 +2,10 @@ import logging
import os
from typing import (
TYPE_CHECKING,
Any,
Dict,
Iterable,
Iterator,
Mapping,
Optional,
Tuple,
@@ -200,3 +202,7 @@ class MachineManager:
def run_shell(self, name: Optional[str]):
config, backend = self.get_config_and_backend(name)
return backend.run_shell(**config)
def status(self, name: str) -> Iterator[Dict[Any, Any]]:
config, backend = self.get_config_and_backend(name)
return backend.instances(**config)
+10
View File
@@ -0,0 +1,10 @@
import textwrap
CONFIG_TEXT = textwrap.dedent(
"""\
[feature]
machine = true
['machine "foo"']
cloud = aws
"""
)
+1 -8
View File
@@ -5,14 +5,7 @@ import pytest
from dvc.main import main
CONFIG_TEXT = textwrap.dedent(
"""\
[feature]
machine = true
['machine \"foo\"']
cloud = aws
"""
)
from . import CONFIG_TEXT
@pytest.mark.parametrize(
+43
View File
@@ -0,0 +1,43 @@
import json
from tpi.terraform import TerraformBackend
from dvc.command.machine import CmdMachineStatus
from dvc.main import main
from . import CONFIG_TEXT
STATUS = """{
"aws_security_group": null,
"cloud": "aws",
"id": "iterative-2jyhw8j9ieov6",
"image": "ubuntu-bionic-18.04-amd64-server-20210818",
"instance_gpu": null,
"instance_hdd_size": 35,
"instance_ip": "123.123.123.123",
"instance_launch_time": "2021-08-25T07:13:03Z",
"instance_type": "m",
"name": "test-resource",
"region": "us-west",
"spot": false,
"spot_price": -1,
"ssh_name": null,
"ssh_private": "-----BEGIN RSA PRIVATE KEY-----\\n",
"startup_script": "IyEvYmluL2Jhc2g=",
"timeouts": null
}"""
def test_status(tmp_dir, scm, dvc, mocker, capsys):
(tmp_dir / ".dvc" / "config").write_text(CONFIG_TEXT)
status = json.loads(STATUS)
mocker.patch.object(
TerraformBackend, "instances", autospec=True, return_value=[status]
)
assert main(["machine", "status", "foo"]) == 0
cap = capsys.readouterr()
assert "instance_num_1:" in cap.out
for key in CmdMachineStatus.SHOWN_FIELD:
assert f"\t{key:20}: {status[key]}" in cap.out
+14
View File
@@ -9,6 +9,7 @@ from dvc.command.machine import (
CmdMachineModify,
CmdMachineRemove,
CmdMachineSsh,
CmdMachineStatus,
)
DATA = {
@@ -56,6 +57,19 @@ def test_create(tmp_dir, dvc, mocker):
m.assert_called_once_with("foo")
def test_status(tmp_dir, dvc, mocker):
cli_args = parse_args(["machine", "status", "foo"])
assert cli_args.func == CmdMachineStatus
cmd = cli_args.func(cli_args)
m = mocker.patch.object(
cmd.repo.machine, "status", autospec=True, return_value=[]
)
assert cmd.run() == 0
m.assert_called_once_with("foo")
def test_destroy(tmp_dir, dvc, mocker):
cli_args = parse_args(["machine", "destroy", "foo"])
assert cli_args.func == CmdMachineDestroy