Repository: softlayer/softlayer-python
Pull request #1712 (2022-07-28 14:59:49)

New Command: user device-access
[#issue1710](https://github.com/softlayer/softlayer-python/issues/1710)

![image](https://user-images.githubusercontent.com/22535437/181570628-9dd3e701-a5a5-4021-b09f-f5a258b3099e.png)



Patch:
diff --git a/SoftLayer/CLI/block/options.py b/SoftLayer/CLI/block/options.py
index b20b67e6..e42e5fbc 100644
--- a/SoftLayer/CLI/block/options.py
+++ b/SoftLayer/CLI/block/options.py
@@ -20,31 +20,18 @@ def cli(env):
     items = order_manager.get_items(PACKAGE_STORAGE)
     datacenters = order_manager.get_regions(PACKAGE_STORAGE)
 
-    network = SoftLayer.NetworkManager(env.client)
-
-    pods = network.get_closed_pods()
-
     iops_table = formatting.Table(['Id', 'Description', 'KeyName'], title='IOPS')
     snapshot_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Snapshot')
-    storage_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Storage')
+    storage_table = formatting.Table(['Id', 'Description', 'KeyName', 'Capacity Minimum'], title='Storage')
     datacenter_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Datacenter')
 
     storage_table.align['Description'] = 'l'
     storage_table.align['KeyName'] = 'l'
     storage_table.sortby = 'Id'
-
     for datacenter in datacenters:
-        closure = []
-        for pod in pods:
-            if datacenter['location']['location']['name'] in str(pod['name']):
-                closure.append(pod['name'])
-
-        notes = '-'
-        if len(closure) > 0:
-            notes = 'closed soon: %s' % (', '.join(closure))
         datacenter_table.add_row([datacenter['location']['locationId'],
                                   datacenter.get('description'),
-                                  datacenter['keyname'], notes])
+                                  datacenter['keyname']])
 
     for item in items:
         if item['itemCategory']['categoryCode'] == 'performance_storage_space':
diff --git a/SoftLayer/CLI/file/options.py b/SoftLayer/CLI/file/options.py
index 61db6050..dfaa3f1e 100644
--- a/SoftLayer/CLI/file/options.py
+++ b/SoftLayer/CLI/file/options.py
@@ -20,44 +20,31 @@ def cli(env):
     items = order_manager.get_items(PACKAGE_STORAGE)
     datacenters = order_manager.get_regions(PACKAGE_STORAGE)
 
-    network = SoftLayer.NetworkManager(env.client)
-
-    pods = network.get_closed_pods()
-
     iops_table = formatting.Table(['Id', 'Description', 'KeyName'], title='IOPS')
     snapshot_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Snapshot')
-    file_storage_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Storage')
+    file_storage_table = formatting.Table(['Id', 'Description', 'KeyName', 'Capacity Minimum'], title='Storage')
     datacenter_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Datacenter')
 
     file_storage_table.align['Description'] = 'l'
     file_storage_table.align['KeyName'] = 'l'
     file_storage_table.sortby = 'Id'
-
     for datacenter in datacenters:
-        closure = []
-        for pod in pods:
-            if datacenter['location']['location']['name'] in str(pod['name']):
-                closure.append(pod['name'])
-
-        notes = '-'
-        if len(closure) > 0:
-            notes = 'closed soon: %s' % (', '.join(closure))
         datacenter_table.add_row([datacenter['location']['locationId'],
                                   datacenter.get('description'),
-                                  datacenter['keyname'], notes])
+                                  datacenter['keyname']])
 
-    for item_file in items:
-        if item_file['itemCategory']['categoryCode'] == 'performance_storage_space':
-            file_storage_table.add_row([item_file.get('id'), item_file.get('description'),
-                                        item_file.get('keyName')])
+    for item in items:
+        if item['itemCategory']['categoryCode'] == 'performance_storage_space':
+            file_storage_table.add_row([item.get('id'), item.get('description'),
+                                        item.get('keyName'), item.get('capacityMinimum') or '-'])
 
