#2766 api getLastHostUpdate returns timestamp
Merged a year ago by tkopecek. Opened a year ago by jcupova.
jcupova/koji issue2497  into  master

file modified
+4 -4
@@ -2888,14 +2888,14 @@ 

      # pull in the last update using multicall to speed it up a bit

      session.multicall = True

      for host in hosts:

-         session.getLastHostUpdate(host['id'])

+         session.getLastHostUpdate(host['id'], ts=True)

      updateList = session.multiCall()

  

      for host, [update] in zip(hosts, updateList):

          if update is None:

              host['update'] = '-'

          else:

-             host['update'] = update.split('.')[0]

+             host['update'] = koji.formatTimeLong(update)

          host['enabled'] = yesno(host['enabled'])

          host['ready'] = yesno(host['ready'])

          host['arches'] = ','.join(host['arches'].split())
@@ -3355,11 +3355,11 @@ 

              print("Comment:")

          print("Enabled: %s" % (info['enabled'] and 'yes' or 'no'))

          print("Ready: %s" % (info['ready'] and 'yes' or 'no'))

-         update = session.getLastHostUpdate(info['id'])

+         update = session.getLastHostUpdate(info['id'], ts=True)

          if update is None:

              update = "never"

          else:

-             update = update[:update.find('.')]

+             update = koji.formatTimeLong(update)

          print("Last Update: %s" % update)

          print("Channels: %s" % ' '.join([c['name']

                                           for c in session.listChannels(hostID=info['id'])]))

file modified
+7 -3
@@ -12636,8 +12636,8 @@ 

                                 tables=tables, joins=joins, clauses=clauses, values=locals())

          return query.execute()

  

-     def getLastHostUpdate(self, hostID):

-         """Return the latest update timestampt for the host

+     def getLastHostUpdate(self, hostID, ts=False):

+         """Return the latest update timestamp for the host

  

          The timestamp represents the last time the host with the given

          ID contacted the hub. Returns None if the host has never contacted
@@ -12648,7 +12648,11 @@ 

          ORDER BY update_time DESC

          LIMIT 1

          """

-         return _singleValue(query, locals(), strict=False)

+         date = _singleValue(query, locals(), strict=False)

+         if ts and date is not None:

+             return date.timestamp()

+         else:

+             return date

  

      getAllArches = staticmethod(get_all_arches)

  

@@ -1,5 +1,8 @@ 

  from __future__ import absolute_import

  import mock

+ import os

+ import time

+ import locale

  from six.moves import StringIO

  

  import koji
@@ -9,10 +12,15 @@ 

  

  class TestHostinfo(utils.CliTestCase):

      def setUp(self):

+         # force locale to compare 'expect' value

+         locale.setlocale(locale.LC_ALL, ('en_US', 'UTF-8'))

          self.options = mock.MagicMock()

          self.options.debug = False

          self.session = mock.MagicMock()

          self.session.getAPIVersion.return_value = koji.API_VERSION

+         self.original_timezone = os.environ.get('TZ')

+         os.environ['TZ'] = 'UTC'

+         time.tzset()

          self.hostinfo = {'arches': 'x86_64',

                           'capacity': 2.0,

                           'comment': None,
@@ -23,9 +31,55 @@ 

                           'ready': True,

                           'task_load': 0.0,

                           'user_id': 2}

-         self.last_update = '2021-03-16 06:19:14.862938+00:00'

+         self.last_update = 1615875554.862938

          self.list_channels = [{'id': 1, 'name': 'default'}, {'id': 2, 'name': 'createrepo'}]

  

+     def tearDown(self):

+         locale.resetlocale()

+         if self.original_timezone is None:

+             del os.environ['TZ']

+         else:

+             os.environ['TZ'] = self.original_timezone

+             time.tzset()

+ 

+     @mock.patch('sys.stderr', new_callable=StringIO)

+     def test_hostinfo_without_option(self, stderr):

+         expected = "Usage: %s hostinfo [options] <hostname> [<hostname> ...]\n" \

+                    "(Specify the --help global option for a list of other help options)\n\n" \

+                    "%s: error: Please specify a host\n" % (self.progname, self.progname)

+         self.session.getChannel.return_value = None

+         with self.assertRaises(SystemExit) as ex:

+             anon_handle_hostinfo(self.options, self.session, [])

+         self.assertExitCode(ex, 2)

+         self.assert_console_message(stderr, expected)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_hostinfo_valid(self, stdout):

+         expected = """Name: kojibuilder

