Skip to content

Commit e87e6e2

Browse files
authored
Merge pull request #301 from roboflow/add-cli-for-roboflow-runner
add cli interface for dedicated deployment
2 parents 3d54406 + 5d5edd4 commit e87e6e2

File tree

8 files changed

+159
-2
lines changed

8 files changed

+159
-2
lines changed

roboflow/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from roboflow.models import CLIPModel, GazeModel # noqa: F401
1616
from roboflow.util.general import write_line
1717

18-
__version__ = "1.1.37"
18+
__version__ = "1.1.38"
1919

2020

2121
def check_key(api_key, model, notebook, num_retries=0):

roboflow/adapters/deploymentapi.py

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import requests
2+
3+
from roboflow.config import DEDICATED_DEPLOYMENT_URL
4+
5+
6+
class DeploymentApiError(Exception):
7+
pass
8+
9+
10+
def add_deployment(api_key, security_level, machine_type, deployment_name, inference_version):
11+
url = f"{DEDICATED_DEPLOYMENT_URL}/add"
12+
response = requests.post(
13+
url,
14+
json={
15+
"api_key": api_key,
16+
"security_level": security_level,
17+
"machine_type": machine_type,
18+
"deployment_name": deployment_name,
19+
"inference_version": inference_version,
20+
},
21+
)
22+
if response.status_code != 200:
23+
raise DeploymentApiError(f"{response.status_code}: {response.text}")
24+
result = response.json()
25+
return result
26+
27+
28+
def get_deployment(api_key, deployment_id):
29+
url = f"{DEDICATED_DEPLOYMENT_URL}/get"
30+
response = requests.get(url, json={"api_key": api_key, "deployment_id": deployment_id})
31+
if response.status_code != 200:
32+
raise DeploymentApiError(f"{response.status_code}: {response.text}")
33+
result = response.json()
34+
return result
35+
36+
37+
def list_deployment(api_key):
38+
url = f"{DEDICATED_DEPLOYMENT_URL}/list"
39+
response = requests.get(url, json={"api_key": api_key})
40+
if response.status_code != 200:
41+
raise DeploymentApiError(f"{response.status_code}: {response.text}")
42+
result = response.json()
43+
return result
44+
45+
46+
def delete_deployment(api_key, deployment_id):
47+
url = f"{DEDICATED_DEPLOYMENT_URL}/delete"
48+
response = requests.post(url, json={"api_key": api_key, "deployment_id": deployment_id})
49+
if response.status_code != 200:
50+
raise DeploymentApiError(f"{response.status_code}: {response.text}")
51+
result = response.json()
52+
return result
53+
54+
55+
def list_machine_types(api_key):
56+
url = f"{DEDICATED_DEPLOYMENT_URL}/machine_types"
57+
response = requests.get(url, json={"api_key": api_key})
58+
if response.status_code != 200:
59+
raise DeploymentApiError(f"{response.status_code}: {response.text}")
60+
result = response.json()
61+
return result

roboflow/config.py

+4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ def get_conditional_configuration_variable(key, default):
6363
CLIP_FEATURIZE_URL = get_conditional_configuration_variable("CLIP_FEATURIZE_URL", "CLIP FEATURIZE URL NOT IN ENV")
6464
OCR_URL = get_conditional_configuration_variable("OCR_URL", "OCR URL NOT IN ENV")
6565

66+
DEDICATED_DEPLOYMENT_URL = get_conditional_configuration_variable(
67+
"DEDICATED_DEPLOYMENT_URL", "https://ddploy.roboflow.com"
68+
)
69+
6670
DEMO_KEYS = ["coco-128-sample", "chess-sample-only-api-key"]
6771

6872
TYPE_CLASSICATION = "classification"