-        if item_file['itemCategory']['categoryCode'] == 'storage_tier_level':
-            iops_table.add_row([item_file.get('id'), item_file.get('description'),
-                                item_file.get('keyName')])
+        if item['itemCategory']['categoryCode'] == 'storage_tier_level':
+            iops_table.add_row([item.get('id'), item.get('description'),
+                                item.get('keyName')])
 
-        if item_file['itemCategory']['categoryCode'] == 'storage_snapshot_space':
-            snapshot_table.add_row([item_file.get('id'), item_file.get('description'),
-                                    item_file.get('keyName')])
+        if item['itemCategory']['categoryCode'] == 'storage_snapshot_space':
+            snapshot_table.add_row([item.get('id'), item.get('description'),
+                                    item.get('keyName')])
 
     env.fout(datacenter_table)
     env.fout(iops_table)
diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py
index 892d2081..2aa793d4 100644
--- a/SoftLayer/CLI/routes.py
+++ b/SoftLayer/CLI/routes.py
@@ -362,6 +362,7 @@
     ('user:edit-details', 'SoftLayer.CLI.user.edit_details:cli'),
     ('user:create', 'SoftLayer.CLI.user.create:cli'),
     ('user:delete', 'SoftLayer.CLI.user.delete:cli'),
+    ('user:device-access', 'SoftLayer.CLI.user.device_access:cli'),
     ('user:vpn-manual', 'SoftLayer.CLI.user.vpn_manual:cli'),
     ('user:vpn-subnet', 'SoftLayer.CLI.user.vpn_subnet:cli'),
 
diff --git a/SoftLayer/CLI/user/device_access.py b/SoftLayer/CLI/user/device_access.py
new file mode 100644
index 00000000..4ad0f295
--- /dev/null
+++ b/SoftLayer/CLI/user/device_access.py
@@ -0,0 +1,60 @@
+"""List  User Device access."""
+import click
+
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import formatting
+
+
+@click.command(cls=SoftLayer.CLI.command.SLCommand, )
+@click.argument('identifier')
+@environment.pass_env
+def cli(env, identifier):
+    """User Device access."""
+
+    mgr = SoftLayer.UserManager(env.client)
+    all_permissions = mgr.get_user_permissions(identifier)
+
+    # verify the table in table
+    table = formatting.Table(['Name', 'Value'])
+    permission_table = formatting.Table(['KeyName', 'Name'])
+    for permission in all_permissions:
+        if 'ALL_' in permission['key']:
+            permission_table.add_row([permission.get('keyName'), permission.get('name')])
+
+    hardwares = mgr.get_user_hardware(identifier)
+    dedicatedhosts = mgr.get_user_dedicated_host(identifier)
+    virtual_guests = mgr.get_user_virtuals(identifier)
+    hardware_table = formatting.KeyValueTable(['Id', 'Device Name', 'Device type', 'Public Ip', 'Private Ip', 'notes'])
+    virtual_table = formatting.KeyValueTable(['Id', 'Device Name', 'Device type', 'Public Ip', 'Private Ip', 'notes'])
+    dedicated_table = formatting.KeyValueTable(['Id', 'Device Name', 'Device type', 'notes'])
+
+    hardware_table.align['Device Name'] = 'l'
+    dedicated_table.align['Device Name'] = 'l'
+    virtual_table.align['Device Name'] = 'l'
+    for hardware in hardwares:
+        hardware_table.add_row([hardware.get('id'),
+                                hardware.get('fullyQualifiedDomainName'),
+                                'Bare Metal',
+                                hardware.get('primaryIpAddress'),
+                                hardware.get('primaryBackendIpAddress'),
+                                hardware.get('notes') or '-'])
+    for host in dedicatedhosts:
+        dedicated_table.add_row([host.get('id'),
+                                 host.get('name'),
+                                 'Dedicated Host',
+                                 host.get('notes') or '-'])
+    for virtual in virtual_guests:
+        virtual_table.add_row([virtual.get('id'),
+                               virtual.get('fullyQualifiedDomainName'),
+                               'virtual Guests',
+                               virtual.get('primaryIpAddress'),
+                               virtual.get('primaryBackendIpAddress'),
+                               virtual.get('notes') or '-'])
+
+    table.add_row(['Permission', permission_table])
+    table.add_row(['Hardware', hardware_table])
+    table.add_row(['Dedicated Host', dedicated_table])
+    table.add_row(['Virtual Guest', virtual_table])
+
+    env.fout(table)
diff --git a/SoftLayer/fixtures/SoftLayer_User_Customer.py b/SoftLayer/fixtures/SoftLayer_User_Customer.py
index 42c8f84c..789c22f9 100644
--- a/SoftLayer/fixtures/SoftLayer_User_Customer.py
+++ b/SoftLayer/fixtures/SoftLayer_User_Customer.py
@@ -86,3 +86,79 @@
 editObject = True
 addApiAuthenticationKey = True
 updateVpnUser = True
