diff --git a/setup.py b/setup.py index 9b0ca9d..c966824 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( name='TDXLib', description='a python library for interacting with the TeamDynamix Web API', - version='0.2.14', + version='0.3.0', author='Nat Biggs, Stephen Gaines, Josiah Lansford', author_email='tdxlib@cedarville.edu', packages=['tdxlib'], diff --git a/tdxlib/__init__.py b/tdxlib/__init__.py index 41dda73..535f8ed 100644 --- a/tdxlib/__init__.py +++ b/tdxlib/__init__.py @@ -7,4 +7,4 @@ import tdxlib.tdx_ticket import tdxlib.tdx_utils -__version__ = "0.2.14" +__version__ = "0.3.0" diff --git a/tdxlib/tdx_asset_integration.py b/tdxlib/tdx_asset_integration.py index d3fb1fc..96393b8 100644 --- a/tdxlib/tdx_asset_integration.py +++ b/tdxlib/tdx_asset_integration.py @@ -1,4 +1,6 @@ +import copy import datetime +import tdx_utils import tdxlib.tdx_integration from tdxlib.tdx_api_exceptions import * @@ -383,6 +385,48 @@ def get_asset_by_id(self, asset_id: str) -> dict: """ return self.make_call(str(asset_id), 'get') + def add_asset_user(self, asset_id: str, user_uid: str): + """ + Adds a users to an asset + + :param asset_id: the ID of the asset to get users + :param user_uid: the UID of the person to add + + :return: the API's response (success/failure only) + """ + return self.make_call(f'{asset_id}/users/{user_uid}', 'post', {'data': None}) + + def get_asset_users(self, asset_id: str) -> list: + """ + Gets users of an asset + + :param asset_id: the ID of the asset to get users + + :return: list of this asset's users, each represented by a dict + + """ + return self.make_call(f'{asset_id}/users', 'get') + + def delete_asset_users(self, asset_id: str, users: list): + """ + Deletes specified users of an asset + + :param asset_id: the ID of the asset to delete users from + :param users: a list of the users (maybe from get_asset_users()) or user UIDs to delete + + :return: list of this asset's users, each represented by a dict + + """ + results = list() + if not isinstance(users, list): + users = [users] + for user in users: + if isinstance(user, str): + id_to_delete = user + else: + id_to_delete = user['Value'] + results.append(self.make_call(f'{asset_id}/users/{id_to_delete}', 'delete')) + def search_assets(self, criteria, max_results=25, retired=False, disposed=False, full_record=False) -> list: """ Searches for assets, based on criteria @@ -620,41 +664,59 @@ def update_assets(self, assets, changed_attributes: dict, clear_custom_attribute :param assets: a list of assets (maybe from search_assets()) or a single asset (only ID required) :param changed_attributes: a dict of attributes in the ticket to be changed - :param clear_custom_attributes: (default: False) Indicates whether or not custom attributes should be cleared + :param clear_custom_attributes: (default: False) Indicates whether or not custom attributes not specified + in the changed_attributes argument should be cleared :return: list of updated assets """ changed_custom_attributes = False + # Get everything into a list if not isinstance(assets, list): asset_list = list() asset_list.append(assets) else: asset_list = assets updated_assets = list() + # Separate CA changes into their own object: 'changed_custom_attributes'.' + # need to make a full copy of this dict so we can reuse it + changed_attributes_copy = copy.deepcopy(changed_attributes) if 'Attributes' in changed_attributes: if isinstance(changed_attributes['Attributes'], list): changed_custom_attributes = changed_attributes['Attributes'] else: changed_custom_attributes = [changed_attributes['Attributes']] - del changed_attributes['Attributes'] + # Remove attributes field of "changed_attributes" so it doesn't mess up the existing asset(s) CA's + # need to set it to an empty list first so it doesn't delete the object that was passed in + del changed_attributes_copy['Attributes'] for this_asset in asset_list: - this_asset = self.get_asset_by_id(this_asset['ID']) - if 'Attributes' not in this_asset.keys(): - this_asset['Attributes'] = [] - if changed_custom_attributes and not clear_custom_attributes: + # Need to get the full record so that we can see existing CA's + if isinstance(this_asset, str) or isinstance(this_asset, int): + full_asset = self.get_asset_by_id(this_asset) + else: + full_asset = self.get_asset_by_id(this_asset['ID']) + # not totally sure the first part is necessary. I think it always comes through as an empty list if no CA's + if 'Attributes' not in full_asset.keys() or clear_custom_attributes: + full_asset['Attributes'] = [] + # we take this branch if we have attributes to update, and we're not clobbering existing CA's + if changed_custom_attributes: + # Loop through each of the CAs to be changed for new_attrib in changed_custom_attributes: + # Drop a marker so we know if new_attrib_marker = True - for attrib in this_asset['Attributes']: + # Loop through the existing CA's, to look for stuff to update + for attrib in full_asset['Attributes']: + # if we find a match, we update it in the existing asset record if str(new_attrib['ID']) == str(attrib['ID']): attrib['Value'] = new_attrib['Value'] new_attrib_marker = False + # if we go through all the asset's CA's, an haven't updated something, we just put it in. if new_attrib_marker: - this_asset['Attributes'].append(new_attrib) - if clear_custom_attributes: - this_asset['Attributes'] = [] - this_asset.update(changed_attributes) - updated_assets.append(self.make_call(str(this_asset['ID']), 'post', this_asset)) + full_asset['Attributes'].append(new_attrib) + # incorporate the non-custom changed attributes to the existing asset record + full_asset.update(changed_attributes_copy) + # Call a post with the existing asset record to update the values + updated_assets.append(self.make_call(str(full_asset['ID']), 'post', full_asset)) return updated_assets def change_asset_owner(self, asset, new_owner, new_dept=None) -> list: @@ -688,6 +750,39 @@ def change_asset_owner(self, asset, new_owner, new_dept=None) -> list: ) return self.update_assets(asset, changed_attributes) + def change_asset_location(self, asset, new_location, new_room=None): + """ + Updates Location data in a list of assets + + :param asset: asset to update (doesn't have to be full record), or list of same + :param new_location: name of new location, or dict of location data + :param new_room: name of new room, or dict of room data + + :return: list of the updated assets + + """ + changed_attributes = dict() + if isinstance(new_location, str): + location = self.get_location_by_name(new_location) + changed_attributes['LocationID'] = location['ID'] + elif isinstance(new_location, dict): + location = new_location + changed_attributes['LocationID'] = new_location['ID'] + else: + raise TdxApiObjectTypeError( + f"Department of type {str(type(new_location))} not searchable." + ) + if new_room: + if isinstance(new_room, str): + changed_attributes['LocationRoomID'] = self.get_room_by_name(location, new_room) + elif isinstance(new_location, dict): + changed_attributes['LocationRoomID'] = new_room['ID'] + else: + raise TdxApiObjectTypeError( + f"Department of type {str(type(new_location))} not searchable." + ) + return self.update_assets(asset, changed_attributes) + def change_asset_requesting_dept(self, asset, new_dept)-> list: """ Updates Requesting Department data in a list of assets @@ -730,6 +825,8 @@ def build_asset_custom_attribute_value(self, custom_attribute, value) -> dict: if len(ca['Choices']) > 0: ca_choice = self.get_custom_attribute_choice_by_name_id(ca, value) value = ca_choice['ID'] + if isinstance(value, datetime.datetime): + value = tdx_utils.export_tdx_date(value) return {'ID': ca['ID'], 'Value': value} def change_asset_custom_attribute_value(self, asset, custom_attributes: list) -> list: @@ -744,6 +841,49 @@ def change_asset_custom_attribute_value(self, asset, custom_attributes: list) -> to_change = {'Attributes': custom_attributes} return self.update_assets(asset, to_change) + def clear_asset_custom_attributes(self, asset: dict, attributes_to_clear: list): + """ + Takes a list of CA names and removes those custom attributes from the provided asset + + :param asset: asset to update (doesn't have to be full record) + :param attributes_to_clear: List of names of custom attributes to remove + :return: the updated asset in dict format + """ + if not isinstance(attributes_to_clear, list): + attributes_to_clear = [attributes_to_clear] + full_asset = self.get_asset_by_id(asset['ID']) + to_change = {'Attributes': []} + for ca in full_asset['Attributes']: + if ca['Name'] not in attributes_to_clear: + to_change['Attributes'].append(ca) + return self.update_assets(full_asset, to_change, clear_custom_attributes=True)[0] + + def get_asset_custom_attribute_value_by_name(self, asset, key: str, id: bool=False) -> str: + """ + Returns the current value of a specific CA in the specified asset + + :param asset: asset to get CA value for, in dict or ID form + :param key: Name or ID of CA to find in the asset + :param id: (Default: False) Return the ID of the value, instead of ValueText (only for choice-based CA's) + + :return: a string representation of the value or ID + """ + if isinstance(asset, str): + this_asset = self.get_asset_by_id(asset) + elif isinstance(asset, dict): + this_asset = asset + else: + raise TdxApiObjectTypeError( + f"Asset of type {str(type(asset))} not searchable." + ) + ca_id = self.get_asset_custom_attribute_by_name_id(key)['ID'] + for ca in this_asset['Attributes']: + if str(ca['ID']) == str(ca_id): + if ca['Choices'] and id: + return ca['Value'] + else: + return ca['ValueText'] + def move_child_assets(self, source_asset: dict, target_asset: dict) -> list: """ Moves child assets from one parent asset to another @@ -759,7 +899,8 @@ def move_child_assets(self, source_asset: dict, target_asset: dict) -> list: children = self.search_assets(search_params) return self.update_assets(children, update_params) - def copy_asset_attributes(self, source_asset, target_asset, copy_name=False, exclude=None, new_status: str = None): + def copy_asset_attributes(self, source_asset, target_asset, copy_name=False, exclude=None, new_status: str = None, + new_name: str = None, is_full_source=False): """ Copies asset attributes from one asset to another. Does not include attributes like Serial Number, Asset Tag, and other hardware-specific fields. @@ -769,24 +910,36 @@ def copy_asset_attributes(self, source_asset, target_asset, copy_name=False, exc :param copy_name: Set to true to copy the name of the source asset to the target asset :param exclude: List of attributes to be excluded, in addition to defaults :param new_status: Name or ID of new status for source asset + :param new_name: New name for source asset (usually used with copy_name=True). Default: False + :param is_full_source: Boolean indicating whether source_asset is a full asset record or not. Default: False :return: list of the target and source asset data """ - excluded_attributes = ['SerialNumber', 'Tag', 'ExternalID', 'ModelID', 'SupplierID', 'ManufacturerID', - 'PurchaseCost', 'ExpectedReplacementDate', 'AcquisitionDate'] + excluded_attributes = ['ID', 'SerialNumber', 'Tag', 'ExternalID', 'ModelID', 'SupplierID', 'ManufacturerID', + 'PurchaseCost', 'ExpectedReplacementDate', 'AcquisitionDate', 'MAC Address', + 'WiFi MAC Address', 'Year Purchased', 'Warranty Expiration Date', 'Order Number', + 'cu.Responsible Group', 'OwningCustomerID', 'OwningDepartmentID'] if exclude: excluded_attributes.append(exclude) if not copy_name: excluded_attributes.append('Name') - full_source = dict(self.get_asset_by_id(source_asset['ID'])) + if is_full_source: + full_source = source_asset + else: + full_source = self.get_asset_by_id(source_asset['ID']) + source_id = full_source['ID'] for protected_attribute in excluded_attributes: full_source.pop(protected_attribute, None) updated_target = self.update_assets(target_asset, full_source) updated_source = None - if new_status: - update_params = {'StatusID': self.get_asset_status_by_name_id(new_status)} - updated_source = self.update_assets(full_source, update_params) + if new_status or new_name or isinstance(new_name, str): + update_params = dict() + if new_status: + update_params['StatusID'] = self.get_asset_status_by_name_id(new_status)['ID'] + if new_name or isinstance(new_name, str): + update_params['Name'] = new_name + updated_source = self.update_assets(source_id, update_params) return [updated_target, updated_source] def build_asset(self, asset_name, serial_number, status_name, location_name=None, room_name=None, @@ -812,7 +965,7 @@ def build_asset(self, asset_name, serial_number, status_name, location_name=None :param external_id: String with external id for new asset (Default: serial Number) :param product_model: String with name of product model :param form: Name of the Asset form to use - :param asset_custom_attributes: a dictionary of asset custom attribute values + :param asset_custom_attributes: a dictionary of asset custom attribute values (or list from asset['Attributes']) :return: dict usable in create_asset() @@ -838,6 +991,10 @@ def build_asset(self, asset_name, serial_number, status_name, location_name=None # set up attribute values if asset_custom_attributes: data['Attributes'] = [] + if isinstance(asset_custom_attributes, dict) and 'Attributes' in asset_custom_attributes.keys(): + asset_custom_attributes = asset_custom_attributes['Attributes'] + if isinstance(asset_custom_attributes, list): + asset_custom_attributes = {i['Name']: i['Value'] for i in asset_custom_attributes} for attrib_name, value in asset_custom_attributes.items(): new_attrib = self.build_asset_custom_attribute_value(attrib_name, value) data['Attributes'].append(new_attrib) diff --git a/tdxlib/tdx_ticket_integration.py b/tdxlib/tdx_ticket_integration.py index b92e12c..878b590 100644 --- a/tdxlib/tdx_ticket_integration.py +++ b/tdxlib/tdx_ticket_integration.py @@ -109,7 +109,9 @@ def get_ticket_by_id(self, ticket_id: int) -> tdxlib.tdx_ticket.TDXTicket: :rtype: dict """ - return tdxlib.tdx_ticket.TDXTicket(self, self.make_call(str(ticket_id), 'get')) + ticket_data = self.make_call(str(ticket_id), 'get') + if ticket_data: + return tdxlib.tdx_ticket.TDXTicket(self, ticket_data) def search_tickets(self, criteria: dict, max_results: int = 25, closed: bool = False, cancelled: bool = False, other_status: bool = False) -> list: diff --git a/tdxlib/tdx_utils.py b/tdxlib/tdx_utils.py index c60535b..c5e13b9 100644 --- a/tdxlib/tdx_utils.py +++ b/tdxlib/tdx_utils.py @@ -2,6 +2,7 @@ import datetime import json + # Prints out dict as JSON with indents def print_nice(myjson): print(json.dumps(myjson, indent=4)) @@ -22,6 +23,7 @@ def print_simple(my_json, attributes=None): if i in j: print(i,':\t', j[i]) + # Print only ['Name'] attribute of list of objects def print_names(myjson): if isinstance(myjson,list): @@ -32,6 +34,7 @@ def print_names(myjson): if 'Name' in i: print(i['Name']) + # Imports a string from a TDX Datetime attribute, returns a python datetime object def import_tdx_date(date_string: str) -> datetime: return dateutil.parser.parse(date_string) diff --git a/testing/tdx_asset_testing.py b/testing/tdx_asset_testing.py index 06f71ea..2714740 100644 --- a/testing/tdx_asset_testing.py +++ b/testing/tdx_asset_testing.py @@ -1,10 +1,7 @@ import unittest import json -import time from datetime import datetime as dt -from datetime import timedelta as td from tdxlib import tdx_asset_integration -from tdxlib import tdx_utils import os from sys import argv @@ -13,8 +10,8 @@ class TdxAssetTesting(unittest.TestCase): # Create TDXIntegration object for testing use. Called before testing methods. def setUp(self): - testing_vars_file = 'testing_vars.json' - self.tax = tdx_asset_integration.TDXAssetIntegration() + testing_vars_file = '../testing_vars.json' + self.tax = tdx_asset_integration.TDXAssetIntegration('../tdxlib.ini') if not self.tax.sandbox: print("Not in Sandbox... Aborting") quit() @@ -29,63 +26,93 @@ def setUp(self): 'Any *.json files are ignored by git.') def test_aaa(self): + if not self.timestamp: + self.setUp() self.assertGreater(len(self.tax.token), 200) def test_asset_forms(self): + if not self.timestamp: + self.setUp() forms = self.tax.get_all_asset_forms() self.assertGreater(len(forms), 1) def test_asset_form_name(self): + if not self.timestamp: + self.setUp() form = self.tax.get_asset_form_by_name_id(self.testing_vars['asset_form']['Name']) self.assertEqual(int(form['ID']), self.testing_vars['asset_form']['ID']) def test_asset_form_id(self): + if not self.timestamp: + self.setUp() form = self.tax.get_asset_form_by_name_id(self.testing_vars['asset_form']['ID']) self.assertEqual(form['Name'], self.testing_vars['asset_form']['Name']) def test_asset_statuses(self): + if not self.timestamp: + self.setUp() statuses = self.tax.get_all_asset_statuses() self.assertGreater(len(statuses),3) def test_asset_status_id(self): + if not self.timestamp: + self.setUp() status = self.tax.get_asset_status_by_name_id(self.testing_vars['asset_status1']['ID']) self.assertEqual(status['Name'], self.testing_vars['asset_status1']['Name']) def test_asset_status_name(self): + if not self.timestamp: + self.setUp() status = self.tax.get_asset_status_by_name_id(self.testing_vars['asset_status1']['Name']) self.assertEqual(int(status['ID']), self.testing_vars['asset_status1']['ID']) def test_asset_product_types(self): + if not self.timestamp: + self.setUp() product_types = self.tax.get_all_product_types() self.assertGreater(len(product_types),3) def test_asset_product_type_id(self): + if not self.timestamp: + self.setUp() product_type = self.tax.get_product_type_by_name_id(self.testing_vars['product_type']['ID']) self.assertEqual(product_type['Name'], self.testing_vars['product_type']['Name']) def test_asset_product_type_name(self): + if not self.timestamp: + self.setUp() product_type = self.tax.get_product_type_by_name_id(self.testing_vars['product_type']['Name']) self.assertEqual(int(product_type['ID']), self.testing_vars['product_type']['ID']) def test_asset_product_models(self): + if not self.timestamp: + self.setUp() product_models = self.tax.get_all_product_models() self.assertGreater(len(product_models),3) def test_asset_product_model_id(self): + if not self.timestamp: + self.setUp() product_model = self.tax.get_product_model_by_name_id(self.testing_vars['product_model']['ID']) self.assertEqual(product_model['Name'], self.testing_vars['product_model']['Name']) def test_asset_product_model_name(self): + if not self.timestamp: + self.setUp() product_model = self.tax.get_product_model_by_name_id(self.testing_vars['product_model']['Name']) self.assertEqual(int(product_model['ID']), self.testing_vars['product_model']['ID']) def test_update_product_type(self): + if not self.timestamp: + self.setUp() product_type = self.tax.get_product_type_by_name_id(self.testing_vars['product_type']['Name']) changed_attributes = {'Description': self.timestamp} updated_product_type = self.tax.update_product_type(product_type, changed_attributes) self.assertEqual(updated_product_type['Description'], self.timestamp) def test_create_product_type(self): + if not self.timestamp: + self.setUp() name = 'Temp Product Type ' + self.timestamp new_product_type = self.tax.create_product_type(name) self.assertTrue(new_product_type['ID']) @@ -94,6 +121,8 @@ def test_create_product_type(self): # TODO: def test_update_product_model(self): def test_create_product_model(self): + if not self.timestamp: + self.setUp() name = 'Temp Product Model ' + self.timestamp type = self.tax.get_product_type_by_name_id(self.testing_vars['product_type']['ID']) vendor = self.tax.get_vendor_by_name_id(self.testing_vars['vendor']['Name']) @@ -102,10 +131,14 @@ def test_create_product_model(self): self.assertEqual(name, new_product_model['Name']) def test_get_all_vendors(self): + if not self.timestamp: + self.setUp() vendors = self.tax.get_all_vendors() self.assertGreaterEqual(len(vendors), 5) def test_get_vendor_by_name_id(self): + if not self.timestamp: + self.setUp() name = self.testing_vars['vendor']['Name'] vendor = self.tax.get_vendor_by_name_id(name) self.assertEqual(int(vendor['ID']), self.testing_vars['vendor']['ID']) @@ -113,59 +146,85 @@ def test_get_vendor_by_name_id(self): # TODO: def test_update_vendor(self): def test_create_vendor(self): + if not self.timestamp: + self.setUp() name = 'Temp Vendor ' + self.timestamp new_vendor = self.tax.create_vendor(name) self.assertTrue(new_vendor['ID']) self.assertEqual(name, new_vendor['Name']) def test_get_asset_id(self): + if not self.timestamp: + self.setUp() asset = self.tax.get_asset_by_id(self.testing_vars['asset1']['ID']) self.assertEqual(asset['Name'], self.testing_vars['asset1']['Name']) def test_search_asset(self): + if not self.timestamp: + self.setUp() assets = self.tax.search_assets(self.testing_vars['asset_search']['Text']) self.assertGreaterEqual(len(assets), self.testing_vars['asset_search']['Count']) def test_find_asset_tag(self): + if not self.timestamp: + self.setUp() asset = self.tax.find_asset_by_tag(self.testing_vars['asset2']['Tag']) self.assertEqual(asset['SerialNumber'], self.testing_vars['asset2']['SerialNumber']) def test_find_asset_SN(self): + if not self.timestamp: + self.setUp() asset = self.tax.find_asset_by_sn(self.testing_vars['asset2']['SerialNumber']) self.assertEqual(asset['Tag'].lstrip('0'), self.testing_vars['asset2']['Tag'].lstrip('0')) def test_get_assets_by_location(self): + if not self.timestamp: + self.setUp() assets = self.tax.get_assets_by_location(self.testing_vars['location1']) self.assertGreaterEqual(len(assets), self.testing_vars['location1']['asset_count']) def test_get_assets_by_locations(self): + if not self.timestamp: + self.setUp() assets = self.tax.get_assets_by_location([self.testing_vars['location1'],self.testing_vars['location2']]) self.assertGreaterEqual(len(assets), self.testing_vars['location1']['asset_count'] + self.testing_vars['location2']['asset_count']) def test_get_assets_by_room(self): + if not self.timestamp: + self.setUp() location = self.tax.get_location_by_name(self.testing_vars['location3']['Name']) room1 = self.tax.get_room_by_name(location, self.testing_vars['room1']['Name']) assets = self.tax.get_assets_by_room(room1, max_results=100) self.assertGreaterEqual(len(assets), self.testing_vars['room1']['asset_count']) def test_get_assets_by_owner(self): + if not self.timestamp: + self.setUp() assets = self.tax.get_assets_by_owner(self.testing_vars['owner']['PrimaryEmail'], max_results=100, disposed=True) self.assertGreaterEqual(len(assets), self.testing_vars['owner']['asset_count']) def test_get_assets_by_requesting_dept(self): - assets = self.tax.get_assets_by_owner(self.testing_vars['department']['Name'], max_results=100, disposed=True) + if not self.timestamp: + self.setUp() + assets = self.tax.get_assets_by_requesting_department(self.testing_vars['department']['Name'], max_results=100, disposed=True) self.assertGreaterEqual(len(assets), self.testing_vars['department']['asset_count']) def test_get_assets_by_product_model(self): + if not self.timestamp: + self.setUp() assets = self.tax.get_assets_by_product_model(self.testing_vars['product_model']['Name'], max_results=100, retired=True, disposed=True) self.assertGreaterEqual(len(assets), self.testing_vars['product_model']['asset_count']) def test_get_assets_by_product_type(self): + if not self.timestamp: + self.setUp() assets = self.tax.get_assets_by_product_type(self.testing_vars['product_type']['Name'], max_results=100, retired=True, disposed=True) self.assertGreaterEqual(len(assets), self.testing_vars['product_type']['asset_count']) def test_update_asset_status(self): + if not self.timestamp: + self.setUp() assets_to_update = self.tax.get_assets_by_owner(self.testing_vars['owner']['PrimaryEmail'], max_results=100, disposed=True) new_status = str(self.testing_vars['asset_status1']['ID']) first_status = str(assets_to_update[0]['StatusID']) @@ -177,6 +236,8 @@ def test_update_asset_status(self): self.assertEqual(str(updated_assets[i]['StatusID']), new_status) def test_update_asset_owner(self): + if not self.timestamp: + self.setUp() asset = self.tax.get_asset_by_id(self.testing_vars['asset1']['ID']) new_owner = self.testing_vars['owner'] if asset['OwningCustomerID'] == new_owner['UID']: @@ -186,6 +247,8 @@ def test_update_asset_owner(self): self.assertEqual(updated_asset['OwningCustomerName'], new_owner['FullName']) def test_update_asset_requesting_dept(self): + if not self.timestamp: + self.setUp() asset = self.tax.get_asset_by_id(self.testing_vars['asset1']['ID']) new_dept = self.testing_vars['department'] if asset['RequestingDepartmentID'] == new_dept['ID']: @@ -194,6 +257,8 @@ def test_update_asset_requesting_dept(self): self.assertEqual(updated_asset['RequestingDepartmentName'], new_dept['Name']) def test_custom_attribute_updating_id(self): + if not self.timestamp: + self.setUp() asset = self.tax.get_asset_by_id(self.testing_vars['asset1']['ID']) new_attributes = self.testing_vars['attributes1'] for i in asset['Attributes']: @@ -211,6 +276,8 @@ def test_custom_attribute_updating_id(self): self.assertEqual(str(desired['Value']), str(existing['Value'])) def test_custom_attribute_updating_name(self): + if not self.timestamp: + self.setUp() asset = self.tax.get_asset_by_id(self.testing_vars['asset1']['ID']) new_attributes = self.testing_vars['attributes1'] for i in asset['Attributes']: @@ -228,6 +295,8 @@ def test_custom_attribute_updating_name(self): self.assertEqual(str(desired['Value']), str(existing['Value'])) def test_add_custom_attributes(self): + if not self.timestamp: + self.setUp() asset = self.tax.get_asset_by_id(self.testing_vars['asset2']['ID']) change = {'Name': asset['Name']+'(Cleared)'} cleared_asset = self.tax.update_assets(asset, change, clear_custom_attributes=True)[0] @@ -248,6 +317,82 @@ def test_add_custom_attributes(self): if desired['ID'] == existing ['ID']: self.assertEqual(str(desired['Value']), str(existing['Value'])) + def test_add_asset_user(self): + if not self.timestamp: + self.setUp() + self.tax.delete_asset_users(self.testing_vars['asset2']['ID'], self.testing_vars['person1']['UID']) + validate1 = self.tax.get_asset_users(self.testing_vars['asset2']['ID']) + self.tax.add_asset_user(self.testing_vars['asset2']['ID'], self.testing_vars['person1']['UID']) + validate2 = self.tax.get_asset_users(self.testing_vars['asset2']['ID']) + self.assertGreater(len(validate2), len(validate1)) + + def test_get_asset_users(self): + if not self.timestamp: + self.setUp() + self.tax.add_asset_user(self.testing_vars['asset2']['ID'], self.testing_vars['person1']['UID']) + validate = self.tax.get_asset_users(self.testing_vars['asset2']['ID']) + self.assertGreater(len(validate), 0) + self.assertTrue('Name' in validate[0]) + + def test_delete_asset_users(self): + if not self.timestamp: + self.setUp() + self.tax.add_asset_user(self.testing_vars['asset2']['ID'], self.testing_vars['person1']['UID']) + self.tax.delete_asset_users(self.testing_vars['asset2']['ID'], self.testing_vars['person1']['UID']) + validate = self.tax.get_asset_users(self.testing_vars['asset2']['ID']) + for i in validate: + self.assertTrue(i['Name'] != self.testing_vars['person1']['FullName']) + + def test_change_asset_location(self): + if not self.timestamp: + self.setUp() + new_asset = self.tax.create_asset( + self.tax.build_asset(f'testing1.{self.timestamp}', f'testing1.{self.timestamp}', + self.testing_vars['asset_status1']['Name'], + self.testing_vars['location1']['Name'])) + self.tax.change_asset_location(new_asset, self.testing_vars['location2']['Name']) + validate = self.tax.get_asset_by_id(new_asset['ID']) + self.assertTrue(validate['LocationName'] == self.testing_vars['location2']['Name']) + + def test_clear_asset_custom_attributes(self): + if not self.timestamp: + self.setUp() + new_asset = self.tax.create_asset( + self.tax.build_asset(f'testing2.{self.timestamp}', f'testing2.{self.timestamp}', + self.testing_vars['asset_status1']['Name'], + asset_custom_attributes=self.testing_vars['attributes1'])) + validate = self.tax.clear_asset_custom_attributes(new_asset, self.testing_vars['attributes1'][0]['Name']) + for i in validate['Attributes']: + self.assertFalse(i['Name'] == self.testing_vars['attributes1'][0]['Name']) + + def test_get_asset_custom_attribute_value_by_name(self): + if not self.timestamp: + self.setUp() + new_asset = self.tax.create_asset( + self.tax.build_asset(f'testing3.{self.timestamp}', f'testing3.{self.timestamp}', + self.testing_vars['asset_status1']['Name'], + asset_custom_attributes={'Attributes': [self.testing_vars['attributes1'][0]]})) + validate = self.tax.get_asset_custom_attribute_value_by_name(new_asset, + self.testing_vars['attributes1'][0]['Name'], True) + self.assertTrue(validate == str(self.testing_vars['attributes1'][0]['Value'])) + + def test_copy_asset_attributes(self): + if not self.timestamp: + self.setUp() + sn1 = f'testing4.{self.timestamp}' + new_asset1 = self.tax.create_asset( + self.tax.build_asset(sn1, sn1, self.testing_vars['asset_status1']['Name'], + asset_custom_attributes={'Attributes': [self.testing_vars['attributes1'][0]]})) + sn2 = f'testing5.{self.timestamp}' + new_asset2 = self.tax.create_asset( + self.tax.build_asset(sn2, sn2, self.testing_vars['asset_status1']['Name'])) + self.tax.copy_asset_attributes(new_asset1, new_asset2, copy_name=True, + new_status=self.testing_vars['asset_status2']['Name']) + validate2 = self.tax.get_asset_by_id(new_asset2['ID']) + validate1 = self.tax.get_asset_by_id(new_asset1['ID']) + self.assertTrue(validate2['Attributes'][0]['Name'] == self.testing_vars['attributes1'][0]['Name']) + self.assertTrue(validate1['StatusName'] == self.testing_vars['asset_status2']['Name']) + if __name__ == "__main__": suite = unittest.TestLoader().loadTestsFromTestCase(TdxAssetTesting) diff --git a/testing/tdx_integration_testing.py b/testing/tdx_integration_testing.py index f1722b6..e966a34 100644 --- a/testing/tdx_integration_testing.py +++ b/testing/tdx_integration_testing.py @@ -10,8 +10,8 @@ class TdxTesting(unittest.TestCase): # Create TDXIntegration object for testing use. Called before testing methods. def setUp(self): - testing_vars_file = 'testing_vars.json' - self.tdx = tdx_integration.TDXIntegration() + testing_vars_file = '../testing_vars.json' + self.tdx = tdx_integration.TDXIntegration('../tdxlib.ini') right_now = dt.today() if os.path.isfile(testing_vars_file): with open(testing_vars_file, 'r') as f: @@ -21,9 +21,13 @@ def setUp(self): 'A sample file is available in testing/sample_ticket_testing_vars. Any *.json files are ignored by git.') def test_authentication(self): + if not self.tdx: + self.setUp() self.assertGreater(len(self.tdx.token), 200) def test_check_auth_exp(self): + if not self.tdx: + self.setUp() # Set token exp to sometime in the past self.tdx.token_exp = 1579203044 # Make an API call to check if old token will be refreshed @@ -32,92 +36,126 @@ def test_check_auth_exp(self): self.assertTrue(test) def test_get_location_by_id(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['location'] test = self.tdx.get_location_by_id(standard['ID']) self.assertTrue(test) self.assertEqual(test['Name'], standard['Name']) def test_get_account_by_id(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['account'] test = self.tdx.get_account_by_id(standard['ID']) self.assertTrue(test) self.assertEqual(test['Name'], standard['Name']) def test_get_group_by_id(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['group'] test = self.tdx.get_group_by_id(standard['ID']) self.assertTrue(test) self.assertEqual(test['Name'], standard['Name']) def test_get_person_by_uid(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['person1'] test = self.tdx.get_person_by_uid(standard['UID']) self.assertTrue(test) self.assertEqual(test['PrimaryEmail'], standard['PrimaryEmail']) def test_get_group_members_by_id(self): + if not self.tdx: + self.setUp() test = self.tdx.get_group_members_by_id(self.testing_vars['group']['ID']) self.assertTrue(isinstance(test, list)) self.assertGreaterEqual(len(test), 2) def test_search_people_name(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['person1'] test = self.tdx.get_person_by_name_email(standard['FullName']) self.assertEqual(test['UID'], standard['UID']) def test_search_people_email(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['person1'] test = self.tdx.get_person_by_name_email(standard['PrimaryEmail']) self.assertEqual(test['UID'], standard['UID']) def test_get_all_accounts(self): + if not self.tdx: + self.setUp() test = self.tdx.get_all_accounts() self.assertTrue(isinstance(test, list)) self.assertGreaterEqual(len(test), 2) def test_get_account_by_name(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['account'] test = self.tdx.get_account_by_name(standard['Name']) self.assertEqual(test['ID'],standard['ID']) def test_get_account_by_name_partial(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['account'] test = self.tdx.get_account_by_name(standard['PartialName']) self.assertEqual(test['ID'], standard['ID']) def test_get_all_groups(self): + if not self.tdx: + self.setUp() test = self.tdx.get_all_groups() self.assertTrue(isinstance(test, list)) self.assertGreaterEqual(len(test), 2) def test_get_group_by_name(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['group'] test= self.tdx.get_group_by_name(standard['Name']) self.assertEqual(test['ID'], standard['ID']) def test_get_group_by_name_partial(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['group'] test = self.tdx.get_group_by_name(standard['PartialName']) self.assertEqual(test['ID'], standard['ID']) def test_get_group_members_by_name(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['group'] test = self.tdx.get_group_members_by_name(standard['Name']) self.assertTrue(isinstance(test, list)) self.assertGreaterEqual(len(test),2) def test_get_all_custom_attributes(self): + if not self.tdx: + self.setUp() test = self.tdx.get_all_custom_attributes(self.tdx.component_ids['ticket']) self.assertTrue(isinstance(test, list)) self.assertGreaterEqual(len(test), 2) def test_get_ca_by_name(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['ticket_ca'] type_id = self.tdx.component_ids[standard['type']] test = self.tdx.get_custom_attribute_by_name_id(standard['Name'], type_id) self.assertEqual(test['ID'], standard['ID']) def test_get_ca_value_by_name(self): + if not self.tdx: + self.setUp() ca_standard = self.testing_vars['ticket_ca'] standard = ca_standard['choice'] type_id = self.tdx.component_ids[ca_standard['type']] @@ -126,21 +164,29 @@ def test_get_ca_value_by_name(self): self.assertEqual(test['ID'], standard['ID']) def test_get_all_locations(self): + if not self.tdx: + self.setUp() test = self.tdx.get_all_locations() self.assertTrue(isinstance(test, list)) self.assertGreaterEqual(len(test), 2) def test_get_location_by_name(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['location'] test = self.tdx.get_location_by_name(standard['Name']) self.assertEqual(test['ID'], standard['ID']) def test_get_location_by_name_partial(self): + if not self.tdx: + self.setUp() standard = self.testing_vars['location2'] test = self.tdx.get_location_by_name(standard['PartialName']) self.assertEqual(test['ID'], standard['ID']) def test_get_room_by_name(self): + if not self.tdx: + self.setUp() location = self.testing_vars['location'] standard = self.testing_vars['room'] test_location = self.tdx.get_location_by_name(location['Name']) @@ -148,6 +194,8 @@ def test_get_room_by_name(self): self.assertEqual(test_room['ID'], standard['ID']) def test_get_room_by_partial_name(self): + if not self.tdx: + self.setUp() location = self.testing_vars['location'] standard = self.testing_vars['room'] test_location = self.tdx.get_location_by_name(location['Name']) @@ -155,6 +203,8 @@ def test_get_room_by_partial_name(self): self.assertEqual(test_room['ID'], standard['ID']) def test_create_account(self): + if not self.tdx: + self.setUp() if not self.tdx.sandbox: return name = 'Testing Account ' + TdxTesting.timestamp @@ -169,6 +219,8 @@ def test_create_account(self): self.assertEqual(account['Name'], name) def test_edit_account(self): + if not self.tdx: + self.setUp() if not self.tdx.sandbox: return # This will fail if test_create_account fails @@ -178,6 +230,8 @@ def test_edit_account(self): self.assertEqual(edited_account['Name'], changed_attributes['Name']) def test_create_room(self): + if not self.tdx: + self.setUp() if not self.tdx.sandbox: return location = self.tdx.get_location_by_name(self.testing_vars['location1']['Name']) diff --git a/testing/tdx_ticket_testing.py b/testing/tdx_ticket_testing.py index b491a77..510af20 100644 --- a/testing/tdx_ticket_testing.py +++ b/testing/tdx_ticket_testing.py @@ -12,8 +12,8 @@ class TdxTicketTesting(unittest.TestCase): # Create TDXIntegration object for testing use. Called before testing methods. def setUp(self): - testing_vars_file = 'testing_vars.json' - self.tix = tdx_ticket_integration.TDXTicketIntegration() + testing_vars_file = '../testing_vars.json' + self.tix = tdx_ticket_integration.TDXTicketIntegration('../tdxlib.ini') right_now = dt.today() self.timestamp = right_now.strftime("%d-%B-%Y %H:%M:%S") if os.path.isfile(testing_vars_file): @@ -282,7 +282,7 @@ def test_upload_attachment(self): filename = self.testing_vars['attachment']['Name'] with open (filename, "rb") as file: update = self.tix.upload_attachment(ticket_id, file) - self.assertEqual(filename, update['Name']) + self.assertEqual(filename.split('/')[-1], update['Name']) def test_upload_attachment_filename(self): if not self.tix.sandbox: