From 50ac1adc6d861679c40813a36a390938efa5d02b Mon Sep 17 00:00:00 2001
From: Jana Cupova <root@localhost>
Date: Oct 10 2022 08:02:43 +0000
Subject: CLI list-hosts fix when list of channels is empty


Fixes: https://pagure.io/koji/issue/3532

---

diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py
index ffa8e2d..faae928 100644
--- a/cli/koji_cli/commands.py
+++ b/cli/koji_cli/commands.py
@@ -3108,8 +3108,7 @@ def anon_handle_list_hosts(goptions, session, args):
         opts['ready'] = options.ready
     if options.enabled is not None:
         opts['enabled'] = options.enabled
-    tmp_list = sorted([(x['name'], x) for x in session.listHosts(**opts)])
-    hosts = [x[1] for x in tmp_list]
+    hosts = sorted(session.listHosts(**opts), key=lambda x: x['name'])
 
     if not hosts:
         warn("No hosts found.")
@@ -3149,11 +3148,11 @@ def anon_handle_list_hosts(goptions, session, args):
     if options.show_channels:
         with session.multicall() as m:
             result = [m.listChannels(host['id']) for host in hosts]
-        first_line_channel = result[0].result[0]
         for host, channels in zip(hosts, result):
             list_channels = []
             for c in channels.result:
-                if 'enabled' in first_line_channel:
+                # enabled column was added in Koji 1.26
+                if c.get('enabled') is not None:
                     if c['enabled']:
                         list_channels.append(c['name'])
                     else:
@@ -3162,10 +3161,7 @@ def anon_handle_list_hosts(goptions, session, args):
                     list_channels.append(c['name'])
             host['channels'] = ','.join(sorted(list_channels))
 
-    if hosts:
-        longest_host = max([len(h['name']) for h in hosts])
-    else:
-        longest_host = 8
+    longest_host = max([len(h['name']) for h in hosts])
 
     if not options.quiet:
         hdr = "{hostname:<{longest_host}} Enb Rdy Load/Cap  Arches           " \
diff --git a/tests/test_cli/test_list_hosts.py b/tests/test_cli/test_list_hosts.py
index f9d1955..0f3857d 100644
--- a/tests/test_cli/test_list_hosts.py
+++ b/tests/test_cli/test_list_hosts.py
@@ -47,6 +47,14 @@ class TestListHosts(utils.CliTestCase):
             os.environ['TZ'] = self.original_timezone
             time.tzset()
 
+    def __vm(self, result):
+        m = koji.VirtualCall('mcall_method', [], {})
+        if isinstance(result, dict) and result.get('faultCode'):
+            m._result = result
+        else:
+            m._result = (result,)
+        return m
+
     @mock.patch('sys.stdout', new_callable=StringIO)
     def test_list_hosts_valid_without_quiet(self, stdout):
         self.options.quiet = False
@@ -224,3 +232,54 @@ kojibuilder N   Y    0.0/2.0  x86_64           Tue, 16 Mar 2021 06:19:14 UTC
         self.session.listHosts.assert_called_once_with()
         self.session.getLastHostUpdate.assert_called_once_with(self.list_hosts[0]['id'], ts=True)
         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)
+
+    @mock.patch('sys.stdout', new_callable=StringIO)
+    def test_list_hosts_with_show_channels(self, stdout):
+        self.options.quiet = False
+        host_update = 1615875554.862938
+        expected = """Hostname    Enb Rdy Load/Cap  Arches           Last Update                         Channels
+-------------------------------------------------------------------------------------------
+kojibuilder N   Y    0.0/2.0  x86_64           Tue, 16 Mar 2021 06:19:14 UTC       *test,default\n"""
+        list_channels = [
+            {'id': 1, 'name': 'default', 'enabled': True, 'comment': 'test-comment-1',
+             'description': 'test-description-1'},
+            {'id': 2, 'name': 'test', 'enabled': False, 'comment': 'test-comment-2',
+             'description': 'test-description-2'},
+        ]
+
+        self.session.getLastHostUpdate.return_value = host_update
+        self.session.multiCall.return_value = [[host_update]]
+        mcall = self.session.multicall.return_value.__enter__.return_value
+        mcall.listChannels.return_value = self.__vm(list_channels)
+
+        self.session.listHosts.return_value = self.list_hosts
+        rv = anon_handle_list_hosts(self.options, self.session, ['--show-channels'])
+        self.assertEqual(rv, None)
+        self.assert_console_message(stdout, expected)
+        self.session.listHosts.assert_called_once_with()
+        self.session.getLastHostUpdate.assert_called_once_with(self.list_hosts[0]['id'], ts=True)
+        self.ensure_connection_mock.assert_called_once_with(self.session, self.options)
+        self.session.listChannels.assert_not_called()
+
+    @mock.patch('sys.stdout', new_callable=StringIO)
+    def test_list_hosts_with_show_channels_empty(self, stdout):
+        self.options.quiet = False
+        host_update = 1615875554.862938
+        expected = """Hostname    Enb Rdy Load/Cap  Arches           Last Update                         Channels
+-------------------------------------------------------------------------------------------
+kojibuilder N   Y    0.0/2.0  x86_64           Tue, 16 Mar 2021 06:19:14 UTC       \n"""
+        list_channels = []
+
+        self.session.getLastHostUpdate.return_value = host_update
+        self.session.multiCall.return_value = [[host_update]]
+        mcall = self.session.multicall.return_value.__enter__.return_value
+        mcall.listChannels.return_value = self.__vm(list_channels)
+
+        self.session.listHosts.return_value = self.list_hosts
+        rv = anon_handle_list_hosts(self.options, self.session, ['--show-channels'])
+        self.assertEqual(rv, None)
+        self.assert_console_message(stdout, expected)
+        self.session.listHosts.assert_called_once_with()
+        self.session.getLastHostUpdate.assert_called_once_with(self.list_hosts[0]['id'], ts=True)
+        self.ensure_connection_mock.assert_called_once_with(self.session, self.options)
+        self.session.listChannels.assert_not_called()