+ ID: 1

+ Arches: x86_64

+ Capacity: 2.0

+ Task Load: 0.00

+ Description:

+ Comment:

+ Enabled: yes

+ Ready: yes

+ Last Update: Tue, 16 Mar 2021 06:19:14 UTC

+ Channels: default createrepo

+ Active Buildroots:

+ None

+ """

+         self.session.getHost.return_value = self.hostinfo

+         self.session.getLastHostUpdate.return_value = self.last_update

+         self.session.listChannels.return_value = self.list_channels

+         rv = anon_handle_hostinfo(self.options, self.session, [self.hostinfo['name']])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.getHost.assert_called_once_with(self.hostinfo['name'])

+         self.session.getLastHostUpdate.assert_called_once_with(self.hostinfo['id'], ts=True)

+         self.session.listChannels.assert_called_once_with(hostID=self.hostinfo['id'])

+         self.assertEqual(self.session.listBuildroots.call_count, 3)

+ 

      @mock.patch('sys.stderr', new_callable=StringIO)

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_hostinfo_more_hosts_with_non_exit_host(self, stdout, stderr):
@@ -40,7 +94,7 @@ 

  Comment:

  Enabled: yes

  Ready: yes

- Last Update: 2021-03-16 06:19:14

+ Last Update: Tue, 16 Mar 2021 06:19:14 UTC

  Channels: default createrepo

  Active Buildroots:

  None
@@ -56,7 +110,7 @@ 

          self.assert_console_message(stdout, expected_stdout)

          self.assert_console_message(stderr, expected_error)

          self.assertEqual(self.session.getHost.call_count, 2)

-         self.session.getLastHostUpdate.assert_called_once_with(self.hostinfo['id'])

+         self.session.getLastHostUpdate.assert_called_once_with(self.hostinfo['id'], ts=True)

          self.session.listChannels.assert_called_once_with(hostID=self.hostinfo['id'])

          self.assertEqual(self.session.listBuildroots.call_count, 3)

  

@@ -1,6 +1,8 @@ 

  from __future__ import absolute_import

- 

  import mock

+ import os

+ import time

+ import locale

  from six.moves import StringIO

  

  import koji
@@ -10,13 +12,51 @@ 

  

  class TestListHosts(utils.CliTestCase):

      def setUp(self):

+         # force locale to compare 'expect' value

+         locale.setlocale(locale.LC_ALL, ('en_US', 'UTF-8'))

          self.options = mock.MagicMock()

          self.options.debug = False

          self.session = mock.MagicMock()

          self.session.getAPIVersion.return_value = koji.API_VERSION

+         self.original_timezone = os.environ.get('TZ')

+         os.environ['TZ'] = 'UTC'

+         time.tzset()

+ 

+     def tearDown(self):

+         locale.resetlocale()

+         if self.original_timezone is None:

+             del os.environ['TZ']

+         else:

+             os.environ['TZ'] = self.original_timezone

+             time.tzset()

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     @mock.patch('koji_cli.commands.ensure_connection')

+     def test_list_hosts_valid(self, ensure_connection, stdout):

+         host_update = 1615875554.862938

+         expected = """kojibuilder Y   Y    0.0/2.0  x86_64           Tue, 16 Mar 2021 06:19:14 UTC