roboflow/deployment.py

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import json
2+
3+
from roboflow.adapters import deploymentapi
4+
from roboflow.config import load_roboflow_api_key
5+
6+
7+
def add_deployment_parser(subparsers):
8+
deployment_parser = subparsers.add_parser(
9+
"deployment",
10+
help="deployment related commands. type 'roboflow deployment' to see detailed command help",
11+
)
12+
deployment_subparsers = deployment_parser.add_subparsers(title="deployment subcommands")
13+
deployment_machine_type_parser = deployment_subparsers.add_parser("machine_type", help="list machine types")
14+
deployment_add_parser = deployment_subparsers.add_parser("add", help="create a dedicated deployment")
15+
deployment_get_parser = deployment_subparsers.add_parser(
16+
"get", help="show detailed info for a dedicated deployment"
17+
)
18+
deployment_list_parser = deployment_subparsers.add_parser("list", help="list dedicated deployments in a workspace")
19+
deployment_delete_parser = deployment_subparsers.add_parser("delete", help="delete a dedicated deployment")
20+
21+
deployment_machine_type_parser.set_defaults(func=list_machine_types)
22+
deployment_machine_type_parser.add_argument("-a", dest="api_key", help="api key")
23+
24+
deployment_add_parser.set_defaults(func=add_deployment)
25+
deployment_add_parser.add_argument("-a", dest="api_key", help="api key")
26+
deployment_add_parser.add_argument(
27+
"-s", dest="security_level", help="security level (protected)", default="protected"
28+
)
29+
deployment_add_parser.add_argument(
30+
"-m",
31+
dest="machine_type",
32+
help="machine type, run `roboflow deployment machine_type` to see available options",
33+
default="gcp-n2-cpu",
34+
)
35+
deployment_add_parser.add_argument(
36+
"-n", dest="deployment_name", help="deployment name, must contain 3-10 lowercase characters"
37+
)
38+
deployment_add_parser.add_argument(
39+
"-v", dest="inference_version", help="inference server version (default: latest)", default="latest"
40+
)
41+
42+
deployment_get_parser.set_defaults(func=get_deployment)
43+
deployment_get_parser.add_argument("-a", dest="api_key", help="api key")
44+
deployment_get_parser.add_argument("-d", dest="deployment_id", help="deployment id")
45+
46+
deployment_list_parser.set_defaults(func=list_deployment)
47+
deployment_list_parser.add_argument("-a", dest="api_key", help="api key")
48+
49+
deployment_delete_parser.set_defaults(func=delete_deployment)
50+
deployment_delete_parser.add_argument("-a", dest="api_key", help="api key")
51+
deployment_delete_parser.add_argument("-d", dest="deployment_id", help="deployment id")
52+
53+
54+
def list_machine_types(args):
55+
api_key = args.api_key or load_roboflow_api_key(None)
56+
ret_json = deploymentapi.list_machine_types(api_key)
57+
print(json.dumps(ret_json, indent=2))
58+
59+
60+
def add_deployment(args):
61+
api_key = args.api_key or load_roboflow_api_key(None)
62+
ret_json = deploymentapi.add_deployment(
63+
api_key,
64+
args.security_level,
65+
args.machine_type,
66+
args.deployment_name,
67+
args.inference_version,
68+
)
69+
print(json.dumps(ret_json, indent=2))
70+
71+
72+
def get_deployment(args):
73+
api_key = args.api_key or load_roboflow_api_key(None)
74+
ret_json = deploymentapi.get_deployment(api_key, args.deployment_id)
75+
print(json.dumps(ret_json, indent=2))
76+
77+
78+
def list_deployment(args):
79+
api_key = args.api_key or load_roboflow_api_key(None)
80+
ret_json = deploymentapi.list_deployment(api_key)
81+
print(json.dumps(ret_json, indent=2))
82+
83+
84+
def delete_deployment(args):
85+
api_key = args.api_key or load_roboflow_api_key(None)
86+
ret_json = deploymentapi.delete_deployment(api_key, args.deployment_id)
87+
print(json.dumps(ret_json, indent=2))

roboflow/roboflowpy.py

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import roboflow
77
from roboflow import config as roboflow_config
8+
from roboflow import deployment
89
from roboflow.adapters import rfapi
910
from roboflow.config import APP_URL, get_conditional_configuration_variable, load_roboflow_api_key
1011
from roboflow.models.classification import ClassificationModel
@@ -173,6 +174,7 @@ def _argparser():
173174
_add_workspaces_parser(subparsers)
174175
_add_upload_model_parser(subparsers)
175176
_add_get_workspace_project_version_parser(subparsers)
177+
deployment.add_deployment_parser(subparsers)
176178

177179
return parser
178180

tests/manual/debugme.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
# f"import {thisdir}/data/cultura-pepino-coco -w wolfodorpythontests -p yellow-auto -c 100".split() # noqa: E501 // docs
4040
# f"import {thisdir}/data/cultura-pepino-yolov8 -w wolfodorpythontests -p yellow-auto -c 100".split() # noqa: E501 // docs
4141
# f"import {thisdir}/data/cultura-pepino-yolov8_voc -w wolfodorpythontests -p yellow-auto -c 100".split() # noqa: E501 // docs
42-
f"import {thisdir}/data/cultura-pepino-yolov5pytorch -w wolfodorpythontests -p yellow-auto -c 100 -n papaiasso".split() # noqa: E501 // docs
42+
# f"import {thisdir}/data/cultura-pepino-yolov5pytorch -w wolfodorpythontests -p yellow-auto -c 100 -n papaiasso".split() # noqa: E501 // docs
4343
# f"import {thisdir}/../datasets/mosquitos -w wolfodorpythontests -p yellow-auto -n papaiasso".split() # noqa: E501 // docs
44+
f"deployment list".split() # noqa: E501 // docs
4445
)
4546
args.func(args)

tests/manual/useprod

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ cp data/.config-prod data/.config
44
export API_URL=https://api.roboflow.com
55
export APP_URL=https://app.roboflow.com
66
export OBJECT_DETECTION_URL=https://detect.roboflow.one
7+
export DEDICATED_DEPLOYMENT_URL=https://deployment.svc.roboflow.com

tests/manual/usestaging

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ cp data/.config-staging data/.config
44
export API_URL=https://api.roboflow.one
55
export APP_URL=https://app.roboflow.one
66
export OBJECT_DETECTION_URL=https://lambda-object-detection.staging.roboflow.com
7+
export DEDICATED_DEPLOYMENT_URL=https://deployment.svc.roboflow.one

0 commit comments

Comments
 (0)