Repository: softlayer/softlayer-python
Pull request #1774 (2022-10-21 15:08:43)

new command hw create-credential
[#issue1677](https://github.com/softlayer/softlayer-python/issues/1773)


![image](https://user-images.githubusercontent.com/22535437/197228453-af6db9c8-edb2-4a5b-998e-da503da6d516.png)



Patch:
diff --git a/SoftLayer/CLI/hardware/create_credential.py b/SoftLayer/CLI/hardware/create_credential.py
new file mode 100644
index 00000000..40bf14f6
--- /dev/null
+++ b/SoftLayer/CLI/hardware/create_credential.py
@@ -0,0 +1,57 @@
+"""Create a password for a software component"""
+# :license: MIT, see LICENSE for more details.
+
+import click
+
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import exceptions
+from SoftLayer.CLI import formatting
+
+
+@click.command(cls=SoftLayer.CLI.command.SLCommand, )
+@click.argument('identifier')
+@click.option('--username', '-U', required=True, help="The username part of the username/password pair")
+@click.option('--password', '-P', required=True, help="The password part of the username/password pair.")
+@click.option('--notes', '-n', help="A note string stored for this username/password pair.")
+@click.option('--system', required=True, help="The name of this specific piece of software.")
+@environment.pass_env
+def cli(env, identifier, username, password, notes, system):
+    """Create a password for a software component."""
+
+    mgr = SoftLayer.HardwareManager(env.client)
+
+    software = mgr.get_software_components(identifier)
+    sw_id = ''
+    try:
+        for sw_instance in software:
+            if (sw_instance['softwareLicense']['softwareDescription']['name']).lower() == system:
+                sw_id = sw_instance['id']
+    except KeyError as ex:
+        raise exceptions.CLIAbort('System id not found') from ex
+
+    template = {
+        "notes": notes,
+        "password": password,
+        "softwareId": sw_id,
+        "username": username,
+        "software": {
+            "hardwareId": identifier,
+            "softwareLicense": {
+                "softwareDescription": {
+                    "name": system
+                }
+            }
+        }}
+
+    result = mgr.create_credential(template)
+
+    table = formatting.KeyValueTable(['name', 'value'])
+    table.align['name'] = 'r'
+    table.align['value'] = 'l'
+    table.add_row(['Software Id', result['id']])
+    table.add_row(['Created', result['createDate']])
+    table.add_row(['Username', result['username']])
+    table.add_row(['Password', result['password']])
+    table.add_row(['Notes', result['notes']])
+    env.fout(table)
diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py
index 1e96961a..6af03600 100644
--- a/SoftLayer/CLI/routes.py
+++ b/SoftLayer/CLI/routes.py
@@ -296,6 +296,7 @@
     ('hardware:monitoring', 'SoftLayer.CLI.hardware.monitoring:cli'),
     ('hardware:notifications', 'SoftLayer.CLI.hardware.notifications:cli'),
     ('hardware:add-notification', 'SoftLayer.CLI.hardware.add_notification:cli'),
+    ('hardware:create-credential', 'SoftLayer.CLI.hardware.create_credential:cli'),
 
     ('securitygroup', 'SoftLayer.CLI.securitygroup'),
     ('securitygroup:list', 'SoftLayer.CLI.securitygroup.list:cli'),
diff --git a/SoftLayer/fixtures/SoftLayer_Hardware.py b/SoftLayer/fixtures/SoftLayer_Hardware.py
index f8164453..38c6fb1d 100644
--- a/SoftLayer/fixtures/SoftLayer_Hardware.py
+++ b/SoftLayer/fixtures/SoftLayer_Hardware.py
@@ -104,3 +104,35 @@
         "upperNonCritical": "12.915",
         "upperNonRecoverable": "13.403"
     }]
