This is an automated email from the ASF dual-hosted git repository.
ericholguin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
The following commit(s) were added to refs/heads/master by this push:
new 44183093f4 Added Api contract tests for origins and delivery_services
endpoints (#7529)
44183093f4 is described below
commit 44183093f436c0325e1e4d78e12f8b410cf5b96c
Author: Gokula Krishnan <[email protected]>
AuthorDate: Thu Jun 1 23:41:42 2023 +0530
Added Api contract tests for origins and delivery_services endpoints (#7529)
* Added Api contract tests for origins and delivery_services endpoints
* Addressed review comments
* updated code
* modified code
* Updated response template and added code to delete prerequisites data in
required TCs
---
traffic_ops/testing/api_contract/v4/conftest.py | 156 +++++--
.../api_contract/v4/data/request_template.json | 83 +++-
.../api_contract/v4/data/response_template.json | 514 ++++++++++++++++++++-
.../testing/api_contract/v4/test_cachegroups.py | 8 +-
traffic_ops/testing/api_contract/v4/test_cdns.py | 6 +-
.../api_contract/v4/test_delivery_services.py | 92 ++++
.../testing/api_contract/v4/test_divisions.py | 8 +-
.../testing/api_contract/v4/test_origins.py | 88 ++++
.../testing/api_contract/v4/test_parameters.py | 8 +-
.../testing/api_contract/v4/test_phys_locations.py | 13 +-
.../testing/api_contract/v4/test_profiles.py | 13 +-
.../testing/api_contract/v4/test_regions.py | 15 +-
traffic_ops/testing/api_contract/v4/test_roles.py | 8 +-
.../api_contract/v4/test_server_capabilities.py | 8 +-
.../testing/api_contract/v4/test_servers.py | 29 +-
.../testing/api_contract/v4/test_tenants.py | 8 +-
16 files changed, 954 insertions(+), 103 deletions(-)
diff --git a/traffic_ops/testing/api_contract/v4/conftest.py
b/traffic_ops/testing/api_contract/v4/conftest.py
index 4e61af218c..e42fa1ddd5 100644
--- a/traffic_ops/testing/api_contract/v4/conftest.py
+++ b/traffic_ops/testing/api_contract/v4/conftest.py
@@ -24,6 +24,7 @@ import os
from random import randint
from typing import Any, NamedTuple, Union, Optional, TypeAlias
from urllib.parse import urlparse
+import munch
import pytest
import requests
@@ -362,7 +363,7 @@ def response_template_data(pytestconfig: pytest.Config
def api_response_data(api_response: tuple[Union[Primitive, dict[str, object],
list[
Union[Primitive, dict[str, object], list[
- object]]]], requests.Response]) -> dict[str, object]:
+ object]]]], requests.Response], create_check: bool) ->
dict[str, object]:
"""
Checks API get/post response.
:param api_response: Raw api response.
@@ -371,14 +372,18 @@ def api_response_data(api_response:
tuple[Union[Primitive, dict[str, object], li
api_data = None
if isinstance(api_response, tuple):
api_response = api_response[0]
- if not isinstance(api_response, list):
- raise ValueError("Malformed API response; 'response'
property not an array")
+ if create_check and not isinstance(api_response, munch.Munch):
+ raise ValueError("Malformed API response; 'response'
property not an munch")
+ if not create_check and not isinstance(api_response, list):
+ raise ValueError("Malformed API response; 'response'
property not an list")
else:
raise ValueError("Invalid API response format")
if api_response:
try:
- api_data = api_response[0]
+ api_data = api_response
+ if not create_check:
+ api_data = api_response[0]
if not isinstance(api_data, dict):
raise ValueError("Malformed API response;
'response' property not a dict")
except IndexError as e:
@@ -399,7 +404,7 @@ def get_existing_object(to_session: TOSession, object_type:
str, query_params: O
api_get_response: tuple[Union[dict[str, object], list[
Union[dict[str, object], list[object], Primitive]], Primitive],
requests.Response] = getattr(
to_session, f"get_{object_type}")(query_params=query_params)
- return api_response_data(api_get_response)
+ return api_response_data(api_get_response, create_check = False)
def create_if_not_exists(to_session: TOSession, object_type: str,
@@ -414,7 +419,7 @@ def create_if_not_exists(to_session: TOSession,
object_type: str,
api_post_response: tuple[Union[dict[str, object], list[
Union[dict[str, object], list[object], Primitive]], Primitive],
requests.Response] = getattr(
to_session, f"create_{object_type}")(data=data)
- return api_response_data(api_post_response)
+ return api_response_data(api_post_response, create_check = True)
def create_or_get_existing(to_session: TOSession, get_object_type: str,
post_object_type: str, data:
@@ -451,8 +456,8 @@ def check_template_data(template_data:
Union[list[JSONData], tuple[JSONData, req
return endpoint
[email protected]()
-def cdn_post_data(to_session: TOSession, request_template_data: list[JSONData]
[email protected](name="cdn_post_data")
+def cdn_data_post(to_session: TOSession, request_template_data: list[JSONData]
) -> dict[str, object]:
"""
PyTest Fixture to create POST data for cdns endpoint.
@@ -587,9 +592,9 @@ def role_post_data(to_session: TOSession,
request_template_data: list[JSONData]
return resp_obj
[email protected]()
-def profile_post_data(to_session: TOSession, request_template_data:
list[JSONData]
- ) -> dict[str, object]:
[email protected](name="profile_post_data")
+def profile_data_post(to_session: TOSession, request_template_data:
list[JSONData],
+ cdn_post_data:dict[str, object]) -> dict[str, object]:
"""
PyTest Fixture to create POST data for profile endpoint.
@@ -609,9 +614,7 @@ def profile_post_data(to_session: TOSession,
request_template_data: list[JSONDat
raise TypeError(f"missing Profile property '{e.args[0]}'") from
e
# Check if cdn already exists, otherwise create it
- cdn_data = check_template_data(request_template_data["cdns"], "cdns")
- cdn_object = create_or_get_existing(to_session, "cdns", "cdn", cdn_data)
- profile["cdn"] = cdn_object["id"]
+ profile["cdn"] = cdn_post_data["id"]
logger.info("New profile data to hit POST method %s", profile)
# Hitting profile POST method
@@ -620,8 +623,8 @@ def profile_post_data(to_session: TOSession,
request_template_data: list[JSONDat
return resp_obj
[email protected]()
-def tenant_post_data(to_session: TOSession, request_template_data:
list[JSONData]
[email protected](name="tenant_post_data")
+def tenant_data_post(to_session: TOSession, request_template_data:
list[JSONData]
) -> dict[str, object]:
"""
PyTest Fixture to create POST data for tenants endpoint.
@@ -681,8 +684,8 @@ def server_capabilities_post_data(to_session: TOSession,
request_template_data:
return resp_obj
[email protected]()
-def division_post_data(to_session: TOSession, request_template_data:
list[JSONData]
[email protected](name="division_post_data")
+def division_data_post(to_session: TOSession, request_template_data:
list[JSONData]
) -> dict[str, object]:
"""
PyTest Fixture to create POST data for divisions endpoint.
@@ -712,8 +715,8 @@ def division_post_data(to_session: TOSession,
request_template_data: list[JSONDa
@pytest.fixture(name="region_post_data")
-def region_data_post(to_session: TOSession, request_template_data:
list[JSONData]
- ) -> dict[str, object]:
+def region_data_post(to_session: TOSession, request_template_data:
list[JSONData],
+ division_post_data: dict[str, object]) -> dict[str,
object]:
"""
PyTest Fixture to create POST data for region endpoint.
@@ -735,10 +738,8 @@ def region_data_post(to_session: TOSession,
request_template_data: list[JSONData
raise TypeError(f"missing Region property '{e.args[0]}'") from e
# Check if division already exists, otherwise create it
- division_data = check_template_data(request_template_data["divisions"],
"divisions")
- division_object = create_or_get_existing(to_session, "divisions",
"division", division_data)
- region["division"] = division_object["id"]
- region["divisionName"] = division_object["name"]
+ region["division"] = division_post_data["id"]
+ region["divisionName"] = division_post_data["name"]
logger.info("New region data to hit POST method %s",
request_template_data)
# Hitting region POST method
@@ -791,7 +792,8 @@ def phys_locations_data_post(to_session: TOSession,
request_template_data: list[
@pytest.fixture()
def server_post_data(to_session: TOSession, request_template_data:
list[JSONData],
- phys_locations_post_data: dict[str, object]) -> dict[str,
object]:
+ cdn_post_data: dict[str, object],
+ phys_locations_post_data: dict[str, object])-> dict[str,
object]:
"""
PyTest Fixture to create POST data for server endpoint.
@@ -801,6 +803,7 @@ def server_post_data(to_session: TOSession,
request_template_data: list[JSONData
:returns: Sample POST data and the actual API response.
"""
server = check_template_data(request_template_data["servers"],
"servers")
+ randstr = str(randint(0, 1000))
# Check if type already exists, otherwise create it
type_data = check_template_data(request_template_data["types"], "types")
@@ -816,15 +819,15 @@ def server_post_data(to_session: TOSession,
request_template_data: list[JSONData
server["cachegroupId"]= cache_group_object["id"]
# Check if cdn already exists, otherwise create it
- cdn_data = check_template_data(request_template_data["cdns"], "cdns")
- cdn_object = create_or_get_existing(to_session, "cdns", "cdn",
cdn_data, {"name": "CDN-in-a-Box"})
- server["cdnId"] = cdn_object["id"]
- server["domainName"] = cdn_object["domainName"]
+ server["cdnId"] = cdn_post_data["id"]
+ server["domainName"] = cdn_post_data["domainName"]
# Check if profile with cdn already exists, otherwise create it
profile_data = check_template_data(request_template_data["profiles"],
"profiles")
- profile_object = create_or_get_existing(to_session, "profiles",
"profile", profile_data,
- {"name": "test"})
+ profile_data["cdn"] = cdn_post_data["id"]
+ name = profile_data["name"]
+ profile_data["name"] = name[:4] + randstr
+ profile_object = create_if_not_exists(to_session, "profile",
profile_data)
server["profileNames"] = [profile_object["name"]]
# Check if status already exists, otherwise create it
@@ -843,8 +846,99 @@ def server_post_data(to_session: TOSession,
request_template_data: list[JSONData
# Hitting server POST method
response: tuple[JSONData, requests.Response] =
to_session.create_server(data=server)
resp_obj = check_template_data(response, "server")
+ return [resp_obj, profile_object["id"]]
+
+
[email protected](name="delivery_services_post_data")
+def delivery_services_data_post(to_session: TOSession, request_template_data:
list[JSONData],
+ profile_post_data: dict[str, object]
+ ) -> dict[str, object]:
+ """
+ PyTest Fixture to create POST data for server endpoint.
+ :param to_session: Fixture to get Traffic Ops session.
+ :param request_template_data: Fixture to get profile data from a
prerequisites file.
+ :returns: Sample POST data and the actual API response.
+ """
+ delivery_services = check_template_data(
+ request_template_data["delivery_services"], "delivery_services")
+
+ randstr = str(randint(0, 1000))
+ try:
+ xml_id = delivery_services["xmlId"]
+ if not isinstance(xml_id, str):
+ raise TypeError(f"xmlId must be str, not
'{type(xml_id)}'")
+ delivery_services["xmlId"] = xml_id[:4] + randstr
+ except KeyError as e:
+ raise TypeError(f"missing delivery_services property
'{e.args[0]}'") from e
+
+ # Check if profile with cdn already exists, otherwise create it
+ delivery_services["profileId"] = profile_post_data["id"]
+
+ # Check if cdn already exists, otherwise create it
+ delivery_services["cdnId"] = profile_post_data["cdn"]
+
+ # Check if tenant already exists, otherwise create it
+ tenant_data = check_template_data(request_template_data["tenants"],
"tenants")
+ tenant_object = create_or_get_existing(to_session, "tenants", "tenant",
+ tenant_data, {"name": "root"})
+ delivery_services["tenantId"] = tenant_object["id"]
+
+ # Check if type already exists, otherwise create it
+ type_data = {"name": "HTTP", "useInTable":"deliveryservice"}
+ type_object = create_or_get_existing(to_session, "types", "type",
type_data,
+ {"name": "HTTP",
"useInTable":"deliveryservice"})
+ delivery_services["typeId"] = type_object["id"]
+ delivery_services["type"] = type_object["name"]
+
+
+ logger.info("New delivery_services data to hit POST method %s",
delivery_services)
+ # Hitting delivery_services POST method
+ response: tuple[JSONData, requests.Response] =
to_session.create_deliveryservice(
+ data=delivery_services)
+ resp_obj = check_template_data(response[0], "delivery_services")
return resp_obj
+
[email protected]()
+def origin_post_data(to_session: TOSession, request_template_data:
list[JSONData],
+ delivery_services_post_data: dict[str, object],
tenant_post_data: dict[str, object]
+ ) -> dict[str, object]:
+ """
+ PyTest Fixture to create POST data for origins endpoint.
+ :param to_session: Fixture to get Traffic Ops session.
+ :param request_template_data: Fixture to get profile data from a
prerequisites file.
+ :returns: Sample POST data and the actual API response.
+ """
+ origin = check_template_data(request_template_data["origins"],
"origins")
+
+ randstr = str(randint(0, 1000))
+ try:
+ name = origin["name"]
+ if not isinstance(name, str):
+ raise TypeError(f"name must be str, not '{type(name)}'")
+ origin["name"] = name[:4] + randstr
+ except KeyError as e:
+ raise TypeError(f"missing origin property '{e.args[0]}'") from e
+
+ # Check if delivery_service already exists, otherwise create it
+ delivery_services_id = delivery_services_post_data["id"]
+ if not isinstance(delivery_services_id, int):
+ raise TypeError("malformed API response; 'id' property not a
integer")
+ origin["deliveryServiceId"] = delivery_services_id
+
+ # Check if tenant already exists, otherwise create it
+ tenant_id = tenant_post_data["id"]
+ if not isinstance(tenant_id, int):
+ raise TypeError("malformed API response; 'id' property not a
integer")
+ origin["tenantId"] = tenant_id
+
+ logger.info("New origin data to hit POST method %s", origin)
+ # Hitting origins POST method
+ response: tuple[JSONData, requests.Response] =
to_session.create_origins(data=origin)
+ resp_obj = check_template_data(response, "origins")
+ return resp_obj
+
+
@pytest.fixture()
def status_post_data(to_session: TOSession, request_template_data:
list[JSONData]
) -> dict[str, object]:
diff --git a/traffic_ops/testing/api_contract/v4/data/request_template.json
b/traffic_ops/testing/api_contract/v4/data/request_template.json
index da10040eae..a54f115edd 100644
--- a/traffic_ops/testing/api_contract/v4/data/request_template.json
+++ b/traffic_ops/testing/api_contract/v4/data/request_template.json
@@ -76,7 +76,7 @@
],
"regions": [
{
- "name": "Manchester",
+ "name": "test",
"division": "4",
"divisionName": "England"
}
@@ -134,5 +134,84 @@
"typeId": 96,
"updPending": false
}
+ ],
+ "delivery_services": [
+ {
+ "active": false,
+ "anonymousBlockingEnabled": false,
+ "ccrDnsTtl": null,
+ "cdnId": 2,
+ "checkPath": null,
+ "consistentHashRegex": null,
+ "consistentHashQueryParams": [],
+ "deepCachingType": "NEVER",
+ "displayName": "test",
+ "dnsBypassCname": null,
+ "dnsBypassIp": null,
+ "dnsBypassIp6": null,
+ "dnsBypassTtl": null,
+ "dscp": 0,
+ "ecsEnabled": true,
+ "edgeHeaderRewrite": null,
+ "firstHeaderRewrite": null,
+ "fqPacingRate": null,
+ "geoLimit": 0,
+ "geoLimitCountries": null,
+ "geoLimitRedirectUrl": null,
+ "geoProvider": 0,
+ "globalMaxMbps": null,
+ "globalMaxTps": null,
+ "httpBypassFqdn": null,
+ "infoUrl": null,
+ "initialDispersion": 1,
+ "innerHeaderRewrite": null,
+ "ipv6RoutingEnabled": false,
+ "lastHeaderRewrite": null,
+ "logsEnabled": true,
+ "longDesc": "A Delivery Service created expressly for
API documentation examples",
+ "maxDnsAnswers": null,
+ "missLat": 0,
+ "missLong": 0,
+ "maxOriginConnections": 0,
+ "maxRequestHeaderBytes": 131072,
+ "midHeaderRewrite": null,
+ "multiSiteOrigin": false,
+ "orgServerFqdn": "http://origin.infra.ciab.test",
+ "originShield": null,
+ "profileId": null,
+ "protocol": 0,
+ "qstringIgnore": 0,
+ "rangeRequestHandling": 0,
+ "regexRemap": null,
+ "regionalGeoBlocking": false,
+ "routingName": "test",
+ "serviceCategory": null,
+ "signed": false,
+ "signingAlgorithm": null,
+ "rangeSliceBlockSize": null,
+ "sslKeyVersion": null,
+ "tenant": "root",
+ "tenantId": 1,
+ "tlsVersions": [
+ "1.2",
+ "1.3"
+ ],
+ "topology": null,
+ "trRequestHeaders": null,
+ "trResponseHeaders": null,
+ "type": "HTTP",
+ "typeId": 1,
+ "xmlId": "test"
+ }
+ ],
+ "origins": [
+ {
+ "deliveryServiceId": 2,
+ "fqdn": "example.com",
+ "name": "test",
+ "port": 80,
+ "protocol": "http",
+ "tenantId": 1
+ }
]
-}
+}
\ No newline at end of file
diff --git a/traffic_ops/testing/api_contract/v4/data/response_template.json
b/traffic_ops/testing/api_contract/v4/data/response_template.json
index ecc4440235..cd94bcebd5 100644
--- a/traffic_ops/testing/api_contract/v4/data/response_template.json
+++ b/traffic_ops/testing/api_contract/v4/data/response_template.json
@@ -432,7 +432,10 @@
"type": "string"
},
"guid": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"hostName": {
"type": "string"
@@ -444,34 +447,61 @@
"type": "integer"
},
"iloIpAddress": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"iloIpGateway": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"iloIpNetmask": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"iloPassword": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"iloUsername": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"lastUpdated": {
"type": "string"
},
"mgmtIpAddress": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"mgmtIpGateway": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"mgmtIpNetmask": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"offlineReason": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"physLocation": {
"type": "string"
@@ -486,7 +516,10 @@
}
},
"rack": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"revalPending": {
"type": "boolean"
@@ -513,7 +546,10 @@
"type": "string"
},
"xmppPasswd": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"interfaces": {
"type": "array",
@@ -552,7 +588,10 @@
}
},
"maxBandwidth": {
- "type": "null"
+ "type": [
+ "null",
+ "integer"
+ ]
},
"monitor": {
"type": "boolean"
@@ -573,7 +612,10 @@
}
},
"statusLastUpdated": {
- "type": "null"
+ "type": [
+ "null",
+ "string"
+ ]
},
"configUpdateTime": {
"type": "string"
@@ -611,5 +653,447 @@
"type": "string"
}
}
+ },
+ "delivery_services": {
+ "type": "object",
+ "properties": {
+ "maxRequestHeaderBytes": {
+ "type": "integer"
+ },
+ "firstHeaderRewrite": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "innerHeaderRewrite": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "lastHeaderRewrite": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "serviceCategory": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "topology": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "ecsEnabled": {
+ "type": "boolean"
+ },
+ "rangeSliceBlockSize": {
+ "type": [
+ "null",
+ "integer"
+ ]
+ },
+ "consistentHashRegex": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "consistentHashQueryParams": {
+ "type": "array",
+ "items": {}
+ },
+ "maxOriginConnections": {
+ "type": "integer"
+ },
+ "deepCachingType": {
+ "type": "string"
+ },
+ "fqPacingRate": {
+ "type": [
+ "null",
+ "integer"
+ ]
+ },
+ "signingAlgorithm": {
+ "type": [
+ "null",
+ "boolean"
+ ]
+ },
+ "tenant": {
+ "type": "string"
+ },
+ "trResponseHeaders": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "trRequestHeaders": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "active": {
+ "type": "boolean"
+ },
+ "anonymousBlockingEnabled": {
+ "type": "boolean"
+ },
+ "ccrDnsTtl": {
+ "type": [
+ "null",
+ "integer"
+ ]
+ },
+ "cdnId": {
+ "type": "integer"
+ },
+ "cdnName": {
+ "type": "string"
+ },
+ "checkPath": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "displayName": {
+ "type": "string"
+ },
+ "dnsBypassCname": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "dnsBypassIp": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "dnsBypassIp6": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "dnsBypassTtl": {
+ "type": [
+ "null",
+ "integer"
+ ]
+ },
+ "dscp": {
+ "type": "integer"
+ },
+ "edgeHeaderRewrite": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "exampleURLs": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "geoLimit": {
+ "type": "integer"
+ },
+ "geoLimitRedirectURL": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "geoProvider": {
+ "type": "integer"
+ },
+ "globalMaxMbps": {
+ "type": [
+ "null",
+ "integer"
+ ]
+ },
+ "globalMaxTps": {
+ "type": [
+ "null",
+ "integer"
+ ]
+ },
+ "httpBypassFqdn": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "id": {
+ "type": "integer"
+ },
+ "infoUrl": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "initialDispersion": {
+ "type": "integer"
+ },
+ "ipv6RoutingEnabled": {
+ "type": "boolean"
+ },
+ "lastUpdated": {
+ "type": "string"
+ },
+ "logsEnabled": {
+ "type": "boolean"
+ },
+ "longDesc": {
+ "type": "string"
+ },
+ "matchList": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "setNumber": {
+ "type": "integer"
+ },
+ "pattern": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "maxDnsAnswers": {
+ "type": [
+ "null",
+ "integer"
+ ]
+ },
+ "midHeaderRewrite": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "missLat": {
+ "type": "integer"
+ },
+ "missLong": {
+ "type": "integer"
+ },
+ "multiSiteOrigin": {
+ "type": "boolean"
+ },
+ "originShield": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "orgServerFqdn": {
+ "type": "string"
+ },
+ "profileDescription": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "profileId": {
+ "type": [
+ "null",
+ "integer"
+ ]
+ },
+ "profileName": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "protocol": {
+ "type": "integer"
+ },
+ "qstringIgnore": {
+ "type": "integer"
+ },
+ "rangeRequestHandling": {
+ "type": "integer"
+ },
+ "regexRemap": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "regionalGeoBlocking": {
+ "type": "boolean"
+ },
+ "remapText": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "routingName": {
+ "type": "string"
+ },
+ "signed": {
+ "type": "boolean"
+ },
+ "sslKeyVersion": {
+ "type": [
+ "null",
+ "integer"
+ ]
+ },
+ "tenantId": {
+ "type": "integer"
+ },
+ "type": {
+ "type": "string"
+ },
+ "typeId": {
+ "type": "integer"
+ },
+ "xmlId": {
+ "type": "string"
+ },
+ "tlsVersions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "geoLimitCountries": {
+ "type": [
+ "null",
+ "array"
+ ]
+ }
+ }
+ },
+ "origins": {
+ "type": "object",
+ "required": [
+ "cachegroup",
+ "cachegroupId",
+ "coordinate",
+ "coordinateId",
+ "deliveryService",
+ "deliveryServiceId",
+ "fqdn",
+ "id",
+ "ip6Address",
+ "ipAddress",
+ "isPrimary",
+ "lastUpdated",
+ "name",
+ "port",
+ "profile",
+ "profileId",
+ "protocol",
+ "tenant",
+ "tenantId"
+ ],
+ "properties": {
+ "cachegroup": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "cachegroupId": {
+ "type": [
+ "integer",
+ "null"
+ ]
+ },
+ "coordinate": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "coordinateId": {
+ "type": [
+ "integer",
+ "null"
+ ]
+ },
+ "deliveryService": {
+ "type": "string"
+ },
+ "deliveryServiceId": {
+ "type": "integer"
+ },
+ "fqdn": {
+ "type": "string"
+ },
+ "id": {
+ "type": "integer"
+ },
+ "ip6Address": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "ipAddress": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "isPrimary": {
+ "type": "boolean"
+ },
+ "lastUpdated": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "port": {
+ "type": "integer"
+ },
+ "profile": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "profileId": {
+ "type": [
+ "integer",
+ "null"
+ ]
+ },
+ "protocol": {
+ "type": "string"
+ },
+ "tenant": {
+ "type": "string"
+ },
+ "tenantId": {
+ "type": "integer"
+ }
+ }
}
-}
+}
\ No newline at end of file
diff --git a/traffic_ops/testing/api_contract/v4/test_cachegroups.py
b/traffic_ops/testing/api_contract/v4/test_cachegroups.py
index b65a445ae5..d4cf6ceadb 100644
--- a/traffic_ops/testing/api_contract/v4/test_cachegroups.py
+++ b/traffic_ops/testing/api_contract/v4/test_cachegroups.py
@@ -60,7 +60,7 @@ def test_cache_group_contract(to_session: TOSession,
first_cache_group = cache_group_data[0]
if not isinstance(first_cache_group, dict):
- raise TypeError("malformed API response; first Cache
group in response is not an object")
+ raise TypeError("malformed API response; first Cache
group in response is not an dict")
logger.info("Cachegroup API get response %s", first_cache_group)
cache_group_response_template =
response_template_data.get("cachegroup")
@@ -77,9 +77,7 @@ def test_cache_group_contract(to_session: TOSession,
pytest.fail("API contract test failed for cachegroup endpoint:
API response was malformed")
finally:
# Delete Cache group after test execution to avoid redundancy.
- try:
- cache_group_id = cache_group_post_data["id"]
-
to_session.delete_cachegroups(cache_group_id=cache_group_id)
- except IndexError:
+ cache_group_id = cache_group_post_data.get("id")
+ if to_session.delete_cachegroups(cache_group_id=cache_group_id)
is None:
logger.error("Cachegroup returned by Traffic Ops is
missing an 'id' property")
pytest.fail("Response from delete request is empty,
Failing test_cachegroup_contract")
diff --git a/traffic_ops/testing/api_contract/v4/test_cdns.py
b/traffic_ops/testing/api_contract/v4/test_cdns.py
index 9901fab773..79691777ec 100644
--- a/traffic_ops/testing/api_contract/v4/test_cdns.py
+++ b/traffic_ops/testing/api_contract/v4/test_cdns.py
@@ -76,9 +76,7 @@ def test_cdn_contract(
pytest.fail("API contract test failed for cdn endpoint: API
response was malformed")
finally:
# Delete CDN after test execution to avoid redundancy.
- try:
- cdn_id = cdn_post_data["id"]
- to_session.delete_cdn_by_id(cdn_id=cdn_id)
- except IndexError:
+ cdn_id = cdn_post_data.get("id")
+ if to_session.delete_cdn_by_id(cdn_id=cdn_id) is None:
logger.error("CDN returned by Traffic Ops is missing an
'id' property")
pytest.fail("Response from delete request is empty,
Failing test_get_cdn")
diff --git a/traffic_ops/testing/api_contract/v4/test_delivery_services.py
b/traffic_ops/testing/api_contract/v4/test_delivery_services.py
new file mode 100644
index 0000000000..41e3963b5b
--- /dev/null
+++ b/traffic_ops/testing/api_contract/v4/test_delivery_services.py
@@ -0,0 +1,92 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""API Contract Test Case for delivery services endpoint."""
+import logging
+from typing import Union
+import pytest
+import requests
+from jsonschema import validate
+
+from trafficops.tosession import TOSession
+
+# Create and configure logger
+logger = logging.getLogger()
+
+Primitive = Union[bool, int, float, str, None]
+
+
+def test_delivery_services_contract(to_session: TOSession,
+ response_template_data: dict[str, Union[Primitive, list[Union[Primitive,
+ dict[str, object],
list[object]]], dict[object, object]]],
+ delivery_services_post_data: dict[str, object]
+) -> None:
+ """
+ Test step to validate keys, values and data types from
delivery_services endpoint
+ response.
+ :param to_session: Fixture to get Traffic Ops session.
+ :param response_template_data: Fixture to get response template data
from a prerequisites file.
+ :param delivery_services_post_data: Fixture to get sample delivery
service data and response.
+ """
+ # validate delivery services keys from api get response
+ logger.info("Accessing /delivery_services endpoint through Traffic ops
session.")
+
+ delivery_services_id = delivery_services_post_data["id"]
+ if not isinstance(delivery_services_id, int):
+ raise TypeError("malformed API response; 'id' property not a
integer")
+
+ delivery_services_get_response: tuple[
+ Union[dict[str, object], list[Union[dict[str, object],
list[object], Primitive]], Primitive],
+ requests.Response
+ ] = to_session.get_deliveryservices(query_params={"id":
delivery_services_id})
+ try:
+ delivery_services_data = delivery_services_get_response[0]
+ if not isinstance(delivery_services_data, list):
+ raise TypeError("malformed API response; 'response'
property not an array")
+
+ first_delivery_services = delivery_services_data[0]
+ if not isinstance(first_delivery_services, dict):
+ raise TypeError("malformed API response; first
delivery_services in response is not an dict")
+ logger.info("delivery_services Api response %s",
first_delivery_services)
+ delivery_services_response_template =
response_template_data.get("delivery_services")
+ if not isinstance(delivery_services_response_template, dict):
+ raise TypeError(f"delivery_services response template
data must be a dict, not '"
+
f"{type(delivery_services_response_template)}'")
+
+ keys = ["cdnId", "profileId", "type", "typeId", "tenantId",
"xmlId"]
+ prereq_values = [delivery_services_post_data[key] for key in
keys]
+ get_values = [first_delivery_services[key] for key in keys]
+
+ assert validate(instance=first_delivery_services,
+ schema=delivery_services_response_template) is None
+ assert get_values == prereq_values
+ except IndexError:
+ logger.error("Either prerequisite data or API response was
malformed")
+ pytest.fail("API contract test failed for delivery_services
endpoint: API response was malformed")
+ finally:
+ # Delete delivery_services after test execution to avoid
redundancy.
+ delivery_service_id = delivery_services_post_data.get("id")
+ if
to_session.delete_deliveryservice_by_id(delivery_service_id=delivery_service_id)
is None:
+ logger.error("delivery_services returned by Traffic Ops
is missing an 'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_delivery_services_contract")
+
+ profile_id = delivery_services_post_data.get("profileId")
+ if to_session.delete_profile_by_id(profile_id=profile_id) is
None:
+ logger.error("profile returned by Traffic Ops is
missing an 'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_delivery_services_contract")
+
+ cdn_id = delivery_services_post_data.get("cdnId")
+ if to_session.delete_cdn_by_id(cdn_id=cdn_id) is None:
+ logger.error("cdn returned by Traffic Ops is missing an
'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_delivery_services_contract")
diff --git a/traffic_ops/testing/api_contract/v4/test_divisions.py
b/traffic_ops/testing/api_contract/v4/test_divisions.py
index 7a464e7cc5..548a093222 100644
--- a/traffic_ops/testing/api_contract/v4/test_divisions.py
+++ b/traffic_ops/testing/api_contract/v4/test_divisions.py
@@ -56,7 +56,7 @@ def test_division_contract(to_session: TOSession,
first_division = division_data[0]
if not isinstance(first_division, dict):
- raise TypeError("malformed API response; first division
in response is not an object")
+ raise TypeError("malformed API response; first division
in response is not an dict")
logger.info("Division Api get response %s", first_division)
division_response_template =
response_template_data.get("divisions")
@@ -75,9 +75,7 @@ def test_division_contract(to_session: TOSession,
pytest.fail("Failed due to malformation")
finally:
# Delete division after test execution to avoid redundancy.
- try:
- division_id = division_post_data["id"]
- to_session.delete_division(division_id=division_id)
- except IndexError:
+ division_id = division_post_data.get("id")
+ if to_session.delete_division(division_id=division_id) is None:
logger.error("Division returned by Traffic Ops is
missing an 'id' property")
pytest.fail("Response from delete request is empty,
Failing test_get_division")
diff --git a/traffic_ops/testing/api_contract/v4/test_origins.py
b/traffic_ops/testing/api_contract/v4/test_origins.py
new file mode 100644
index 0000000000..0943b24b79
--- /dev/null
+++ b/traffic_ops/testing/api_contract/v4/test_origins.py
@@ -0,0 +1,88 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""API Contract Test Case for origins endpoint."""
+import logging
+from typing import Union
+
+import pytest
+import requests
+from jsonschema import validate
+
+from trafficops.tosession import TOSession
+
+# Create and configure logger
+logger = logging.getLogger()
+
+Primitive = Union[bool, int, float, str, None]
+
+
+def test_origin_contract(
+ to_session: TOSession,
+ response_template_data: dict[str, Union[Primitive, list[Union[Primitive,
+ dict[str, object],
list[object]]], dict[object, object]]],
+ origin_post_data: dict[str, object]
+) -> None:
+ """
+ Test step to validate keys, values and data types from origins endpoint
+ response.
+ :param to_session: Fixture to get Traffic Ops session.
+ :param response_template_data: Fixture to get response template data
from a prerequisites file.
+ :param origin_post_data: Fixture to get sample server data and actual
origin response.
+ """
+ # validate origin keys from origin get response
+ logger.info("Accessing /origins endpoint through Traffic ops session.")
+
+ origin_id = origin_post_data.get("id")
+ if not isinstance(origin_id, int):
+ raise TypeError("malformed API response; 'id' property not a
integer")
+
+ origin_get_response: tuple[
+ Union[dict[str, object], list[dict[str, object] | list[object]
| Primitive], Primitive],
+ requests.Response
+ ] = to_session.get_origins(query_params={"id": origin_id})
+ try:
+ origin_data = origin_get_response[0]
+ if not isinstance(origin_data, list):
+ raise TypeError("malformed API response; 'response'
property not an array")
+
+ first_origin = origin_data[0]
+ if not isinstance(first_origin, dict):
+ raise TypeError("malformed API response; first origin
in response is not an dict")
+ logger.info("origin Api get response %s", first_origin)
+ origin_response_template = response_template_data.get("origins")
+ if not isinstance(origin_response_template, dict):
+ raise TypeError(
+ f"origin response template data must be a dict,
not '{type(origin_response_template)}'")
+
+ keys = ["deliveryServiceId", "fqdn", "name", "port",
"protocol", "tenantId"]
+ prereq_values = [origin_post_data[key] for key in keys]
+ get_values = [first_origin[key] for key in keys]
+
+ assert validate(instance=first_origin,
schema=origin_response_template) is None
+ assert get_values == prereq_values
+ except IndexError:
+ logger.error("Either prerequisite data or API response was
malformed")
+ pytest.fail("API contract test failed for origin endpoint: API
response was malformed")
+ finally:
+ # Delete origin after test execution to avoid redundancy.
+ origin_id = origin_post_data.get("id")
+ if to_session.delete_origins(query_params={"id": origin_id}) is
None:
+ logger.error("Origin returned by Traffic Ops is missing
an 'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_origin_contract")
+
+ delivery_service_id = origin_post_data.get("deliveryServiceId")
+ if
to_session.delete_deliveryservice_by_id(delivery_service_id=delivery_service_id)
is None:
+ logger.error("Delivery service returned by Traffic Ops
is missing an 'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_origin_contract")
diff --git a/traffic_ops/testing/api_contract/v4/test_parameters.py
b/traffic_ops/testing/api_contract/v4/test_parameters.py
index 62935d5e20..2cff807ed8 100644
--- a/traffic_ops/testing/api_contract/v4/test_parameters.py
+++ b/traffic_ops/testing/api_contract/v4/test_parameters.py
@@ -57,7 +57,7 @@ def test_parameter_contract(to_session: TOSession,
first_parameter = parameter_data[0]
if not isinstance(first_parameter, dict):
- raise TypeError("malformed API response; first
Parameter in response is not an object")
+ raise TypeError("malformed API response; first
Parameter in response is not an dict")
logger.info("Parameter Api get response %s", first_parameter)
parameter_response_template =
response_template_data.get("parameters")
@@ -78,9 +78,7 @@ def test_parameter_contract(to_session: TOSession,
pytest.fail("API contract test failed for cdn endpoint: API
response was malformed")
finally:
# Delete Parameter after test execution to avoid redundancy.
- try:
- parameter_id = parameter_post_data["id"]
- to_session.delete_parameter(parameter_id=parameter_id)
- except IndexError:
+ parameter_id = parameter_post_data.get("id")
+ if to_session.delete_parameter(parameter_id=parameter_id) is
None:
logger.error("Parameter returned by Traffic Ops is
missing an 'id' property")
pytest.fail("Response from delete request is empty,
Failing test_parameter_contract")
diff --git a/traffic_ops/testing/api_contract/v4/test_phys_locations.py
b/traffic_ops/testing/api_contract/v4/test_phys_locations.py
index f6894864dc..ab32a602c9 100644
--- a/traffic_ops/testing/api_contract/v4/test_phys_locations.py
+++ b/traffic_ops/testing/api_contract/v4/test_phys_locations.py
@@ -57,7 +57,7 @@ def test_phys_locations_contract(to_session: TOSession,
first_phys_location = phys_location_data[0]
if not isinstance(first_phys_location, dict):
- raise TypeError("malformed API response; first
phys_location in response is not an object")
+ raise TypeError("malformed API response; first
phys_location in response is not an dict")
logger.info("phys_location Api response %s",
first_phys_location)
phys_location_response_template =
response_template_data.get("phys_locations")
@@ -79,9 +79,12 @@ def test_phys_locations_contract(to_session: TOSession,
pytest.fail("API contract test failed for phys_locations
endpoint: API response was malformed")
finally:
# Delete phys_location after test execution to avoid redundancy.
- try:
- physical_location_id = phys_locations_post_data["id"]
-
to_session.delete_physical_location(physical_location_id=physical_location_id)
- except IndexError:
+ physical_location_id = phys_locations_post_data["id"]
+ if
to_session.delete_physical_location(physical_location_id=physical_location_id)
is None:
logger.error("phys_location returned by Traffic Ops is
missing an 'id' property")
pytest.fail("Response from delete request is empty,
Failing test_get_phys_location")
+
+ region_id = phys_locations_post_data["regionId"]
+ if to_session.delete_region(query_params={"id": region_id}) is
None:
+ logger.error("Region returned by Traffic Ops is missing
an 'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_get_phys_location")
diff --git a/traffic_ops/testing/api_contract/v4/test_profiles.py
b/traffic_ops/testing/api_contract/v4/test_profiles.py
index 67e124645a..6745bcf8d0 100644
--- a/traffic_ops/testing/api_contract/v4/test_profiles.py
+++ b/traffic_ops/testing/api_contract/v4/test_profiles.py
@@ -56,7 +56,7 @@ def test_profile_contract(to_session: TOSession,
first_profile = profile_data[0]
if not isinstance(first_profile, dict):
- raise TypeError("malformed API response; first Profile
in response is not an object")
+ raise TypeError("malformed API response; first Profile
in response is not an dict")
logger.info("Profile Api get response %s", first_profile)
profile_response_template =
response_template_data.get("profiles")
@@ -75,9 +75,12 @@ def test_profile_contract(to_session: TOSession,
pytest.fail("API contract test failed for cdn endpoint: API
response was malformed")
finally:
# Delete Profile after test execution to avoid redundancy.
- try:
- profile_id = profile_post_data["id"]
- to_session.delete_profile_by_id(profile_id=profile_id)
- except IndexError:
+ profile_id = profile_post_data.get("id")
+ if to_session.delete_profile_by_id(profile_id=profile_id) is
None:
logger.error("Profile returned by Traffic Ops is
missing an 'id' property")
pytest.fail("Response from delete request is empty,
Failing test_profile_contract")
+
+ cdn_id = profile_post_data.get("cdn")
+ if to_session.delete_cdn_by_id(cdn_id=cdn_id) is None:
+ logger.error("Cdn returned by Traffic Ops is missing an
'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_profile_contract")
diff --git a/traffic_ops/testing/api_contract/v4/test_regions.py
b/traffic_ops/testing/api_contract/v4/test_regions.py
index 7a0a6fb795..49fd985bd9 100644
--- a/traffic_ops/testing/api_contract/v4/test_regions.py
+++ b/traffic_ops/testing/api_contract/v4/test_regions.py
@@ -29,7 +29,7 @@ Primitive = Union[bool, int, float, str, None]
def test_region_contract(to_session: TOSession,
- response_template_data: dict[str, Union[Primitive,
list[Union[Primitive,
+ response_template_data: dict[str, Union[Primitive, list[Union[Primitive,
dict[str, object], list[object]]], dict[object, object]]],
region_post_data: dict[str, object]
) -> None:
@@ -57,7 +57,7 @@ def test_region_contract(to_session: TOSession,
first_region = region_data[0]
if not isinstance(first_region, dict):
- raise TypeError("malformed API response; first region
in response is not an object")
+ raise TypeError("malformed API response; first region
in response is not an dict")
logger.info("Region Api response %s", first_region)
region_response_template = response_template_data.get("regions")
@@ -78,9 +78,12 @@ def test_region_contract(to_session: TOSession,
pytest.fail("API contract test failed for regions endpoint: API
response was malformed")
finally:
# Delete region after test execution to avoid redundancy.
- try:
- region_name = region_post_data["name"]
- to_session.delete_region(query_params={"name":
region_name})
- except IndexError:
+ region_name = region_post_data.get("name")
+ if to_session.delete_region(query_params={"name": region_name})
is None:
logger.error("region returned by Traffic Ops is missing
a 'name' property")
pytest.fail("Response from delete request is empty,
Failing test_region_contract")
+
+ division_id = region_post_data.get("division")
+ if to_session.delete_division(division_id=division_id) is None:
+ logger.error("division returned by Traffic Ops is
missing a 'name' property")
+ pytest.fail("Response from delete request is empty,
Failing test_region_contract")
diff --git a/traffic_ops/testing/api_contract/v4/test_roles.py
b/traffic_ops/testing/api_contract/v4/test_roles.py
index 79b4bda342..16ba345e16 100644
--- a/traffic_ops/testing/api_contract/v4/test_roles.py
+++ b/traffic_ops/testing/api_contract/v4/test_roles.py
@@ -57,7 +57,7 @@ def test_role_contract(to_session: TOSession,
first_role = role_data[0]
if not isinstance(first_role, dict):
- raise TypeError("malformed API response; first role in
response is not an object")
+ raise TypeError("malformed API response; first role in
response is not an dict")
logger.info("Role Api get response %s", first_role)
role_response_template = response_template_data.get("roles")
@@ -77,9 +77,7 @@ def test_role_contract(to_session: TOSession,
pytest.fail("API contract test failed for roles endpoint: API
response was malformed")
finally:
# Delete Role after test execution to avoid redundancy.
- try:
- role_name = role_post_data["name"]
- to_session.delete_role(query_params={"name": role_name})
- except IndexError:
+ role_name = role_post_data.get("name")
+ if to_session.delete_role(query_params={"name": role_name}) is
None:
logger.error("Role returned by Traffic Ops is missing
an 'name' property")
pytest.fail("Response from delete request is empty,
Failing test_role_contract")
diff --git a/traffic_ops/testing/api_contract/v4/test_server_capabilities.py
b/traffic_ops/testing/api_contract/v4/test_server_capabilities.py
index 59066d7302..adaa064c09 100644
--- a/traffic_ops/testing/api_contract/v4/test_server_capabilities.py
+++ b/traffic_ops/testing/api_contract/v4/test_server_capabilities.py
@@ -58,7 +58,7 @@ def test_server_capabilities_contract(to_session: TOSession,
first_server_capabilities = server_capabilities_data[0]
if not isinstance(first_server_capabilities, dict):
- raise TypeError("malformed API response; first
server_capabilities in response is not an object")
+ raise TypeError("malformed API response; first
server_capabilities in response is not an dict")
logger.info("Server capabilities Api get response %s",
first_server_capabilities)
response_template =
response_template_data.get("server_capabilities")
@@ -75,9 +75,7 @@ def test_server_capabilities_contract(to_session: TOSession,
pytest.fail("API contract test failed for server_capabilities:
API response was malformed")
finally:
# Delete server_capabilities after test execution to avoid
redundancy.
- try:
- server_capability_name =
server_capabilities_post_data["name"]
-
to_session.delete_server_capabilities(query_params={"name":
server_capability_name})
- except IndexError:
+ server_capability_name =
server_capabilities_post_data.get("name")
+ if to_session.delete_server_capabilities(query_params={"name":
server_capability_name}) is None:
logger.error("server_capabilities returned by Traffic
Ops is missing an 'id' property")
pytest.fail("Response from delete request is empty,
Failing test_server_capabilities_contract")
diff --git a/traffic_ops/testing/api_contract/v4/test_servers.py
b/traffic_ops/testing/api_contract/v4/test_servers.py
index 37d7245cfd..51c0eed475 100644
--- a/traffic_ops/testing/api_contract/v4/test_servers.py
+++ b/traffic_ops/testing/api_contract/v4/test_servers.py
@@ -41,6 +41,8 @@ def test_server_contract(to_session: TOSession,
"""
# validate server keys from server get response
logger.info("Accessing /servers endpoint through Traffic ops session.")
+ profile_id = server_post_data[1]
+ server_post_data = server_post_data[0]
server_id = server_post_data.get("id")
if not isinstance(server_id, int):
@@ -57,7 +59,7 @@ def test_server_contract(to_session: TOSession,
first_server = server_data[0]
if not isinstance(first_server, dict):
- raise TypeError("malformed API response; first Server
in response is not an object")
+ raise TypeError("malformed API response; first Server
in response is not an dict")
logger.info("Server Api get response %s", first_server)
server_response_template = response_template_data.get("servers")
if not isinstance(server_response_template, dict):
@@ -76,9 +78,26 @@ def test_server_contract(to_session: TOSession,
pytest.fail("API contract test failed for server endpoint: API
response was malformed")
finally:
# Delete Server after test execution to avoid redundancy.
- try:
- server_id = server_post_data["id"]
- to_session.delete_server_by_id(server_id=server_id)
- except IndexError:
+ server_id = server_post_data.get("id")
+ if to_session.delete_server_by_id(server_id=server_id) is None:
+ logger.error("Server returned by Traffic Ops is missing
an 'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_server_contract")
+
+ cachegroup_id = server_post_data.get("cachegroupId")
+ if to_session.delete_cachegroups(cache_group_id=cachegroup_id)
is None:
+ logger.error("cachegroup returned by Traffic Ops is
missing an 'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_server_contract")
+
+ if to_session.delete_profile_by_id(profile_id=profile_id) is
None:
logger.error("Profile returned by Traffic Ops is
missing an 'id' property")
pytest.fail("Response from delete request is empty,
Failing test_server_contract")
+
+ cdn_id = server_post_data.get("cdnId")
+ if to_session.delete_cdn_by_id(cdn_id=cdn_id) is None:
+ logger.error("Cdn returned by Traffic Ops is missing an
'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_server_contract")
+
+ phys_loc_id = server_post_data.get("physLocationId")
+ if
to_session.delete_physical_location(physical_location_id=phys_loc_id) is None:
+ logger.error("Physical location returned by Traffic Ops
is missing an 'id' property")
+ pytest.fail("Response from delete request is empty,
Failing test_server_contract")
diff --git a/traffic_ops/testing/api_contract/v4/test_tenants.py
b/traffic_ops/testing/api_contract/v4/test_tenants.py
index ee643b693b..eaaae253ee 100644
--- a/traffic_ops/testing/api_contract/v4/test_tenants.py
+++ b/traffic_ops/testing/api_contract/v4/test_tenants.py
@@ -57,7 +57,7 @@ def test_tenant_contract(to_session: TOSession,
first_tenant = tenant_data[0]
if not isinstance(first_tenant, dict):
- raise TypeError("malformed API response; first tenant
in response is not an object")
+ raise TypeError("malformed API response; first tenant
in response is not an dict")
logger.info("Tenant Api get response %s", first_tenant)
tenant_response_template = response_template_data.get("tenants")
@@ -78,9 +78,7 @@ def test_tenant_contract(to_session: TOSession,
pytest.fail("API contract test failed for tenants endpoint: API
response was malformed")
finally:
# Delete tenant after test execution to avoid redundancy.
- try:
- tenant_id = tenant_post_data["id"]
- to_session.delete_tenant(tenant_id=tenant_id)
- except IndexError:
+ tenant_id = tenant_post_data.get("id")
+ if to_session.delete_tenant(tenant_id=tenant_id) is None:
logger.error("Tenant returned by Traffic Ops is missing
an 'id' property")
pytest.fail("Response from delete request is empty,
Failing test_tenant_contract")