diff --git a/SoftLayer/CLI/tags/__init__.py b/SoftLayer/CLI/tags/__init__.py index e5caefa78..f8dd3783b 100644 --- a/SoftLayer/CLI/tags/__init__.py +++ b/SoftLayer/CLI/tags/__init__.py @@ -1 +1 @@ -"""Manage Tags""" \ No newline at end of file +"""Manage Tags""" diff --git a/SoftLayer/CLI/tags/list.py b/SoftLayer/CLI/tags/list.py index 71634478a..870d5faf5 100644 --- a/SoftLayer/CLI/tags/list.py +++ b/SoftLayer/CLI/tags/list.py @@ -3,15 +3,14 @@ import click -from SoftLayer.exceptions import SoftLayerAPIError -from SoftLayer.managers.tags import TagManager from SoftLayer.CLI import environment from SoftLayer.CLI import formatting +from SoftLayer.exceptions import SoftLayerAPIError +from SoftLayer.managers.tags import TagManager from SoftLayer import utils # pylint: disable=unnecessary-lambda -from pprint import pprint as pp @click.command() @click.option('--detail', '-d', is_flag=True, default=False, @@ -21,7 +20,7 @@ def cli(env, detail): """List Tags.""" tag_manager = TagManager(env.client) - + if detail: tables = detailed_table(tag_manager) for table in tables: @@ -33,7 +32,9 @@ def cli(env, detail): def tag_row(tag): - return [tag.get('id'), tag.get('name'), tag.get('referenceCount',0)] + """Format a tag table row""" + return [tag.get('id'), tag.get('name'), tag.get('referenceCount', 0)] + def detailed_table(tag_manager): """Creates a table for each tag, with details about resources using it""" @@ -52,6 +53,7 @@ def detailed_table(tag_manager): return tables + def simple_table(tag_manager): """Just tags and how many resources on each""" tags = tag_manager.list_tags() @@ -62,6 +64,7 @@ def simple_table(tag_manager): table.add_row(tag_row(tag)) return table + def get_resource_name(tag_manager, resource_id, tag_type): """Returns a string to identify a resource""" try: @@ -70,6 +73,6 @@ def get_resource_name(tag_manager, resource_id, tag_type): resource_row = resource.get('primaryIpAddress') else: resource_row = resource.get('fullyQualifiedDomainName') - except SoftLayerAPIError as e: - resource_row = "{}".format(e.reason) - return resource_row \ No newline at end of file + except SoftLayerAPIError as exception: + resource_row = "{}".format(exception.reason) + return resource_row diff --git a/SoftLayer/fixtures/SoftLayer_Hardware.py b/SoftLayer/fixtures/SoftLayer_Hardware.py new file mode 100644 index 000000000..cb902b556 --- /dev/null +++ b/SoftLayer/fixtures/SoftLayer_Hardware.py @@ -0,0 +1,59 @@ +getObject = { + 'id': 1234, + 'globalIdentifier': 'xxxxc-asd', + 'datacenter': {'id': 12, 'name': 'DALLAS21', + 'description': 'Dallas 21'}, + 'billingItem': { + 'id': 6327, + 'recurringFee': 1.54, + 'nextInvoiceTotalRecurringAmount': 16.08, + 'children': [ + {'description': 'test', 'nextInvoiceTotalRecurringAmount': 1}, + ], + 'orderItem': { + 'order': { + 'userRecord': { + 'username': 'bob', + } + } + } + }, + 'primaryIpAddress': '4.4.4.4', + 'hostname': 'testtest1', + 'domain': 'test.sftlyr.ws', + 'bareMetalInstanceFlag': True, + 'fullyQualifiedDomainName': 'testtest1.test.sftlyr.ws', + 'processorPhysicalCoreAmount': 4, + 'memoryCapacity': 4, + 'primaryBackendIpAddress': '10.4.4.4', + 'networkManagementIpAddress': '10.4.4.4', + 'hardwareStatus': {'status': 'ACTIVE'}, + 'primaryNetworkComponent': {'maxSpeed': 1000, 'speed': 1000}, + 'provisionDate': '2020-08-01 15:23:45', + 'notes': 'NOTES NOTES NOTES', + 'operatingSystem': { + 'softwareLicense': { + 'softwareDescription': { + 'referenceCode': 'UBUNTU_20_64', + 'name': 'Ubuntu', + 'version': 'Ubuntu 20.04 LTS', + } + }, + 'passwords': [ + {'username': 'root', 'password': 'xxxxxxxxxxxx'} + ], + }, + 'remoteManagementAccounts': [ + {'username': 'root', 'password': 'zzzzzzzzzzzzzz'} + ], + 'networkVlans': [ + { + 'networkSpace': 'PRIVATE', + 'vlanNumber': 1234, + 'id': 11111 + }, + ], + 'tagReferences': [ + {'tag': {'name': 'a tag'}} + ], +} diff --git a/SoftLayer/fixtures/SoftLayer_Network_Storage_Allowed_Host.py b/SoftLayer/fixtures/SoftLayer_Network_Storage_Allowed_Host.py index 5bf8c3354..923147a58 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_Storage_Allowed_Host.py +++ b/SoftLayer/fixtures/SoftLayer_Network_Storage_Allowed_Host.py @@ -32,22 +32,22 @@ getObject = TEST_ALLOWED_HOST getSubnetsInAcl = [{ - 'id': 12345678, - 'accountId': 1234, - 'networkIdentifier': '10.11.12.13', - 'cidr': '14', - 'billingRecordId': None, - 'parentId': None, - 'networkVlanId': None, - 'createDate': '2020-01-02 00:00:01', - 'modifyDate': None, - 'subnetType': 'SECONDARY_ON_VLAN', - 'restrictAllocationFlag': 0, - 'leafFlag': 1, - 'ownerId': 1, - 'ipAddressBegin': 129123, - 'ipAddressEnd': 129145, - 'purgeFlag': 0 + 'id': 12345678, + 'accountId': 1234, + 'networkIdentifier': '10.11.12.13', + 'cidr': '14', + 'billingRecordId': None, + 'parentId': None, + 'networkVlanId': None, + 'createDate': '2020-01-02 00:00:01', + 'modifyDate': None, + 'subnetType': 'SECONDARY_ON_VLAN', + 'restrictAllocationFlag': 0, + 'leafFlag': 1, + 'ownerId': 1, + 'ipAddressBegin': 129123, + 'ipAddressEnd': 129145, + 'purgeFlag': 0 }] assignSubnetsToAcl = [ diff --git a/SoftLayer/fixtures/SoftLayer_Tag.py b/SoftLayer/fixtures/SoftLayer_Tag.py new file mode 100644 index 000000000..3246870c0 --- /dev/null +++ b/SoftLayer/fixtures/SoftLayer_Tag.py @@ -0,0 +1,16 @@ +getUnattachedTagsForCurrentUser = [{'id': 287895, 'name': 'coreos', 'referenceCount': 0}] +getAttachedTagsForCurrentUser = [{'id': 1286571, 'name': 'bs_test_instance', 'referenceCount': 5}] +getReferences = [ + { + 'id': 73009305, + 'resourceTableId': 33488921, + 'tag': { + 'id': 1286571, + 'name': 'bs_test_instance', + }, + 'tagId': 1286571, + 'tagType': {'description': 'CCI', 'keyName': 'GUEST'}, + 'tagTypeId': 2, + 'usrRecordId': 6625205 + } +] diff --git a/SoftLayer/managers/tags.py b/SoftLayer/managers/tags.py index 8e6d282bd..e22e94654 100644 --- a/SoftLayer/managers/tags.py +++ b/SoftLayer/managers/tags.py @@ -9,6 +9,7 @@ from SoftLayer.exceptions import SoftLayerAPIError + class TagManager(object): """Manager for Tag functions.""" @@ -25,21 +26,31 @@ def list_tags(self, mask=None): unattached = self.get_unattached_tags(mask) attached = self.get_attached_tags(mask) return {'attached': attached, 'unattached': unattached} - # return [unattached, attached] def get_unattached_tags(self, mask=None): - """Calls SoftLayer_Tag::getUnattachedTagsForCurrentUser()""" + """Calls SoftLayer_Tag::getUnattachedTagsForCurrentUser() + + :params string mask: Mask to use. + """ return self.client.call('SoftLayer_Tag', 'getUnattachedTagsForCurrentUser', mask=mask, iter=True) def get_attached_tags(self, mask=None): - """Calls SoftLayer_Tag::getAttachedTagsForCurrentUser()""" + """Calls SoftLayer_Tag::getAttachedTagsForCurrentUser() + + :params string mask: Mask to use. + """ return self.client.call('SoftLayer_Tag', 'getAttachedTagsForCurrentUser', mask=mask, iter=True) def get_tag_references(self, tag_id, mask=None): + """Calls SoftLayer_Tag::getReferences(id=tag_id) + + :params int tag_id: Tag id to get references from + :params string mask: Mask to use. + """ if mask is None: - mask="mask[tagType]" + mask = "mask[tagType]" return self.client.call('SoftLayer_Tag', 'getReferences', id=tag_id, mask=mask, iter=True) def reference_lookup(self, resource_table_id, tag_type): @@ -50,8 +61,8 @@ def reference_lookup(self, resource_table_id, tag_type): From SoftLayer_Tag::getAllTagTypes() - |Type |Service | - | ----------------------------- | ------ | + |Type |Service | + | ----------------------------- | ------ | |Hardware |HARDWARE| |CCI |GUEST| |Account Document |ACCOUNT_DOCUMENT| @@ -67,7 +78,7 @@ def reference_lookup(self, resource_table_id, tag_type): if tag_type in ['ACCOUNT_DOCUMENT', 'CONTRACT']: raise SoftLayerAPIError(404, "Unable to lookup {} types".format(tag_type)) - if tag_type == 'APPLICATION_DELIVERY_CONTROLLER' : + if tag_type == 'APPLICATION_DELIVERY_CONTROLLER': service = 'Network_Application_Delivery_Controller' elif tag_type == 'GUEST': service = 'Virtual_Guest' @@ -82,6 +93,3 @@ def reference_lookup(self, resource_table_id, tag_type): # return {} return self.client.call(service, 'getObject', id=resource_table_id) - - - diff --git a/tests/CLI/modules/block_tests.py b/tests/CLI/modules/block_tests.py index b39face10..e5f6ba8c5 100644 --- a/tests/CLI/modules/block_tests.py +++ b/tests/CLI/modules/block_tests.py @@ -112,7 +112,7 @@ def test_volume_detail_name_identifier(self): 'keyName': {'operation': '*= BLOCK_STORAGE'} }, 'username': {'operation': '_= SL-12345'} - } + } } self.assert_called_with('SoftLayer_Account', 'getIscsiNetworkStorage', filter=expected_filter) diff --git a/tests/CLI/modules/server_tests.py b/tests/CLI/modules/server_tests.py index 157acfcc1..a7fd4e908 100644 --- a/tests/CLI/modules/server_tests.py +++ b/tests/CLI/modules/server_tests.py @@ -694,19 +694,19 @@ def test_dns_sync_both(self, confirm_mock): 'getResourceRecords') getResourceRecords.return_value = [] createAargs = ({ - 'type': 'a', - 'host': 'hardware-test1', - 'domainId': 12345, # from SoftLayer_Account::getDomains - 'data': '172.16.1.100', - 'ttl': 7200 - },) + 'type': 'a', + 'host': 'hardware-test1', + 'domainId': 12345, # from SoftLayer_Account::getDomains + 'data': '172.16.1.100', + 'ttl': 7200 + },) createPTRargs = ({ - 'type': 'ptr', - 'host': '100', - 'domainId': 123456, - 'data': 'hardware-test1.test.sftlyr.ws', - 'ttl': 7200 - },) + 'type': 'ptr', + 'host': '100', + 'domainId': 123456, + 'data': 'hardware-test1.test.sftlyr.ws', + 'ttl': 7200 + },) result = self.run_command(['hw', 'dns-sync', '1000']) @@ -749,12 +749,12 @@ def test_dns_sync_v6(self, confirm_mock): } } createV6args = ({ - 'type': 'aaaa', - 'host': 'hardware-test1', - 'domainId': 12345, # from SoftLayer_Account::getDomains - 'data': '2607:f0d0:1b01:0023:0000:0000:0000:0004', - 'ttl': 7200 - },) + 'type': 'aaaa', + 'host': 'hardware-test1', + 'domainId': 12345, # from SoftLayer_Account::getDomains + 'data': '2607:f0d0:1b01:0023:0000:0000:0000:0004', + 'ttl': 7200 + },) server.return_value = test_server result = self.run_command(['hw', 'dns-sync', '--aaaa-record', '1000']) self.assert_no_fail(result) diff --git a/tests/CLI/modules/tag_tests.py b/tests/CLI/modules/tag_tests.py new file mode 100644 index 000000000..357364063 --- /dev/null +++ b/tests/CLI/modules/tag_tests.py @@ -0,0 +1,26 @@ +""" + SoftLayer.tests.CLI.modules.tag_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Tests for the user cli command +""" +from SoftLayer import testing + + +class TagCLITests(testing.TestCase): + + def test_list(self): + result = self.run_command(['tags', 'list']) + self.assert_no_fail(result) + self.assert_called_with('SoftLayer_Tag', 'getUnattachedTagsForCurrentUser') + self.assert_called_with('SoftLayer_Tag', 'getAttachedTagsForCurrentUser') + self.assertIn('coreos', result.output) + + def test_list_detail(self): + result = self.run_command(['tags', 'list', '-d']) + self.assert_no_fail(result) + self.assertIn('"vs-test1.test.sftlyr.ws', result.output) # From fixtures/virutal_guest.getObject + # self.assert_called_with('SoftLayer_Tag', 'getUnattachedTagsForCurrentUser') + self.assert_called_with('SoftLayer_Tag', 'getAttachedTagsForCurrentUser') + self.assert_called_with('SoftLayer_Tag', 'getReferences', identifier=1286571) + self.assert_called_with('SoftLayer_Virtual_Guest', 'getObject', identifier=33488921) diff --git a/tests/CLI/modules/vs/vs_tests.py b/tests/CLI/modules/vs/vs_tests.py index c61883385..a4bf28509 100644 --- a/tests/CLI/modules/vs/vs_tests.py +++ b/tests/CLI/modules/vs/vs_tests.py @@ -370,19 +370,19 @@ def test_dns_sync_both(self, confirm_mock): 'getResourceRecords') getResourceRecords.return_value = [] createAargs = ({ - 'type': 'a', - 'host': 'vs-test1', - 'domainId': 12345, # from SoftLayer_Account::getDomains - 'data': '172.16.240.2', - 'ttl': 7200 - },) + 'type': 'a', + 'host': 'vs-test1', + 'domainId': 12345, # from SoftLayer_Account::getDomains + 'data': '172.16.240.2', + 'ttl': 7200 + },) createPTRargs = ({ - 'type': 'ptr', - 'host': '2', - 'domainId': 123456, - 'data': 'vs-test1.test.sftlyr.ws', - 'ttl': 7200 - },) + 'type': 'ptr', + 'host': '2', + 'domainId': 123456, + 'data': 'vs-test1.test.sftlyr.ws', + 'ttl': 7200 + },) result = self.run_command(['vs', 'dns-sync', '100']) @@ -425,12 +425,12 @@ def test_dns_sync_v6(self, confirm_mock): } } createV6args = ({ - 'type': 'aaaa', - 'host': 'vs-test1', - 'domainId': 12345, - 'data': '2607:f0d0:1b01:0023:0000:0000:0000:0004', - 'ttl': 7200 - },) + 'type': 'aaaa', + 'host': 'vs-test1', + 'domainId': 12345, + 'data': '2607:f0d0:1b01:0023:0000:0000:0000:0004', + 'ttl': 7200 + },) guest.return_value = test_guest result = self.run_command(['vs', 'dns-sync', '--aaaa-record', '100']) self.assert_no_fail(result) diff --git a/tests/managers/hardware_tests.py b/tests/managers/hardware_tests.py index f504dba94..69e7ae52a 100644 --- a/tests/managers/hardware_tests.py +++ b/tests/managers/hardware_tests.py @@ -374,10 +374,10 @@ def test_edit(self): self.assert_called_with('SoftLayer_Hardware_Server', 'editObject', args=({ - 'hostname': 'new-host', - 'domain': 'new.sftlyr.ws', - 'notes': 'random notes', - },), + 'hostname': 'new-host', + 'domain': 'new.sftlyr.ws', + 'notes': 'random notes', + },), identifier=100) def test_rescue(self): diff --git a/tests/managers/tag_tests.py b/tests/managers/tag_tests.py new file mode 100644 index 000000000..38f198ae9 --- /dev/null +++ b/tests/managers/tag_tests.py @@ -0,0 +1,105 @@ +""" + SoftLayer.tests.managers.tag_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :license: MIT, see LICENSE for more details. +""" + +from SoftLayer.exceptions import SoftLayerAPIError +from SoftLayer.managers import tags +from SoftLayer import testing + + +class TagTests(testing.TestCase): + + def set_up(self): + self.tag_manager = tags.TagManager(self.client) + self.test_mask = "mask[id]" + + def test_list_tags(self): + result = self.tag_manager.list_tags() + self.assert_called_with('SoftLayer_Tag', 'getUnattachedTagsForCurrentUser') + self.assert_called_with('SoftLayer_Tag', 'getAttachedTagsForCurrentUser') + self.assertIn('attached', result.keys()) + self.assertIn('unattached', result.keys()) + + def test_list_tags_mask(self): + result = self.tag_manager.list_tags(mask=self.test_mask) + self.assert_called_with('SoftLayer_Tag', 'getUnattachedTagsForCurrentUser', mask=self.test_mask) + self.assert_called_with('SoftLayer_Tag', 'getAttachedTagsForCurrentUser', mask=self.test_mask) + self.assertIn('attached', result.keys()) + self.assertIn('unattached', result.keys()) + + def test_unattached_tags(self): + result = self.tag_manager.get_unattached_tags() + self.assertEqual('coreos', result[0].get('name')) + self.assert_called_with('SoftLayer_Tag', 'getUnattachedTagsForCurrentUser', mask=None) + + def test_unattached_tags_mask(self): + result = self.tag_manager.get_unattached_tags(mask=self.test_mask) + self.assertEqual('coreos', result[0].get('name')) + self.assert_called_with('SoftLayer_Tag', 'getUnattachedTagsForCurrentUser', mask=self.test_mask) + + def test_attached_tags(self): + result = self.tag_manager.get_attached_tags() + self.assertEqual('bs_test_instance', result[0].get('name')) + self.assert_called_with('SoftLayer_Tag', 'getAttachedTagsForCurrentUser', mask=None) + + def test_attached_tags_mask(self): + result = self.tag_manager.get_attached_tags(mask=self.test_mask) + self.assertEqual('bs_test_instance', result[0].get('name')) + self.assert_called_with('SoftLayer_Tag', 'getAttachedTagsForCurrentUser', mask=self.test_mask) + + def test_get_tag_references(self): + tag_id = 1286571 + result = self.tag_manager.get_tag_references(tag_id) + self.assertEqual(tag_id, result[0].get('tagId')) + self.assert_called_with('SoftLayer_Tag', 'getReferences', identifier=tag_id) + + def test_get_tag_references_mask(self): + tag_id = 1286571 + result = self.tag_manager.get_tag_references(tag_id, mask=self.test_mask) + self.assertEqual(tag_id, result[0].get('tagId')) + self.assert_called_with('SoftLayer_Tag', 'getReferences', identifier=tag_id, mask=self.test_mask) + + def test_reference_lookup_hardware(self): + resource_id = 12345 + tag_type = 'HARDWARE' + + self.tag_manager.reference_lookup(resource_id, tag_type) + self.assert_called_with('SoftLayer_Hardware', 'getObject', identifier=resource_id) + + def test_reference_lookup_guest(self): + resource_id = 12345 + tag_type = 'GUEST' + + self.tag_manager.reference_lookup(resource_id, tag_type) + self.assert_called_with('SoftLayer_Virtual_Guest', 'getObject', identifier=resource_id) + + def test_reference_lookup_app_delivery(self): + resource_id = 12345 + tag_type = 'APPLICATION_DELIVERY_CONTROLLER' + + self.tag_manager.reference_lookup(resource_id, tag_type) + self.assert_called_with('SoftLayer_Network_Application_Delivery_Controller', + 'getObject', identifier=resource_id) + + def test_reference_lookup_dedicated(self): + resource_id = 12345 + tag_type = 'DEDICATED_HOST' + + self.tag_manager.reference_lookup(resource_id, tag_type) + self.assert_called_with('SoftLayer_Virtual_DedicatedHost', 'getObject', identifier=resource_id) + + def test_reference_lookup_document(self): + resource_id = 12345 + tag_type = 'ACCOUNT_DOCUMENT' + + exception = self.assertRaises( + SoftLayerAPIError, + self.tag_manager.reference_lookup, + resource_id, + tag_type + ) + self.assertEqual(exception.faultCode, 404) + self.assertEqual(exception.reason, "Unable to lookup ACCOUNT_DOCUMENT types") diff --git a/tests/managers/user_tests.py b/tests/managers/user_tests.py index b75a5a772..b0ab015f9 100644 --- a/tests/managers/user_tests.py +++ b/tests/managers/user_tests.py @@ -231,7 +231,7 @@ def test_vpn_subnet_add(self): subnet_id = 1234 expected_args = ( [{"userId": user_id, "subnetId": subnet_id}], - ) + ) self.manager.vpn_subnet_add(user_id, [subnet_id]) self.assert_called_with('SoftLayer_Network_Service_Vpn_Overrides', 'createObjects', args=expected_args) self.assert_called_with('SoftLayer_User_Customer', 'updateVpnUser', identifier=user_id) @@ -242,7 +242,7 @@ def test_vpn_subnet_remove(self): overrides = [{'id': 3661234, 'subnetId': subnet_id}] expected_args = ( overrides, - ) + ) self.manager.vpn_subnet_remove(user_id, [subnet_id]) self.assert_called_with('SoftLayer_Network_Service_Vpn_Overrides', 'deleteObjects', args=expected_args) self.assert_called_with('SoftLayer_User_Customer', 'updateVpnUser', identifier=user_id)