+ """

+         list_hosts = [{'arches': 'x86_64',

+                        'capacity': 2.0,

+                        'comment': None,

+                        'description': None,

+                        'enabled': True,

+                        'id': 1,

+                        'name': 'kojibuilder',

+                        'ready': True,

+                        'task_load': 0.0,

+                        'user_id': 2}]

+         self.session.getLastHostUpdate.return_value = host_update

+         self.session.multiCall.return_value = [[host_update]]

+         self.session.listHosts.return_value = list_hosts

+         rv = anon_handle_list_hosts(self.options, self.session, [])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.listHosts.assert_called_once_with()

+         self.session.getLastHostUpdate.assert_called_once_with(list_hosts[0]['id'], ts=True)

  

      @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_pkgs_non_exist_channel(self, stderr):

+     def test_list_hosts_non_exist_channel(self, stderr):

          channel = 'test-channel'

          expected = "Usage: %s list-hosts [options]\n" \

                     "(Specify the --help global option for a list of other help options)\n\n" \

@@ -0,0 +1,38 @@ 

+ import unittest

+ import mock

+ import datetime

+ import sys

+ 

+ import kojihub

+ 

+ 

+ class TestGetLastHostUpdate(unittest.TestCase):

+ 

+     def setUp(self):

+         self.exports = kojihub.RootExports()

+ 

+     @mock.patch('kojihub._singleValue')

+     def test_valid_ts(self, _singleValue):

+         expected = 1615875554.862938

+         if sys.version_info[1] <= 6:

+             dt = datetime.datetime.strptime(

+                 "2021-03-16T06:19:14.862938+0000", "%Y-%m-%dT%H:%M:%S.%f%z")

+         else:

+             dt = datetime.datetime.strptime(

+                 "2021-03-16T06:19:14.862938+00:00", "%Y-%m-%dT%H:%M:%S.%f%z")

+         _singleValue.return_value = dt

+         rv = self.exports.getLastHostUpdate(1, ts=True)

+         self.assertEqual(rv, expected)

+ 

+     @mock.patch('kojihub._singleValue')

+     def test_valid_datetime(self, _singleValue):

+         if sys.version_info[1] <= 6:

+             dt = datetime.datetime.strptime(

+                 "2021-03-16T06:19:14.862938+0000", "%Y-%m-%dT%H:%M:%S.%f%z")

+         else:

+             dt = datetime.datetime.strptime(

+                 "2021-03-16T06:19:14.862938+00:00", "%Y-%m-%dT%H:%M:%S.%f%z")

+             expected = "2021-03-16T06:19:14.862938+00:00"

+         _singleValue.return_value = dt

+         rv = self.exports.getLastHostUpdate(1)

+         self.assertEqual(rv, dt)

file modified
+2 -2
@@ -1637,7 +1637,7 @@ 

  

      server.multicall = True

      for host in hosts:

-         server.getLastHostUpdate(host['id'])

+         server.getLastHostUpdate(host['id'], ts=True)

      updates = server.multiCall()

      for host, [lastUpdate] in zip(hosts, updates):

          host['last_update'] = lastUpdate
@@ -1680,7 +1680,7 @@ 

      values['host'] = host

      values['channels'] = channels

      values['buildroots'] = buildroots

-     values['lastUpdate'] = server.getLastHostUpdate(host['id'])

+     values['lastUpdate'] = server.getLastHostUpdate(host['id'], ts=True)

      if environ['koji.currentUser']:

          values['perms'] = server.getUserPerms(environ['koji.currentUser']['id'])

      else:

rebased onto bc7d358189b91541afe30c845b3b768e2e6bbaea

a year ago

rebased onto f8a858bfce368e9771ba621ba6bbfe86881529af

a year ago

rebased onto 076564819823b6ec8cbd828b55b1bdd187b6f2f2

a year ago

rebased onto dded273a7d09395b25243733d0c3ba4b676a05e9

a year ago

Metadata Update from @tkopecek:
- Pull-request tagged with: testing-ready

a year ago

rebased onto 1208140a876fa1cd3122a2668dd06dccaac033d0

a year ago

@tkopecek can you review it again? I pushed check when hostID is not existing. There were a problem when ts=True.

I would simplify it a bit (just check that it is working correctly for invalid host):

date = return _singleValue(query, locals(), strict=False)
if ts and date is not None:
    return date.timestamp()
else:
    return date

rebased onto 74a34fad17a10264cd4786ecc2569e0d5811f739

a year ago

rebased onto 421555c

a year ago

Metadata Update from @jobrauer:
- Pull-request tagged with: testing-done

a year ago

Commit f7a6338 fixes this pull-request

Pull-Request has been merged by tkopecek

a year ago