Skip to content

Commit 3992f22

Browse files
authored
Added handler to list private endpoint (#981)
2 parents 611b9d4 + 01561be commit 3992f22

File tree

6 files changed

+129
-0
lines changed

6 files changed

+129
-0
lines changed

ads/aqua/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
LIFECYCLE_DETAILS_MISSING_JOBRUN = "The associated JobRun resource has been deleted."
2828
READY_TO_DEPLOY_STATUS = "ACTIVE"
2929
READY_TO_FINE_TUNE_STATUS = "TRUE"
30+
PRIVATE_ENDPOINT_TYPE = "MODEL_DEPLOYMENT"
3031
AQUA_GA_LIST = ["id19sfcrra6z"]
3132
AQUA_MODEL_TYPE_SERVICE = "service"
3233
AQUA_MODEL_TYPE_CUSTOM = "custom"

ads/aqua/extension/ui_handler.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from ads.aqua.common.decorator import handle_exceptions
1212
from ads.aqua.common.enums import Tags
13+
from ads.aqua.constants import PRIVATE_ENDPOINT_TYPE
1314
from ads.aqua.extension.errors import Errors
1415
from ads.aqua.extension.base_handler import AquaAPIhandler
1516
from ads.aqua.extension.utils import validate_function_parameters
@@ -72,6 +73,8 @@ def get(self, id=""):
7273
return self.list_vcn()
7374
elif paths.startswith("aqua/subnets"):
7475
return self.list_subnets()
76+
elif paths.startswith("aqua/privateendpoints"):
77+
return self.list_private_endpoints()
7578
elif paths.startswith("aqua/shapes/limit"):
7679
return self.get_shape_availability()
7780
elif paths.startswith("aqua/bucket/versioning"):
@@ -175,6 +178,16 @@ def list_subnets(self, **kwargs):
175178
)
176179
)
177180

181+
def list_private_endpoints(self, **kwargs):
182+
"""Lists the private endpoints in the specified compartment."""
183+
compartment_id = self.get_argument("compartment_id", default=COMPARTMENT_OCID)
184+
resource_type = self.get_argument("resource_type", default=PRIVATE_ENDPOINT_TYPE)
185+
return self.finish(
186+
AquaUIApp().list_private_endpoints(
187+
compartment_id=compartment_id, resource_type=resource_type, **kwargs
188+
)
189+
)
190+
178191
def get_shape_availability(self, **kwargs):
179192
"""For a given compartmentId, resource limit name, and scope, returns the number of available resources associated
180193
with the given limit."""
@@ -244,6 +257,7 @@ def post(self, *args, **kwargs):
244257
("job/shapes/?([^/]*)", AquaUIHandler),
245258
("vcn/?([^/]*)", AquaUIHandler),
246259
("subnets/?([^/]*)", AquaUIHandler),
260+
("privateendpoints/?([^/]*)", AquaUIHandler),
247261
("shapes/limit/?([^/]*)", AquaUIHandler),
248262
("bucket/versioning/?([^/]*)", AquaUIHandler),
249263
("containers/?([^/]*)", AquaUIHandler),

ads/aqua/ui.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from ads.aqua.common.enums import Tags
1919
from ads.aqua.common.errors import AquaResourceAccessError, AquaValueError
2020
from ads.aqua.common.utils import get_container_config, load_config, sanitize_response
21+
from ads.aqua.constants import PRIVATE_ENDPOINT_TYPE
2122
from ads.common import oci_client as oc
2223
from ads.common.auth import default_signer
2324
from ads.common.object_storage_details import ObjectStorageDetails
@@ -549,6 +550,34 @@ def list_subnets(self, **kwargs) -> list:
549550

550551
return sanitize_response(oci_client=vcn_client, response=res)
551552

