Skip to content

Commit d13d94e

Browse files
committed
add int test
1 parent c9e1b72 commit d13d94e

File tree

7 files changed

+154
-11
lines changed

7 files changed

+154
-11
lines changed

linode_api4/groups/monitor_api.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
"MetricsGroup",
33
]
44

5-
from typing import Optional
5+
from typing import Any, Dict, List, Optional, Union
66

7+
from linode_api4 import drop_null_keys
78
from linode_api4.groups import Group
8-
from linode_api4.objects.monitor_api import EntityMetrics
9+
from linode_api4.objects.base import _flatten_request_body_recursive
10+
from linode_api4.objects.monitor_api import EntityMetricOptions, EntityMetrics
911

1012

1113
class MetricsGroup(Group):
@@ -19,6 +21,7 @@ def fetch_metrics(
1921
self,
2022
service_type: str,
2123
entity_ids: list,
24+
metrics: List[Union[EntityMetricOptions, Dict[str, Any]]],
2225
**kwargs,
2326
) -> Optional[EntityMetrics]:
2427
"""
@@ -33,18 +36,24 @@ def fetch_metrics(
3336
:param entity_ids: The id for each individual entity from a service_type.
3437
:type entity_ids: list
3538
39+
:param metrics: A list of metric objects, each specifying a metric name and its corresponding aggregation function.
40+
:type metrics: list of EntityMetricOptions or Dict[str, Any]
41+
3642
:param kwargs: Any other arguments accepted by the api. Please refer to the API documentation for full info.
3743
3844
:returns: Service metrics requested.
3945
:rtype: EntityMetrics or None
4046
"""
41-
42-
params = {"entity_ids": entity_ids}
47+
params = {
48+
"entity_ids": entity_ids,
49+
"metrics": metrics,
50+
}
4351

4452
params.update(kwargs)
4553

4654
result = self.client.post(
47-
f"/monitor/services/{service_type}/metrics", data=params
55+
f"/monitor/services/{service_type}/metrics",
56+
data=drop_null_keys(_flatten_request_body_recursive(params)),
4857
)
4958

5059
return EntityMetrics.from_json(result)

linode_api4/linode_client.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,43 @@ def get_backoff_time(self):
5353

5454

5555
class BaseClient:
56+
"""
57+
The base class for a client.
58+
59+
:param token: The authentication token to use for communication with the
60+
API. Can be either a Personal Access Token or an OAuth Token.
61+
:type token: str
62+
:param base_url: The base URL for API requests. Generally, you shouldn't
63+
change this.
64+
:type base_url: str
65+
:param user_agent: What to append to the User Agent of all requests made
66+
by this client. Setting this allows Linode's internal
67+
monitoring applications to track the usage of your
68+
application. Setting this is not necessary, but some
69+
applications may desire this behavior.
70+
:type user_agent: str
71+
:param page_size: The default size to request pages at. If not given,
72+
the API's default page size is used. Valid values
73+
can be found in the API docs, but at time of writing
74+
are between 25 and 500.
75+
:type page_size: int
76+
:param retry: Whether API requests should automatically be retries on known
77+
intermittent responses.
78+
:type retry: bool
79+
:param retry_rate_limit_interval: The amount of time to wait between HTTP request
80+
retries.
81+
:type retry_rate_limit_interval: Union[float, int]
82+
:param retry_max: The number of request retries that should be attempted before
83+
raising an API error.
84+
:type retry_max: int
85+
:type retry_statuses: List of int
86+
:param retry_statuses: Additional HTTP response statuses to retry on.
87+
By default, the client will retry on 408, 429, and 502
88+
responses.
89+
:param ca_path: The path to a CA file to use for API requests in this client.
90+
:type ca_path: str
91+
"""
92+
5693
def __init__(
5794
self,
5895
token,

linode_api4/objects/monitor.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"MonitorMetricsDefinition",
44
"MonitorService",
55
"MonitorServiceToken",
6+
"AggregateFunction",
67
]
78
from dataclasses import dataclass, field
89
from typing import List, Optional

linode_api4/objects/monitor_api.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
"EntityMetricsData",
44
"EntityMetricsDataResult",
55
"EntityMetricsStats",
6+
"EntityMetricOptions",
67
]
78
from dataclasses import dataclass, field
89
from typing import List, Optional
910

11+
from linode_api4.objects.monitor import AggregateFunction
1012
from linode_api4.objects.serializable import JSONObject
1113

1214

@@ -34,3 +36,9 @@ class EntityMetrics(JSONObject):
3436
isPartial: bool = False
3537
stats: Optional[EntityMetricsStats] = None
3638
status: str = ""
39+
40+
41+
@dataclass
42+
class EntityMetricOptions(JSONObject):
43+
name: str = ""
44+
aggregate_function: AggregateFunction = ""

test/integration/conftest.py

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,21 @@
55
from test.integration.helpers import (
66
get_test_label,
77
send_request_when_resource_available,
8+
wait_for_condition,
89
)
10+
from test.integration.models.database.helpers import get_db_engine_id
911
from typing import Optional, Set
1012

