Skip to content

Commit 4528e7f

Browse files
authored
Merge pull request #194 from Paperspace/PS-12518-Add_deployments_details_command
Add deployments details command
2 parents 188641b + 3994a78 commit 4528e7f

File tree

11 files changed

+303
-23
lines changed

11 files changed

+303
-23
lines changed

gradient/api_sdk/clients/deployment_client.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,18 @@ def create(
121121
deployment_id = repository.create(deployment, use_vpc=use_vpc)
122122
return deployment_id
123123

124+
def get(self, deployment_id):
125+
"""Get deployment instance
126+
127+
:param str deployment_id: Deployment ID
128+
129+
:return: Deployment instance
130+
:rtype: models.Deployment
131+
"""
132+
repository = repositories.GetDeployment(self.api_key, logger=self.logger)
133+
deployment = repository.get(deployment_id=deployment_id)
134+
return deployment
135+
124136
def start(self, deployment_id, use_vpc=False):
125137
"""
126138
Start deployment

gradient/api_sdk/repositories/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from .deployments import ListDeployments, CreateDeployment, StartDeployment, StopDeployment, DeleteDeployment, \
2-
UpdateDeployment
2+
UpdateDeployment, GetDeployment
33
from .experiments import ListExperiments, GetExperiment, ListExperimentLogs, StartExperiment, StopExperiment, \
44
CreateSingleNodeExperiment, CreateMultiNodeExperiment, RunSingleNodeExperiment, RunMultiNodeExperiment, \
55
CreateMpiMultiNodeExperiment, RunMpiMultiNodeExperiment, DeleteExperiment

gradient/api_sdk/repositories/deployments.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
from .common import ListResources, CreateResource, StartResource, StopResource, DeleteResource, AlterResource
1+
from .common import ListResources, CreateResource, StartResource, StopResource, DeleteResource, AlterResource, \
2+
GetResource
23
from .. import serializers, config
4+
from ..sdk_exceptions import ResourceFetchingError, MalformedResponseError
35

46

57
class GetBaseDeploymentApiUrlMixin(object):
@@ -141,3 +143,26 @@ def _get_request_json(self, kwargs):
141143
"upd": kwargs,
142144
}
143145
return j
146+
147+
148+
class GetDeployment(GetBaseDeploymentApiUrlMixin, GetResource):
149+
SERIALIZER_CLS = serializers.DeploymentSchema
150+
151+
def get_request_url(self, **kwargs):
152+
return "/deployments/getDeploymentList/"
153+
154+
def _get_request_json(self, kwargs):
155+
deployment_id = kwargs["deployment_id"]
156+
filter_ = {"where": {"and": [{"id": deployment_id}]}}
157+
json_ = {"filter": filter_}
158+
return json_
159+
160+
def _parse_object(self, instance_dict, **kwargs):
161+
try:
162+
instance_dict = instance_dict["deploymentList"][0]
163+
except KeyError:
164+
raise MalformedResponseError("Malformed response from API")
165+
except IndexError:
166+
raise ResourceFetchingError("Deployment not found")
167+
168+
return super(GetDeployment, self)._parse_object(instance_dict, **kwargs)

gradient/api_sdk/sdk_exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ class ResourceCreatingError(GradientSdkError):
1010
pass
1111

1212

13+
class MalformedResponseError(GradientSdkError):
14+
pass
15+
16+
1317
class ResourceCreatingDataError(ResourceCreatingError):
1418
pass
1519

gradient/cli/deployments.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from gradient import exceptions, logger, DEPLOYMENT_TYPES_MAP
66
from gradient import utils
7-
from gradient.api_sdk import DeploymentsClient, constants
7+
from gradient.api_sdk import DeploymentsClient
88
from gradient.cli import common
99
from gradient.cli.cli import cli
1010
from gradient.cli.cli_types import ChoiceType, json_string
@@ -17,15 +17,6 @@ def deployments():
1717
pass
1818

1919

20-
DEPLOYMENT_MACHINE_TYPES = (
21-
"G1", "G6", "G12",
22-
"K80", "P100", "GV100",
23-
# VPC machine types
24-
"c5.xlarge", "c5.4xlarge", "c5.12xlarge",
25-
"p2.xlarge", "p3.2xlarge", "p3.16xlarge",
26-
)
27-
28-
2920
def get_deployment_client(api_key):
3021
deployment_client = DeploymentsClient(api_key=api_key, logger=logger.Logger())
3122
return deployment_client
@@ -447,3 +438,19 @@ def update_deployment(deployment_id, api_key, use_vpc, options_file, **kwargs):
447438
deployment_client = get_deployment_client(api_key)
448439
command = deployments_commands.UpdateDeploymentCommand(deployment_client=deployment_client)
449440
command.execute(deployment_id, use_vpc=use_vpc, **kwargs)
441+
442+
443+
@deployments.command("details", help="Get details of model deployment")
444+
@click.option(
445+
"--id",
446+
"deployment_id",
447+
required=True,
448+
help="Deployment ID",
449+
cls=common.GradientOption,
450+
)
451+
@api_key_option
452+
@common.options_file
453+
def get_deployment(deployment_id, api_key, options_file):
454+
deployment_client = get_deployment_client(api_key)
455+
command = deployments_commands.GetDeploymentDetails(deployment_client=deployment_client)
456+
command.execute(deployment_id)

gradient/commands/common.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33

44
import six
55
import terminaltables
6-
from gradient import exceptions
7-
from gradient.api_sdk import sdk_exceptions
6+
from halo import halo
7+
88
from gradient.logger import Logger
99
from gradient.utils import get_terminal_lines
10-
from halo import halo
1110

1211

1312
@six.add_metaclass(abc.ABCMeta)

gradient/commands/deployments.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
from halo import halo
77

88
from gradient import version, logger as gradient_logger, exceptions
9-
from gradient.api_sdk import sdk_exceptions, utils
9+
from gradient.api_sdk import sdk_exceptions, utils, models
1010
from gradient.api_sdk.clients import http_client
1111
from gradient.api_sdk.config import config
1212
from gradient.api_sdk.utils import urljoin
13+
from gradient.commands.common import DetailsCommandMixin
1314
from gradient.utils import get_terminal_lines
1415

1516
default_headers = {"X-API-Key": config.PAPERSPACE_API_KEY,
@@ -21,7 +22,7 @@
2122
@six.add_metaclass(abc.ABCMeta)
2223
class _DeploymentCommand(object):
2324
def __init__(self, deployment_client, logger_=gradient_logger.Logger()):
24-
self.deployment_client = deployment_client
25+
self.client = deployment_client
2526
self.logger = logger_
2627

2728
@abc.abstractmethod
@@ -34,7 +35,7 @@ def execute(self, use_vpc=False, **kwargs):
3435
self._handle_auth(kwargs)
3536

3637
with halo.Halo(text="Creating new deployment", spinner="dots"):
37-
deployment_id = self.deployment_client.create(use_vpc=use_vpc, **kwargs)
38+
deployment_id = self.client.create(use_vpc=use_vpc, **kwargs)
3839

3940
self.logger.log("New deployment created with id: {}".format(deployment_id))
4041
self.logger.log(self.get_instance_url(deployment_id))
@@ -62,7 +63,7 @@ def execute(self, use_vpc=False, **kwargs):
6263

6364
def _get_instances(self, use_vpc=False, **kwargs):
6465
try:
65-
instances = self.deployment_client.list(use_vpc=use_vpc, **kwargs)
66+
instances = self.client.list(use_vpc=use_vpc, **kwargs)
6667
except sdk_exceptions.GradientSdkError as e:
6768
raise exceptions.ReceivingDataFailedError(e)
6869

@@ -103,25 +104,46 @@ def _make_table(table_data):
103104

104105
class StartDeploymentCommand(_DeploymentCommand):
105106
def execute(self, use_vpc=False, **kwargs):
106-
self.deployment_client.start(use_vpc=use_vpc, **kwargs)
107+
self.client.start(use_vpc=use_vpc, **kwargs)
107108
self.logger.log("Deployment started")
108109

109110

110111
class StopDeploymentCommand(_DeploymentCommand):
111112
def execute(self, use_vpc=False, **kwargs):
112-
self.deployment_client.stop(use_vpc=use_vpc, **kwargs)
113+
self.client.stop(use_vpc=use_vpc, **kwargs)
113114
self.logger.log("Deployment stopped")
114115

115116

116117
class DeleteDeploymentCommand(_DeploymentCommand):
117118
def execute(self, **kwargs):
118-
self.deployment_client.delete(**kwargs)
119+
self.client.delete(**kwargs)
119120
self.logger.log("Deployment deleted")
120121

121122

122123
class UpdateDeploymentCommand(_DeploymentCommand):
123124
def execute(self, deployment_id, use_vpc=False, **kwargs):
124125
with halo.Halo(text="Updating deployment data", spinner="dots"):
125-
self.deployment_client.update(deployment_id, use_vpc=use_vpc, **kwargs)
126+
self.client.update(deployment_id, use_vpc=use_vpc, **kwargs)
126127

127128
self.logger.log("Deployment data updated")
129+
130+
131+
class GetDeploymentDetails(DetailsCommandMixin, _DeploymentCommand):
132+
def _get_table_data(self, instance):
133+
"""
134+
:param models.Deployment instance:
135+
"""
136+
data = (
137+
("ID", instance.id),
138+
("Name", instance.name),
139+
("State", instance.state),
140+
("Machine type", instance.machine_type),
141+
("Instance count", instance.instance_count),
142+
("Deployment type", instance.deployment_type),
143+
("Model ID", instance.model_id),
144+
("Project ID", instance.project_id),
145+
("Endpoint", instance.endpoint),
146+
("API type", instance.api_type),
147+
("Cluster ID", instance.cluster_id),
148+
)
149+
return data
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
apiKey: some_key
2+
id: some_id
3+
vpc: true

tests/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ def deployments_delete_config_path():
9797
return str(fixture_dir.resolve())
9898

9999

100+
@pytest.fixture
101+
def deployments_details_config_path():
102+
p = Path(__file__)
103+
fixture_dir = p.parent / "config_files" / "deployments_details.yaml"
104+
return str(fixture_dir.resolve())
105+
106+
100107
@pytest.fixture
101108
def hyperparameters_create_config_path():
102109
p = Path(__file__)

tests/example_responses.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5596,3 +5596,71 @@
55965596
"url": "https://ps-projects.s3.amazonaws.com/some/path/model/keton/elo.txt?AWSAccessKeyId=some_aws_access_key_id&Expires=713274132&Signature=tHriojGx03S%2FKkVGQGVI5CQRFTo%3D&response-content-disposition=attachment%3Bfilename%3D%22elo.txt%22&x-amz-security-token=some_amz_security_token"
55975597
}
55985598
]
5599+
5600+
GET_DEPLOYMENT_DETAILS_JSON_RESPONSE = {
5601+
"deploymentList": [
5602+
{
5603+
"id": "some_id",
5604+
"ownerId": "some_owner_id",
5605+
"projectId": "some_project_id",
5606+
"experimentId": "some_experiment_id",
5607+
"state": "Stopped",
5608+
"startedByUserId": "some_user_id",
5609+
"startedByUserEmail": "[email protected]",
5610+
"deploymentType": "TFServing",
5611+
"deploymentTypeDescription": "Tensorflow Serving on K8s",
5612+
"modelId": "some_model_id",
5613+
"modelUrl": "s3://ps-projects/asdf/some/model/url",
5614+
"name": "some_name",
5615+
"tag": None,
5616+
"params": None,
5617+
"code": None,
5618+
"cluster": "KPS Jobs",
5619+
"clusterId": "some_cluster_id",
5620+
"machineType": "p3.2xlarge",
5621+
"imageUrl": "tensorflow/serving",
5622+
"imageUsername": None,
5623+
"imagePassword": None,
5624+
"imageServer": None,
5625+
"workspaceUrl": None,
5626+
"workspaceUsername": None,
5627+
"workspacePassword": None,
5628+
"instanceCount": 1,
5629+
"runningCount": 0,
5630+
"error": None,
5631+
"authToken": None,
5632+
"annotations": {},
5633+
"oauthKey": None,
5634+
"oauthSecret": None,
5635+
"serviceType": "model",
5636+
"apiType": "REST",
5637+
"endpoint": "https://paperspace.io/model-serving/some_id:predict",
5638+
"ports": None,
5639+
"dtCreated": "2020-01-13T22:21:28.210Z",
5640+
"dtModified": "2020-01-14T00:32:27.577Z",
5641+
"dtBuildStarted": "2020-01-13T22:21:28.482Z",
5642+
"dtBuildFinished": None,
5643+
"dtProvisioningStarted": None,
5644+
"dtProvisioningFinished": None,
5645+
"dtStarted": None,
5646+
"dtTeardownStarted": None,
5647+
"dtTeardownFinished": None,
5648+
"dtStopped": "2020-01-13T22:48:40.107Z",
5649+
"dtDeleted": None,
5650+
"isDeleted": False,
5651+
"modelType": "Tensorflow",
5652+
"modelPath": None,
5653+
"command": None,
5654+
"args": None,
5655+
"env": None,
5656+
"containerModelPath": None,
5657+
"containerUrlPath": None,
5658+
"endpointUrlPath": None,
5659+
"method": None,
5660+
"tags": None
5661+
}
5662+
],
5663+
"total": 129,
5664+
"displayTotal": 129,
5665+
"runningTotal": 0
5666+
}

0 commit comments

Comments
 (0)