553+
@telemetry(entry_point="plugin=ui&action=list_private_endpoints", name="aqua")
554+
def list_private_endpoints(self, **kwargs) -> list:
555+
"""Lists the private endpoints in the specified compartment.
556+
Data seicne private endpoints have two types: `NOTEBOOK_SESSION` and `MODEL_DEPLOYMENT`.
557+
This api will by default list `MODEL_DEPLOYMENT` type as needed by AQUA model deployment.
558+
559+
Parameters
560+
----------
561+
**kwargs
562+
Addtional arguments, such as `compartment_id`,
563+
for `list_data_science_private_endpoints <https://docs.oracle.com/en-us/iaas/tools/python/latest/api/data_science/client/oci.data_science.DataScienceClient.html#oci.data_science.DataScienceClient.list_data_science_private_endpoints>`_
564+
565+
Returns
566+
-------
567+
json representation of `oci.data_science.models.DataSciencePrivateEndpointSummary`.
568+
"""
569+
compartment_id = kwargs.pop("compartment_id", COMPARTMENT_OCID)
570+
resource_type = kwargs.pop("resource_type", PRIVATE_ENDPOINT_TYPE)
571+
logger.info(
572+
f"Loading private endpoints from compartment: {compartment_id}"
573+
)
574+
575+
res = self.ds_client.list_data_science_private_endpoints(
576+
compartment_id=compartment_id, data_science_resource_type=resource_type
577+
).data
578+
579+
return sanitize_response(oci_client=self.ds_client, response=res)
580+
552581
@telemetry(entry_point="plugin=ui&action=get_shape_availability", name="aqua")
553582
def get_shape_availability(self, **kwargs):
554583
"""
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[
2+
{
3+
"compartment_id": "ocid1.compartment.oc1..<OCID>",
4+
"defined_tags": {},
5+
"display_name": "datascienceprivateendpoint20241024145113",
6+
"freeform_tags": {},
7+
"system_tags": {},
8+
"id": "ocid1.datascienceprivateendpointint.oc1.iad.<OCID>",
9+
"lifecycle_state": "ACTIVE",
10+
"data_science_resource_type": "MODEL_DEPLOYMENT",
11+
"created_by": "ocid1.datasciencenotebooksessionint.oc1.iad.<OCID>",
12+
"subnet_id": "ocid1.subnet.oc1.iad.<OCID>",
13+
"fqdn": "<OCID>.md2-pe.modeldeployment-int.us-ashburn-1.oci.oc-test.com",
14+
"time_created": "2024-10-24T14:51:13.883000Z",
15+
"time_updated": "2024-10-24T14:51:13.883000Z"
16+
},
17+
{
18+
"compartment_id": "ocid1.compartment.oc1..<OCID>",
19+
"defined_tags": {},
20+
"display_name": "datascienceprivateendpoint20241023220645",
21+
"freeform_tags": {},
22+
"system_tags": {},
23+
"id": "ocid1.datascienceprivateendpointint.oc1.iad.<OCID>",
24+
"lifecycle_state": "ACTIVE",
25+
"data_science_resource_type": "MODEL_DEPLOYMENT",
26+
"created_by": "ocid1.datasciencenotebooksessionint.oc1.iad.<OCID>",
27+
"subnet_id": "ocid1.subnet.oc1.iad.<OCID>",
28+
"fqdn": "<OCID>.md2-pe.modeldeployment-int.us-ashburn-1.oci.oc-test.com",
29+
"time_created": "2024-10-23T22:06:45.224000Z",
30+
"time_updated": "2024-10-23T22:06:45.224000Z"
31+
}
32+
]

tests/unitary/with_extras/aqua/test_ui.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,48 @@ def test_list_subnets(self, mock_list_subnets):
398398
)
399399
assert len(results) == len(subnets)
400400

401+
def test_list_private_endpoints(self):
402+
"""Test to list the private endpoints in the specified compartment."""
403+
private_endpoints_list_json = os.path.join(
404+
self.curr_dir, f"test_data/ui/private_endpoints_list.json"
405+
)
406+
with open(private_endpoints_list_json, "r") as _file:
407+
private_endpoints = json.load(_file)
408+
409+
self.app.ds_client.list_data_science_private_endpoints = MagicMock(
410+
return_value=oci.response.Response(
411+
status=200,
412+
request=MagicMock(),
413+
headers=MagicMock(),
414+
data=[
415+
oci.data_science.models.DataSciencePrivateEndpointSummary(**pe)
416+
for pe in private_endpoints
417+
],
418+
)
419+
)
420+
421+
results = self.app.list_private_endpoints()
422+
expected_attributes = {
423+
"compartmentId",
424+
"definedTags",
425+
"displayName",
426+
"freeformTags",
427+
"systemTags",
428+
"id",
429+
"lifecycleState",
430+
"dataScienceResourceType",
431+
"createdBy",
432+
"subnetId",
433+
"fqdn",
434+
"timeCreated",
435+
"timeUpdated"
436+
}
437+
for result in results:
438+
self.assertTrue(
439+
expected_attributes.issuperset(set(result)), "Attributes mismatch"
440+
)
441+
assert len(results) == len(private_endpoints)
442+
401443
@patch.object(oci.limits.limits_client.LimitsClient, "get_resource_availability")
402444
def test_get_shape_availability(self, mock_get_resource_availability):
403445
"""Test whether the function returns the number of available resources associated with the given shape."""

tests/unitary/with_extras/aqua/test_ui_handler.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
class TestDataset:
2222
USER_COMPARTMENT_ID = "ocid1.compartment.oc1..<USER_COMPARTMENT_OCID>"
2323
USER_PROJECT_ID = "ocid1.datascienceproject.oc1.iad.<USER_PROJECT_OCID>"
24+
PRIVATE_ENDPOINT_RESOURCE_TYPE = "MODEL_DEPLOYMENT"
2425
DEPLOYMENT_SHAPE_NAME = "VM.GPU.A10.1"
2526

2627

@@ -149,6 +150,16 @@ def test_list_subnets(self, mock_list_subnets):
149150
compartment_id=TestDataset.USER_COMPARTMENT_ID, vcn_id="mock-vcn-id"
150151
)
151152

153+
@patch("ads.aqua.ui.AquaUIApp.list_private_endpoints")
154+
def test_list_private_endpoints(self, mock_list_private_endpoints):
155+
"""Test the get method to fetch list of private endpoints."""
156+
self.ui_handler.request.path = "aqua/privateendpoints"
157+
self.ui_handler.get()
158+
mock_list_private_endpoints.assert_called_with(
159+
compartment_id=TestDataset.USER_COMPARTMENT_ID,
160+
resource_type=TestDataset.PRIVATE_ENDPOINT_RESOURCE_TYPE
161+
)
162+
152163
@patch("ads.aqua.ui.AquaUIApp.get_shape_availability")
153164
def test_get_shape_availability(self, mock_get_shape_availability):
154165
"""Test get shape availability."""

0 commit comments

Comments
 (0)