From 2c2e8e122317e17768d9a807bf5ca2f4f120d571 Mon Sep 17 00:00:00 2001 From: Kitson Date: Fri, 12 Jan 2024 17:00:15 -0500 Subject: [PATCH 1/2] settings changes to align with API and rest of project --- dynatrace/environment_v2/settings.py | 183 +++++++++++++----- test/environment_v2/test_settings.py | 70 ++++--- ...i_v2_settings_objects_1eafd8dc0bf2543.json | 69 +++++++ ...i_v2_settings_objects_804a7afa1d2a354.json | 31 --- ...zMC05NWFiLTliMzNkMmQwZGRkY77vVN4V2t6t.json | 24 --- ...TEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ.json | 43 ++++ ...i_v2_settings_objects_48f5d7ab33b29d3.json | 1 + ...i_v2_settings_objects_a47ba18512efbe8.json | 6 - ...ings_objects_unittest_6ea3a764200250e.json | 4 - ...jE3OTc0YjC-71TeFdrerQ_193f82b398660c4.json | 1 + 10 files changed, 299 insertions(+), 133 deletions(-) create mode 100644 test/mock_data/GET_api_v2_settings_objects_1eafd8dc0bf2543.json delete mode 100644 test/mock_data/GET_api_v2_settings_objects_804a7afa1d2a354.json delete mode 100644 test/mock_data/GET_api_v2_settings_objects_vu9U3hXa3q0AAAABABdidWlsdGluOm93bmVyc2hpcC50ZWFtcwAGdGVuYW50AAZ0ZW5hbnQAJGVjN2UyNTdhLWM5MTktM2YzMC05NWFiLTliMzNkMmQwZGRkY77vVN4V2t6t.json create mode 100644 test/mock_data/GET_api_v2_settings_objects_vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ.json create mode 100644 test/mock_data/POST_api_v2_settings_objects_48f5d7ab33b29d3.json delete mode 100644 test/mock_data/POST_api_v2_settings_objects_a47ba18512efbe8.json delete mode 100644 test/mock_data/PUT_api_v2_settings_objects_unittest_6ea3a764200250e.json create mode 100644 test/mock_data/PUT_api_v2_settings_objects_vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ_193f82b398660c4.json diff --git a/dynatrace/environment_v2/settings.py b/dynatrace/environment_v2/settings.py index bdd78e4..68dee56 100644 --- a/dynatrace/environment_v2/settings.py +++ b/dynatrace/environment_v2/settings.py @@ -1,8 +1,10 @@ -from typing import Optional, Dict, Any +from typing import Optional, Dict, Any, List, Union +from datetime import datetime from dynatrace.dynatrace_object import DynatraceObject from dynatrace.http_client import HttpClient from dynatrace.pagination import PaginatedList +from dynatrace.utils import int64_to_datetime class SettingService: @@ -10,11 +12,17 @@ class SettingService: def __init__(self, http_client: HttpClient): self.__http_client = http_client - - def list_objects(self,schema_id: Optional[str] = None, - scope: Optional[str] = None,external_ids: Optional[str] = None, - fields: Optional[str] = None, - filter:Optional[str] = None, sort:Optional[str] = None, page_size:Optional[str] = None) -> PaginatedList["DynatraceObject"]: + + def list_objects( + self, + schema_id: Optional[str] = None, + scope: Optional[str] = None, + external_ids: Optional[str] = None, + fields: Optional[str] = None, + filter: Optional[str] = None, + sort: Optional[str] = None, + page_size: Optional[str] = None, + ) -> PaginatedList["SettingsObject"]: """Lists settings :return: a list of settings with details @@ -28,64 +36,151 @@ def list_objects(self,schema_id: Optional[str] = None, "sort": sort, "pageSize": page_size, } - return PaginatedList(Settings, self.__http_client, target_url=self.ENDPOINT, list_item="items", target_params=params) - - def create_object(self,external_id,object_id,schema_id,schema_version,scope, value,validate_only): - """Creates a new settings object + return PaginatedList( + SettingsObject, + self.__http_client, + target_url=self.ENDPOINT, + list_item="items", + target_params=params, + ) - :param external_id: External identifier for the object being created - :param object_id: The ID of the settings object that should be replaced. Only applicable if an external identifier - :param object_id: the ID of the object - :param schema_id: The schema on which the object is based - :param schema_version: The version of the schema on which the object is based. - :param scope The scope that the object targets. For more details, please see Dynatrace Documentation. - :param value The value of the setting. - :return: a Settings object - """ - params = { - "validate_only": validate_only, - } - body =[ { - "externalId" : external_id, - "objectId": object_id, - "schemaId": schema_id, - "schemaVersion": schema_version, - "scope": scope, - "value" : value + def create_object( + self, + validate_only: Optional[bool] = False, + body: Union[ + Optional[List["SettingsObjectCreate"]], Optional["SettingsObjectCreate"] + ] = [], + ): + """ + Creates a new settings object or validates the provided settigns object + + :param validate_only: If true, the request runs only validation of the submitted settings objects, without saving them + :param body: The JSON body of the request. Contains the settings objects + """ + query_params = {"validateOnly": validate_only} - }] - - response = self.__http_client.make_request(self.ENDPOINT,params=body, method="POST",query_params=params).json() + if type(body) == SettingsObjectCreate: + body = [body] + + body = [o.json() for o in body] + + response = self.__http_client.make_request( + self.ENDPOINT, params=body, method="POST", query_params=query_params + ).json() return response - - + def get_object(self, object_id: str): """Gets parameters of specified settings object :param object_id: the ID of the object :return: a Settings object """ - response = self.__http_client.make_request(f"{self.ENDPOINT}/{object_id}").json() - return Settings(raw_element=response) + response = self.__http_client.make_request( + f"{self.ENDPOINT}/{object_id}" + ).json() + return SettingsObject(raw_element=response) - def update_object(self, object_id: str, value): + def update_object( + self, object_id: str, value: Optional["SettingsObjectCreate"] = None + ): """Updates an existing settings object - - :param object_id: the ID of the object + :param object_id: the ID of the object + :param value: the JSON body of the request. Contains updated parameters of the settings object. """ - return self.__http_client.make_request(path=f"{self.ENDPOINT}/{object_id}", params=value, method="PUT") + return self.__http_client.make_request( + f"{self.ENDPOINT}/{object_id}", params=value.json(), method="PUT" + ) - def delete_object(self, object_id: str): + def delete_object(self, object_id: str, update_token: Optional[str] = None): """Deletes the specified object :param object_id: the ID of the object + :param update_token: The update token of the object. You can use it to detect simultaneous modifications by different users :return: HTTP response """ - return self.__http_client.make_request(path=f"{self.ENDPOINT}/{object_id}", method="DELETE") + query_params = {"updateToken": update_token} + return self.__http_client.make_request( + f"{self.ENDPOINT}/{object_id}", + method="DELETE", + query_params=query_params, + ).json() + + +class ModificationInfo(DynatraceObject): + def _create_from_raw_data(self, raw_element: Dict[str, Any]): + self.deleteable: bool = raw_element.get("deleteable") + self.first: bool = raw_element.get("first") + self.modifiable: bool = raw_element.get("modifiable") + self.modifiable_paths: List[str] = raw_element.get("modifiablePaths", []) + self.movable: bool = raw_element.get("movable") + self.non_modifiable_paths: List[str] = raw_element.get("nonModifiablePaths", []) + -class Settings(DynatraceObject): +class SettingsObject(DynatraceObject): def _create_from_raw_data(self, raw_element: Dict[str, Any]): # Mandatory self.objectId: str = raw_element["objectId"] - self.value: str = raw_element["value"] + self.value: dict = raw_element["value"] + # Optional + self.author: str = raw_element.get("author") + self.created: datetime = ( + int64_to_datetime(int(raw_element.get("created"))) + if raw_element.get("created") + else None + ) + self.created_by: str = raw_element.get("createdBy") + self.external_id: str = raw_element.get("externalId") + self.modification_info: ModificationInfo = ( + ModificationInfo( + self._http_client, self._headers, raw_element.get("modificationInfo") + ) + if raw_element.get("modificationInfo") + else None + ) + self.modified: datetime = ( + int64_to_datetime(int(raw_element.get("modified"))) + if raw_element.get("modified") + else None + ) + self.modified_by: str = raw_element.get("modifiedBy") + self.schema_id: str = raw_element.get("schemaId") + self.schema_version: str = raw_element.get("schemaVersion") + self.scope: str = raw_element.get("scope") + self.search_summary: str = raw_element.get("searchSummary") + self.summary: str = raw_element.get("summary") + self.update_token: str = raw_element.get("updateToken") + + +class SettingsObjectCreate: + def __init__( + self, + schema_id: str, + value: dict, + scope: str, + external_id: Optional[str] = None, + insert_after: Optional[str] = None, + object_id: Optional[str] = None, + schema_version: Optional[str] = None, + ): + self.schema_id = schema_id + self.value = value + self.scope = scope + self.external_id = external_id + self.insert_after = insert_after + self.object_id = object_id + self.schema_version = schema_version + + def json(self) -> dict: + body = {"schemaId": self.schema_id, "value": self.value, "scope": self.scope} + + if self.external_id: + body["externalId"] = self.external_id + if self.insert_after: + body["insertAfter"] = self.insert_after + if self.object_id: + body["objectId"] = self.object_id + if self.schema_version: + body["schemaVersion"] = self.schema_version + + return body diff --git a/test/environment_v2/test_settings.py b/test/environment_v2/test_settings.py index 7f8f00a..8a19ec1 100644 --- a/test/environment_v2/test_settings.py +++ b/test/environment_v2/test_settings.py @@ -1,37 +1,59 @@ from datetime import datetime -import dynatrace.environment_v2.settings as st +from dynatrace.environment_v2.settings import SettingsObject, SettingsObjectCreate from dynatrace import Dynatrace from dynatrace.pagination import PaginatedList -payload = {"additionalInformation": [], - "contactDetails":[{"email": 'unittest@contoso.com', "integrationType": "EMAIL"}], - "description": 'unittest', - "identifier":'unittest', - "links": [], - "name": 'unittest', - "responsibilities": {"development": False, - "infrastructure": False, - "lineOfBusiness": True, - "operations": False, - "security": False}, - "supplementaryIdentifiers": [] } + +settings_dict = { + "enabled": True, + "summary": "DT API TEST 22", + "queryDefinition": { + "type": "METRIC_KEY", + "metricKey": "netapp.ontap.node.fru.state", + "aggregation": "AVG", + "entityFilter": { + "dimensionKey": "dt.entity.netapp_ontap:fru", + "conditions": [], + }, + "dimensionFilter": [], + }, + "modelProperties": { + "type": "STATIC_THRESHOLD", + "threshold": 100.0, + "alertOnNoData": False, + "alertCondition": "BELOW", + "violatingSamples": 3, + "samples": 5, + "dealertingSamples": 5, + }, + "eventTemplate": { + "title": "OnTap {dims:type} {dims:fru_id} is in Error State", + "description": "OnTap field replaceable unit (FRU) {dims:type} with id {dims:fru_id} on node {dims:node} in cluster {dims:cluster} is in an error state.\n", + "eventType": "RESOURCE", + "davisMerge": True, + "metadata": [], + }, + "eventEntityDimensionKey": "dt.entity.netapp_ontap:fru", + } +settings_object = SettingsObjectCreate("builtin:anomaly-detection.metric-events", settings_dict, "environment") +test_object_id = "vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ" + def test_list_objects(dt: Dynatrace): - settings = dt.settings.list_objects(schema_id="builtin:ownership.teams") + settings = dt.settings.list_objects(schema_id="builtin:anomaly-detection.metric-events") assert isinstance(settings, PaginatedList) - assert len(list(settings)) == 1 - assert all(isinstance(s, st.Settings) for s in settings) + assert len(list(settings)) == 2 + assert all(isinstance(s, SettingsObject) for s in settings) def test_get_object(dt: Dynatrace): - setting = dt.settings.get_object(object_id="vu9U3hXa3q0AAAABABdidWlsdGluOm93bmVyc2hpcC50ZWFtcwAGdGVuYW50AAZ0ZW5hbnQAJGVjN2UyNTdhLWM5MTktM2YzMC05NWFiLTliMzNkMmQwZGRkY77vVN4V2t6t") - assert isinstance(setting, st.Settings) + setting = dt.settings.get_object(object_id=test_object_id) + assert isinstance(setting, SettingsObject) + assert setting.schema_version == "1.0.16" def test_post_object(dt: Dynatrace): - - response = dt.settings.create_object(external_id='unittest',object_id='unittest',schema_id="builtin:ownership.teams",schema_version="1.0.6",scope="environment", value=payload,validate_only=False) + response = dt.settings.create_object(body=settings_object) assert response[0].get("code") == 200 - assert response[0].get("code") is not None def test_put_object(dt: Dynatrace): - payload["identifier"] = "unittestupdate" - response = dt.settings.update_object("unittest",payload) - print(response) \ No newline at end of file + response = dt.settings.update_object(test_object_id, settings_object) + print(response) + \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_settings_objects_1eafd8dc0bf2543.json b/test/mock_data/GET_api_v2_settings_objects_1eafd8dc0bf2543.json new file mode 100644 index 0000000..dc3c252 --- /dev/null +++ b/test/mock_data/GET_api_v2_settings_objects_1eafd8dc0bf2543.json @@ -0,0 +1,69 @@ +{ + "items": [ + { + "objectId": "vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACQ4OWNhMmY2Ny0wY2Q3LTM0MzAtYmU5Ny1kOTg4YTRmMWRiYWa-71TeFdrerQ", + "value": { + "enabled": true, + "summary": "OnTap Node Field Replaceable Unit in Error State", + "queryDefinition": { + "type": "METRIC_KEY", + "metricKey": "netapp.ontap.node.fru.state", + "aggregation": "AVG", + "entityFilter": { + "dimensionKey": "dt.entity.netapp_ontap:fru", + "conditions": [] + }, + "dimensionFilter": [] + }, + "modelProperties": { + "type": "STATIC_THRESHOLD", + "threshold": 100.0, + "alertOnNoData": false, + "alertCondition": "BELOW", + "violatingSamples": 3, + "samples": 5, + "dealertingSamples": 5 + }, + "eventTemplate": { + "title": "OnTap {dims:type} {dims:fru_id} is in Error State", + "description": "OnTap field replaceable unit (FRU) {dims:type} with id {dims:fru_id} on node {dims:node} in cluster {dims:cluster} is in an error state.\n", + "eventType": "RESOURCE", + "davisMerge": true, + "metadata": [] + }, + "eventEntityDimensionKey": "dt.entity.netapp_ontap:fru" + } + }, + { + "objectId": "vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACQ5MjRiNjdiYS00OGQ1LTM0NDctODg4Zi05NzUzMzg5NzcxMze-71TeFdrerQ", + "value": { + "enabled": false, + "summary": "High outbound bandwidth utilization", + "queryDefinition": { + "type": "METRIC_SELECTOR", + "metricSelector": "func:com.dynatrace.extension.snmp-generic-cisco-device.if.out.bandwidth" + }, + "modelProperties": { + "type": "STATIC_THRESHOLD", + "threshold": 90.0, + "alertOnNoData": false, + "alertCondition": "ABOVE", + "violatingSamples": 3, + "samples": 5, + "dealertingSamples": 5 + }, + "eventTemplate": { + "title": "High outbound bandwidth utilization", + "description": "The {metricname} value of {severity} was {alert_condition} your custom threshold of {threshold}.", + "eventType": "CUSTOM_ALERT", + "davisMerge": false, + "metadata": [] + }, + "eventEntityDimensionKey": "dt.entity.snmp:com_dynatrace_extension_snmp_generic_cisco_network_interface", + "legacyId": "E|649d5713-380b-6751-a64f-6904a2c4cd2f" + } + } + ], + "totalCount": 25, + "pageSize": 100 +} \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_settings_objects_804a7afa1d2a354.json b/test/mock_data/GET_api_v2_settings_objects_804a7afa1d2a354.json deleted file mode 100644 index a9548af..0000000 --- a/test/mock_data/GET_api_v2_settings_objects_804a7afa1d2a354.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "items": [ - - { - "objectId": "vu9U3hXa3q0AAAABABdidWlsdGluOm93bmVyc2hpcC50ZWFtcwAGdGVuYW50AAZ0ZW5hbnQAJGVjN2UyNTdhLWM5MTktM2YzMC05NWFiLTliMzNkMmQwZGRkY77vVN4V2t6t", - "value": { - "name": "user", - "description": "user", - "identifier": "user", - "supplementaryIdentifiers": [], - "responsibilities": { - "development": false, - "security": false, - "operations": false, - "infrastructure": true, - "lineOfBusiness": false - }, - "contactDetails": [ - { - "integrationType": "EMAIL", - "email": "test@contoso.com" - } - ], - "links": [], - "additionalInformation": [] - } - } - ], - "totalCount": 1, - "pageSize": 500 -} \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_settings_objects_vu9U3hXa3q0AAAABABdidWlsdGluOm93bmVyc2hpcC50ZWFtcwAGdGVuYW50AAZ0ZW5hbnQAJGVjN2UyNTdhLWM5MTktM2YzMC05NWFiLTliMzNkMmQwZGRkY77vVN4V2t6t.json b/test/mock_data/GET_api_v2_settings_objects_vu9U3hXa3q0AAAABABdidWlsdGluOm93bmVyc2hpcC50ZWFtcwAGdGVuYW50AAZ0ZW5hbnQAJGVjN2UyNTdhLWM5MTktM2YzMC05NWFiLTliMzNkMmQwZGRkY77vVN4V2t6t.json deleted file mode 100644 index ce6aebb..0000000 --- a/test/mock_data/GET_api_v2_settings_objects_vu9U3hXa3q0AAAABABdidWlsdGluOm93bmVyc2hpcC50ZWFtcwAGdGVuYW50AAZ0ZW5hbnQAJGVjN2UyNTdhLWM5MTktM2YzMC05NWFiLTliMzNkMmQwZGRkY77vVN4V2t6t.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "objectId": "vu9U3hXa3q0AAAABABdidWlsdGluOm93bmVyc2hpcC50ZWFtcwAGdGVuYW50AAZ0ZW5hbnQAJGVjN2UyNTdhLWM5MTktM2YzMC05NWFiLTliMzNkMmQwZGRkY77vVN4V2t6t", - "value": { - "name": "user", - "description": "user", - "identifier": "user", - "supplementaryIdentifiers": [], - "responsibilities": { - "development": false, - "security": false, - "operations": false, - "infrastructure": true, - "lineOfBusiness": false - }, - "contactDetails": [ - { - "integrationType": "EMAIL", - "email": "test@contoso.com" - } - ], - "links": [], - "additionalInformation": [] - } -} \ No newline at end of file diff --git a/test/mock_data/GET_api_v2_settings_objects_vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ.json b/test/mock_data/GET_api_v2_settings_objects_vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ.json new file mode 100644 index 0000000..a84dd70 --- /dev/null +++ b/test/mock_data/GET_api_v2_settings_objects_vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ.json @@ -0,0 +1,43 @@ +{ + "objectId": "vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ", + "summary": "DT API TEST 22", + "searchSummary": "DT API TEST 22", + "created": 1705095249587, + "modified": 1705095274757, + "author": "dt0c01.EZN2OP5XE26C3I5ZA2NTHTF5", + "updateToken": "vu9U3hXY3q0ATAAkYmJmM2VjYTctMzJmZi0zNmUxLTkxYjktOWNkMWYxNzk3NGIwACQ2MTFiMTM1MC1iMTkyLTExZWUtODAwMS0wMTAwMDAwMDAwMDi-71TeFdjerQ", + "scope": "environment", + "schemaId": "builtin:anomaly-detection.metric-events", + "schemaVersion": "1.0.16", + "value": { + "enabled": true, + "summary": "DT API TEST 22", + "queryDefinition": { + "type": "METRIC_KEY", + "metricKey": "netapp.ontap.node.fru.state", + "aggregation": "AVG", + "entityFilter": { + "dimensionKey": "dt.entity.netapp_ontap:fru", + "conditions": [] + }, + "dimensionFilter": [] + }, + "modelProperties": { + "type": "STATIC_THRESHOLD", + "threshold": 100.0, + "alertOnNoData": false, + "alertCondition": "BELOW", + "violatingSamples": 3, + "samples": 5, + "dealertingSamples": 5 + }, + "eventTemplate": { + "title": "OnTap {dims:type} {dims:fru_id} is in Error State", + "description": "OnTap field replaceable unit (FRU) {dims:type} with id {dims:fru_id} on node {dims:node} in cluster {dims:cluster} is in an error state.\n", + "eventType": "RESOURCE", + "davisMerge": true, + "metadata": [] + }, + "eventEntityDimensionKey": "dt.entity.netapp_ontap:fru" + } +} \ No newline at end of file diff --git a/test/mock_data/POST_api_v2_settings_objects_48f5d7ab33b29d3.json b/test/mock_data/POST_api_v2_settings_objects_48f5d7ab33b29d3.json new file mode 100644 index 0000000..f684b81 --- /dev/null +++ b/test/mock_data/POST_api_v2_settings_objects_48f5d7ab33b29d3.json @@ -0,0 +1 @@ +[{"code": 200, "objectId": "vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACQwMjA1ZjE2ZS0yMzI5LTMxMzktYmJmNS0zZTNmMTAyNzA0MjC-71TeFdrerQ"}] \ No newline at end of file diff --git a/test/mock_data/POST_api_v2_settings_objects_a47ba18512efbe8.json b/test/mock_data/POST_api_v2_settings_objects_a47ba18512efbe8.json deleted file mode 100644 index eea4685..0000000 --- a/test/mock_data/POST_api_v2_settings_objects_a47ba18512efbe8.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "code": 200, - "objectId": "vu9U3hXa3q0AAAABABdidWlsdGluOm93bmVyc2hpcC50ZWFtcwAGdGVuYW50AAZ0ZW5hbnQAJDVhNjk1MzViLWQ3NDYtMzVmYi05MDdjLTM2ODNkMmMyNWQzOb7vVN4V2t6t" - } -] \ No newline at end of file diff --git a/test/mock_data/PUT_api_v2_settings_objects_unittest_6ea3a764200250e.json b/test/mock_data/PUT_api_v2_settings_objects_unittest_6ea3a764200250e.json deleted file mode 100644 index d8fcd3c..0000000 --- a/test/mock_data/PUT_api_v2_settings_objects_unittest_6ea3a764200250e.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "code": 200, - "objectId": "vu9U3hXa3q0AAAABABdidWlsdGluOm93bmVyc2hpcC50ZWFtcwAGdGVuYW50AAZ0ZW5hbnQAJDVhNjk1MzViLWQ3NDYtMzVmYi05MDdjLTM2ODNkMmMyNWQzOb7vVN4V2t6t" -} \ No newline at end of file diff --git a/test/mock_data/PUT_api_v2_settings_objects_vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ_193f82b398660c4.json b/test/mock_data/PUT_api_v2_settings_objects_vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ_193f82b398660c4.json new file mode 100644 index 0000000..8d30390 --- /dev/null +++ b/test/mock_data/PUT_api_v2_settings_objects_vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ_193f82b398660c4.json @@ -0,0 +1 @@ +{"code": 200, "objectId": "vu9U3hXa3q0AAAABACdidWlsdGluOmFub21hbHktZGV0ZWN0aW9uLm1ldHJpYy1ldmVudHMABnRlbmFudAAGdGVuYW50ACRiYmYzZWNhNy0zMmZmLTM2ZTEtOTFiOS05Y2QxZjE3OTc0YjC-71TeFdrerQ"} \ No newline at end of file From 67fd8cfb91af26c407a127a05fe39e5467443901 Mon Sep 17 00:00:00 2001 From: Kitson Date: Fri, 12 Jan 2024 17:04:02 -0500 Subject: [PATCH 2/2] use isinstance for typecheck --- dynatrace/environment_v2/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynatrace/environment_v2/settings.py b/dynatrace/environment_v2/settings.py index 68dee56..b3f8f46 100644 --- a/dynatrace/environment_v2/settings.py +++ b/dynatrace/environment_v2/settings.py @@ -59,7 +59,7 @@ def create_object( """ query_params = {"validateOnly": validate_only} - if type(body) == SettingsObjectCreate: + if isinstance(body, SettingsObjectCreate): body = [body] body = [o.json() for o in body]