-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add cli commands for disk management
- Loading branch information
Roman Skurikhin
committed
Sep 3, 2020
1 parent
3948994
commit c476e5d
Showing
8 changed files
with
305 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
Added persistent disks management subsystem to api. | ||
Implemented disks management commands. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
from .formatters.disks import DiskFormatter, DisksFormatter | ||
from .formatters.utils import URIFormatter, uri_formatter | ||
from .parse_utils import parse_memory | ||
from .root import Root | ||
from .utils import argument, command, group, option, pager_maybe | ||
|
||
|
||
@group() | ||
def disk() -> None: | ||
""" | ||
Operations with disks. | ||
""" | ||
|
||
|
||
@command() | ||
@option("--full-uri", is_flag=True, help="Output full disk URI.") | ||
async def ls(root: Root, full_uri: bool) -> None: | ||
""" | ||
List disks. | ||
""" | ||
|
||
if full_uri: | ||
uri_fmtr: URIFormatter = str | ||
else: | ||
uri_fmtr = uri_formatter( | ||
username=root.client.username, cluster_name=root.client.cluster_name | ||
) | ||
disks_fmtr = DisksFormatter(uri_fmtr) | ||
|
||
disks = [] | ||
async for disk in root.client.disks.list(): | ||
disks.append(disk) | ||
|
||
pager_maybe(disks_fmtr(disks), root.tty, root.terminal_size) | ||
|
||
|
||
@command() | ||
@argument("storage") | ||
async def create(root: Root, storage: str) -> None: | ||
""" | ||
Create disk with storage amount STORAGE. | ||
Examples: | ||
neuro disk create 10Gi | ||
neuro disk create 500Mi | ||
""" | ||
disk = await root.client.disks.create(parse_memory(storage)) | ||
disk_fmtr = DiskFormatter(str) | ||
pager_maybe(disk_fmtr(disk), root.tty, root.terminal_size) | ||
|
||
|
||
@command() | ||
@argument("disk_id") | ||
async def get(root: Root, disk_id: str) -> None: | ||
""" | ||
Get disk DISK_ID. | ||
""" | ||
disk = await root.client.disks.get(disk_id) | ||
disk_fmtr = DiskFormatter(str) | ||
pager_maybe(disk_fmtr(disk), root.tty, root.terminal_size) | ||
|
||
|
||
@command() | ||
@argument("disk_id") | ||
async def rm(root: Root, disk_id: str) -> None: | ||
""" | ||
Remove disk DISK_ID. | ||
""" | ||
|
||
await root.client.disks.rm(disk_id) | ||
|
||
|
||
disk.add_command(ls) | ||
disk.add_command(create) | ||
disk.add_command(get) | ||
disk.add_command(rm) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from typing import Iterator, Sequence | ||
|
||
import click | ||
|
||
from neuromation.api import Disk | ||
from neuromation.cli.formatters.ftable import table | ||
from neuromation.cli.formatters.utils import URIFormatter | ||
|
||
|
||
class DisksFormatter: | ||
_table_header = [ | ||
click.style("Id", bold=True), | ||
click.style("Storage", bold=True), | ||
click.style("Uri", bold=True), | ||
] | ||
|
||
def __init__(self, uri_formatter: URIFormatter): | ||
self._uri_formatter = uri_formatter | ||
|
||
def _disk_to_table_row(self, disk: Disk) -> Sequence[str]: | ||
if disk.storage >= 1024 ** 3: | ||
storage_str = f"{disk.storage / (1024 ** 3):.2f}Gi" | ||
elif disk.storage >= 1024 ** 2: | ||
storage_str = f"{disk.storage / (1024 ** 2):.2f}Mi" | ||
elif disk.storage >= 1024: | ||
storage_str = f"{disk.storage / 1024:.2f}Ki" | ||
else: | ||
storage_str = str(disk.storage) | ||
return [disk.id, storage_str, self._uri_formatter(disk.uri)] | ||
|
||
def __call__(self, disks: Sequence[Disk]) -> Iterator[str]: | ||
disks_info = [ | ||
self._table_header, | ||
*(self._disk_to_table_row(disk) for disk in disks), | ||
] | ||
return table(disks_info) | ||
|
||
|
||
class DiskFormatter: | ||
def __init__(self, uri_formatter: URIFormatter): | ||
self._disks_formatter = DisksFormatter(uri_formatter) | ||
|
||
def __call__(self, disk: Disk) -> Iterator[str]: | ||
return self._disks_formatter([disk]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import click | ||
|
||
from neuromation.api import Disk | ||
from neuromation.cli.formatters.disks import DiskFormatter, DisksFormatter | ||
|
||
|
||
def test_disk_formatter() -> None: | ||
disk = Disk("disk", int(11.93 * (1024 ** 3)), "user", Disk.Status.READY, "cluster") | ||
fmtr = DiskFormatter(str) | ||
header_line, info_line = (click.unstyle(line).rstrip() for line in fmtr(disk)) | ||
assert header_line.split() == ["Id", "Storage", "Uri"] | ||
assert info_line.split() == ["disk", "11.93Gi", "disk://cluster/user/disk-id"] | ||
|
||
|
||
def test_disks_formatter() -> None: | ||
disks = [ | ||
Disk("disk-1", 50 * (1024 ** 3), "user", Disk.Status.READY, "cluster"), | ||
Disk("disk-2", 50 * (1024 ** 2), "user", Disk.Status.READY, "cluster"), | ||
Disk("disk-3", 50 * (1024 ** 1), "user", Disk.Status.READY, "cluster"), | ||
Disk("disk-4", 50, "user", Disk.Status.READY, "cluster"), | ||
] | ||
fmtr = DisksFormatter(str) | ||
header_line, *info_lines = (click.unstyle(line).rstrip() for line in fmtr(disks)) | ||
assert header_line.split() == ["Id", "Storage", "Uri"] | ||
assert info_lines[0].split() == ["disk-1", "50.00Gi", "disk://cluster/user/disk-1"] | ||
assert info_lines[1].split() == ["disk-2", "50.00Mi", "disk://cluster/user/disk-2"] | ||
assert info_lines[2].split() == ["disk-3", "50.00Ki", "disk://cluster/user/disk-3"] | ||
assert info_lines[3].split() == ["disk-4", "50", "disk://cluster/user/disk-4"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import pytest | ||
|
||
from tests.e2e.conftest import Helper | ||
|
||
|
||
@pytest.mark.e2e | ||
def test_create_get_list_delete(helper: Helper) -> None: | ||
cap = helper.run_cli(["disk", "ls"]) | ||
assert cap.err == "" | ||
|
||
cap = helper.run_cli(["disk", "create", "2Gi"]) | ||
assert cap.err == "" | ||
disk_id, *_ = cap.out.splitlines()[1].split() | ||
|
||
cap = helper.run_cli(["disk", "ls"]) | ||
assert cap.err == "" | ||
assert disk_id in cap.out | ||
|
||
cap = helper.run_cli(["disk", "get", disk_id]) | ||
assert cap.err == "" | ||
assert disk_id in cap.out | ||
assert "2Gi" in cap.out | ||
|
||
cap = helper.run_cli(["disk", "rm", disk_id]) | ||
assert cap.err == "" | ||
|
||
cap = helper.run_cli(["disk", "ls"]) | ||
assert cap.err == "" | ||
assert disk_id not in cap.out |