proximl 0.5.5__tar.gz → 0.5.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {proximl-0.5.5/proximl.egg-info → proximl-0.5.6}/PKG-INFO +1 -1
- {proximl-0.5.5 → proximl-0.5.6}/proximl/__init__.py +1 -1
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/cloudbender/__init__.py +1 -1
- proximl-0.5.6/proximl/cli/cloudbender/service.py +129 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/project.py +10 -15
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cloudbender/cloudbender.py +2 -2
- proximl-0.5.5/proximl/cloudbender/reservations.py → proximl-0.5.6/proximl/cloudbender/services.py +28 -39
- {proximl-0.5.5 → proximl-0.5.6}/proximl/projects.py +19 -30
- {proximl-0.5.5 → proximl-0.5.6/proximl.egg-info}/PKG-INFO +1 -1
- {proximl-0.5.5 → proximl-0.5.6}/proximl.egg-info/SOURCES.txt +3 -3
- {proximl-0.5.5 → proximl-0.5.6}/pyproject.toml +1 -1
- proximl-0.5.6/tests/unit/cli/cloudbender/test_cli_reservation_unit.py +34 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/test_cli_project_unit.py +5 -9
- proximl-0.5.6/tests/unit/cloudbender/test_services_unit.py +161 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/conftest.py +13 -13
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_projects_unit.py +34 -48
- proximl-0.5.5/proximl/cli/cloudbender/reservation.py +0 -159
- proximl-0.5.5/tests/unit/cli/cloudbender/test_cli_reservation_unit.py +0 -38
- proximl-0.5.5/tests/unit/cloudbender/test_reservations_unit.py +0 -173
- {proximl-0.5.5 → proximl-0.5.6}/LICENSE +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/README.md +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/examples/__init__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/examples/create_dataset_and_training_job.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/examples/local_storage.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/examples/training_inference_pipeline.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/__main__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/auth.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/checkpoints.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/__init__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/checkpoint.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/cloudbender/datastore.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/cloudbender/device.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/cloudbender/node.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/cloudbender/provider.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/cloudbender/region.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/connection.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/dataset.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/environment.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/gpu.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/job/__init__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/job/create.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/model.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cli/volume.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cloudbender/__init__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cloudbender/datastores.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cloudbender/device_configs.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cloudbender/devices.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cloudbender/nodes.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cloudbender/providers.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/cloudbender/regions.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/connections.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/datasets.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/environments.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/exceptions.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/gpu_types.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/jobs.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/models.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/proximl.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl/volumes.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl.egg-info/dependency_links.txt +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl.egg-info/entry_points.txt +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl.egg-info/requires.txt +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/proximl.egg-info/top_level.txt +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/setup.cfg +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/setup.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/__init__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/cloudbender/__init__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/cloudbender/test_providers_integration.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/conftest.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/test_checkpoints_integration.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/test_datasets_integration.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/test_environments_integration.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/test_gpu_types_integration.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/test_jobs_integration.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/test_models_integration.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/test_projects_integration.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/integration/test_volumes_integration.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/__init__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/__init__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/cloudbender/__init__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/cloudbender/test_cli_datastore_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/cloudbender/test_cli_device_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/cloudbender/test_cli_node_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/cloudbender/test_cli_provider_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/cloudbender/test_cli_region_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/conftest.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/test_cli_checkpoint_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/test_cli_datasets_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/test_cli_environment_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/test_cli_gpu_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/test_cli_job_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/test_cli_model_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cli/test_cli_volume_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cloudbender/__init__.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cloudbender/test_datastores_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cloudbender/test_device_configs_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cloudbender/test_devices_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cloudbender/test_nodes_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cloudbender/test_providers_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/cloudbender/test_regions_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_auth.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_checkpoints_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_connections_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_datasets_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_environments_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_exceptions.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_gpu_types_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_jobs_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_models_unit.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_proximl.py +0 -0
- {proximl-0.5.5 → proximl-0.5.6}/tests/unit/test_volumes_unit.py +0 -0
|
@@ -15,4 +15,4 @@ from proximl.cli.cloudbender.region import region
|
|
|
15
15
|
from proximl.cli.cloudbender.node import node
|
|
16
16
|
from proximl.cli.cloudbender.device import device
|
|
17
17
|
from proximl.cli.cloudbender.datastore import datastore
|
|
18
|
-
from proximl.cli.cloudbender.
|
|
18
|
+
from proximl.cli.cloudbender.service import service
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from proximl.cli import cli, pass_config, search_by_id_name
|
|
3
|
+
from proximl.cli.cloudbender import cloudbender
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@cloudbender.group()
|
|
7
|
+
@pass_config
|
|
8
|
+
def service(config):
|
|
9
|
+
"""proxiML CloudBender service commands."""
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@service.command()
|
|
14
|
+
@click.option(
|
|
15
|
+
"--provider",
|
|
16
|
+
"-p",
|
|
17
|
+
type=click.STRING,
|
|
18
|
+
required=True,
|
|
19
|
+
help="The provider ID of the region.",
|
|
20
|
+
)
|
|
21
|
+
@click.option(
|
|
22
|
+
"--region",
|
|
23
|
+
"-r",
|
|
24
|
+
type=click.STRING,
|
|
25
|
+
required=True,
|
|
26
|
+
help="The region ID to list services for.",
|
|
27
|
+
)
|
|
28
|
+
@pass_config
|
|
29
|
+
def list(config, provider, region):
|
|
30
|
+
"""List services."""
|
|
31
|
+
data = [
|
|
32
|
+
["ID", "NAME", "HOSTNAME"],
|
|
33
|
+
[
|
|
34
|
+
"-" * 80,
|
|
35
|
+
"-" * 80,
|
|
36
|
+
"-" * 80,
|
|
37
|
+
],
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
services = config.proximl.run(
|
|
41
|
+
config.proximl.client.cloudbender.services.list(
|
|
42
|
+
provider_uuid=provider, region_uuid=region
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
for service in services:
|
|
47
|
+
data.append(
|
|
48
|
+
[
|
|
49
|
+
service.id,
|
|
50
|
+
service.name,
|
|
51
|
+
service.hostname,
|
|
52
|
+
]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
for row in data:
|
|
56
|
+
click.echo(
|
|
57
|
+
"{: >25.24} {: >29.28} {: >40.39}" "".format(*row),
|
|
58
|
+
file=config.stdout,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@service.command()
|
|
63
|
+
@click.option(
|
|
64
|
+
"--provider",
|
|
65
|
+
"-p",
|
|
66
|
+
type=click.STRING,
|
|
67
|
+
required=True,
|
|
68
|
+
help="The provider ID of the region.",
|
|
69
|
+
)
|
|
70
|
+
@click.option(
|
|
71
|
+
"--region",
|
|
72
|
+
"-r",
|
|
73
|
+
type=click.STRING,
|
|
74
|
+
required=True,
|
|
75
|
+
help="The region ID to create the service in.",
|
|
76
|
+
)
|
|
77
|
+
@click.option(
|
|
78
|
+
"--public/--no-public",
|
|
79
|
+
default=True,
|
|
80
|
+
show_default=True,
|
|
81
|
+
help="Service should be accessible from the public internet.",
|
|
82
|
+
)
|
|
83
|
+
@click.argument("name", type=click.STRING, required=True)
|
|
84
|
+
@pass_config
|
|
85
|
+
def create(config, provider, region, public, name):
|
|
86
|
+
"""
|
|
87
|
+
Creates a service.
|
|
88
|
+
"""
|
|
89
|
+
return config.proximl.run(
|
|
90
|
+
config.proximl.client.cloudbender.services.create(
|
|
91
|
+
provider_uuid=provider, region_uuid=region, name=name, public=public
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@service.command()
|
|
97
|
+
@click.option(
|
|
98
|
+
"--provider",
|
|
99
|
+
"-p",
|
|
100
|
+
type=click.STRING,
|
|
101
|
+
required=True,
|
|
102
|
+
help="The provider ID of the region.",
|
|
103
|
+
)
|
|
104
|
+
@click.option(
|
|
105
|
+
"--region",
|
|
106
|
+
"-r",
|
|
107
|
+
type=click.STRING,
|
|
108
|
+
required=True,
|
|
109
|
+
help="The region ID to remove the service from.",
|
|
110
|
+
)
|
|
111
|
+
@click.argument("service", type=click.STRING)
|
|
112
|
+
@pass_config
|
|
113
|
+
def remove(config, provider, region, service):
|
|
114
|
+
"""
|
|
115
|
+
Remove a service.
|
|
116
|
+
|
|
117
|
+
RESERVATION may be specified by name or ID, but ID is preferred.
|
|
118
|
+
"""
|
|
119
|
+
services = config.proximl.run(
|
|
120
|
+
config.proximl.client.cloudbender.services.list(
|
|
121
|
+
provider_uuid=provider, region_uuid=region
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
found = search_by_id_name(service, services)
|
|
126
|
+
if None is found:
|
|
127
|
+
raise click.UsageError("Cannot find specified service.")
|
|
128
|
+
|
|
129
|
+
return config.proximl.run(found.remove())
|
|
@@ -115,40 +115,35 @@ def list_datastores(config):
|
|
|
115
115
|
|
|
116
116
|
@project.command()
|
|
117
117
|
@pass_config
|
|
118
|
-
def
|
|
119
|
-
"""List project
|
|
118
|
+
def list_services(config):
|
|
119
|
+
"""List project services."""
|
|
120
120
|
data = [
|
|
121
|
-
["ID", "NAME", "
|
|
121
|
+
["ID", "NAME", "HOSTNAME", "REGION_UUID"],
|
|
122
122
|
[
|
|
123
123
|
"-" * 80,
|
|
124
124
|
"-" * 80,
|
|
125
125
|
"-" * 80,
|
|
126
126
|
"-" * 80,
|
|
127
|
-
"-" * 80,
|
|
128
|
-
"-" * 80,
|
|
129
127
|
],
|
|
130
128
|
]
|
|
131
129
|
project = config.proximl.run(
|
|
132
130
|
config.proximl.client.projects.get(config.proximl.client.project)
|
|
133
131
|
)
|
|
134
132
|
|
|
135
|
-
|
|
133
|
+
services = config.proximl.run(project.list_services())
|
|
136
134
|
|
|
137
|
-
for
|
|
135
|
+
for service in services:
|
|
138
136
|
data.append(
|
|
139
137
|
[
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
reservation.hostname,
|
|
145
|
-
reservation.region_uuid,
|
|
138
|
+
service.id,
|
|
139
|
+
service.name,
|
|
140
|
+
service.hostname,
|
|
141
|
+
service.region_uuid,
|
|
146
142
|
]
|
|
147
143
|
)
|
|
148
144
|
|
|
149
145
|
for row in data:
|
|
150
146
|
click.echo(
|
|
151
|
-
"{: >38.36} {: >30.28} {: >
|
|
152
|
-
"".format(*row),
|
|
147
|
+
"{: >38.36} {: >30.28} {: >30.28} {: >38.36}" "".format(*row),
|
|
153
148
|
file=config.stdout,
|
|
154
149
|
)
|
|
@@ -3,7 +3,7 @@ from .regions import Regions
|
|
|
3
3
|
from .nodes import Nodes
|
|
4
4
|
from .devices import Devices
|
|
5
5
|
from .datastores import Datastores
|
|
6
|
-
from .
|
|
6
|
+
from .services import Services
|
|
7
7
|
from .device_configs import DeviceConfigs
|
|
8
8
|
|
|
9
9
|
|
|
@@ -15,5 +15,5 @@ class Cloudbender(object):
|
|
|
15
15
|
self.nodes = Nodes(proximl)
|
|
16
16
|
self.devices = Devices(proximl)
|
|
17
17
|
self.datastores = Datastores(proximl)
|
|
18
|
-
self.
|
|
18
|
+
self.services = Services(proximl)
|
|
19
19
|
self.device_configs = DeviceConfigs(proximl)
|
proximl-0.5.5/proximl/cloudbender/reservations.py → proximl-0.5.6/proximl/cloudbender/services.py
RENAMED
|
@@ -2,77 +2,70 @@ import json
|
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
class
|
|
5
|
+
class Services(object):
|
|
6
6
|
def __init__(self, proximl):
|
|
7
7
|
self.proximl = proximl
|
|
8
8
|
|
|
9
9
|
async def get(self, provider_uuid, region_uuid, id, **kwargs):
|
|
10
10
|
resp = await self.proximl._query(
|
|
11
|
-
f"/provider/{provider_uuid}/region/{region_uuid}/
|
|
11
|
+
f"/provider/{provider_uuid}/region/{region_uuid}/service/{id}",
|
|
12
12
|
"GET",
|
|
13
13
|
kwargs,
|
|
14
14
|
)
|
|
15
|
-
return
|
|
15
|
+
return Service(self.proximl, **resp)
|
|
16
16
|
|
|
17
17
|
async def list(self, provider_uuid, region_uuid, **kwargs):
|
|
18
18
|
resp = await self.proximl._query(
|
|
19
|
-
f"/provider/{provider_uuid}/region/{region_uuid}/
|
|
19
|
+
f"/provider/{provider_uuid}/region/{region_uuid}/service",
|
|
20
20
|
"GET",
|
|
21
21
|
kwargs,
|
|
22
22
|
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
]
|
|
26
|
-
return reservations
|
|
23
|
+
services = [Service(self.proximl, **service) for service in resp]
|
|
24
|
+
return services
|
|
27
25
|
|
|
28
26
|
async def create(
|
|
29
27
|
self,
|
|
30
28
|
provider_uuid,
|
|
31
29
|
region_uuid,
|
|
32
30
|
name,
|
|
33
|
-
|
|
34
|
-
resource,
|
|
35
|
-
hostname,
|
|
31
|
+
public,
|
|
36
32
|
**kwargs,
|
|
37
33
|
):
|
|
38
|
-
logging.info(f"Creating
|
|
34
|
+
logging.info(f"Creating Service {name}")
|
|
39
35
|
data = dict(
|
|
40
36
|
name=name,
|
|
41
|
-
|
|
42
|
-
resource=resource,
|
|
43
|
-
hostname=hostname,
|
|
37
|
+
public=public,
|
|
44
38
|
**kwargs,
|
|
45
39
|
)
|
|
46
40
|
payload = {k: v for k, v in data.items() if v is not None}
|
|
47
41
|
resp = await self.proximl._query(
|
|
48
|
-
f"/provider/{provider_uuid}/region/{region_uuid}/
|
|
42
|
+
f"/provider/{provider_uuid}/region/{region_uuid}/service",
|
|
49
43
|
"POST",
|
|
50
44
|
None,
|
|
51
45
|
payload,
|
|
52
46
|
)
|
|
53
|
-
|
|
54
|
-
logging.info(f"Created
|
|
55
|
-
return
|
|
47
|
+
service = Service(self.proximl, **resp)
|
|
48
|
+
logging.info(f"Created Service {name} with id {service.id}")
|
|
49
|
+
return service
|
|
56
50
|
|
|
57
51
|
async def remove(self, provider_uuid, region_uuid, id, **kwargs):
|
|
58
52
|
await self.proximl._query(
|
|
59
|
-
f"/provider/{provider_uuid}/region/{region_uuid}/
|
|
53
|
+
f"/provider/{provider_uuid}/region/{region_uuid}/service/{id}",
|
|
60
54
|
"DELETE",
|
|
61
55
|
kwargs,
|
|
62
56
|
)
|
|
63
57
|
|
|
64
58
|
|
|
65
|
-
class
|
|
59
|
+
class Service:
|
|
66
60
|
def __init__(self, proximl, **kwargs):
|
|
67
61
|
self.proximl = proximl
|
|
68
|
-
self.
|
|
69
|
-
self._id = self.
|
|
70
|
-
self._provider_uuid = self.
|
|
71
|
-
self._region_uuid = self.
|
|
72
|
-
self.
|
|
73
|
-
self._name = self.
|
|
74
|
-
self.
|
|
75
|
-
self._hostname = self._reservation.get("hostname")
|
|
62
|
+
self._service = kwargs
|
|
63
|
+
self._id = self._service.get("service_id")
|
|
64
|
+
self._provider_uuid = self._service.get("provider_uuid")
|
|
65
|
+
self._region_uuid = self._service.get("region_uuid")
|
|
66
|
+
self._public = self._service.get("public")
|
|
67
|
+
self._name = self._service.get("name")
|
|
68
|
+
self._hostname = self._service.get("hostname")
|
|
76
69
|
|
|
77
70
|
@property
|
|
78
71
|
def id(self) -> str:
|
|
@@ -87,39 +80,35 @@ class Reservation:
|
|
|
87
80
|
return self._region_uuid
|
|
88
81
|
|
|
89
82
|
@property
|
|
90
|
-
def
|
|
91
|
-
return self.
|
|
83
|
+
def public(self) -> bool:
|
|
84
|
+
return self._public
|
|
92
85
|
|
|
93
86
|
@property
|
|
94
87
|
def name(self) -> str:
|
|
95
88
|
return self._name
|
|
96
89
|
|
|
97
|
-
@property
|
|
98
|
-
def resource(self) -> str:
|
|
99
|
-
return self._resource
|
|
100
|
-
|
|
101
90
|
@property
|
|
102
91
|
def hostname(self) -> str:
|
|
103
92
|
return self._hostname
|
|
104
93
|
|
|
105
94
|
def __str__(self):
|
|
106
|
-
return json.dumps({k: v for k, v in self.
|
|
95
|
+
return json.dumps({k: v for k, v in self._service.items()})
|
|
107
96
|
|
|
108
97
|
def __repr__(self):
|
|
109
|
-
return f"
|
|
98
|
+
return f"Service( proximl , **{self._service.__repr__()})"
|
|
110
99
|
|
|
111
100
|
def __bool__(self):
|
|
112
101
|
return bool(self._id)
|
|
113
102
|
|
|
114
103
|
async def remove(self):
|
|
115
104
|
await self.proximl._query(
|
|
116
|
-
f"/provider/{self._provider_uuid}/region/{self._region_uuid}/
|
|
105
|
+
f"/provider/{self._provider_uuid}/region/{self._region_uuid}/service/{self._id}",
|
|
117
106
|
"DELETE",
|
|
118
107
|
)
|
|
119
108
|
|
|
120
109
|
async def refresh(self):
|
|
121
110
|
resp = await self.proximl._query(
|
|
122
|
-
f"/provider/{self._provider_uuid}/region/{self._region_uuid}/
|
|
111
|
+
f"/provider/{self._provider_uuid}/region/{self._region_uuid}/service/{self._id}",
|
|
123
112
|
"GET",
|
|
124
113
|
)
|
|
125
114
|
self.__init__(self.proximl, **resp)
|
|
@@ -72,17 +72,17 @@ class ProjectDatastore:
|
|
|
72
72
|
return bool(self._id)
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
class
|
|
75
|
+
class ProjectService:
|
|
76
76
|
def __init__(self, proximl, **kwargs):
|
|
77
77
|
self.proximl = proximl
|
|
78
|
-
self.
|
|
79
|
-
self._id = self.
|
|
80
|
-
self._project_uuid = self.
|
|
81
|
-
self._name = self.
|
|
82
|
-
self._type = self.
|
|
83
|
-
self._hostname = self.
|
|
84
|
-
self._resource = self.
|
|
85
|
-
self._region_uuid = self.
|
|
78
|
+
self._service = kwargs
|
|
79
|
+
self._id = self._service.get("id")
|
|
80
|
+
self._project_uuid = self._service.get("project_uuid")
|
|
81
|
+
self._name = self._service.get("name")
|
|
82
|
+
self._type = self._service.get("type")
|
|
83
|
+
self._hostname = self._service.get("hostname")
|
|
84
|
+
self._resource = self._service.get("resource")
|
|
85
|
+
self._region_uuid = self._service.get("region_uuid")
|
|
86
86
|
|
|
87
87
|
@property
|
|
88
88
|
def id(self) -> str:
|
|
@@ -113,12 +113,10 @@ class ProjectReservation:
|
|
|
113
113
|
return self._region_uuid
|
|
114
114
|
|
|
115
115
|
def __str__(self):
|
|
116
|
-
return json.dumps({k: v for k, v in self.
|
|
116
|
+
return json.dumps({k: v for k, v in self._service.items()})
|
|
117
117
|
|
|
118
118
|
def __repr__(self):
|
|
119
|
-
return (
|
|
120
|
-
f"ProjectReservation( proximl , **{self._reservation.__repr__()})"
|
|
121
|
-
)
|
|
119
|
+
return f"ProjectService( proximl , **{self._service.__repr__()})"
|
|
122
120
|
|
|
123
121
|
def __bool__(self):
|
|
124
122
|
return bool(self._id)
|
|
@@ -162,26 +160,17 @@ class Project:
|
|
|
162
160
|
await self.proximl._query(f"/project/{self._id}", "DELETE")
|
|
163
161
|
|
|
164
162
|
async def list_datastores(self):
|
|
165
|
-
resp = await self.proximl._query(
|
|
166
|
-
|
|
167
|
-
)
|
|
168
|
-
datastores = [
|
|
169
|
-
ProjectDatastore(self.proximl, **datastore) for datastore in resp
|
|
170
|
-
]
|
|
163
|
+
resp = await self.proximl._query(f"/project/{self._id}/datastores", "GET")
|
|
164
|
+
datastores = [ProjectDatastore(self.proximl, **datastore) for datastore in resp]
|
|
171
165
|
return datastores
|
|
172
166
|
|
|
173
|
-
async def
|
|
174
|
-
resp = await self.proximl._query(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
reservations = [
|
|
178
|
-
ProjectReservation(self.proximl, **reservation)
|
|
179
|
-
for reservation in resp
|
|
180
|
-
]
|
|
181
|
-
return reservations
|
|
167
|
+
async def list_services(self):
|
|
168
|
+
resp = await self.proximl._query(f"/project/{self._id}/services", "GET")
|
|
169
|
+
services = [ProjectService(self.proximl, **service) for service in resp]
|
|
170
|
+
return services
|
|
182
171
|
|
|
183
172
|
async def refresh_datastores(self):
|
|
184
173
|
await self.proximl._query(f"/project/{self._id}/datastores", "PATCH")
|
|
185
174
|
|
|
186
|
-
async def
|
|
187
|
-
await self.proximl._query(f"/project/{self._id}/
|
|
175
|
+
async def refresh_services(self):
|
|
176
|
+
await self.proximl._query(f"/project/{self._id}/services", "PATCH")
|
|
@@ -41,7 +41,7 @@ proximl/cli/cloudbender/device.py
|
|
|
41
41
|
proximl/cli/cloudbender/node.py
|
|
42
42
|
proximl/cli/cloudbender/provider.py
|
|
43
43
|
proximl/cli/cloudbender/region.py
|
|
44
|
-
proximl/cli/cloudbender/
|
|
44
|
+
proximl/cli/cloudbender/service.py
|
|
45
45
|
proximl/cli/job/__init__.py
|
|
46
46
|
proximl/cli/job/create.py
|
|
47
47
|
proximl/cloudbender/__init__.py
|
|
@@ -52,7 +52,7 @@ proximl/cloudbender/devices.py
|
|
|
52
52
|
proximl/cloudbender/nodes.py
|
|
53
53
|
proximl/cloudbender/providers.py
|
|
54
54
|
proximl/cloudbender/regions.py
|
|
55
|
-
proximl/cloudbender/
|
|
55
|
+
proximl/cloudbender/services.py
|
|
56
56
|
tests/integration/__init__.py
|
|
57
57
|
tests/integration/conftest.py
|
|
58
58
|
tests/integration/test_checkpoints_integration.py
|
|
@@ -103,4 +103,4 @@ tests/unit/cloudbender/test_devices_unit.py
|
|
|
103
103
|
tests/unit/cloudbender/test_nodes_unit.py
|
|
104
104
|
tests/unit/cloudbender/test_providers_unit.py
|
|
105
105
|
tests/unit/cloudbender/test_regions_unit.py
|
|
106
|
-
tests/unit/cloudbender/
|
|
106
|
+
tests/unit/cloudbender/test_services_unit.py
|
|
@@ -21,7 +21,7 @@ markers = [
|
|
|
21
21
|
"nodes: Nodes tests",
|
|
22
22
|
"devices: Devices tests",
|
|
23
23
|
"datastores: Datastores tests",
|
|
24
|
-
"
|
|
24
|
+
"services: Services tests",
|
|
25
25
|
"device_configs: DeviceConfigs tests",
|
|
26
26
|
"unit: All unit tests (no proxiML environment required)",
|
|
27
27
|
"integration: All integration tests (proxiML environment required)",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import json
|
|
3
|
+
import click
|
|
4
|
+
from unittest.mock import AsyncMock, patch
|
|
5
|
+
from pytest import mark, fixture, raises
|
|
6
|
+
|
|
7
|
+
pytestmark = [mark.cli, mark.unit, mark.cloudbender, mark.services]
|
|
8
|
+
|
|
9
|
+
from proximl.cli.cloudbender import service as specimen
|
|
10
|
+
from proximl.cloudbender.services import Service
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_list(runner, mock_services):
|
|
14
|
+
with patch("proximl.cli.ProxiML", new=AsyncMock) as mock_proximl:
|
|
15
|
+
mock_proximl.cloudbender = AsyncMock()
|
|
16
|
+
mock_proximl.cloudbender.services = AsyncMock()
|
|
17
|
+
mock_proximl.cloudbender.services.list = AsyncMock(return_value=mock_services)
|
|
18
|
+
result = runner.invoke(
|
|
19
|
+
specimen,
|
|
20
|
+
args=["list", "--provider=prov-id-1", "--region=reg-id-1"],
|
|
21
|
+
)
|
|
22
|
+
assert result.exit_code == 0
|
|
23
|
+
mock_proximl.cloudbender.services.list.assert_called_once_with(
|
|
24
|
+
provider_uuid="prov-id-1", region_uuid="reg-id-1"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_list_no_provider(runner, mock_services):
|
|
29
|
+
with patch("proximl.cli.ProxiML", new=AsyncMock) as mock_proximl:
|
|
30
|
+
mock_proximl.cloudbender = AsyncMock()
|
|
31
|
+
mock_proximl.cloudbender.services = AsyncMock()
|
|
32
|
+
mock_proximl.cloudbender.services.list = AsyncMock(return_value=mock_services)
|
|
33
|
+
result = runner.invoke(specimen, ["list"])
|
|
34
|
+
assert result.exit_code != 0
|
|
@@ -23,9 +23,7 @@ def test_list(runner, mock_projects):
|
|
|
23
23
|
def test_list_datastores(runner, mock_project_datastores):
|
|
24
24
|
with patch("proximl.cli.ProxiML", new=AsyncMock) as mock_proximl:
|
|
25
25
|
mock_project = create_autospec(Project)
|
|
26
|
-
mock_project.list_datastores = AsyncMock(
|
|
27
|
-
return_value=mock_project_datastores
|
|
28
|
-
)
|
|
26
|
+
mock_project.list_datastores = AsyncMock(return_value=mock_project_datastores)
|
|
29
27
|
mock_proximl.projects.get = AsyncMock(return_value=mock_project)
|
|
30
28
|
result = runner.invoke(specimen, ["list-datastores"])
|
|
31
29
|
print(result)
|
|
@@ -33,14 +31,12 @@ def test_list_datastores(runner, mock_project_datastores):
|
|
|
33
31
|
mock_project.list_datastores.assert_called_once()
|
|
34
32
|
|
|
35
33
|
|
|
36
|
-
def
|
|
34
|
+
def test_list_services(runner, mock_project_services):
|
|
37
35
|
with patch("proximl.cli.ProxiML", new=AsyncMock) as mock_proximl:
|
|
38
36
|
mock_project = create_autospec(Project)
|
|
39
|
-
mock_project.
|
|
40
|
-
return_value=mock_project_reservations
|
|
41
|
-
)
|
|
37
|
+
mock_project.list_services = AsyncMock(return_value=mock_project_services)
|
|
42
38
|
mock_proximl.projects.get = AsyncMock(return_value=mock_project)
|
|
43
|
-
result = runner.invoke(specimen, ["list-
|
|
39
|
+
result = runner.invoke(specimen, ["list-services"])
|
|
44
40
|
print(result)
|
|
45
41
|
assert result.exit_code == 0
|
|
46
|
-
mock_project.
|
|
42
|
+
mock_project.list_services.assert_called_once()
|