+
+getSoftwareComponents = [{
+    "hardwareId": 123456,
+    "id": 67064532,
+    "passwords": [
+        {
+            "id": 77995567,
+            "notes": "testslcli1",
+            "password": "123456",
+            "softwareId": 67064532,
+            "username": "testslcli1",
+        },
+        {
+            "id": 77944803,
+            "notes": "testslcli2",
+            "password": "test123",
+            "softwareId": 67064532,
+            "username": "testslcli2",
+        }
+    ],
+    "softwareLicense": {
+        "id": 21854,
+        "softwareDescriptionId": 2914,
+        "softwareDescription": {
+            "id": 2914,
+            "longDescription": "Ubuntu 20.04.1-64",
+            "name": "Ubuntu",
+            "referenceCode": "UBUNTU_20_64",
+            "version": "20.04.1-64"
+        }
+    }
+}]
diff --git a/SoftLayer/fixtures/SoftLayer_Software_Component_Password.py b/SoftLayer/fixtures/SoftLayer_Software_Component_Password.py
new file mode 100644
index 00000000..e5bd1673
--- /dev/null
+++ b/SoftLayer/fixtures/SoftLayer_Software_Component_Password.py
@@ -0,0 +1,13 @@
+createObject = {
+    "createDate": "2022-10-18T09:27:48-06:00",
+    "id": 78026761,
+    "notes": "test slcli",
+    "password": "123456",
+    "softwareId": 67064532,
+    "username": "testslcli",
+    "software": {
+        "hardwareId": 1532729,
+        "id": 67064532,
+        "manufacturerLicenseInstance": ""
+    }
+}
diff --git a/SoftLayer/managers/hardware.py b/SoftLayer/managers/hardware.py
index 92a820ca..0d2ad46a 100644
--- a/SoftLayer/managers/hardware.py
+++ b/SoftLayer/managers/hardware.py
@@ -1102,6 +1102,14 @@ def add_notification(self, hardware_id, user_id):
         template = {"hardwareId": hardware_id, "userId": user_id}
         return self.client.call('SoftLayer_User_Customer_Notification_Hardware', 'createObject', template)
 
+    def get_software_components(self, hardware_id):
+        """Returns  a piece of hardware’s installed software."""
+        return self.client.call('Hardware', 'getSoftwareComponents', id=hardware_id)
+
+    def create_credential(self, template):
+        """Create a password for a software component"""
+        return self.client.call('SoftLayer_Software_Component_Password', 'createObject', template)
+
 
 def _get_bandwidth_key(items, hourly=True, no_public=False, location=None):
     """Picks a valid Bandwidth Item, returns the KeyName"""
diff --git a/docs/cli/hardware.rst b/docs/cli/hardware.rst
index dfd10e82..5689b5e4 100644
--- a/docs/cli/hardware.rst
+++ b/docs/cli/hardware.rst
@@ -139,3 +139,7 @@ This function updates the firmware of a server. If already at the latest version
 .. click:: SoftLayer.CLI.hardware.add_notification:cli
    :prog: hardware add-notification
    :show-nested:
+
+.. click:: SoftLayer.CLI.hardware.create_credential:cli
+   :prog: hardware create-credential
+   :show-nested:


Test patch:
diff --git a/tests/CLI/modules/server_tests.py b/tests/CLI/modules/server_tests.py
index d2353f32..82f05e14 100644
--- a/tests/CLI/modules/server_tests.py
+++ b/tests/CLI/modules/server_tests.py
@@ -1045,3 +1045,9 @@ def test_notifications(self):
     def test_add_notification(self):
         result = self.run_command(['hardware', 'add-notification', '100', '--users', '123456'])
         self.assert_no_fail(result)
+
+    def test_create_credential(self):
+        result = self.run_command(['hw', 'create-credential', '123456',
+                                   '--username', 'testslcli', '--password', 'test-123456',
+                                   '--notes', 'test slcli', '--system', 'system'])
+        self.assert_no_fail(result)
diff --git a/tests/managers/hardware_tests.py b/tests/managers/hardware_tests.py
index b4e177bd..2d324d9d 100644
--- a/tests/managers/hardware_tests.py
+++ b/tests/managers/hardware_tests.py
@@ -557,10 +557,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):
@@ -928,6 +928,27 @@ def test_add_notification(self):
         self.hardware.add_notification(100, 123456)
         self.assert_called_with('SoftLayer_User_Customer_Notification_Hardware', 'createObject')
 
+    def test_get_software_component(self):
+        self.hardware.get_software_components(123456)
+        self.assert_called_with('SoftLayer_Hardware', 'getSoftwareComponents')
+
+    def test_create_credential(self):
+        template = {
+            "notes": 'notes',
+            "password": 'password',
+            "softwareId": 'sw_id',
+            "username": 'username',
+            "software": {
+                "hardwareId": 123456,
+                "softwareLicense": {
+                    "softwareDescription": {
+                        "name": 'system'
+                    }
+                }
+            }}
+        self.hardware.create_credential(template)
+        self.assert_called_with('SoftLayer_Software_Component_Password', 'createObject')
+
 
 class HardwareHelperTests(testing.TestCase):