+
+getHardware = [{
+        "domain": "testedit.com",
+        "fullyQualifiedDomainName": "test.testedit.com",
+        "hardwareStatusId": 5,
+        "hostname": "test",
+        "id": 1403539,
+        "manufacturerSerialNumber": "J33H9TX",
+        "notes": "My golang note",
+        "provisionDate": "2020-04-27T16:10:56-06:00",
+        "serialNumber": "SL01FJUI",
+        "globalIdentifier": "81434794-af69-44d5-bb97-6b6f43454eee",
+        "hardwareStatus": {
+            "id": 5,
+            "status": "ACTIVE"
+        },
+        "networkManagementIpAddress": "10.93.138.222",
+        "primaryBackendIpAddress": "10.93.138.202",
+        "primaryIpAddress": "169.48.191.244",
+        "privateIpAddress": "10.93.138.202"
+    }]
+getDedicatedHosts = [
+    {
+        'createDate': '2021-11-18T15:13:57-06:00',
+        'diskCapacity': 1200,
+        'id': 656700,
+        'memoryCapacity': 242,
+        'modifyDate': '2022-04-26T10:49:48-06:00',
+        'name': 'dedicatedhost01'
+    },
+    {
+        'accountId': 307608,
+        'cpuCount': 56,
+        'createDate': '2022-02-18T12:47:30-06:00',
+        'diskCapacity': 1200,
+        'id': 691394,
+        'memoryCapacity': 242,
+        'modifyDate': '2022-04-18T11:24:20-06:00',
+        'name': 'test'
+    }
+]
+getVirtualGuests = [
+    {
+        "fullyQualifiedDomainName": "KVM-Test.cgallo.com",
+        "hostname": "KVM-Test",
+        "id": 121401696,
+        "maxCpu": 2,
+        "maxCpuUnits": "CORE",
+        "maxMemory": 4096,
+        "modifyDate": "2022-01-25T23:23:13-06:00",
+        "provisionDate": "2021-06-09T14:51:54-06:00",
+        "startCpus": 2,
+        "typeId": 1,
+        "uuid": "15951561-6171-0dfc-f3d2-be039e51cc10",
+        "globalIdentifier": "a245a7dd-acd1-4d1a-9356-cc1ac6b55b98",
+        "primaryBackendIpAddress": "10.208.73.53",
+        "primaryIpAddress": "169.48.96.27",
+    },
+    {
+        "createDate": "2020-11-16T09:01:57-06:00",
+        "deviceStatusId": 8,
+        "domain": "softlayer.test",
+        "fullyQualifiedDomainName": "SuspendVsTest.softlayer.test",
+        "hostname": "SuspendVsTest",
+        "id": 112238162,
+        "maxCpu": 8,
+        "maxCpuUnits": "CORE",
+        "maxMemory": 16384,
+        "modifyDate": "2022-01-25T14:15:37-06:00",
+        "provisionDate": "2020-11-16T09:09:04-06:00",
+        "startCpus": 8,
+        "typeId": 1,
+        "uuid": "d8908a64-f4d4-5637-49c7-650572d47120",
+        "globalIdentifier": "7fe777af-d38b-47c2-9f1c-b1ec26751b58",
+        "primaryBackendIpAddress": "10.74.54.76",
+    }]
diff --git a/SoftLayer/managers/user.py b/SoftLayer/managers/user.py
index 56acf163..b4999844 100644
--- a/SoftLayer/managers/user.py
+++ b/SoftLayer/managers/user.py
@@ -392,6 +392,30 @@ def get_overrides_list(self, user_id, subnet_ids):
 
         return overrides_list
 