1113
import pytest
1214
import requests
1315
from requests.exceptions import ConnectionError, RequestException
1416

15-
from linode_api4 import PlacementGroupPolicy, PlacementGroupType
16-
from linode_api4.linode_client import LinodeClient
17+
from linode_api4 import (
18+
PlacementGroupPolicy,
19+
PlacementGroupType,
20+
PostgreSQLDatabase,
21+
)
22+
from linode_api4.linode_client import LinodeClient, MonitorClient
1723
from linode_api4.objects import Region
1824

1925
ENV_TOKEN_NAME = "LINODE_TOKEN"
@@ -521,3 +527,68 @@ def linode_for_vlan_tests(test_linode_client, e2e_test_firewall):
521527
yield linode_instance
522528

523529
linode_instance.delete()
530+
531+
532+
@pytest.fixture(scope="session")
533+
def test_create_postgres_db(test_linode_client):
534+
client = test_linode_client
535+
label = get_test_label() + "-postgresqldb"
536+
region = "us-ord"
537+
engine_id = get_db_engine_id(client, "postgresql")
538+
dbtype = "g6-standard-1"
539+
540+
db = client.database.postgresql_create(
541+
label=label,
542+
region=region,
543+
engine=engine_id,
544+
ltype=dbtype,
545+
cluster_size=None,
546+
)
547+
548+
def get_db_status():
549+
return db.status == "active"
550+
551+
# TAKES 15-30 MINUTES TO FULLY PROVISION DB
552+
wait_for_condition(60, 2000, get_db_status)
553+
554+
yield db
555+
556+
send_request_when_resource_available(300, db.delete)
557+
558+
559+
@pytest.fixture(scope="session")
560+
def get_monitor_token_for_db_entities(test_linode_client):
561+
client = test_linode_client
562+
563+
dbs = client.database.postgresql_instances()
564+
565+
if len(dbs) < 1:
566+
db_id = test_create_postgres_db.id
567+
else:
568+
db_id = dbs[0].id
569+
570+
region = client.load(PostgreSQLDatabase, db_id).region
571+
dbs = client.database.instances()
572+
573+
# only collect entity_ids in the same region
574+
entity_ids = [db.id for db in dbs if db.region == region]
575+
576+
# create token for the particular service
577+
token = client.monitor.create_token(
578+
service_type="dbaas", entity_ids=entity_ids
579+
)
580+
581+
yield token, entity_ids
582+
583+
584+
@pytest.fixture(scope="session")
585+
def test_monitor_client(get_monitor_token_for_db_entities):
586+
api_ca_file = get_api_ca_file()
587+
token, entity_ids = get_monitor_token_for_db_entities
588+
589+
client = MonitorClient(
590+
token.token,
591+
ca_path=api_ca_file,
592+
)
593+
594+
return client, entity_ids
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
def test_monitor_api_fetch_dbaas_metrics(test_monitor_client):
2+
client, entity_ids = test_monitor_client
3+
4+
metrics = client.metrics.fetch_metrics(
5+
"dbaas",
6+
entity_ids=entity_ids,
7+
metrics=[{"name": "read_iops", "aggregate_function": "avg"}],
8+
relative_time_duration={"unit": "hr", "value": 1},
9+
)
10+
11+
assert metrics.status == "success"
12+
assert len(metrics.data.result) > 0

test/unit/groups/monitor_api_test.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from test.unit.base import MonitorClientBaseCase
22

3+
from linode_api4.objects import AggregateFunction, EntityMetricOptions
4+
35

46
class MonitorAPITest(MonitorClientBaseCase):
57
"""
@@ -14,8 +16,11 @@ def test_fetch_metrics(self):
1416
service_type,
1517
entity_ids=[13217, 13316],
1618
metrics=[
17-
{"name": "avg_read_iops", "aggregate": "avg"},
18-
{"name": "avg_cpu_usage", "aggregate": "avg"},
19+
EntityMetricOptions(
20+
name="avg_read_iops",
21+
aggregate_function=AggregateFunction("avg"),
22+
),
23+
{"name": "avg_cpu_usage", "aggregate_function": "avg"},
1924
],
2025
relative_time_duration={"unit": "hr", "value": 1},
2126
)
@@ -25,8 +30,8 @@ def test_fetch_metrics(self):
2530
assert m.call_data == {
2631
"entity_ids": [13217, 13316],
2732
"metrics": [
28-
{"name": "avg_read_iops", "aggregate": "avg"},
29-
{"name": "avg_cpu_usage", "aggregate": "avg"},
33+
{"name": "avg_read_iops", "aggregate_function": "avg"},
34+
{"name": "avg_cpu_usage", "aggregate_function": "avg"},
3035
],
3136
"relative_time_duration": {"unit": "hr", "value": 1},
3237
}

0 commit comments

Comments
 (0)