Compare commits

...

2 Commits
4.2.0 ... main

Author SHA1 Message Date
Kevin Han
75929e93d0
Feat: Add core integration test mock server support (#165)
Some checks failed
Python CI / build (push) Has been cancelled
* CP-2453 Add core test mock server and exception status mapping

Move the integration mock server into test-only sdk_test_support helpers
and expose ApiException.exception_class_for_http_status for generated
integration error assertions.

Co-authored-by: Cursor <cursoragent@cursor.com>

* add test for validating OAS not match case

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 15:41:13 +01:00
Miguel Pragosa
7e7c1c4c0a
[GitHub Bot] Generated python SDK (#164)
Some checks failed
Python CI / build (push) Has been cancelled
Co-authored-by: API Team <api-team@thousandeyes.com>
2026-07-23 12:14:38 +01:00
40 changed files with 698 additions and 44 deletions

View File

@ -12,7 +12,7 @@ This API provides the following operations to manage your organization:
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -5,7 +5,7 @@ Manage Cloud and Enterprise Agents available to your account in ThousandEyes.
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -14,7 +14,7 @@ For more information about the alerts, see [Alerts](https://docs.thousandeyes.co
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -10,7 +10,7 @@ For more information about monitors, see [Inside-Out BGP Visibility](https://doc
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -6,7 +6,7 @@ Manage connectors and operations.
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -14,7 +14,7 @@
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
from typing import Any, Optional from typing import Any, Optional, Type
from typing_extensions import Self from typing_extensions import Self
@ -135,6 +135,22 @@ class ApiException(OpenApiException):
pass pass
self.headers = http_resp.getheaders() self.headers = http_resp.getheaders()
@classmethod
def exception_class_for_http_status(cls, status: int) -> Type["ApiException"]:
if status == 400:
return BadRequestException
if status == 401:
return UnauthorizedException
if status == 403:
return ForbiddenException
if status == 404:
return NotFoundException
if status == 429:
return TooManyRequestsException
if 500 <= status <= 599:
return ServiceException
return ApiException
@classmethod @classmethod
def from_response( def from_response(
cls, cls,
@ -143,24 +159,8 @@ class ApiException(OpenApiException):
body: Optional[str], body: Optional[str],
data: Optional[Any], data: Optional[Any],
) -> Self: ) -> Self:
if http_resp.status == 400: exc_class = cls.exception_class_for_http_status(http_resp.status)
raise BadRequestException(http_resp=http_resp, body=body, data=data) raise exc_class(http_resp=http_resp, body=body, data=data)
if http_resp.status == 401:
raise UnauthorizedException(http_resp=http_resp, body=body, data=data)
if http_resp.status == 403:
raise ForbiddenException(http_resp=http_resp, body=body, data=data)
if http_resp.status == 404:
raise NotFoundException(http_resp=http_resp, body=body, data=data)
if http_resp.status == 429:
raise TooManyRequestsException(http_resp=http_resp, body=body, data=data)
if 500 <= http_resp.status <= 599:
raise ServiceException(http_resp=http_resp, body=body, data=data)
raise ApiException(http_resp=http_resp, body=body, data=data)
def __str__(self): def __str__(self):
"""Custom error messages for exception""" """Custom error messages for exception"""

View File

@ -0,0 +1,6 @@
import sys
from pathlib import Path
_core_test_support = Path(__file__).resolve().parent
if str(_core_test_support) not in sys.path:
sys.path.insert(0, str(_core_test_support))

View File

@ -0,0 +1 @@
# Test-only helpers for SDK integration tests. Not shipped in the published package.

View File

@ -0,0 +1,228 @@
# Copyright 2024 Cisco Systems, Inc. and its affiliates
#
# 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.
#
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
import json
import re
import threading
from datetime import datetime
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from typing import Any, Dict, Mapping, Optional
from urllib.parse import urlparse
from sdk_test_support.mock_server_types import OperationExpectation
OPERATION_ID_HEADER = "X-TE-Operation-Id"
ERROR_STATUS_HEADER = "X-TE-Error-Status"
AUTHORIZATION_HEADER = "Authorization"
def _normalize_scalar(value: Any) -> Any:
if isinstance(value, str) and "T" in value:
try:
return datetime.fromisoformat(value.replace("Z", "+00:00")).isoformat().replace("+00:00", "Z")
except ValueError:
return value
return value
def _normalize_json(value: Any) -> Any:
if isinstance(value, dict):
return {key: _normalize_json(value[key]) for key in sorted(value.keys())}
if isinstance(value, list):
return [_normalize_json(item) for item in value]
return _normalize_scalar(value)
def _json_body_matches(expected: Any, actual: Any) -> bool:
if isinstance(expected, dict) and isinstance(actual, dict):
for key in actual:
if key not in expected:
return False
if not _json_body_matches(expected[key], actual[key]):
return False
return True
if isinstance(expected, list) and isinstance(actual, list):
if len(expected) != len(actual):
return False
return all(_json_body_matches(expected_item, actual_item)
for expected_item, actual_item in zip(expected, actual))
return _normalize_json(expected) == _normalize_json(actual)
class MockApiServer:
def __init__(self, manifest: Mapping[str, OperationExpectation], host: str = "127.0.0.1", port: int = 0):
self._manifest = dict(manifest)
self._host = host
self._port = port
self._server: Optional[ThreadingHTTPServer] = None
self._thread: Optional[threading.Thread] = None
@property
def base_url(self) -> str:
if self._server is None:
raise RuntimeError("MockApiServer has not been started")
return f"http://{self._host}:{self._server.server_port}"
def start(self) -> None:
if self._server is not None:
return
manifest = self._manifest
handler = _build_handler(manifest)
self._server = ThreadingHTTPServer((self._host, self._port), handler)
self._thread = threading.Thread(target=self._server.serve_forever, daemon=True)
self._thread.start()
def stop(self) -> None:
if self._server is None:
return
self._server.shutdown()
self._server.server_close()
if self._thread is not None:
self._thread.join(timeout=5)
self._server = None
self._thread = None
def __enter__(self) -> "MockApiServer":
self.start()
return self
def __exit__(self, exc_type, exc, tb) -> None:
self.stop()
def _build_handler(manifest: Mapping[str, OperationExpectation]):
class MockApiRequestHandler(BaseHTTPRequestHandler):
def log_message(self, format: str, *args) -> None:
return
def do_GET(self) -> None:
self._handle_request("GET")
def do_POST(self) -> None:
self._handle_request("POST")
def do_PUT(self) -> None:
self._handle_request("PUT")
def do_PATCH(self) -> None:
self._handle_request("PATCH")
def do_DELETE(self) -> None:
self._handle_request("DELETE")
def _handle_request(self, method: str) -> None:
auth_error = _validate_authorization(self.headers.get(AUTHORIZATION_HEADER))
if auth_error is not None:
self._write_json(auth_error, 401)
return
operation_id = self.headers.get(OPERATION_ID_HEADER)
if not operation_id:
self._write_json({"detail": f"Missing required header {OPERATION_ID_HEADER}"}, 400)
return
expectation = manifest.get(operation_id)
if expectation is None:
self._write_json({"detail": f"Unknown operation id {operation_id}"}, 400)
return
if expectation.method.upper() != method.upper():
self._write_json(
{"detail": f"Unexpected HTTP method {method} for operation {operation_id}"},
400,
)
return
parsed = urlparse(self.path)
if not _path_matches(expectation.path, parsed.path):
self._write_json({"detail": "Path does not match operation expectation"}, 400)
return
error_status_header = self.headers.get(ERROR_STATUS_HEADER)
if error_status_header:
self._handle_error_response(expectation, error_status_header)
return
body_bytes = _read_body(self)
if expectation.request_body_example is not None:
if not body_bytes:
self._write_json({"detail": "Expected request body"}, 400)
return
try:
request_json = json.loads(body_bytes.decode("utf-8"))
except json.JSONDecodeError:
self._write_json({"detail": "Invalid JSON request body"}, 400)
return
if not _json_body_matches(expectation.request_body_example, request_json):
self._write_json({"detail": "Request body does not match OAS example"}, 400)
return
if expectation.success_body is None:
self.send_response(expectation.success_status)
self.end_headers()
return
self._write_json(
expectation.success_body,
expectation.success_status,
expectation.success_content_type,
)
def _handle_error_response(self, expectation: OperationExpectation, error_status_header: str) -> None:
error_response = expectation.error_responses.get(error_status_header)
if error_response is None:
self._write_json(
{"detail": f"No configured error response for status {error_status_header}"},
400,
)
return
if error_response.body is None:
self.send_response(error_response.status)
self.end_headers()
return
self._write_json(error_response.body, error_response.status, error_response.content_type)
def _write_json(self, body: Any, status: int, content_type: str = "application/json") -> None:
payload = json.dumps(body).encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", content_type)
self.send_header("Content-Length", str(len(payload)))
self.end_headers()
self.wfile.write(payload)
return MockApiRequestHandler
def _validate_authorization(value: Optional[str]) -> Optional[Dict[str, str]]:
if value is None or not value.strip():
return {"detail": f"Missing or empty required header {AUTHORIZATION_HEADER}"}
return None
def _read_body(handler: BaseHTTPRequestHandler) -> bytes:
length = handler.headers.get("Content-Length")
if not length:
return b""
return handler.rfile.read(int(length))
def _path_matches(template: str, actual_path: str) -> bool:
pattern = re.sub(r"\{[^/]+\}", r"[^/]+", template)
pattern = f"^{pattern}$"
return re.match(pattern, actual_path) is not None

View File

@ -0,0 +1,41 @@
# Copyright 2024 Cisco Systems, Inc. and its affiliates
#
# 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.
#
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Dict
@dataclass(frozen=True)
class ErrorResponseExpectation:
status: int
body: Any
content_type: str = "application/problem+json"
@dataclass(frozen=True)
class OperationExpectation:
operation_id: str
method: str
path: str
success_status: int
success_body: Any = None
success_content_type: str = "application/json"
request_body_example: Any = None
path_param_examples: Dict[str, str] = field(default_factory=dict)
query_param_examples: Dict[str, str] = field(default_factory=dict)
error_responses: Dict[str, ErrorResponseExpectation] = field(default_factory=dict)

View File

@ -0,0 +1,28 @@
import pytest
from thousandeyes_sdk.core.exceptions import (
ApiException,
BadRequestException,
ForbiddenException,
NotFoundException,
ServiceException,
TooManyRequestsException,
UnauthorizedException,
)
@pytest.mark.parametrize(
("status", "expected"),
[
(400, BadRequestException),
(401, UnauthorizedException),
(403, ForbiddenException),
(404, NotFoundException),
(429, TooManyRequestsException),
(500, ServiceException),
(503, ServiceException),
(418, ApiException),
],
)
def test_exception_class_for_http_status(status, expected):
assert ApiException.exception_class_for_http_status(status) is expected

View File

@ -0,0 +1,315 @@
import json
import pytest
from sdk_test_support.mock_server import (
AUTHORIZATION_HEADER,
ERROR_STATUS_HEADER,
OPERATION_ID_HEADER,
MockApiServer,
)
from sdk_test_support.mock_server_types import ErrorResponseExpectation, OperationExpectation
@pytest.fixture
def manifest():
return {
"createAlertRule": OperationExpectation(
operation_id="createAlertRule",
method="POST",
path="/alerts/rules",
request_body_example={"ruleName": "Example"},
success_status=201,
success_body={"ruleId": "1"},
error_responses={
"400": ErrorResponseExpectation(
status=400,
body={"title": "Bad Request", "status": 400},
)
},
),
"deleteAlertRule": OperationExpectation(
operation_id="deleteAlertRule",
method="DELETE",
path="/alerts/rules/{ruleId}",
path_param_examples={"ruleId": "127094"},
success_status=204,
success_body=None,
),
"getAlertRule": OperationExpectation(
operation_id="getAlertRule",
method="GET",
path="/alerts/rules/{ruleId}",
path_param_examples={"ruleId": "127094"},
success_status=200,
success_body={"ruleId": "127094", "ruleName": "Example"},
),
}
def _request(server: MockApiServer, *, method: str, path: str, headers=None, body=None):
import urllib.request
request_headers = {
AUTHORIZATION_HEADER: "Bearer test-token",
OPERATION_ID_HEADER: "createAlertRule",
}
if headers:
request_headers.update(headers)
data = None
if body is not None:
data = json.dumps(body).encode("utf-8")
request_headers["Content-Type"] = "application/json"
request = urllib.request.Request(
server.base_url + path,
data=data,
headers=request_headers,
method=method,
)
try:
with urllib.request.urlopen(request) as response:
return response.status, response.read()
except urllib.error.HTTPError as exc:
return exc.code, exc.read()
def test_mock_server_happy_path(manifest):
with MockApiServer(manifest) as server:
status, body = _request(
server,
method="POST",
path="/alerts/rules",
body={"ruleName": "Example"},
)
assert status == 201
assert json.loads(body.decode("utf-8")) == {"ruleId": "1"}
def test_mock_server_rejects_missing_authorization(manifest):
with MockApiServer(manifest) as server:
status, _ = _request(
server,
method="POST",
path="/alerts/rules",
headers={AUTHORIZATION_HEADER: ""},
body={"ruleName": "Example"},
)
assert status == 401
def test_mock_server_rejects_invalid_request_body(manifest):
with MockApiServer(manifest) as server:
status, _ = _request(
server,
method="POST",
path="/alerts/rules",
body={"ruleName": "Wrong"},
)
assert status == 400
def test_mock_server_error_path(manifest):
with MockApiServer(manifest) as server:
status, body = _request(
server,
method="POST",
path="/alerts/rules",
headers={ERROR_STATUS_HEADER: "400"},
body={"unexpected": True},
)
assert status == 400
assert json.loads(body.decode("utf-8"))["title"] == "Bad Request"
def test_mock_server_ignores_readonly_fields_in_expected_body(manifest):
readonly_manifest = {
**manifest,
"createAlertRule": OperationExpectation(
operation_id="createAlertRule",
method="POST",
path="/alerts/rules",
request_body_example={"ruleName": "Example", "ruleId": "read-only"},
success_status=201,
success_body={"ruleId": "1"},
),
}
with MockApiServer(readonly_manifest) as server:
status, body = _request(
server,
method="POST",
path="/alerts/rules",
body={"ruleName": "Example"},
)
assert status == 201
assert json.loads(body.decode("utf-8")) == {"ruleId": "1"}
def test_mock_server_no_content_response(manifest):
with MockApiServer(manifest) as server:
import urllib.request
request = urllib.request.Request(
server.base_url + "/alerts/rules/127094",
headers={
AUTHORIZATION_HEADER: "Bearer test-token",
OPERATION_ID_HEADER: "deleteAlertRule",
},
method="DELETE",
)
with urllib.request.urlopen(request) as response:
assert response.status == 204
assert response.read() == b""
def test_mock_server_matches_path_variable(manifest):
with MockApiServer(manifest) as server:
status, body = _request(
server,
method="GET",
path="/alerts/rules/127094",
headers={OPERATION_ID_HEADER: "getAlertRule"},
)
assert status == 200
assert json.loads(body.decode("utf-8")) == {"ruleId": "127094", "ruleName": "Example"}
def test_mock_server_rejects_path_missing_path_variable(manifest):
with MockApiServer(manifest) as server:
status, body = _request(
server,
method="GET",
path="/alerts/rules",
headers={OPERATION_ID_HEADER: "getAlertRule"},
)
assert status == 400
assert json.loads(body.decode("utf-8"))["detail"] == "Path does not match operation expectation"
def test_mock_server_accepts_equivalent_iso8601_datetime_formats(manifest):
datetime_manifest = {
**manifest,
"createAlertRule": OperationExpectation(
operation_id="createAlertRule",
method="POST",
path="/alerts/rules",
request_body_example={
"ruleName": "Example",
"startDate": "2017-07-01T05:00:00Z",
},
success_status=201,
success_body={"ruleId": "1"},
),
}
with MockApiServer(datetime_manifest) as server:
status, body = _request(
server,
method="POST",
path="/alerts/rules",
body={
"ruleName": "Example",
"startDate": "2017-07-01T05:00:00+00:00",
},
)
assert status == 201
assert json.loads(body.decode("utf-8")) == {"ruleId": "1"}
def test_mock_server_ignores_readonly_fields_in_nested_request_objects(manifest):
nested_manifest = {
**manifest,
"createAlertRule": OperationExpectation(
operation_id="createAlertRule",
method="POST",
path="/alerts/rules",
request_body_example={
"ruleName": "Example",
"widgets": [
{
"title": "Widget Title",
"id": "read-only-id",
"embedUrl": "https://example.com/embed",
}
],
},
success_status=201,
success_body={"ruleId": "1"},
),
}
with MockApiServer(nested_manifest) as server:
status, body = _request(
server,
method="POST",
path="/alerts/rules",
body={
"ruleName": "Example",
"widgets": [{"title": "Widget Title"}],
},
)
assert status == 201
assert json.loads(body.decode("utf-8")) == {"ruleId": "1"}
def test_integration_error_assertion_fails_when_deserialized_error_does_not_match_oas_example():
"""Generated error-path tests compare ApiException.data to the OAS error example."""
import unittest
import urllib.error
import urllib.request
from pydantic import BaseModel, ConfigDict
class Error(BaseModel):
title: str
status: int
model_config = ConfigDict(extra="allow")
def to_json(self) -> str:
return self.model_dump_json()
mismatched_manifest = {
"createAlertRule": OperationExpectation(
operation_id="createAlertRule",
method="POST",
path="/alerts/rules",
request_body_example={"ruleName": "Example"},
success_status=201,
success_body={"ruleId": "1"},
error_responses={
"400": ErrorResponseExpectation(
status=400,
body={"title": "Wrong Title", "status": 400},
)
},
),
}
oas_example = {"title": "Bad Request", "status": 400}
with MockApiServer(mismatched_manifest) as server:
request = urllib.request.Request(
server.base_url + "/alerts/rules",
data=json.dumps({"unexpected": True}).encode("utf-8"),
headers={
AUTHORIZATION_HEADER: "Bearer test-token",
OPERATION_ID_HEADER: "createAlertRule",
ERROR_STATUS_HEADER: "400",
"Content-Type": "application/json",
},
method="POST",
)
with pytest.raises(urllib.error.HTTPError) as http_error:
urllib.request.urlopen(request)
wire_body = json.loads(http_error.value.read().decode("utf-8"))
exception_data = Error.model_validate(wire_body)
def assert_constructed_model_matches_example_json(model, loaded_json):
test_case = unittest.TestCase()
test_case.assertEqual(
json.dumps(loaded_json, sort_keys=True),
json.dumps(json.loads(model.to_json()), sort_keys=True),
)
with pytest.raises(AssertionError):
assert_constructed_model_matches_example_json(exception_data, oas_example)

View File

@ -13,7 +13,7 @@ For more information about credentials, see [Working With Secure Credentials](ht
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -3,7 +3,7 @@ Manage ThousandEyes Dashboards.
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -11,7 +11,7 @@ To access Emulation API operations, the following permissions are required:
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -7,7 +7,7 @@ For more information about Endpoint Agents, see [Endpoint Agents](https://docs.t
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -30,6 +30,7 @@ class Platform(str, Enum):
PHONEOS = 'phoneos' PHONEOS = 'phoneos'
ELUX = 'elux' ELUX = 'elux'
CISCO_MINUS_WIRELESS = 'cisco-wireless' CISCO_MINUS_WIRELESS = 'cisco-wireless'
CISCO_MINUS_WIRELESS_MINUS_CLOUD = 'cisco-wireless-cloud'
LINUX = 'linux' LINUX = 'linux'
MAC = 'mac' MAC = 'mac'
ANDROID = 'android' ANDROID = 'android'

View File

@ -12,7 +12,7 @@ The URLs for these API test data endpoints are provided within the test definiti
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -4,7 +4,7 @@ Manage labels applied to endpoint agents using this API.
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -3,7 +3,7 @@ Retrieve results for scheduled and dynamic tests on endpoint agents.
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -6,6 +6,7 @@
Name | Type | Description | Notes Name | Type | Description | Notes
------------ | ------------- | ------------- | ------------- ------------ | ------------- | ------------- | -------------
**results** | [**List[HttpEndpointTestResult]**](HttpEndpointTestResult.md) | | [optional] **results** | [**List[HttpEndpointTestResult]**](HttpEndpointTestResult.md) | | [optional]
**total_hits** | **int** | Total number of measurements that match the search criteria. | [optional]
**test** | [**EndpointHttpServerTest**](EndpointHttpServerTest.md) | | [optional] **test** | [**EndpointHttpServerTest**](EndpointHttpServerTest.md) | | [optional]
**start_date** | **datetime** | (Optional) When passing &#x60;window&#x60; or &#x60;startDate&#x60; parameter, the client will also receive the &#x60;startDate&#x60; field indicating the UTC start date of the data&#39;s time range being retrieved (ISO date-time format). | [optional] [readonly] **start_date** | **datetime** | (Optional) When passing &#x60;window&#x60; or &#x60;startDate&#x60; parameter, the client will also receive the &#x60;startDate&#x60; field indicating the UTC start date of the data&#39;s time range being retrieved (ISO date-time format). | [optional] [readonly]
**end_date** | **datetime** | (Optional) When passing &#x60;window&#x60; or &#x60;endDate&#x60; parameter, the client will also receive the &#x60;endDate&#x60; field indicating the UTC end date of the data&#39;s time range being retrieved (ISO date-time format). | [optional] [readonly] **end_date** | **datetime** | (Optional) When passing &#x60;window&#x60; or &#x60;endDate&#x60; parameter, the client will also receive the &#x60;endDate&#x60; field indicating the UTC end date of the data&#39;s time range being retrieved (ISO date-time format). | [optional] [readonly]

View File

@ -11,6 +11,7 @@ Name | Type | Description | Notes
**phy_mode** | **str** | Wireless network PHY mode. | [optional] [readonly] **phy_mode** | **str** | Wireless network PHY mode. | [optional] [readonly]
**rssi** | **int** | Wireless network RSSI. | [optional] [readonly] **rssi** | **int** | Wireless network RSSI. | [optional] [readonly]
**noise** | **int** | Wireless network noise. | [optional] [readonly] **noise** | **int** | Wireless network noise. | [optional] [readonly]
**snr** | **int** | Wireless network signal-to-noise ratio (SNR), in dB. | [optional] [readonly]
**quality** | **int** | Wireless network quality. | [optional] [readonly] **quality** | **int** | Wireless network quality. | [optional] [readonly]
**tx_rate** | **int** | Wireless network transmitted rate. | [optional] [readonly] **tx_rate** | **int** | Wireless network transmitted rate. | [optional] [readonly]
**vendor** | **str** | Wireless network device vendor. | [optional] [readonly] **vendor** | **str** | Wireless network device vendor. | [optional] [readonly]

View File

@ -17,7 +17,7 @@ import re # noqa: F401
import json import json
from datetime import datetime from datetime import datetime
from pydantic import BaseModel, ConfigDict, Field from pydantic import BaseModel, ConfigDict, Field, StrictInt
from typing import Any, ClassVar, Dict, List, Optional from typing import Any, ClassVar, Dict, List, Optional
from thousandeyes_sdk.endpoint_test_results.models.endpoint_http_server_test import EndpointHttpServerTest from thousandeyes_sdk.endpoint_test_results.models.endpoint_http_server_test import EndpointHttpServerTest
from thousandeyes_sdk.endpoint_test_results.models.http_endpoint_test_result import HttpEndpointTestResult from thousandeyes_sdk.endpoint_test_results.models.http_endpoint_test_result import HttpEndpointTestResult
@ -30,11 +30,12 @@ class HttpEndpointTestResults(BaseModel):
HttpEndpointTestResults HttpEndpointTestResults
""" # noqa: E501 """ # noqa: E501
results: Optional[List[HttpEndpointTestResult]] = None results: Optional[List[HttpEndpointTestResult]] = None
total_hits: Optional[StrictInt] = Field(default=None, description="Total number of measurements that match the search criteria.", alias="totalHits")
test: Optional[EndpointHttpServerTest] = None test: Optional[EndpointHttpServerTest] = None
start_date: Optional[datetime] = Field(default=None, description="(Optional) When passing `window` or `startDate` parameter, the client will also receive the `startDate` field indicating the UTC start date of the data's time range being retrieved (ISO date-time format).", alias="startDate") start_date: Optional[datetime] = Field(default=None, description="(Optional) When passing `window` or `startDate` parameter, the client will also receive the `startDate` field indicating the UTC start date of the data's time range being retrieved (ISO date-time format).", alias="startDate")
end_date: Optional[datetime] = Field(default=None, description="(Optional) When passing `window` or `endDate` parameter, the client will also receive the `endDate` field indicating the UTC end date of the data's time range being retrieved (ISO date-time format).", alias="endDate") end_date: Optional[datetime] = Field(default=None, description="(Optional) When passing `window` or `endDate` parameter, the client will also receive the `endDate` field indicating the UTC end date of the data's time range being retrieved (ISO date-time format).", alias="endDate")
links: Optional[PaginationNextAndSelfLink] = Field(default=None, alias="_links") links: Optional[PaginationNextAndSelfLink] = Field(default=None, alias="_links")
__properties: ClassVar[List[str]] = ["results", "test", "startDate", "endDate", "_links"] __properties: ClassVar[List[str]] = ["results", "totalHits", "test", "startDate", "endDate", "_links"]
model_config = ConfigDict( model_config = ConfigDict(
populate_by_name=True, populate_by_name=True,
@ -106,6 +107,7 @@ class HttpEndpointTestResults(BaseModel):
_obj = cls.model_validate({ _obj = cls.model_validate({
"results": [HttpEndpointTestResult.from_dict(_item) for _item in obj["results"]] if obj.get("results") is not None else None, "results": [HttpEndpointTestResult.from_dict(_item) for _item in obj["results"]] if obj.get("results") is not None else None,
"totalHits": obj.get("totalHits"),
"test": EndpointHttpServerTest.from_dict(obj["test"]) if obj.get("test") is not None else None, "test": EndpointHttpServerTest.from_dict(obj["test"]) if obj.get("test") is not None else None,
"startDate": obj.get("startDate"), "startDate": obj.get("startDate"),
"endDate": obj.get("endDate"), "endDate": obj.get("endDate"),

View File

@ -31,10 +31,11 @@ class NetworkWirelessProfile(BaseModel):
phy_mode: Optional[StrictStr] = Field(default=None, description="Wireless network PHY mode.", alias="phyMode") phy_mode: Optional[StrictStr] = Field(default=None, description="Wireless network PHY mode.", alias="phyMode")
rssi: Optional[StrictInt] = Field(default=None, description="Wireless network RSSI.") rssi: Optional[StrictInt] = Field(default=None, description="Wireless network RSSI.")
noise: Optional[StrictInt] = Field(default=None, description="Wireless network noise.") noise: Optional[StrictInt] = Field(default=None, description="Wireless network noise.")
snr: Optional[StrictInt] = Field(default=None, description="Wireless network signal-to-noise ratio (SNR), in dB.")
quality: Optional[StrictInt] = Field(default=None, description="Wireless network quality.") quality: Optional[StrictInt] = Field(default=None, description="Wireless network quality.")
tx_rate: Optional[StrictInt] = Field(default=None, description="Wireless network transmitted rate.", alias="txRate") tx_rate: Optional[StrictInt] = Field(default=None, description="Wireless network transmitted rate.", alias="txRate")
vendor: Optional[StrictStr] = Field(default=None, description="Wireless network device vendor.") vendor: Optional[StrictStr] = Field(default=None, description="Wireless network device vendor.")
__properties: ClassVar[List[str]] = ["ssid", "bssid", "channel", "phyMode", "rssi", "noise", "quality", "txRate", "vendor"] __properties: ClassVar[List[str]] = ["ssid", "bssid", "channel", "phyMode", "rssi", "noise", "snr", "quality", "txRate", "vendor"]
model_config = ConfigDict( model_config = ConfigDict(
populate_by_name=True, populate_by_name=True,
@ -76,6 +77,7 @@ class NetworkWirelessProfile(BaseModel):
* OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded.
* OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded.
* OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded.
* OpenAPI `readOnly` fields are excluded.
""" """
excluded_fields: Set[str] = set([ excluded_fields: Set[str] = set([
"ssid", "ssid",
@ -84,6 +86,7 @@ class NetworkWirelessProfile(BaseModel):
"phy_mode", "phy_mode",
"rssi", "rssi",
"noise", "noise",
"snr",
"quality", "quality",
"tx_rate", "tx_rate",
"vendor", "vendor",
@ -112,6 +115,7 @@ class NetworkWirelessProfile(BaseModel):
"phyMode": obj.get("phyMode"), "phyMode": obj.get("phyMode"),
"rssi": obj.get("rssi"), "rssi": obj.get("rssi"),
"noise": obj.get("noise"), "noise": obj.get("noise"),
"snr": obj.get("snr"),
"quality": obj.get("quality"), "quality": obj.get("quality"),
"txRate": obj.get("txRate"), "txRate": obj.get("txRate"),
"vendor": obj.get("vendor") "vendor": obj.get("vendor")

View File

@ -30,6 +30,7 @@ class Platform(str, Enum):
PHONEOS = 'phoneos' PHONEOS = 'phoneos'
ELUX = 'elux' ELUX = 'elux'
CISCO_MINUS_WIRELESS = 'cisco-wireless' CISCO_MINUS_WIRELESS = 'cisco-wireless'
CISCO_MINUS_WIRELESS_MINUS_CLOUD = 'cisco-wireless-cloud'
LINUX = 'linux' LINUX = 'linux'
MAC = 'mac' MAC = 'mac'
ANDROID = 'android' ANDROID = 'android'

View File

@ -93,6 +93,7 @@ class TestHTTPServerEndpointScheduledTestResultsApi(unittest.TestCase):
"username" : "username", "username" : "username",
"sslVersionId" : "0" "sslVersionId" : "0"
}, },
"totalHits" : 12,
"endDate" : "2022-07-18T22:00:54Z", "endDate" : "2022-07-18T22:00:54Z",
"_links" : { "_links" : {
"next" : { "next" : {
@ -193,6 +194,7 @@ class TestHTTPServerEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -321,6 +323,7 @@ class TestHTTPServerEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -518,6 +521,7 @@ class TestHTTPServerEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -646,6 +650,7 @@ class TestHTTPServerEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -843,6 +848,7 @@ class TestHTTPServerEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -971,6 +977,7 @@ class TestHTTPServerEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,

View File

@ -553,6 +553,7 @@ class TestLocalNetworkEndpointTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -836,6 +837,7 @@ class TestLocalNetworkEndpointTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,

View File

@ -206,6 +206,7 @@ class TestNetworkDynamicEndpointTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -347,6 +348,7 @@ class TestNetworkDynamicEndpointTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -676,6 +678,7 @@ class TestNetworkDynamicEndpointTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -890,6 +893,7 @@ class TestNetworkDynamicEndpointTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -1115,6 +1119,7 @@ class TestNetworkDynamicEndpointTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -1257,6 +1262,7 @@ class TestNetworkDynamicEndpointTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,

View File

@ -228,6 +228,7 @@ class TestNetworkEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -358,6 +359,7 @@ class TestNetworkEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -546,6 +548,7 @@ class TestNetworkEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -676,6 +679,7 @@ class TestNetworkEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -967,6 +971,7 @@ class TestNetworkEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -1170,6 +1175,7 @@ class TestNetworkEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -1384,6 +1390,7 @@ class TestNetworkEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -1515,6 +1522,7 @@ class TestNetworkEndpointScheduledTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,

View File

@ -717,6 +717,7 @@ class TestRealUserEndpointTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,
@ -911,6 +912,7 @@ class TestRealUserEndpointTestResultsApi(unittest.TestCase):
"wirelessProfile" : { "wirelessProfile" : {
"rssi" : -38, "rssi" : -38,
"bssid" : "4c:ba:ba:f4:fa:fa", "bssid" : "4c:ba:ba:f4:fa:fa",
"snr" : 57,
"vendor" : "Cisco", "vendor" : "Cisco",
"txRate" : 130, "txRate" : 130,
"channel" : 1, "channel" : 1,

View File

@ -4,7 +4,7 @@ Manage endpoint agent dynamic and scheduled tests using the Endpoint Tests API.
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -11,7 +11,7 @@ With the Events API, you can perform the following tasks on the ThousandEyes pla
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -6,7 +6,7 @@ The response does not include the immediate test results. Use the Test Results e
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -16,7 +16,7 @@ For more information about Internet Insights, see the [Internet Insights](https:
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -3,7 +3,7 @@ Creates a new test snapshot in ThousandEyes.
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -24,7 +24,7 @@ For more information about ThousandEyes for OpenTelemetry, see the [product docu
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -16,7 +16,7 @@ Things to note with the ThousandEyes Tags API:
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -3,7 +3,7 @@ Get test result metrics for Network and Application Synthetics tests.
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -6,7 +6,7 @@ This API allows you to list, create, edit, and delete Network and Application Sy
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator

View File

@ -17,7 +17,7 @@ Refer to the Usage API operations for detailed usage instructions and optional p
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 7.0.94 - API version: 7.0.96
- Generator version: 7.6.0 - Generator version: 7.6.0
- Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator - Build package: com.thousandeyes.api.codegen.ThousandeyesPythonGenerator