Skip to content

Commit dbf47ab

Browse files
committed
Adding commands for Streaming
1 parent f6712d2 commit dbf47ab

File tree

18 files changed

+664
-1
lines changed

18 files changed

+664
-1
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ attr = "globus_cli.version.__version__"
9393
profile = "black"
9494

9595
[tool.pytest.ini_options]
96-
addopts = "-n auto --maxprocesses 4 --dist loadscope --timeout 3 --color=yes"
96+
#addopts = "-n auto --maxprocesses 4 --dist loadscope --timeout 3 --color=yes"
9797
filterwarnings = [
9898
"error",
9999
]

src/__init__.py

Whitespace-only changes.

src/globus_cli/commands/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"task": ("task", "task_command"),
2828
"timer": ("timer", "timer_command"),
2929
"transfer": ("transfer", "transfer_command"),
30+
"streams": ("streams", "stream_command"),
3031
"update": ("update", "update_command"),
3132
"version": ("version", "version_command"),
3233
"whoami": ("whoami", "whoami_command"),
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import typing as t
2+
3+
from globus_cli.parsing import group
4+
5+
6+
def streams_flatten_response(in_doc: dict[str, t.Any]) -> dict[str, list[t.Any]]:
7+
output_dict: dict[str, list[t.Any]] = {}
8+
attributes_doc = in_doc.pop("attributes")
9+
for i in attributes_doc:
10+
output_dict[f"attributes_{i}"] = attributes_doc.get(i)
11+
for i in in_doc:
12+
output_dict[i] = in_doc.get(i)
13+
relationships = in_doc.get("relationships")
14+
for o in relationships:
15+
inner = relationships.get(o).get("data")
16+
for i in inner:
17+
output_dict[f"relationships_{o}_{i}"] = relationships.get(i)
18+
return output_dict
19+
20+
21+
def streams_display_flatten_response(
22+
in_doc: dict[str, t.Any],
23+
) -> dict[str, list[t.Any]]:
24+
return streams_flatten_response(in_doc["data"])
25+
26+
27+
def streams_display_response_status(in_doc: dict[str, t.Any]) -> str:
28+
data_doc = in_doc["data"]
29+
attributes_doc = data_doc.get("attributes")
30+
if attributes_doc:
31+
return attributes_doc["status"]
32+
return "unknown"
33+
34+
35+
@group(
36+
"streams",
37+
lazy_subcommands={
38+
"tunnel": (".tunnel", "tunnel_command"),
39+
"access-point": (".access_point", "access_point_command"),
40+
},
41+
)
42+
def stream_command() -> None:
43+
"""Manage Globus Tunnels."""
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from globus_cli.parsing import group
2+
3+
4+
@group(
5+
"access-point",
6+
lazy_subcommands={
7+
"show": (".show", "show_access_point_command"),
8+
},
9+
)
10+
def access_point_command() -> None:
11+
"""Manage Globus Tunnels."""
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import uuid
2+
3+
import click
4+
5+
from globus_cli.commands.streams import streams_display_flatten_response
6+
from globus_cli.login_manager import LoginManager
7+
from globus_cli.parsing import command
8+
from globus_cli.termio import Field, display
9+
10+
STANDARD_FIELDS = [
11+
Field("ID", "id"),
12+
Field("Display Name", "attributes_display_name"),
13+
Field("Contact Email", "attributes_contact_email"),
14+
Field("Contact Info", "attributes_contact_info"),
15+
Field("Department", "attributes_department"),
16+
Field("Description", "attributes_description"),
17+
Field("Info Link", "attributes_info_link"),
18+
Field("Organization", "attributes_organization"),
19+
]
20+
21+
22+
@command("show", short_help="Show the attributes of a stream access point.")
23+
@click.argument(
24+
"stream_access_point_id", metavar="STREAM_ACCESS_POINT_ID", type=click.UUID
25+
)
26+
@LoginManager.requires_login("auth", "transfer")
27+
def show_access_point_command(
28+
login_manager: LoginManager,
29+
*,
30+
stream_access_point_id: uuid.UUID,
31+
) -> None:
32+
"""
33+
Create a Globus Tunnel.
34+
"""
35+
tunnel_client = login_manager.get_transfer_client()
36+
res = tunnel_client.get_stream_ap(stream_access_point_id)
37+
display(
38+
res,
39+
text_mode=display.RECORD,
40+
fields=STANDARD_FIELDS,
41+
response_key=streams_display_flatten_response,
42+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from globus_cli.parsing import group
2+
3+
4+
@group(
5+
"tunnel",
6+
lazy_subcommands={
7+
"create": (".create", "create_tunnel_command"),
8+
"update": (".update", "update_tunnel_command"),
9+
"delete": (".delete", "delete_tunnel_command"),
10+
"list": (".list", "list_tunnel_command"),
11+
"show": (".show", "show_tunnel_command"),
12+
"stop": (".stop", "stop_tunnel_command"),
13+
},
14+
)
15+
def tunnel_command() -> None:
16+
"""Manage Globus Tunnels."""
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import uuid
2+
3+
import click
4+
from globus_sdk.services.transfer.data.tunnel_data import CreateTunnelData
5+
6+
from globus_cli.commands.streams import streams_display_flatten_response
7+
from globus_cli.constants import ExplicitNullType
8+
from globus_cli.login_manager import LoginManager
9+
from globus_cli.parsing import command
10+
from globus_cli.termio import Field, display
11+
12+
STANDARD_FIELDS = [
13+
Field("ID", "id"),
14+
Field("Label", "attributes_label"),
15+
Field("State", "attributes_state"),
16+
Field("Status", "attributes_status"),
17+
]
18+
19+
20+
@command("create", short_help="Create a Globus Tunnel.")
21+
@click.argument(
22+
"initiator_stream_ap_id", metavar="INITIATOR_STREAM_AP_ID", type=click.UUID
23+
)
24+
@click.argument(
25+
"listener_stream_ap_id", metavar="LISTENER_STREAM_AP_ID", type=click.UUID
26+
)
27+
@click.option(
28+
"--label",
29+
type=str,
30+
default=None,
31+
help="A friendly label to associate with the Tunnel.",
32+
)
33+
@click.option(
34+
"--lifetime-minutes",
35+
type=int,
36+
help="The amount of time in minutes that the tunnel will exist.",
37+
)
38+
@click.option(
39+
"--restartable",
40+
type=bool,
41+
default=False,
42+
help=(
43+
"A boolean to indicate if the tunnel should be restart in the "
44+
"event of an error."
45+
),
46+
)
47+
@LoginManager.requires_login("auth", "transfer")
48+
def create_tunnel_command(
49+
login_manager: LoginManager,
50+
*,
51+
initiator_stream_ap_id: uuid.UUID,
52+
listener_stream_ap_id: uuid.UUID,
53+
label: str | None,
54+
lifetime_minutes: int | None,
55+
restartable: bool,
56+
) -> None:
57+
"""
58+
Create a Globus Tunnel.
59+
"""
60+
data = CreateTunnelData(
61+
initiator_stream_ap_id,
62+
listener_stream_ap_id,
63+
label=label,
64+
lifetime_mins=lifetime_minutes,
65+
restartable=restartable,
66+
)
67+
tunnel_client = login_manager.get_transfer_client()
68+
res = tunnel_client.create_tunnel(data)
69+
display(
70+
res,
71+
text_mode=display.RECORD,
72+
fields=STANDARD_FIELDS,
73+
response_key=streams_display_flatten_response,
74+
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import uuid
2+
3+
import click
4+
5+
from globus_cli.commands.streams import streams_display_response_status
6+
from globus_cli.login_manager import LoginManager
7+
from globus_cli.parsing import command
8+
from globus_cli.termio import display
9+
10+
11+
@command("delete", short_help="Delete a Globus Tunnel.")
12+
@click.argument("tunnel_id", metavar="TUNNEL_ID", type=click.UUID)
13+
@LoginManager.requires_login("auth", "transfer")
14+
def delete_tunnel_command(
15+
login_manager: LoginManager,
16+
*,
17+
tunnel_id: uuid.UUID,
18+
) -> None:
19+
"""
20+
Delete a Globus Tunnel document.
21+
"""
22+
tunnel_client = login_manager.get_transfer_client()
23+
res = tunnel_client.delete_tunnel(str(tunnel_id))
24+
display(res, text_mode=display.SILENT, response_key=streams_display_response_status)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import typing as t
2+
3+
from globus_cli.commands.streams import streams_flatten_response
4+
from globus_cli.login_manager import LoginManager
5+
from globus_cli.parsing import command
6+
from globus_cli.termio import Field, display
7+
8+
STANDARD_FIELDS = [
9+
Field("ID", "id"),
10+
Field("Label", "attributes_label"),
11+
Field("State", "attributes_state"),
12+
Field("Created Time", "attributes_created_time"),
13+
]
14+
15+
16+
def tunnel_response_to_list(in_doc: dict[str, t.Any]) -> list[t.Any]:
17+
out_list = []
18+
data_doc: list[dict[str, t.Any]] = in_doc["data"]
19+
for ent in data_doc:
20+
new_ent = streams_flatten_response(ent)
21+
out_list.append(new_ent)
22+
return out_list
23+
24+
25+
@command("list", short_help="List Globus Tunnels.")
26+
@LoginManager.requires_login("auth", "transfer")
27+
def list_tunnel_command(
28+
login_manager: LoginManager,
29+
) -> None:
30+
"""
31+
List all the Globus Tunnels that this user can see.
32+
"""
33+
tunnel_client = login_manager.get_transfer_client()
34+
res = tunnel_client.list_tunnels()
35+
display(
36+
res,
37+
text_mode=display.TABLE,
38+
fields=STANDARD_FIELDS,
39+
response_key=tunnel_response_to_list,
40+
)

0 commit comments

Comments
 (0)