diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 179c134..188f3fe 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,12 @@ jobs: - ubuntu-20.04 # ubuntu-20.04 - macos-latest # macOS-10.14 - windows-latest # windows-2019 - python-version: [ 3.6, 3.7, 3.8, 3.9 ] + python-version: [ '3.6', '3.7', '3.8', '3.9', '3.10' ] + exclude: + - platform: macos-latest + python-version: '3.6' + - platform: macos-latest + python-version: '3.7' steps: - uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7fca1ad --- /dev/null +++ b/.gitignore @@ -0,0 +1,162 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ \ No newline at end of file diff --git a/dynatrace/environment_v2/metrics.py b/dynatrace/environment_v2/metrics.py index 3d9264a..9a45386 100644 --- a/dynatrace/environment_v2/metrics.py +++ b/dynatrace/environment_v2/metrics.py @@ -227,7 +227,7 @@ def _create_from_raw_data(self, raw_element): self.root_cause_relevant: Optional[bool] = raw_element.get("rootCauseRelevant") self.tags: Optional[List[str]] = raw_element.get("tags") self.transformations: Optional[List[Transformation]] = [Transformation(element) for element in raw_element.get("transformations", [])] - self.unit: Optional[Unit] = Unit(raw_element.get("unit")) + self.unit: Optional[Unit] = Unit(raw_element.get("unit")) if raw_element.get("unit") else None self.warnings: Optional[List[str]] = raw_element.get("warnings") diff --git a/dynatrace/environment_v2/monitored_entities.py b/dynatrace/environment_v2/monitored_entities.py index c0b30ce..91128d6 100644 --- a/dynatrace/environment_v2/monitored_entities.py +++ b/dynatrace/environment_v2/monitored_entities.py @@ -194,7 +194,7 @@ def _create_from_raw_data(self, raw_element: Dict[str, Any]): self.icon: Optional[ EntityIcon] = EntityIcon(raw_element=raw_element.get("icon")) if raw_element.get("icon") else None self.display_name: str = raw_element["displayName"] - self.type: str = raw_element['type'] + self.type: str | None = raw_element.get('type') self.entity_id: str = raw_element["entityId"] self.properties: Optional[Dict[str, Any]] = raw_element.get("properties", {}) self.tags: List[METag] = [METag(raw_element=tag) for tag in raw_element.get("tags", [])] diff --git a/dynatrace/environment_v2/remote_configuration.py b/dynatrace/environment_v2/remote_configuration.py new file mode 100644 index 0000000..65b2b21 --- /dev/null +++ b/dynatrace/environment_v2/remote_configuration.py @@ -0,0 +1,329 @@ +""" +Copyright 2021 Dynatrace LLC + +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. +""" + +from enum import Enum +from datetime import datetime +from typing import List, Optional, Union, Dict, Any + +from dynatrace.dynatrace_object import DynatraceObject +from dynatrace.http_client import HttpClient +from dynatrace.pagination import PaginatedList +from dynatrace.utils import timestamp_to_string + +class ActiveGatesRemoteConfigurationService: + ENDPOINT = "/api/v2/activeGates/remoteConfigurationManagement" + + def __init__(self, http_client: HttpClient) -> None: + self.__http_client = http_client + + def list(self, time_from: Optional[Union[datetime, str]] = None, time_to: Optional[Union[datetime, str]] = None) -> "PaginatedList[RemoteConfigurationManagementJobSummary]": + """Lists finished ActiveGate remote configuration management jobs + + :param time_from: The start of the requested timeframe + :param time_to: The end of the requested timeframe + :return: A paginated list of remote configuration management job summaries + """ + params = {"from": timestamp_to_string(time_from), "to": timestamp_to_string(time_to)} + return PaginatedList( + RemoteConfigurationManagementJobSummary, + self.__http_client, + target_url=self.ENDPOINT, + list_item="jobs", + target_params=params + ) + + def post(self, entities: List[str], operations: List["RemoteConfigurationManagementOperation"]) -> "RemoteConfigurationManagementJob": + """Creates a new remote configuration management job + + :param entities: The list of entities to apply the operations to + :param operations: The list of operations to apply + :return: The created job + """ + payload = RemoteConfigurationManagementOperationActiveGateRequest(entities=entities, operations=operations) + response = self.__http_client.make_request( + self.ENDPOINT, + method="POST", + data=payload.to_json() + ).json() + return RemoteConfigurationManagementJob(raw_element=response) + + def get_current(self) -> Optional["RemoteConfigurationManagementJob"]: + """Gets remote configuration management job that is currently running + + :return: The currently running job or None if no job is running + """ + response = self.__http_client.make_request(f"{self.ENDPOINT}/current") + if not response.content: + return None + return RemoteConfigurationManagementJob(raw_element=response.json()) + + def post_preview(self, entities: List[str], operations: List["RemoteConfigurationManagementOperation"]) -> "PaginatedList[RemoteConfigurationManagementJobPreview]": + """Creates a preview for remote configuration management job + + :param entities: The list of entities to apply the operations to + :param operations: The list of operations to apply + :return: A paginated list of job previews + """ + payload = RemoteConfigurationManagementOperationActiveGateRequest(entities=entities, operations=operations) + return PaginatedList( + RemoteConfigurationManagementJobPreview, + self.__http_client, + target_url=f"{self.ENDPOINT}/preview", + list_item="previews", + target_params=payload.to_json() + ) + + def validate(self, entities: List[str], operations: List["RemoteConfigurationManagementOperation"]) -> Optional["RemoteConfigurationManagementValidationResult"]: + """Validates the payload for a remote configuration management job + + :param entities: The list of entities to apply the operations to + :param operations: The list of operations to apply + :return: Validation result if validation failed, None if validation succeeded + """ + payload = RemoteConfigurationManagementOperationActiveGateRequest(entities=entities, operations=operations) + response = self.__http_client.make_request( + f"{self.ENDPOINT}/validator", + method="POST", + data=payload.to_json() + ) + if not response.content: + return None + return RemoteConfigurationManagementValidationResult(raw_element=response.json()) + + def get(self, job_id: str) -> "RemoteConfigurationManagementJob": + """Gets the specified remote configuration management job + + :param job_id: The ID of the required job + :return: The specified job + """ + response = self.__http_client.make_request( + f"{self.ENDPOINT}/{job_id}" + ).json() + return RemoteConfigurationManagementJob(raw_element=response) + + +class OneAgentsRemoteConfigurationService: + ENDPOINT = "/api/v2/oneagents/remoteConfigurationManagement" + + def __init__(self, http_client: HttpClient) -> None: + self.__http_client = http_client + + def list(self, time_from: Optional[Union[datetime, str]] = None, time_to: Optional[Union[datetime, str]] = None) -> "PaginatedList[RemoteConfigurationManagementJobSummary]": + """Lists finished OneAgent remote configuration management jobs + + :param time_from: The start of the requested timeframe + :param time_to: The end of the requested timeframe + :return: A paginated list of remote configuration management job summaries + """ + params = {"from": timestamp_to_string(time_from), "to": timestamp_to_string(time_to)} + return PaginatedList( + RemoteConfigurationManagementJobSummary, + self.__http_client, + target_url=self.ENDPOINT, + list_item="jobs", + target_params=params + ) + + def post(self, entities: List[str], operations: List["RemoteConfigurationManagementOperation"]) -> "RemoteConfigurationManagementJob": + """Creates a new remote configuration management job + + :param entities: The list of entities to apply the operations to + :param operations: The list of operations to apply + :return: The created job + """ + payload = RemoteConfigurationManagementOperationOneAgentRequest(entities=entities, operations=operations) + response = self.__http_client.make_request( + self.ENDPOINT, + method="POST", + data=payload.to_json() + ).json() + return RemoteConfigurationManagementJob(raw_element=response) + + def get_current(self) -> Optional["RemoteConfigurationManagementJob"]: + """Gets remote configuration management job that is currently running + + :return: The currently running job or None if no job is running + """ + response = self.__http_client.make_request(f"{self.ENDPOINT}/current") + if not response.content: + return None + return RemoteConfigurationManagementJob(raw_element=response.json()) + + def post_preview(self, entities: List[str], operations: List["RemoteConfigurationManagementOperation"]) -> "PaginatedList[RemoteConfigurationManagementJobPreview]": + """Creates a preview for remote configuration management job + + :param entities: The list of entities to apply the operations to + :param operations: The list of operations to apply + :return: A paginated list of job previews + """ + payload = RemoteConfigurationManagementOperationOneAgentRequest(entities=entities, operations=operations) + return PaginatedList( + RemoteConfigurationManagementJobPreview, + self.__http_client, + target_url=f"{self.ENDPOINT}/preview", + list_item="previews", + target_params=payload.to_json() + ) + + def validate(self, entities: List[str], operations: List["RemoteConfigurationManagementOperation"]) -> Optional["RemoteConfigurationManagementValidationResult"]: + """Validates the payload for a remote configuration management job + + :param entities: The list of entities to apply the operations to + :param operations: The list of operations to apply + :return: Validation result if validation failed, None if validation succeeded + """ + payload = RemoteConfigurationManagementOperationOneAgentRequest(entities=entities, operations=operations) + response = self.__http_client.make_request( + f"{self.ENDPOINT}/validator", + method="POST", + data=payload.to_json() + ) + if not response.content: + return None + return RemoteConfigurationManagementValidationResult(raw_element=response.json()) + + def get(self, job_id: str) -> "RemoteConfigurationManagementJob": + """Gets the specified remote configuration management job + + :param job_id: The ID of the required job + :return: The specified job + """ + response = self.__http_client.make_request( + f"{self.ENDPOINT}/{job_id}" + ).json() + return RemoteConfigurationManagementJob(raw_element=response) + + +class EntityType(Enum): + ACTIVE_GATE = "ACTIVE_GATE" + ONE_AGENT = "ONE_AGENT" + + +class AttributeType(Enum): + GROUP = "group" + HOST_GROUP = "hostGroup" + HOST_PROPERTY = "hostProperty" + HOST_TAG = "hostTag" + NETWORK_ZONE = "networkZone" + + +class OperationType(Enum): + CLEAR = "clear" + SET = "set" + + +class RemoteConfigurationManagementOperation(DynatraceObject): + """Definition of a single remote configuration management operation""" + def _create_from_raw_data(self, raw_element: Dict[str, Any]): + self.attribute: AttributeType = AttributeType(raw_element["attribute"]) + self.operation: OperationType = OperationType(raw_element["operation"]) + self.value: Optional[str] = raw_element.get("value") + + def to_json(self) -> Dict[str, Any]: + return { + "attribute": self.attribute.value, + "operation": self.operation.value, + "value": self.value + } + + @staticmethod + def build(attribute: AttributeType, operation: OperationType, value: Optional[str] = None) -> "RemoteConfigurationManagementOperation": + return RemoteConfigurationManagementOperation(raw_element={ + "attribute": attribute.value, + "operation": operation.value, + "value": value + }) + +class RemoteConfigurationManagementOperationActiveGateRequest: + """Remote configuration management operation creation request""" + def __init__(self, entities: List[str], operations: List[RemoteConfigurationManagementOperation]): + self.entities = entities + self.operations = operations + + def to_json(self) -> Dict[str, Any]: + return { + "entities": self.entities, + "operations": [op.to_json() for op in self.operations] + } + +class RemoteConfigurationManagementOperationOneAgentRequest: + """Remote configuration management operation creation request""" + def __init__(self, entities: List[str], operations: List[RemoteConfigurationManagementOperation]): + self.entities = entities + self.operations = operations + + def to_json(self) -> Dict[str, Any]: + return { + "entities": self.entities, + "operations": [op.to_json() for op in self.operations] + } + +class RemoteConfigurationManagementJob(DynatraceObject): + """Remote configuration management job""" + def _create_from_raw_data(self, raw_element: Dict[str, Any]): + self.id: str = raw_element["id"] + self.entity_type: EntityType = EntityType(raw_element["entityType"]) + self.start_time: str = raw_element["startTime"] + self.end_time: Optional[str] = raw_element.get("endTime") + self.timeout_time: Optional[str] = raw_element.get("timeoutTime") + self.total_entities_count: int = raw_element["totalEntitiesCount"] + self.processed_entities_count: int = raw_element["processedEntitiesCount"] + self.operations: List[RemoteConfigurationManagementOperation] = [ + RemoteConfigurationManagementOperation(raw_element=op) for op in raw_element.get("operations", []) + ] + +class RemoteConfigurationManagementJobSummary(DynatraceObject): + """Remote configuration management job with basic data""" + def _create_from_raw_data(self, raw_element: Dict[str, Any]): + self.id: str = raw_element["id"] + self.entity_type: EntityType = EntityType(raw_element["entityType"]) + self.start_time: str = raw_element["startTime"] + self.end_time: Optional[str] = raw_element.get("endTime") + +class RemoteConfigurationManagementJobPreview(DynatraceObject): + """A preview of remote configuration management job""" + def _create_from_raw_data(self, raw_element: Dict[str, Any]): + self.attribute: AttributeType = AttributeType(raw_element["attribute"]) + self.operation: OperationType = OperationType(raw_element["operation"]) + self.value: Optional[str] = raw_element.get("value") + self.already_configured_entities_count: int = raw_element["alreadyConfiguredEntitiesCount"] + self.target_entities_count: int = raw_element["targetEntitiesCount"] + +class RemoteConfigurationManagementValidationResult(DynatraceObject): + """The result of remote configuration management validation""" + def _create_from_raw_data(self, raw_element: Dict[str, Any]): + self.invalid_entities: List[RemoteConfigurationManagementEntityValidationError] = [ + RemoteConfigurationManagementEntityValidationError(raw_element=error) + for error in raw_element.get("invalidEntities", []) + ] + self.invalid_operations: List[RemoteConfigurationManagementOperationValidationError] = [ + RemoteConfigurationManagementOperationValidationError(raw_element=error) + for error in raw_element.get("invalidOperations", []) + ] + +class RemoteConfigurationManagementEntityValidationError(DynatraceObject): + """Entity validation error for remote configuration management""" + def _create_from_raw_data(self, raw_element: Dict[str, Any]): + self.entity: str = raw_element["entity"] + self.reasons: List[str] = raw_element.get("reasons", []) + +class RemoteConfigurationManagementOperationValidationError(DynatraceObject): + """Validation error of remote configuration management operation definition""" + def _create_from_raw_data(self, raw_element: Dict[str, Any]): + self.attribute: Optional[AttributeType] = AttributeType(raw_element["attribute"]) if "attribute" in raw_element else None + self.operation: Optional[OperationType] = OperationType(raw_element["operation"]) if "operation" in raw_element else None + self.value: Optional[str] = raw_element.get("value") + self.reason: str = raw_element["reason"] diff --git a/dynatrace/main.py b/dynatrace/main.py index 1dd0476..89911bb 100644 --- a/dynatrace/main.py +++ b/dynatrace/main.py @@ -44,6 +44,7 @@ from dynatrace.environment_v2.activegates import ActiveGateService from dynatrace.environment_v2.activegates_autoupdate_configuration import ActiveGateAutoUpdateConfigurationService from dynatrace.environment_v2.activegates_autoupdate_jobs import ActiveGateAutoUpdateJobsService +from dynatrace.environment_v2.remote_configuration import ActiveGatesRemoteConfigurationService, OneAgentsRemoteConfigurationService from dynatrace.environment_v2.audit_logs import AuditLogsService from dynatrace.environment_v2.extensions import ExtensionsServiceV2 from dynatrace.environment_v2.events import EventServiceV2 @@ -95,6 +96,7 @@ def __init__( self.activegates: ActiveGateService = ActiveGateService(self.__http_client) self.activegates_autoupdate_configuration: ActiveGateAutoUpdateConfigurationService = ActiveGateAutoUpdateConfigurationService(self.__http_client) self.activegates_autoupdate_jobs = ActiveGateAutoUpdateJobsService(self.__http_client) + self.activegates_remote_configuration: ActiveGatesRemoteConfigurationService = ActiveGatesRemoteConfigurationService(self.__http_client) self.alerting_profiles: AlertingProfileService = AlertingProfileService(self.__http_client) self.anomaly_detection_metric_events = MetricEventService(self.__http_client) self.anomaly_detection_process_groups = AnomalyDetectionPGService(self.__http_client) @@ -120,6 +122,7 @@ def __init__( self.oneagents_config_environment: OneAgentEnvironmentWideConfigService = OneAgentEnvironmentWideConfigService(self.__http_client) self.oneagents_config_host: OneAgentOnAHostConfigService = OneAgentOnAHostConfigService(self.__http_client) self.oneagents_config_hostgroup: OneAgentInAHostGroupService = OneAgentInAHostGroupService(self.__http_client) + self.oneagents_remote_configuration: OneAgentsRemoteConfigurationService = OneAgentsRemoteConfigurationService(self.__http_client) self.settings : SettingService = SettingService(self.__http_client) self.plugins: PluginService = PluginService(self.__http_client) self.problems: ProblemService = ProblemService(self.__http_client) diff --git a/setup.py b/setup.py index 0d31fed..14770c2 100644 --- a/setup.py +++ b/setup.py @@ -2,8 +2,8 @@ setup( name="dt", - version="1.1.67", - packages=find_packages(), + version="1.1.68", + packages=find_packages(include=["dynatrace"]), install_requires=["requests>=2.22"], tests_require=["pytest", "mock", "tox"], python_requires=">=3.6", diff --git a/test/configuration_v1/test_auto_tags.py b/test/configuration_v1/test_auto_tags.py index 47ccd3d..314307c 100644 --- a/test/configuration_v1/test_auto_tags.py +++ b/test/configuration_v1/test_auto_tags.py @@ -29,7 +29,6 @@ def test_list(dt: Dynatrace): def test_get(dt: Dynatrace): tags = dt.auto_tags.list() for tag in tags: - print(tag.name) full_tag = tag.get_full_configuration() assert isinstance(full_tag, AutoTag) assert isinstance(full_tag.metadata, ConfigurationMetadata) @@ -38,7 +37,6 @@ def test_get(dt: Dynatrace): assert full_tag.name == "frontend" assert isinstance(full_tag.rules, List) for rule in full_tag.rules: - print(rule) assert isinstance(rule, AutoTagRule) assert rule.type == RuleType.SERVICE assert rule.enabled == True diff --git a/test/configuration_v1/test_management_zones.py b/test/configuration_v1/test_management_zones.py index 23aa224..0cc3b3a 100644 --- a/test/configuration_v1/test_management_zones.py +++ b/test/configuration_v1/test_management_zones.py @@ -13,7 +13,7 @@ ) from dynatrace.environment_v2.schemas import ConfigurationMetadata from dynatrace.pagination import PaginatedList -from dynatrace.configuration_v1.auto_tags import ConditionKeyAttribute, RuleType +from dynatrace.configuration_v1.management_zones import ConditionKeyAttribute, RuleType def test_list(dt: Dynatrace): @@ -30,7 +30,6 @@ def test_list(dt: Dynatrace): def test_get(dt: Dynatrace): management_zones = dt.management_zones.list() for management_zone in management_zones: - print(management_zone.name) full_management_zone = management_zone.get_full_configuration() assert isinstance(full_management_zone, ManagementZone) assert isinstance(full_management_zone.metadata, ConfigurationMetadata) @@ -39,7 +38,6 @@ def test_get(dt: Dynatrace): assert full_management_zone.name == "Frontend Services" assert isinstance(full_management_zone.rules, List) for rule in full_management_zone.rules: - print(rule) assert isinstance(rule, ManagementZoneRule) assert rule.type == RuleType.SERVICE assert rule.enabled == True diff --git a/test/conftest.py b/test/conftest.py index c5cf21b..92ebf5f 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -18,6 +18,7 @@ class MockResponse: def __init__(self, json_data): self.json_data = json_data self.headers = {} + self.content = json.dumps(json_data).encode() if json_data else None def json(self): return self.json_data @@ -38,7 +39,8 @@ def local_make_request( file_name = f"{method}{path}{params}.json" file_path = Path(current_file_path, "mock_data", file_name) with open(file_path) as f: - json_data = json.load(f) + content = f.read() + json_data = json.loads(content) if content else None return MockResponse(json_data) diff --git a/test/environment_v2/test_activegates_remote_configuration.py b/test/environment_v2/test_activegates_remote_configuration.py new file mode 100644 index 0000000..b6ff469 --- /dev/null +++ b/test/environment_v2/test_activegates_remote_configuration.py @@ -0,0 +1,107 @@ +from datetime import datetime +from typing import List +from dynatrace import Dynatrace +from dynatrace.environment_v2.remote_configuration import ( + RemoteConfigurationManagementOperation, + RemoteConfigurationManagementOperationActiveGateRequest, + AttributeType, + OperationType, + EntityType, + RemoteConfigurationManagementJobPreview, + RemoteConfigurationManagementJobSummary +) +from dynatrace.pagination import PaginatedList + +TEST_ENTITY_ID = "0x2b7c0b02" + +def test_list(dt: Dynatrace): + jobs = dt.activegates_remote_configuration.list() + + assert isinstance(jobs, PaginatedList) + + for job in jobs: + assert isinstance(job, RemoteConfigurationManagementJobSummary) + assert hasattr(job, "id") + assert hasattr(job, "entity_type") + assert hasattr(job, "start_time") + assert isinstance(job.entity_type, EntityType) + break + +def test_post(dt: Dynatrace): + operation = RemoteConfigurationManagementOperation.build( + attribute=AttributeType.NETWORK_ZONE, + operation=OperationType.SET, + value="test-zone", + ) + + job = dt.activegates_remote_configuration.post(entities=[TEST_ENTITY_ID], operations=[operation]) + + assert job is not None + assert job.id is not None + assert job.entity_type == EntityType.ACTIVE_GATE + assert len(job.operations) == 1 + assert job.operations[0].attribute == AttributeType.NETWORK_ZONE + assert job.operations[0].operation == OperationType.SET + assert job.operations[0].value == "test-zone" + +def test_get_current(dt: Dynatrace): + current_job = dt.activegates_remote_configuration.get_current() + + if current_job is not None: + assert current_job.id is not None + assert hasattr(current_job, "timeout_time") + assert current_job.processed_entities_count <= current_job.total_entities_count + +def test_post_preview(dt: Dynatrace): + operation = RemoteConfigurationManagementOperation.build( + attribute=AttributeType.NETWORK_ZONE, + operation=OperationType.SET, + value="test-zone", + ) + + previews = dt.activegates_remote_configuration.post_preview( + entities=[TEST_ENTITY_ID], + operations=[operation], + ) + + assert isinstance(previews, PaginatedList) + + for preview in previews: + assert isinstance(preview, RemoteConfigurationManagementJobPreview) + assert preview.attribute == AttributeType.NETWORK_ZONE + assert preview.operation == OperationType.SET + assert preview.value == "test-zone" + assert isinstance(preview.already_configured_entities_count, int) + assert isinstance(preview.target_entities_count, int) + break + +def test_validate(dt: Dynatrace): + operation = RemoteConfigurationManagementOperation.build( + attribute=AttributeType.NETWORK_ZONE, + operation=OperationType.SET, + value="test-zone", + ) + validation_result = dt.activegates_remote_configuration.validate( + entities=[TEST_ENTITY_ID], + operations=[operation] + ) + + # If validation succeeds, result should be None + # If validation fails, result should contain error details + if validation_result is not None: + assert hasattr(validation_result, "invalid_entities") + assert hasattr(validation_result, "invalid_operations") + assert isinstance(validation_result.invalid_entities, list) + assert isinstance(validation_result.invalid_operations, list) + +def test_get_job(dt: Dynatrace): + ID = "7974003406714390819" + job = dt.activegates_remote_configuration.get(ID) + + assert job is not None + assert job.id == ID + assert job.entity_type == EntityType.ACTIVE_GATE + assert len(job.operations) == 1 + assert job.operations[0].attribute == AttributeType.NETWORK_ZONE + assert job.operations[0].operation == OperationType.SET + assert job.operations[0].value == "test-zone" \ No newline at end of file diff --git a/test/environment_v2/test_metrics.py b/test/environment_v2/test_metrics.py index c6c426c..8758d8b 100644 --- a/test/environment_v2/test_metrics.py +++ b/test/environment_v2/test_metrics.py @@ -1,4 +1,5 @@ from dynatrace import Dynatrace +import pytest from dynatrace.environment_v2.metrics import MetricDescriptor, Unit, AggregationType, Transformation, ValueType, MetricSeriesCollection from dynatrace.pagination import PaginatedList @@ -93,8 +94,10 @@ def test_query(dt: Dynatrace): results = dt.metrics.query("builtin:host.cpu.idle", time_from=time_from, time_to=time_to) assert isinstance(results, PaginatedList) + print("Asserting first element") first = list(results)[0] + print("Start") assert isinstance(first, MetricSeriesCollection) assert first.metric_id == "builtin:host.cpu.idle" assert len(first.data) == 1 @@ -102,10 +105,9 @@ def test_query(dt: Dynatrace): first_data = first.data[0] assert first_data.dimension_map == {"dt.entity.host": "HOST-82F576674F19AC16"} assert first_data.dimensions == ["HOST-82F576674F19AC16"] - assert len(first_data.timestamps) == 84 + assert len(first_data.timestamps) == 3 assert len(first_data.timestamps) == len(first_data.values) - assert first_data.timestamps[0] == int64_to_datetime(1621020060000) - assert first_data.values[0] == 89.91581217447917 + assert first_data.timestamps[0] == int64_to_datetime(3151435100000) def test_ingest(dt: Dynatrace): diff --git a/test/environment_v2/test_oneagents_remote_configuration.py b/test/environment_v2/test_oneagents_remote_configuration.py new file mode 100644 index 0000000..062393c --- /dev/null +++ b/test/environment_v2/test_oneagents_remote_configuration.py @@ -0,0 +1,111 @@ +from datetime import datetime +from typing import List +from dynatrace import Dynatrace +from dynatrace.environment_v2.remote_configuration import ( + RemoteConfigurationManagementOperation, + RemoteConfigurationManagementOperationOneAgentRequest, + AttributeType, + OperationType, + EntityType, + RemoteConfigurationManagementJobPreview, + RemoteConfigurationManagementJobSummary +) +from dynatrace.pagination import PaginatedList + +TEST_ENTITY_ID = "0x2b7c0b02" + +def test_list(dt: Dynatrace): + jobs = dt.oneagents_remote_configuration.list() + + assert isinstance(jobs, PaginatedList) + + for job in jobs: + assert isinstance(job, RemoteConfigurationManagementJobSummary) + assert hasattr(job, "id") + assert hasattr(job, "entity_type") + assert hasattr(job, "start_time") + assert isinstance(job.entity_type, EntityType) + break + +def test_post(dt: Dynatrace): + operation = RemoteConfigurationManagementOperation.build( + attribute=AttributeType.NETWORK_ZONE, + operation=OperationType.SET, + value="test-zone" + ) + + job = dt.oneagents_remote_configuration.post( + entities=[TEST_ENTITY_ID], + operations=[operation] + ) + + assert job is not None + assert job.id is not None + assert job.entity_type == EntityType.ONE_AGENT + assert len(job.operations) == 1 + assert job.operations[0].attribute == AttributeType.NETWORK_ZONE + assert job.operations[0].operation == OperationType.SET + assert job.operations[0].value == "test-zone" + +def test_get_current(dt: Dynatrace): + current_job = dt.oneagents_remote_configuration.get_current() + + if current_job is not None: + assert current_job.id is not None + assert hasattr(current_job, "timeout_time") + assert current_job.processed_entities_count <= current_job.total_entities_count + +def test_post_preview(dt: Dynatrace): + operation = RemoteConfigurationManagementOperation.build( + attribute=AttributeType.NETWORK_ZONE, + operation=OperationType.SET, + value="test-zone" + ) + + previews = dt.oneagents_remote_configuration.post_preview( + entities=[TEST_ENTITY_ID], + operations=[operation] + ) + + assert isinstance(previews, PaginatedList) + + for preview in previews: + assert isinstance(preview, RemoteConfigurationManagementJobPreview) + assert preview.attribute == AttributeType.NETWORK_ZONE + assert preview.operation == OperationType.SET + assert preview.value == "test-zone" + assert isinstance(preview.already_configured_entities_count, int) + assert isinstance(preview.target_entities_count, int) + break + +def test_validate(dt: Dynatrace): + operation = RemoteConfigurationManagementOperation.build( + attribute=AttributeType.NETWORK_ZONE, + operation=OperationType.SET, + value="test-zone", + ) + + validation_result = dt.oneagents_remote_configuration.validate( + entities=[TEST_ENTITY_ID], + operations=[operation] + ) + + # If validation succeeds, result should be None + # If validation fails, result should contain error details + if validation_result is not None: + assert hasattr(validation_result, "invalid_entities") + assert hasattr(validation_result, "invalid_operations") + assert isinstance(validation_result.invalid_entities, list) + assert isinstance(validation_result.invalid_operations, list) + +def test_get_job(dt: Dynatrace): + ID = "7974003406714390819" + job = dt.oneagents_remote_configuration.get(ID) + + assert job is not None + assert job.id == ID + assert job.entity_type == EntityType.ONE_AGENT + assert len(job.operations) == 1 + assert job.operations[0].attribute == AttributeType.NETWORK_ZONE + assert job.operations[0].operation == OperationType.SET + assert job.operations[0].value == "test-zone" \ No newline at end of file diff --git a/test/mock_data/GET_api_v1_entity_infrastructure_hosts_eb6d39453f5207d.json b/test/mock_data/GET_api_v1_entity_infrastructure_hosts_eb6d39453f5207d.json new file mode 100644 index 0000000..51c90b7 --- /dev/null +++ b/test/mock_data/GET_api_v1_entity_infrastructure_hosts_eb6d39453f5207d.json @@ -0,0 +1,163 @@ +[ + { + "agentVersion": { + "major": 0, + "minor": 0, + "revision": 0, + "sourceRevision": "string", + "timestamp": "string" + }, + "amiId": "string", + "autoInjection": "DISABLED_MANUALLY", + "autoScalingGroup": "string", + "awsInstanceId": "string", + "awsInstanceType": "string", + "awsNameTag": "string", + "awsSecurityGroup": [ + "string" + ], + "azureComputeModeName": "DEDICATED", + "azureEnvironment": "string", + "azureHostNames": [ + "string" + ], + "azureResourceGroupName": "string", + "azureResourceId": "string", + "azureSiteNames": [ + "string" + ], + "azureSku": "BASIC", + "azureVmName": "string", + "azureVmScaleSetName": "string", + "azureVmSizeLabel": "string", + "azureZone": "string", + "beanstalkEnvironmentName": "string", + "bitness": "32bit", + "boshAvailabilityZone": "string", + "boshDeploymentId": "string", + "boshInstanceId": "string", + "boshInstanceName": "string", + "boshName": "string", + "boshStemcellVersion": "string", + "cloudPlatformVendorVersion": "string", + "cloudType": "AZURE", + "consumedHostUnits": 2.0, + "cpuCores": 8, + "customizedName": "string", + "discoveredName": "TAG009444368559.clients.example.com", + "displayName": "string", + "entityId": "HOST-7EC661999923A6B9", + "esxiHostName": "string", + "firstSeenTimestamp": 0, + "fromRelationships": { + "isNetworkClientOfHost": [ + "string" + ] + }, + "gceInstanceId": "string", + "gceInstanceName": "string", + "gceMachineType": "string", + "gceProject": "string", + "gceProjectId": "string", + "gcePublicIpAddresses": [ + "string" + ], + "gcpZone": "string", + "hostGroup": { + "meId": "string", + "name": "string" + }, + "hypervisorType": "AHV", + "ipAddresses": [ + "string" + ], + "isMonitoringCandidate": true, + "kubernetesCluster": "string", + "kubernetesLabels": { + "additionalProp1": {}, + "additionalProp2": {}, + "additionalProp3": {} + }, + "kubernetesNode": "string", + "lastSeenTimestamp": 1621519976487, + "localHostName": "string", + "localIp": "string", + "logicalCpuCores": 0, + "logicalCpus": 0, + "managementZones": [ + { + "description": "Dynatrace entity for the REST API example", + "id": "6a98d7bc-abb9-44f8-ae6a-73e68e71812a", + "name": "Dynatrace entity" + } + ], + "monitoringMode": "FULL_STACK", + "networkZoneId": "string", + "oneAgentCustomHostName": "string", + "openStackInstaceType": "string", + "openstackAvZone": "string", + "openstackComputeNodeName": "string", + "openstackProjectName": "string", + "openstackSecurityGroups": [ + "string" + ], + "openstackVmName": "string", + "osArchitecture": "X86", + "osType": "AIX", + "osVersion": "Windows 10 Enterprise 20H2 2009, ver. 10.0.19042", + "paasAgentVersions": [ + { + "major": 0, + "minor": 0, + "revision": 0, + "sourceRevision": "string", + "timestamp": "string" + } + ], + "paasMemoryLimit": 0, + "paasType": "AWS_ECS_EC2", + "publicHostName": "string", + "publicIp": "string", + "scaleSetName": "string", + "simultaneousMultithreading": 0, + "softwareTechnologies": [ + { + "edition": "string", + "type": "string", + "version": "string" + } + ], + "tags": [ + { + "context": "CONTEXTLESS", + "key": "APP1234567", + "value": "string" + } + ], + "toRelationships": { + "isNetworkClientOfHost": [ + "string" + ], + "isProcessOf": [ + "string" + ], + "isSiteOf": [ + "string" + ], + "runsOn": [ + "string" + ] + }, + "userLevel": "NON_SUPERUSER", + "virtualCpus": 0, + "vmwareName": "string", + "zosCPUModelNumber": "string", + "zosCPUSerialNumber": "string", + "zosLpaName": "string", + "zosSystemName": "string", + "zosTotalGeneralPurposeProcessors": 0, + "zosTotalPhysicalMemory": 0, + "zosTotalZiipProcessors": 0, + "zosVirtualization": "string" + } + ] \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_2e5fcbd2c8d0e63.json b/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_2e5fcbd2c8d0e63.json new file mode 100644 index 0000000..ef159f0 --- /dev/null +++ b/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_2e5fcbd2c8d0e63.json @@ -0,0 +1,10 @@ +{ + "jobs": [ + { + "endTime": "2020-11-05T08:15:30.144Z", + "entityType": "ACTIVE_GATE", + "id": "7974003406714390819", + "startTime": "2020-11-05T08:15:30.144Z" + } + ] + } \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_7974003406714390819.json b/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_7974003406714390819.json new file mode 100644 index 0000000..70180a2 --- /dev/null +++ b/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_7974003406714390819.json @@ -0,0 +1,16 @@ +{ + "endTime": "2020-11-05T08:15:30.144Z", + "entityType": "ACTIVE_GATE", + "id": "7974003406714390819", + "operations": [ + { + "attribute": "networkZone", + "operation": "set", + "value": "test-zone" + } + ], + "processedEntitiesCount": 1, + "startTime": "2020-11-05T08:15:30.144Z", + "timeoutTime": "2020-11-05T08:15:30.144Z", + "totalEntitiesCount": 1 + } \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_current.json b/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_current.json new file mode 100644 index 0000000..85d8540 --- /dev/null +++ b/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_current.json @@ -0,0 +1,16 @@ +{ + "endTime": "2020-11-05T08:15:30.144Z", + "entityType": "ACTIVE_GATE", + "id": "7974003406714390819", + "operations": [ + { + "attribute": "networkZone", + "operation": "set", + "value": "exampleNetworkZoneName" + } + ], + "processedEntitiesCount": 1, + "startTime": "2020-11-05T08:15:30.144Z", + "timeoutTime": "2020-11-05T08:15:30.144Z", + "totalEntitiesCount": 1 + } \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_preview_4cfaf0a9b26d2dd.json b/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_preview_4cfaf0a9b26d2dd.json new file mode 100644 index 0000000..4d9d0b7 --- /dev/null +++ b/test/mock_data/GET_api_v2_activeGates_remoteConfigurationManagement_preview_4cfaf0a9b26d2dd.json @@ -0,0 +1,11 @@ +{ + "previews": [ + { + "alreadyConfiguredEntitiesCount": 1, + "attribute": "networkZone", + "operation": "set", + "targetEntitiesCount": 2, + "value": "test-zone" + } + ] + } \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_metrics_query_0f81e686e69f013.json b/test/mock_data/GET_api_v2_metrics_query_0f81e686e69f013.json new file mode 100644 index 0000000..7c6e316 --- /dev/null +++ b/test/mock_data/GET_api_v2_metrics_query_0f81e686e69f013.json @@ -0,0 +1,42 @@ +{ + "nextPageKey": "null", + "resolution": "1h", + "result": [ + { + "data": [ + { + "dimensionMap": { + "dt.entity.host": "HOST-82F576674F19AC16" + }, + "dimensions": [ + "HOST-82F576674F19AC16" + ], + "timestamps": [ + 3151435100000, + 3151438700000, + 3151442300000 + ], + "values": [ + 11.1, + 22.2, + 33.3 + ] + } + ], + "dataPointCountRatio": "0.1211", + "dimensionCountRatio": "0.0322", + "metricId": "builtin:host.cpu.idle" + }, + { + "data": [], + "metricId": "builtin:host.cpu.idle:filter(eq(\"dt.entityhost\",HOST-123))", + "warnings": [ + "The dimension key `dt.entityhost` has been referenced, but the metric has no such key." + ] + } + ], + "totalCount": 3, + "warnings": [ + "The dimension key `dt.entityhost` has been referenced, but the metric has no such key." + ] + } \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_metrics_query_4fa21773411125d.json b/test/mock_data/GET_api_v2_metrics_query_4fa21773411125d.json new file mode 100644 index 0000000..cff2113 --- /dev/null +++ b/test/mock_data/GET_api_v2_metrics_query_4fa21773411125d.json @@ -0,0 +1,42 @@ +{ + "nextPageKey": null, + "resolution": "1h", + "result": [ + { + "data": [ + { + "dimensionMap": { + "dt.entity.host": "HOST-82F576674F19AC16" + }, + "dimensions": [ + "HOST-82F576674F19AC16" + ], + "timestamps": [ + 3151435100000, + 3151438700000, + 3151442300000 + ], + "values": [ + 11.1, + 22.2, + 33.3 + ] + } + ], + "dataPointCountRatio": "0.1211", + "dimensionCountRatio": "0.0322", + "metricId": "builtin:host.cpu.idle" + }, + { + "data": [], + "metricId": "builtin:host.cpu.idle:filter(eq(\"dt.entityhost\",HOST-123))", + "warnings": [ + "The dimension key `dt.entityhost` has been referenced, but the metric has no such key." + ] + } + ], + "totalCount": 3, + "warnings": [ + "The dimension key `dt.entityhost` has been referenced, but the metric has no such key." + ] + } \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_2e5fcbd2c8d0e63.json b/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_2e5fcbd2c8d0e63.json new file mode 100644 index 0000000..a5d26cd --- /dev/null +++ b/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_2e5fcbd2c8d0e63.json @@ -0,0 +1,10 @@ +{ + "jobs": [ + { + "endTime": "2020-11-05T08:15:30.144Z", + "entityType": "ONE_AGENT", + "id": "7974003406714390819", + "startTime": "2020-11-05T08:15:30.144Z" + } + ] + } \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_7974003406714390819.json b/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_7974003406714390819.json new file mode 100644 index 0000000..fa2a4f4 --- /dev/null +++ b/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_7974003406714390819.json @@ -0,0 +1,16 @@ +{ + "endTime": "2020-11-05T08:15:30.144Z", + "entityType": "ONE_AGENT", + "id": "7974003406714390819", + "operations": [ + { + "attribute": "networkZone", + "operation": "set", + "value": "test-zone" + } + ], + "processedEntitiesCount": 1, + "startTime": "2020-11-05T08:15:30.144Z", + "timeoutTime": "2020-11-05T08:15:30.144Z", + "totalEntitiesCount": 1 + } \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_current.json b/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_current.json new file mode 100644 index 0000000..fa2a4f4 --- /dev/null +++ b/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_current.json @@ -0,0 +1,16 @@ +{ + "endTime": "2020-11-05T08:15:30.144Z", + "entityType": "ONE_AGENT", + "id": "7974003406714390819", + "operations": [ + { + "attribute": "networkZone", + "operation": "set", + "value": "test-zone" + } + ], + "processedEntitiesCount": 1, + "startTime": "2020-11-05T08:15:30.144Z", + "timeoutTime": "2020-11-05T08:15:30.144Z", + "totalEntitiesCount": 1 + } \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_preview_4cfaf0a9b26d2dd.json b/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_preview_4cfaf0a9b26d2dd.json new file mode 100644 index 0000000..4d9d0b7 --- /dev/null +++ b/test/mock_data/GET_api_v2_oneagents_remoteConfigurationManagement_preview_4cfaf0a9b26d2dd.json @@ -0,0 +1,11 @@ +{ + "previews": [ + { + "alreadyConfiguredEntitiesCount": 1, + "attribute": "networkZone", + "operation": "set", + "targetEntitiesCount": 2, + "value": "test-zone" + } + ] + } \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_problems_-1719139739592062093_1623004451641V2_comments_0fe92b50cb1bdcb.json b/test/mock_data/GET_api_v2_problems_-1719139739592062093_1623004451641V2_comments_0fe92b50cb1bdcb.json new file mode 100644 index 0000000..da976ec --- /dev/null +++ b/test/mock_data/GET_api_v2_problems_-1719139739592062093_1623004451641V2_comments_0fe92b50cb1bdcb.json @@ -0,0 +1,7 @@ +{ + "authorName": "string", + "content": "string", + "context": "string", + "createdAtTimestamp": 1, + "id": "string" +} \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_problems_-1719139739592062093_1623004451641V2_comments_adba23bf24edbcc.json b/test/mock_data/GET_api_v2_problems_-1719139739592062093_1623004451641V2_comments_adba23bf24edbcc.json new file mode 100644 index 0000000..13a446b --- /dev/null +++ b/test/mock_data/GET_api_v2_problems_-1719139739592062093_1623004451641V2_comments_adba23bf24edbcc.json @@ -0,0 +1,21 @@ +{ + "comments": [ + { + "authorName": "string", + "content": "string", + "context": "string", + "createdAtTimestamp": 1, + "id": "string" + }, + { + "authorName": "string", + "content": "string", + "context": "string", + "createdAtTimestamp": 2, + "id": "string" + } + ], + "nextPageKey": "AQAAABQBAAAABQ==", + "pageSize": 1, + "totalCount": 1 + } \ No newline at end of file diff --git a/test/mock_data/POST_api_v2_activeGates_remoteConfigurationManagement.json b/test/mock_data/POST_api_v2_activeGates_remoteConfigurationManagement.json new file mode 100644 index 0000000..70180a2 --- /dev/null +++ b/test/mock_data/POST_api_v2_activeGates_remoteConfigurationManagement.json @@ -0,0 +1,16 @@ +{ + "endTime": "2020-11-05T08:15:30.144Z", + "entityType": "ACTIVE_GATE", + "id": "7974003406714390819", + "operations": [ + { + "attribute": "networkZone", + "operation": "set", + "value": "test-zone" + } + ], + "processedEntitiesCount": 1, + "startTime": "2020-11-05T08:15:30.144Z", + "timeoutTime": "2020-11-05T08:15:30.144Z", + "totalEntitiesCount": 1 + } \ No newline at end of file diff --git a/test/mock_data/POST_api_v2_activeGates_remoteConfigurationManagement_validator.json b/test/mock_data/POST_api_v2_activeGates_remoteConfigurationManagement_validator.json new file mode 100644 index 0000000..e69de29 diff --git a/test/mock_data/POST_api_v2_oneagents_remoteConfigurationManagement.json b/test/mock_data/POST_api_v2_oneagents_remoteConfigurationManagement.json new file mode 100644 index 0000000..fa2a4f4 --- /dev/null +++ b/test/mock_data/POST_api_v2_oneagents_remoteConfigurationManagement.json @@ -0,0 +1,16 @@ +{ + "endTime": "2020-11-05T08:15:30.144Z", + "entityType": "ONE_AGENT", + "id": "7974003406714390819", + "operations": [ + { + "attribute": "networkZone", + "operation": "set", + "value": "test-zone" + } + ], + "processedEntitiesCount": 1, + "startTime": "2020-11-05T08:15:30.144Z", + "timeoutTime": "2020-11-05T08:15:30.144Z", + "totalEntitiesCount": 1 + } \ No newline at end of file diff --git a/test/mock_data/POST_api_v2_oneagents_remoteConfigurationManagement_validator.json b/test/mock_data/POST_api_v2_oneagents_remoteConfigurationManagement_validator.json new file mode 100644 index 0000000..e69de29