+    def get_user_hardware(self, user_id):
+        """User Hardware list.
+
+        :param int user_id:
+        :return: List hardware relate to user
+        """
+        return self.user_service.getHardware(id=user_id)
+
+    def get_user_dedicated_host(self, user_id):
+        """User dedicate host list.
+
+        :param int user_id:
+        :return: List dedicated host relate to user
+        """
+        return self.user_service.getDedicatedHosts(id=user_id)
+
+    def get_user_virtuals(self, user_id):
+        """User virtual guest list.
+
+        :param int user_id:
+        :return: List virtual guest relate to user
+        """
+        return self.user_service.getVirtualGuests(id=user_id)
+
 
 def _keyname_search(haystack, needle):
     for item in haystack:
diff --git a/docs/cli/users.rst b/docs/cli/users.rst
index 5195a778..e4ab6046 100644
--- a/docs/cli/users.rst
+++ b/docs/cli/users.rst
@@ -40,6 +40,10 @@ Version 5.6.0 introduces the ability to interact with user accounts from the cli
     :prog: user delete
     :show-nested:
 
+.. click:: SoftLayer.CLI.user.device_access:cli
+    :prog: user device-access
+    :show-nested:
+
 .. click:: SoftLayer.CLI.user.vpn_manual:cli
     :prog: user vpn-manual
     :show-nested:


Test patch:
diff --git a/tests/CLI/modules/user_tests.py b/tests/CLI/modules/user_tests.py
index a11a9483..acb35ba2 100644
--- a/tests/CLI/modules/user_tests.py
+++ b/tests/CLI/modules/user_tests.py
@@ -336,3 +336,11 @@ def test_edit_notification_off_failure(self, click):
         click.secho.assert_called_with('Failed to update notifications: Test notification', fg='red')
         self.assert_no_fail(result)
         self.assert_called_with('SoftLayer_Email_Subscription', 'disable', identifier=111)
+
+    def test_devices_access(self):
+        result = self.run_command(['user', 'device-access', '111'])
+        self.assert_no_fail(result)
+        self.assert_called_with('SoftLayer_User_Customer', 'getPermissions')
+        self.assert_called_with('SoftLayer_User_Customer', 'getHardware')
+        self.assert_called_with('SoftLayer_User_Customer', 'getDedicatedHosts')
+        self.assert_called_with('SoftLayer_User_Customer', 'getVirtualGuests')
diff --git a/tests/managers/user_tests.py b/tests/managers/user_tests.py
index 5ea4d269..a0a20155 100644
--- a/tests/managers/user_tests.py
+++ b/tests/managers/user_tests.py
@@ -294,3 +294,15 @@ def test_gather_notifications_fail(self):
                                self.manager.gather_notifications,
                                ['Test not exit'])
         self.assertEqual("Test not exit is not a valid notification name", str(ex))
+
+    def test_get_hardware(self):
+        self.manager.get_user_hardware(1234)
+        self.assert_called_with('SoftLayer_User_Customer', 'getHardware')
+
+    def test_get_dedicated_host(self):
+        self.manager.get_user_dedicated_host(1234)
+        self.assert_called_with('SoftLayer_User_Customer', 'getDedicatedHosts')
+
+    def test_get_virtual(self):
+        self.manager.get_user_virtuals(1234)
+        self.assert_called_with('SoftLayer_User_Customer', 'getVirtualGuests')