Skip to content

Commit a3369c3

Browse files
author
Jonathan Visser
committed
add bin/get_insights_annotations
1 parent d68d542 commit a3369c3

5 files changed

Lines changed: 162 additions & 0 deletions

File tree

bin/get_insights_annotations

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
command

hypernode_api_python/client.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
HYPERNODE_API_BRANCHER_APP_ENDPOINT = "/v2/brancher/app/{}/"
2424
HYPERNODE_API_FPM_STATUS_APP_ENDPOINT = "/v2/nats/{}/hypernode.show-fpm-status"
2525
HYPERNODE_API_BRANCHER_ENDPOINT = "/v2/brancher/{}/"
26+
HYPERNODE_API_INSIGHTS_ANNOTATION_LIST_ENDPOINT = "/v2/insights-annotation/"
2627
HYPERNODE_API_PRODUCT_APP_DETAIL_ENDPOINT = "/v2/product/app/{}/current/"
2728
HYPERNODE_API_PRODUCT_LIST_ENDPOINT = "/v2/product/"
2829
HYPERNODE_API_PRODUCT_PRICE_DETAIL_ENDPOINT = "/v2/product/{}/with_price/"
@@ -925,6 +926,38 @@ def get_fpm_status(self, app_name):
925926
"POST", HYPERNODE_API_FPM_STATUS_APP_ENDPOINT.format(app_name)
926927
)
927928

929+
def get_insights_annotations(self, params=None):
930+
"""
931+
List all custom Insights annotations for the Hypernodes you have
932+
access to. Only annotations created through the API are listed,
933+
system annotations generated from platform events are not included.
934+
Example:
935+
> client.get_insights_annotations().json()
936+
> {
937+
> 'count': 1,
938+
> 'next': None,
939+
> 'previous': None,
940+
> 'results': [
941+
> {
942+
> 'id': 123,
943+
> 'name': 'Deployed release 1.2.3',
944+
> 'x_axis': 1756384957,
945+
> 'app': 'yourhypernodeappname',
946+
> 'metrics': 'memory_usage',
947+
> 'created': '2025-08-28T12:42:37Z',
948+
> 'modified': '2025-08-28T12:42:37Z'
949+
> }
950+
> ]
951+
> }
952+
953+
:param dict params: Optional query parameters to paginate the
954+
results with. An example could be: {'limit': 10, 'offset': 20}
955+
:return obj response: The request response object
956+
"""
957+
return self.requests(
958+
"GET", HYPERNODE_API_INSIGHTS_ANNOTATION_LIST_ENDPOINT, params=params
959+
)
960+
928961
def create_brancher(self, app_name, data):
929962
"""
930963
Create a new branch (server replica) of your Hypernode.

hypernode_api_python/commands.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,54 @@ def destroy_brancher(args=None):
799799
exit(EX_UNAVAILABLE)
800800

801801

802+
def get_insights_annotations(args=None):
803+
parser = ArgumentParser(
804+
description="""
805+
List all custom Insights annotations for the Hypernodes you have access to.
806+
Only annotations created through the API are listed, system annotations
807+
generated from platform events are not included.
808+
809+
Example:
810+
$ ./bin/get_insights_annotations
811+
{
812+
"count": 1,
813+
"next": null,
814+
"previous": null,
815+
"results": [
816+
{
817+
"id": 123,
818+
"name": "Deployed release 1.2.3",
819+
"x_axis": 1756384957,
820+
"app": "yourhypernodeappname",
821+
"metrics": "memory_usage",
822+
"created": "2025-08-28T12:42:37Z",
823+
"modified": "2025-08-28T12:42:37Z"
824+
}
825+
]
826+
}
827+
""",
828+
formatter_class=RawTextHelpFormatter,
829+
)
830+
parser.add_argument(
831+
"--limit",
832+
help="Number of results to return per page",
833+
type=int,
834+
)
835+
parser.add_argument(
836+
"--offset",
837+
help="The initial index from which to return the results",
838+
type=int,
839+
)
840+
args = parser.parse_args(args=args)
841+
client = get_client()
842+
params = {}
843+
if args.limit is not None:
844+
params["limit"] = args.limit
845+
if args.offset is not None:
846+
params["offset"] = args.offset
847+
print_response(client.get_insights_annotations(params=params))
848+
849+
802850
def get_fpm_status(args=None):
803851
parser = ArgumentParser(
804852
description="""
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from unittest import TestCase
2+
from unittest.mock import Mock
3+
4+
from hypernode_api_python.client import (
5+
HYPERNODE_API_INSIGHTS_ANNOTATION_LIST_ENDPOINT,
6+
HypernodeAPIPython,
7+
)
8+
9+
10+
class TestGetInsightsAnnotations(TestCase):
11+
def setUp(self):
12+
self.client = HypernodeAPIPython(token="my_token")
13+
self.mock_request = Mock()
14+
self.client.requests = self.mock_request
15+
16+
def test_insights_annotation_list_endpoint_is_correct(self):
17+
self.assertEqual(
18+
"/v2/insights-annotation/",
19+
HYPERNODE_API_INSIGHTS_ANNOTATION_LIST_ENDPOINT,
20+
)
21+
22+
def test_calls_get_insights_annotations_endpoint_properly(self):
23+
self.client.get_insights_annotations()
24+
25+
self.mock_request.assert_called_once_with(
26+
"GET", "/v2/insights-annotation/", params=None
27+
)
28+
29+
def test_calls_get_insights_annotations_endpoint_with_pagination_params(self):
30+
params = {"limit": 10, "offset": 20}
31+
self.client.get_insights_annotations(params=params)
32+
33+
self.mock_request.assert_called_once_with(
34+
"GET", "/v2/insights-annotation/", params=params
35+
)
36+
37+
def test_returns_get_insights_annotations_response(self):
38+
response = Mock()
39+
response.status_code = 200
40+
self.mock_request.return_value = response
41+
42+
self.assertEqual(
43+
self.client.get_insights_annotations(),
44+
self.mock_request.return_value,
45+
)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from hypernode_api_python.commands import get_insights_annotations
2+
from tests.testcase import TestCase
3+
4+
5+
class TestGetInsightsAnnotations(TestCase):
6+
def setUp(self):
7+
self.print_response = self.set_up_patch(
8+
"hypernode_api_python.commands.print_response"
9+
)
10+
self.get_client = self.set_up_patch("hypernode_api_python.commands.get_client")
11+
self.client = self.get_client.return_value
12+
13+
def test_get_insights_annotations_gets_client(self):
14+
get_insights_annotations([])
15+
16+
self.get_client.assert_called_once_with()
17+
18+
def test_get_insights_annotations_gets_insights_annotations(self):
19+
get_insights_annotations([])
20+
21+
self.client.get_insights_annotations.assert_called_once_with(params={})
22+
23+
def test_get_insights_annotations_passes_pagination_params(self):
24+
get_insights_annotations(["--limit", "10", "--offset", "20"])
25+
26+
self.client.get_insights_annotations.assert_called_once_with(
27+
params={"limit": 10, "offset": 20}
28+
)
29+
30+
def test_get_insights_annotations_prints_response(self):
31+
get_insights_annotations([])
32+
33+
self.print_response.assert_called_once_with(
34+
self.client.get_insights_annotations.return_value
35+
)

0 commit comments

Comments
 (0)