Skip to content

Commit 912dd93

Browse files
georgebocthpierce
andauthored
Adds contract test for CREATE DATABASE for MySQL (#215)
*Issue #, if available:* N/A *Description of changes:* Adding MySQL contract tests for app signals to ensure that customer experience doesn't break with any change. The new contract test covers the CREATE DATABASE SQL command. It also takes the opportunity to refactor the code in common with [the PostgreSQL contract tests](https://github.com/aws-observability/aws-otel-python-instrumentation/blob/main/contract-tests/tests/test/amazon/psycopg2/psycopg2_test.py) to avoid code duplication. Contract tests running successfully: ``` $ ./scripts/build_and_install_distro.sh ... $ ./scripts/set-up-contract-tests.sh ... $ pytest contract-tests/tests ============================= test session starts ============================== platform linux -- Python 3.8.11, pytest-7.1.3, pluggy-1.5.0 rootdir: /local/home/gbochile/aws-otel-python-instrumentation/contract-tests/tests, configfile: pyproject.toml plugins: cov-4.1.0, flaky-3.7.0 collected 39 items contract-tests/tests/test/amazon/psycopg2/psycopg2_test.py::Psycopg2Test::test_create_database_succeeds -------------------------------- live log setup -------------------------------- 2024-06-20 14:55:44 [ INFO] Pulling image aws-application-signals-mock-collector-python (container.py:53) 2024-06-20 14:55:45 [ INFO] Container started: d9689f28b345 (container.py:64) 2024-06-20 14:55:46 [ INFO] Pulling image postgres:latest (container.py:53) 2024-06-20 14:55:46 [ INFO] Container started: 23e433c8ee6e (container.py:64) 2024-06-20 14:55:46 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:55:46 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:55:47 [ INFO] Waiting to be ready... (waiting_utils.py:46) -------------------------------- live log call --------------------------------- 2024-06-20 14:55:47 [ INFO] Pulling image aws-application-signals-tests-psycopg2-app (container.py:53) 2024-06-20 14:55:48 [ INFO] Container started: 68f62688d322 (container.py:64) 2024-06-20 14:55:54 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:55:54 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:55:54 [ INFO] Application stdout (contract_test_base.py:118) 2024-06-20 14:55:54 [ INFO] Ready (contract_test_base.py:119) 2024-06-20 14:55:54 [ INFO] Application stderr (contract_test_base.py:120) 2024-06-20 14:55:54 [ INFO] Failed to get k8s token: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' AwsEcsResourceDetector failed: Missing ECS_CONTAINER_METADATA_URI therefore process is not on ECS. AwsEksResourceDetector failed: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' Exception in detector <opentelemetry.sdk.extension.aws.resource.ec2.AwsEc2ResourceDetector object at 0x7f2938bc3730>, ignoring AwsEc2ResourceDetector failed: timed out Configuration of configurator not loaded, aws_configurator already loaded (contract_test_base.py:121) PASSED [ 71%] contract-tests/tests/test/amazon/psycopg2/psycopg2_test.py::Psycopg2Test::test_drop_table_succeeds -------------------------------- live log call --------------------------------- 2024-06-20 14:55:55 [ INFO] Pulling image aws-application-signals-tests-psycopg2-app (container.py:53) 2024-06-20 14:55:55 [ INFO] Container started: 38c2e2937827 (container.py:64) 2024-06-20 14:56:01 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:01 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:02 [ INFO] Application stdout (contract_test_base.py:118) 2024-06-20 14:56:02 [ INFO] Ready (contract_test_base.py:119) 2024-06-20 14:56:02 [ INFO] Application stderr (contract_test_base.py:120) 2024-06-20 14:56:02 [ INFO] Failed to get k8s token: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' AwsEcsResourceDetector failed: Missing ECS_CONTAINER_METADATA_URI therefore process is not on ECS. AwsEksResourceDetector failed: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' Exception in detector <opentelemetry.sdk.extension.aws.resource.ec2.AwsEc2ResourceDetector object at 0x7fa54b22f790>, ignoring AwsEc2ResourceDetector failed: timed out Configuration of configurator not loaded, aws_configurator already loaded (contract_test_base.py:121) PASSED [ 74%] contract-tests/tests/test/amazon/psycopg2/psycopg2_test.py::Psycopg2Test::test_fault -------------------------------- live log call --------------------------------- 2024-06-20 14:56:02 [ INFO] Pulling image aws-application-signals-tests-psycopg2-app (container.py:53) 2024-06-20 14:56:03 [ INFO] Container started: 2df7a0957e52 (container.py:64) 2024-06-20 14:56:09 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:09 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:09 [ INFO] Application stdout (contract_test_base.py:118) 2024-06-20 14:56:09 [ INFO] Ready Expected Exception with Invalid SQL occurred: relation "invalid_table" does not exist LINE 1: SELECT DISTINCT id, name FROM invalid_table ^ (contract_test_base.py:119) 2024-06-20 14:56:09 [ INFO] Application stderr (contract_test_base.py:120) 2024-06-20 14:56:09 [ INFO] Failed to get k8s token: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' AwsEksResourceDetector failed: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' AwsEcsResourceDetector failed: Missing ECS_CONTAINER_METADATA_URI therefore process is not on ECS. Exception in detector <opentelemetry.sdk.extension.aws.resource.ec2.AwsEc2ResourceDetector object at 0x7f4a5f0e77f0>, ignoring AwsEc2ResourceDetector failed: timed out Configuration of configurator not loaded, aws_configurator already loaded (contract_test_base.py:121) PASSED [ 76%] ... contract-tests/tests/test/amazon/pymysql/pymysql_test.py::PyMysqlTest::test_create_database_succeeds -------------------------------- live log setup -------------------------------- 2024-06-20 14:56:11 [ INFO] Pulling image aws-application-signals-mock-collector-python (container.py:53) 2024-06-20 14:56:12 [ INFO] Container started: 593e6565ee45 (container.py:64) 2024-06-20 14:56:13 [ INFO] Pulling image mysql:latest (container.py:53) 2024-06-20 14:56:13 [ INFO] Container started: 5e44c6384697 (container.py:64) 2024-06-20 14:56:13 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:13 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:14 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:15 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:17 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:18 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:19 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:20 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:21 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:22 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:23 [ INFO] Waiting to be ready... (waiting_utils.py:46) -------------------------------- live log call --------------------------------- 2024-06-20 14:56:23 [ INFO] Pulling image aws-application-signals-tests-pymysql-app (container.py:53) 2024-06-20 14:56:24 [ INFO] Container started: 518b7ef0c507 (container.py:64) 2024-06-20 14:56:30 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:30 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:30 [ INFO] Application stdout (contract_test_base.py:118) 2024-06-20 14:56:30 [ INFO] Ready (contract_test_base.py:119) 2024-06-20 14:56:30 [ INFO] Application stderr (contract_test_base.py:120) 2024-06-20 14:56:30 [ INFO] Failed to get k8s token: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' AwsEcsResourceDetector failed: Missing ECS_CONTAINER_METADATA_URI therefore process is not on ECS. AwsEksResourceDetector failed: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' Exception in detector <opentelemetry.sdk.extension.aws.resource.ec2.AwsEc2ResourceDetector object at 0x7fbfc92c7ac0>, ignoring AwsEc2ResourceDetector failed: timed out Configuration of configurator not loaded, aws_configurator already loaded (contract_test_base.py:121) PASSED [ 79%] contract-tests/tests/test/amazon/pymysql/pymysql_test.py::PyMysqlTest::test_drop_table_succeeds -------------------------------- live log call --------------------------------- 2024-06-20 14:56:31 [ INFO] Pulling image aws-application-signals-tests-pymysql-app (container.py:53) 2024-06-20 14:56:31 [ INFO] Container started: 079eaf40b262 (container.py:64) 2024-06-20 14:56:37 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:37 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:38 [ INFO] Application stdout (contract_test_base.py:118) 2024-06-20 14:56:38 [ INFO] Ready (contract_test_base.py:119) 2024-06-20 14:56:38 [ INFO] Application stderr (contract_test_base.py:120) 2024-06-20 14:56:38 [ INFO] Failed to get k8s token: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' AwsEcsResourceDetector failed: Missing ECS_CONTAINER_METADATA_URI therefore process is not on ECS. AwsEksResourceDetector failed: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' Exception in detector <opentelemetry.sdk.extension.aws.resource.ec2.AwsEc2ResourceDetector object at 0x7fc21bf53a00>, ignoring AwsEc2ResourceDetector failed: timed out Configuration of configurator not loaded, aws_configurator already loaded (contract_test_base.py:121) PASSED [ 82%] contract-tests/tests/test/amazon/pymysql/pymysql_test.py::PyMysqlTest::test_fault -------------------------------- live log call --------------------------------- 2024-06-20 14:56:38 [ INFO] Pulling image aws-application-signals-tests-pymysql-app (container.py:53) 2024-06-20 14:56:39 [ INFO] Container started: 1e5f0eaf1238 (container.py:64) 2024-06-20 14:56:45 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:45 [ INFO] Waiting to be ready... (waiting_utils.py:46) 2024-06-20 14:56:45 [ INFO] Application stdout (contract_test_base.py:118) 2024-06-20 14:56:45 [ INFO] Ready Expected Exception with Invalid SQL occurred: (1146, "Table 'testdb.invalid_table' doesn't exist") (contract_test_base.py:119) 2024-06-20 14:56:45 [ INFO] Application stderr (contract_test_base.py:120) 2024-06-20 14:56:45 [ INFO] Failed to get k8s token: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' AwsEcsResourceDetector failed: Missing ECS_CONTAINER_METADATA_URI therefore process is not on ECS. AwsEksResourceDetector failed: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token' Exception in detector <opentelemetry.sdk.extension.aws.resource.ec2.AwsEc2ResourceDetector object at 0x7f4b2a841420>, ignoring AwsEc2ResourceDetector failed: timed out Configuration of configurator not loaded, aws_configurator already loaded (contract_test_base.py:121) PASSED [ 84%] ... ======================== 39 passed in 363.85s (0:06:03) ======================== ``` By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. --------- Co-authored-by: Thomas Pierce <[email protected]>
1 parent 65cf8e3 commit 912dd93

File tree

11 files changed

+226
-257
lines changed

11 files changed

+226
-257
lines changed

contract-tests/images/applications/botocore/botocore_server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import requests
1111
from botocore.client import BaseClient
1212
from botocore.config import Config
13-
from typing_extensions import override
13+
from typing_extensions import Tuple, override
1414

1515
_PORT: int = 8080
1616
_ERROR: str = "error"
@@ -253,7 +253,7 @@ def prepare_aws_server() -> None:
253253

254254
def main() -> None:
255255
prepare_aws_server()
256-
server_address: tuple[str, int] = ("0.0.0.0", _PORT)
256+
server_address: Tuple[str, int] = ("0.0.0.0", _PORT)
257257
request_handler_class: type = RequestHandler
258258
requests_server: ThreadingHTTPServer = ThreadingHTTPServer(server_address, request_handler_class)
259259
atexit.register(requests_server.shutdown)

contract-tests/images/applications/pymysql/pymysql_server.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
import pymysql
1010
from typing_extensions import override
1111

12-
_PORT: int = 8080
13-
_SUCCESS: str = "success"
12+
_CREATE_DATABASE: str = "create_database"
13+
_DROP_TABLE: str = "drop_table"
1414
_ERROR: str = "error"
1515
_FAULT: str = "fault"
16+
_PORT: int = 8080
1617

1718
_DB_HOST = os.getenv("DB_HOST")
1819
_DB_USER = os.getenv("DB_USER")
@@ -26,11 +27,17 @@ class RequestHandler(BaseHTTPRequestHandler):
2627
def do_GET(self):
2728
status_code: int = 200
2829
conn = pymysql.connect(host=_DB_HOST, user=_DB_USER, password=_DB_PASS, database=_DB_NAME)
29-
if self.in_path(_SUCCESS):
30+
conn.autocommit = True # CREATE DATABASE cannot run in a transaction block
31+
if self.in_path(_DROP_TABLE):
3032
cur = conn.cursor()
3133
cur.execute("DROP TABLE IF EXISTS test_table")
3234
cur.close()
3335
status_code = 200
36+
elif self.in_path(_CREATE_DATABASE):
37+
cur = conn.cursor()
38+
cur.execute("CREATE DATABASE test_database")
39+
cur.close()
40+
status_code = 200
3441
elif self.in_path(_FAULT):
3542
cur = conn.cursor()
3643
try:

contract-tests/tests/test/amazon/base/contract_test_base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ def get_application_extra_environment_variables(self) -> Dict[str, str]:
193193
def get_application_network_aliases(self) -> List[str]:
194194
return []
195195

196-
def get_application_image_name(self) -> str:
196+
@staticmethod
197+
def get_application_image_name() -> str:
197198
return None
198199

199200
def get_application_wait_pattern(self) -> str:
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
from typing import Dict, List
4+
5+
from mock_collector_client import ResourceScopeMetric, ResourceScopeSpan
6+
from typing_extensions import override
7+
8+
from amazon.base.contract_test_base import ContractTestBase
9+
from amazon.utils.application_signals_constants import (
10+
AWS_LOCAL_OPERATION,
11+
AWS_LOCAL_SERVICE,
12+
AWS_REMOTE_OPERATION,
13+
AWS_REMOTE_RESOURCE_IDENTIFIER,
14+
AWS_REMOTE_RESOURCE_TYPE,
15+
AWS_REMOTE_SERVICE,
16+
AWS_SPAN_KIND,
17+
)
18+
from opentelemetry.proto.common.v1.common_pb2 import AnyValue, KeyValue
19+
from opentelemetry.proto.metrics.v1.metrics_pb2 import ExponentialHistogramDataPoint, Metric
20+
from opentelemetry.proto.trace.v1.trace_pb2 import Span
21+
from opentelemetry.trace import StatusCode
22+
23+
DATABASE_HOST: str = "mydb"
24+
DATABASE_USER: str = "root"
25+
DATABASE_PASSWORD: str = "example"
26+
DATABASE_NAME: str = "testdb"
27+
28+
29+
class DatabaseContractTestBase(ContractTestBase):
30+
@staticmethod
31+
def get_remote_service() -> str:
32+
return None
33+
34+
@staticmethod
35+
def get_database_port() -> int:
36+
return None
37+
38+
def get_remote_resource_identifier(self) -> str:
39+
return f"{DATABASE_NAME}|{DATABASE_HOST}|{self.get_database_port()}"
40+
41+
@override
42+
def get_application_extra_environment_variables(self) -> Dict[str, str]:
43+
return {
44+
"DB_HOST": DATABASE_HOST,
45+
"DB_USER": DATABASE_USER,
46+
"DB_PASS": DATABASE_PASSWORD,
47+
"DB_NAME": DATABASE_NAME,
48+
}
49+
50+
def assert_drop_table_succeeds(self) -> None:
51+
self.mock_collector_client.clear_signals()
52+
self.do_test_requests("drop_table", "GET", 200, 0, 0, sql_command="DROP TABLE")
53+
54+
def assert_create_database_succeeds(self) -> None:
55+
self.mock_collector_client.clear_signals()
56+
self.do_test_requests("create_database", "GET", 200, 0, 0, sql_command="CREATE DATABASE")
57+
58+
def assert_fault(self) -> None:
59+
self.mock_collector_client.clear_signals()
60+
self.do_test_requests("fault", "GET", 500, 0, 1, sql_command="SELECT DISTINCT")
61+
62+
@override
63+
def _assert_aws_span_attributes(self, resource_scope_spans: List[ResourceScopeSpan], path: str, **kwargs) -> None:
64+
target_spans: List[Span] = []
65+
for resource_scope_span in resource_scope_spans:
66+
# pylint: disable=no-member
67+
if resource_scope_span.span.kind == Span.SPAN_KIND_CLIENT:
68+
target_spans.append(resource_scope_span.span)
69+
70+
self.assertEqual(len(target_spans), 1)
71+
self._assert_aws_attributes(target_spans[0].attributes, **kwargs)
72+
73+
@override
74+
def _assert_semantic_conventions_span_attributes(
75+
self, resource_scope_spans: List[ResourceScopeSpan], method: str, path: str, status_code: int, **kwargs
76+
) -> None:
77+
target_spans: List[Span] = []
78+
for resource_scope_span in resource_scope_spans:
79+
# pylint: disable=no-member
80+
if resource_scope_span.span.kind == Span.SPAN_KIND_CLIENT:
81+
target_spans.append(resource_scope_span.span)
82+
83+
self.assertEqual(target_spans[0].name, kwargs.get("sql_command").split()[0])
84+
if status_code == 200:
85+
self.assertEqual(target_spans[0].status.code, StatusCode.UNSET.value)
86+
else:
87+
self.assertEqual(target_spans[0].status.code, StatusCode.ERROR.value)
88+
89+
self._assert_semantic_conventions_attributes(target_spans[0].attributes, kwargs.get("sql_command"))
90+
91+
def _assert_semantic_conventions_attributes(self, attributes_list: List[KeyValue], command: str) -> None:
92+
attributes_dict: Dict[str, AnyValue] = self._get_attributes_dict(attributes_list)
93+
self.assertTrue(attributes_dict.get("db.statement").string_value.startswith(command))
94+
self._assert_str_attribute(attributes_dict, "db.system", self.get_remote_service())
95+
self._assert_str_attribute(attributes_dict, "db.name", DATABASE_NAME)
96+
self._assert_str_attribute(attributes_dict, "net.peer.name", DATABASE_HOST)
97+
self._assert_int_attribute(attributes_dict, "net.peer.port", self.get_database_port())
98+
self.assertTrue("server.address" not in attributes_dict)
99+
self.assertTrue("server.port" not in attributes_dict)
100+
self.assertTrue("db.operation" not in attributes_dict)
101+
102+
@override
103+
def _assert_aws_attributes(self, attributes_list: List[KeyValue], **kwargs) -> None:
104+
attributes_dict: Dict[str, AnyValue] = self._get_attributes_dict(attributes_list)
105+
self._assert_str_attribute(attributes_dict, AWS_LOCAL_SERVICE, self.get_application_otel_service_name())
106+
# InternalOperation as OTEL does not instrument the basic server we are using, so the client span is a local
107+
# root.
108+
self._assert_str_attribute(attributes_dict, AWS_LOCAL_OPERATION, "InternalOperation")
109+
self._assert_str_attribute(attributes_dict, AWS_REMOTE_SERVICE, self.get_remote_service())
110+
self._assert_str_attribute(attributes_dict, AWS_REMOTE_OPERATION, kwargs.get("sql_command"))
111+
self._assert_str_attribute(attributes_dict, AWS_REMOTE_RESOURCE_TYPE, "DB::Connection")
112+
self._assert_str_attribute(
113+
attributes_dict, AWS_REMOTE_RESOURCE_IDENTIFIER, self.get_remote_resource_identifier()
114+
)
115+
# See comment above AWS_LOCAL_OPERATION
116+
self._assert_str_attribute(attributes_dict, AWS_SPAN_KIND, "LOCAL_ROOT")
117+
118+
@override
119+
def _assert_metric_attributes(
120+
self, resource_scope_metrics: List[ResourceScopeMetric], metric_name: str, expected_sum: int, **kwargs
121+
) -> None:
122+
target_metrics: List[Metric] = []
123+
for resource_scope_metric in resource_scope_metrics:
124+
if resource_scope_metric.metric.name.lower() == metric_name.lower():
125+
target_metrics.append(resource_scope_metric.metric)
126+
127+
self.assertEqual(len(target_metrics), 1)
128+
target_metric: Metric = target_metrics[0]
129+
dp_list: List[ExponentialHistogramDataPoint] = target_metric.exponential_histogram.data_points
130+
131+
self.assertEqual(len(dp_list), 2)
132+
dependency_dp: ExponentialHistogramDataPoint = dp_list[0]
133+
service_dp: ExponentialHistogramDataPoint = dp_list[1]
134+
if len(dp_list[1].attributes) > len(dp_list[0].attributes):
135+
dependency_dp = dp_list[1]
136+
service_dp = dp_list[0]
137+
attribute_dict: Dict[str, AnyValue] = self._get_attributes_dict(dependency_dp.attributes)
138+
self._assert_str_attribute(attribute_dict, AWS_LOCAL_SERVICE, self.get_application_otel_service_name())
139+
# See comment on AWS_LOCAL_OPERATION in _assert_aws_attributes
140+
self._assert_str_attribute(attribute_dict, AWS_LOCAL_OPERATION, "InternalOperation")
141+
self._assert_str_attribute(attribute_dict, AWS_REMOTE_SERVICE, self.get_remote_service())
142+
self._assert_str_attribute(attribute_dict, AWS_REMOTE_OPERATION, kwargs.get("sql_command"))
143+
self._assert_str_attribute(attribute_dict, AWS_REMOTE_RESOURCE_TYPE, "DB::Connection")
144+
self._assert_str_attribute(
145+
attribute_dict, AWS_REMOTE_RESOURCE_IDENTIFIER, self.get_remote_resource_identifier()
146+
)
147+
self._assert_str_attribute(attribute_dict, AWS_SPAN_KIND, "CLIENT")
148+
self.check_sum(metric_name, dependency_dp.sum, expected_sum)
149+
150+
attribute_dict: Dict[str, AnyValue] = self._get_attributes_dict(service_dp.attributes)
151+
# See comment on AWS_LOCAL_OPERATION in _assert_aws_attributes
152+
self._assert_str_attribute(attribute_dict, AWS_LOCAL_OPERATION, "InternalOperation")
153+
self._assert_str_attribute(attribute_dict, AWS_SPAN_KIND, "LOCAL_ROOT")
154+
self.check_sum(metric_name, service_dp.sum, expected_sum)

contract-tests/tests/test/amazon/botocore/botocore_test.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ def get_application_network_aliases(self) -> List[str]:
4949
return ["error.test", "fault.test"]
5050

5151
@override
52-
def get_application_image_name(self) -> str:
52+
@staticmethod
53+
def get_application_image_name() -> str:
5354
return "aws-application-signals-tests-botocore-app"
5455

5556
@classmethod

contract-tests/tests/test/amazon/django/django_test.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
class DjangoTest(ContractTestBase):
1717
@override
18-
def get_application_image_name(self) -> str:
18+
@staticmethod
19+
def get_application_image_name() -> str:
1920
return "aws-application-signals-tests-django-app"
2021

2122
@override

contract-tests/tests/test/amazon/misc/configuration_test.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717

1818
class ConfigurationTest(ContractTestBase):
1919
@override
20-
def get_application_image_name(self) -> str:
20+
@staticmethod
21+
def get_application_image_name() -> str:
2122
return "aws-application-signals-tests-django-app"
2223

2324
@override

contract-tests/tests/test/amazon/misc/resource_attributes_test_base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ def _get_k8s_attributes():
3030

3131
class ResourceAttributesTest(ContractTestBase):
3232
@override
33-
def get_application_image_name(self) -> str:
33+
@staticmethod
34+
def get_application_image_name() -> str:
3435
return "aws-application-signals-tests-django-app"
3536

3637
@override

0 commit comments

Comments
 (0)