mirror of
https://github.com/thousandeyes/thousandeyes-sdk-python.git
synced 2026-08-04 00:46:52 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75929e93d0 | ||
|
|
7e7c1c4c0a |
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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"""
|
||||||
|
|||||||
6
thousandeyes-sdk-core/test/conftest.py
Normal file
6
thousandeyes-sdk-core/test/conftest.py
Normal 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))
|
||||||
1
thousandeyes-sdk-core/test/sdk_test_support/__init__.py
Normal file
1
thousandeyes-sdk-core/test/sdk_test_support/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Test-only helpers for SDK integration tests. Not shipped in the published package.
|
||||||
228
thousandeyes-sdk-core/test/sdk_test_support/mock_server.py
Normal file
228
thousandeyes-sdk-core/test/sdk_test_support/mock_server.py
Normal 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
|
||||||
@ -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)
|
||||||
28
thousandeyes-sdk-core/test/test_exceptions.py
Normal file
28
thousandeyes-sdk-core/test/test_exceptions.py
Normal 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
|
||||||
315
thousandeyes-sdk-core/test/test_mock_server.py
Normal file
315
thousandeyes-sdk-core/test/test_mock_server.py
Normal 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)
|
||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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'
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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 `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). | [optional] [readonly]
|
**start_date** | **datetime** | (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). | [optional] [readonly]
|
||||||
**end_date** | **datetime** | (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). | [optional] [readonly]
|
**end_date** | **datetime** | (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). | [optional] [readonly]
|
||||||
|
|||||||
@ -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]
|
||||||
|
|||||||
@ -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"),
|
||||||
|
|||||||
@ -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")
|
||||||
|
|||||||
@ -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'
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user