#2505 cli: show log urls for failed tasks
Merged 2 years ago by mikem. Opened 2 years ago by tkopecek.
tkopecek/koji issue2188  into  master

file modified
+18 -18
@@ -537,7 +537,7 @@ 

      if build_opts.wait or (build_opts.wait is None and not _running_in_bg()):

          session.logout()

          return watch_tasks(session, [task_id], quiet=build_opts.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  def handle_chain_build(options, session, args):
@@ -612,7 +612,7 @@ 

      else:

          session.logout()

          return watch_tasks(session, [task_id], quiet=build_opts.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  def handle_maven_build(options, session, args):
@@ -713,7 +713,7 @@ 

      else:

          session.logout()

          return watch_tasks(session, [task_id], quiet=build_opts.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  def handle_wrapper_rpm(options, session, args):
@@ -785,7 +785,7 @@ 

      else:

          session.logout()

          return watch_tasks(session, [task_id], quiet=options.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  def handle_maven_chain(options, session, args):
@@ -837,7 +837,7 @@ 

      else:

          session.logout()

          return watch_tasks(session, [task_id], quiet=options.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  def handle_resubmit(goptions, session, args):
@@ -865,7 +865,7 @@ 

      else:

          session.logout()

          return watch_tasks(session, [newID], quiet=options.quiet,

-                            poll_interval=goptions.poll_interval)

+                            poll_interval=goptions.poll_interval, topurl=goptions.topurl)

  

  

  def handle_call(goptions, session, args):
@@ -1152,7 +1152,7 @@ 

      if my_opts.wait or (my_opts.wait is None and not _running_in_bg()):

          session.logout()

          return watch_tasks(session, [task_id], quiet=my_opts.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  def handle_import(goptions, session, args):
@@ -5889,7 +5889,7 @@ 

          print("Task info: %s/taskinfo?taskID=%s" % (options.weburl, task_id))

      if task_opts.wait or (task_opts.wait is None and not _running_in_bg()):

          session.logout()

-         return watch_tasks(session, [task_id], quiet=options.quiet)

+         return watch_tasks(session, [task_id], quiet=options.quiet, topurl=options.topurl)

  

  

  def handle_image_build(options, session, args):
@@ -6085,7 +6085,7 @@ 

      if task_opts.wait or (task_opts.wait is None and not _running_in_bg()):

          session.logout()

          return watch_tasks(session, [task_id], quiet=options.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  def _build_image_oz(options, task_opts, session, args):
@@ -6154,7 +6154,7 @@ 

      if task_opts.wait or (task_opts.wait is None and not _running_in_bg()):

          session.logout()

          return watch_tasks(session, [task_id], quiet=options.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  def handle_win_build(options, session, args):
@@ -6229,7 +6229,7 @@ 

      if build_opts.wait or (build_opts.wait is None and not _running_in_bg()):

          session.logout()

          return watch_tasks(session, [task_id], quiet=build_opts.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  def handle_free_task(goptions, session, args):
@@ -6476,7 +6476,7 @@ 

              parser.error(_("at least one task id must be specified"))

  

      return watch_tasks(session, tasks, quiet=options.quiet,

-                        poll_interval=goptions.poll_interval)

+                        poll_interval=goptions.poll_interval, topurl=goptions.topurl)

  

  

  def anon_handle_watch_logs(goptions, session, args):
@@ -6540,7 +6540,7 @@ 

      else:

          session.logout()

          return watch_tasks(session, [task_id], quiet=goptions.quiet,

-                            poll_interval=goptions.poll_interval)

+                            poll_interval=goptions.poll_interval, topurl=goptions.topurl)

  

  

  def handle_tag_build(opts, session, args):
@@ -6566,7 +6566,7 @@ 

      else:

          session.logout()

          return watch_tasks(session, tasks, quiet=opts.quiet,

-                            poll_interval=opts.poll_interval)

+                            poll_interval=opts.poll_interval, topurl=opts.topurl)

  

  

  def handle_move_build(opts, session, args):
@@ -6617,7 +6617,7 @@ 

      else:

          session.logout()

          return watch_tasks(session, tasks, quiet=opts.quiet,

-                            poll_interval=opts.poll_interval)

+                            poll_interval=opts.poll_interval, topurl=opts.topurl)

  

  

  def handle_untag_build(goptions, session, args):
@@ -6981,7 +6981,7 @@ 

              koji.TASK_STATES['CANCELED'],

              koji.TASK_STATES['FAILED']):

          watch_tasks(session, [base_task_id], quiet=suboptions.quiet,

-                     poll_interval=options.poll_interval)

+                     poll_interval=options.poll_interval, topurl=options.topurl)

  

      def check_downloadable(task):

          return task["method"] == "buildArch"
@@ -7188,7 +7188,7 @@ 

      else:

          session.logout()

          return watch_tasks(session, [task_id], quiet=options.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  def handle_dist_repo(options, session, args):
@@ -7327,7 +7327,7 @@ 

      else:

          session.logout()

          return watch_tasks(session, [task_id], quiet=options.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

  

  _search_types = ('package', 'build', 'tag', 'target', 'user', 'host', 'rpm',

file modified
+27 -8
@@ -139,12 +139,13 @@ 

  

  class TaskWatcher(object):

  

-     def __init__(self, task_id, session, level=0, quiet=False):

+     def __init__(self, task_id, session, level=0, quiet=False, topurl=None):

          self.id = task_id

          self.session = session

          self.info = None

          self.level = level

          self.quiet = quiet

+         self.topurl = topurl

  

      # XXX - a bunch of this stuff needs to adapt to different tasks

  
@@ -198,7 +199,7 @@ 

          else:

              # First time we're seeing this task, so just show the current state

              if not self.quiet:

-                 print("%s: %s" % (self.str(), self.display_state(self.info)))

+                 print("%s: %s" % (self.str(), self.display_state(self.info, level=self.level)))

              return False

  

      def is_done(self):
@@ -213,7 +214,7 @@ 

          state = koji.TASK_STATES[self.info['state']]

          return (state == 'CLOSED')

  

-     def display_state(self, info):

+     def display_state(self, info, level=0):

          # We can sometimes be passed a task that is not yet open, but

          # not finished either.  info would be none.

          if not info:
@@ -225,7 +226,25 @@ 

              else:

                  return 'open'

          elif info['state'] == koji.TASK_STATES['FAILED']:

-             return 'FAILED: %s' % self.get_failure()

+             s = 'FAILED: %s' % self.get_failure()

+ 

+             if self.topurl:

+                 # add relevant logs if there are any

+                 output = list_task_output_all_volumes(self.session, self.id)

+                 files = []

+                 for filename, volumes in six.iteritems(output):

+                     files += [(filename, volume) for volume in volumes]

+ 

+                 files = [file_volume for file_volume in files if file_volume[0].endswith('log')]

+ 

+                 pi = koji.PathInfo(topdir=self.topurl)

+                 # indent more than current level

+                 level += 1

+                 logs = ['  ' * level + os.path.join(pi.task(self.id, f[1]), f[0]) for f in files]

+                 if logs:

+                     s += '\n' + '  ' * level + 'Relevant logs:\n'

+                     s += '\n'.join(logs)

+             return s

          else:

              return koji.TASK_STATES[info['state']].lower()

  
@@ -264,7 +283,7 @@ 

              print('%s has not completed' % task_label)

  

  

- def watch_tasks(session, tasklist, quiet=False, poll_interval=60, ki_handler=None):

+ def watch_tasks(session, tasklist, quiet=False, poll_interval=60, ki_handler=None, topurl=None):

      if not tasklist:

          return

      if not quiet:
@@ -272,7 +291,7 @@ 

      if ki_handler is None:

          def ki_handler(progname, tasks, quiet):

              if not quiet:

-                 tlist = ['%s: %s' % (t.str(), t.display_state(t.info))

+                 tlist = ['%s: %s' % (t.str(), t.display_state(t.info, level=t.level))

                           for t in tasks.values() if not t.is_done()]

                  print(

                      "Tasks still running. You can continue to watch with the"
@@ -283,7 +302,7 @@ 

      try:

          tasks = {}

          for task_id in tasklist:

-             tasks[task_id] = TaskWatcher(task_id, session, quiet=quiet)

+             tasks[task_id] = TaskWatcher(task_id, session, quiet=quiet, topurl=topurl)

          while True:

              all_done = True

              for task_id, task in list(tasks.items()):
@@ -301,7 +320,7 @@ 

                      child_id = child['id']

                      if child_id not in tasks.keys():

                          tasks[child_id] = TaskWatcher(child_id, session, task.level + 1,

-                                                       quiet=quiet)

+                                                       quiet=quiet, topurl=topurl)

                          tasks[child_id].update()

                          # If we found new children, go through the list again,

                          # in case they have children also

file modified
+1 -1
@@ -87,7 +87,7 @@ 

      if opts.watch:

          session.logout()

          return watch_tasks(session, [task_id], quiet=opts.quiet,

-                            poll_interval=options.poll_interval)

+                            poll_interval=options.poll_interval, topurl=options.topurl)

  

      try:

          while True:

@@ -71,4 +71,5 @@ 

      else:

          session.logout()

          return watch_tasks(session, [task_id],

-                            quiet=opts.quiet, poll_interval=options.poll_interval)

+                            quiet=opts.quiet, poll_interval=options.poll_interval,

+                            topurl=options.topurl)

file modified
+9 -8
@@ -82,7 +82,8 @@ 

          self.session.logout.assert_called()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval,

+             topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -131,7 +132,7 @@ 

          self.session.logout.assert_called()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -326,7 +327,7 @@ 

          self.session.logout.assert_called()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

      @mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -510,7 +511,7 @@ 

          self.session.logout.assert_called()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -559,7 +560,7 @@ 

          self.session.logout.assert_called()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -663,7 +664,7 @@ 

          self.session.logout.assert_called_once()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -713,7 +714,7 @@ 

          self.session.logout.assert_called_once()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -767,7 +768,7 @@ 

          self.session.logout.assert_called_once()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

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

@@ -82,7 +82,7 @@ 

          self.session.logout.assert_called()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -528,7 +528,7 @@ 

          self.session.logout.assert_called()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -591,7 +591,7 @@ 

          self.session.logout.assert_called()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

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

@@ -97,7 +97,7 @@ 

                  self.session,

                  [self.task_id],

                  quiet=self.options.quiet,

-                 poll_interval=self.options.poll_interval)

+                 poll_interval=self.options.poll_interval, topurl=self.options.topurl)

  

      def test_handle_dist_repo_nowait(self):

          arguments = [self.tag_name, self.fake_key, '--nowait']

@@ -139,7 +139,7 @@ 

          self.watch_tasks.assert_called_with(

              self.session, [task_id],

              quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.session.buildImageOz.assert_called_once()

  

      def test_build_image_oz_background(self):

@@ -85,7 +85,7 @@ 

          self.session.logout.assert_called()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -438,7 +438,7 @@ 

          self.session.logout.assert_called_once()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=build_opts.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

          stdout.seek(0)
@@ -608,7 +608,7 @@ 

          self.session.logout.assert_called_once()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=build_opts['quiet'],

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

          stdout.seek(0)
@@ -678,7 +678,7 @@ 

          self.session.logout.assert_called()

          watch_tasks_mock.assert_called_once_with(

              self.session, [task_id], quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

          self.assertEqual(rv, 0)

  

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

@@ -139,7 +139,7 @@ 

          running_in_bg_mock.assert_called()

          watch_tasks_mock.assert_called_with(

              session, [self.task_id], quiet=options.quiet,

-             poll_interval=options.poll_interval)

+             poll_interval=options.poll_interval, topurl=options.topurl)

  

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

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

@@ -67,7 +67,7 @@ 

              self.session,

              tasks,

              quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

  

      def test_handle_move_build_nowait(self):

          """Test handle_move_build function with --nowait option"""

@@ -46,7 +46,7 @@ 

          session.restartHosts.assert_called_with()

          session.logout.assert_called_once()

          watch_tasks_mock.assert_called_with(

-             session, [self.task_id], quiet=None, poll_interval=3)

+             session, [self.task_id], quiet=None, poll_interval=3, topurl=options.topurl)

  

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

      @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -148,7 +148,7 @@ 

          session.restartHosts.assert_called_with()

          session.logout.assert_called_once()

          watch_tasks_mock.assert_called_with(

-             session, [self.task_id], quiet=None, poll_interval=3)

+             session, [self.task_id], quiet=None, poll_interval=3, topurl=options.topurl)

  

      @mock.patch('koji_cli.commands.watch_tasks')

      @mock.patch('koji_cli.commands._running_in_bg')

@@ -83,7 +83,8 @@ 

              session,

              [new_task_id],

              quiet=True,

-             poll_interval=options.poll_interval)

+             poll_interval=options.poll_interval,

+             topurl=options.topurl)

          session.logout.assert_called_once()

          session.resubmitTask.assert_called_with(self.task_id)

          session.resubmitTask.assert_called_once()

@@ -56,7 +56,7 @@ 

              self.session,

              tasks,

              quiet=self.options.quiet,

-             poll_interval=self.options.poll_interval)

+             poll_interval=self.options.poll_interval, topurl=self.options.topurl)

  

      def test_handle_tag_build_quiet_mode(self):

          """Test handle_tag_build function with --nowait option"""

@@ -47,7 +47,7 @@ 

  

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

      def test_watch_tasks_no_tasklist(self, stdout):

-         returned = watch_tasks(self.session, [], poll_interval=0)

+         returned = watch_tasks(self.session, [], poll_interval=0, topurl=self.options.topurl)

          actual = stdout.getvalue()

          expected = ""

          self.assertIsNone(returned)
@@ -60,7 +60,8 @@ 

          with open(cfile) as fp:

              cdata = json.load(fp)

          self.session.load_calls(cdata)

-         rv = watch_tasks(self.session, [1188], quiet=False, poll_interval=0)

+         rv = watch_tasks(self.session, [1188], quiet=False, poll_interval=0,

+                          topurl=self.options.topurl)

          self.assertEqual(rv, 0)

          expected = (

  '''Watching tasks (this may be safely interrupted)...
@@ -80,7 +81,7 @@ 

          with open(cfile) as fp:

              cdata = json.load(fp)

          self.session.load_calls(cdata)

-         rv = watch_tasks(self.session, [1208], quiet=False, poll_interval=5)

+         rv = watch_tasks(self.session, [1208], quiet=False, poll_interval=5, topurl=None)

          self.assertEqual(rv, 1)

          expected = ('''Watching tasks (this may be safely interrupted)...

  1208 build (f24, /users/mikem/fake.git:master): free
@@ -108,7 +109,8 @@ 

          sleep.side_effect = [None] * 10  + [KeyboardInterrupt]

          with self.assertRaises(KeyboardInterrupt):

              # watch_tasks catches and re-raises it to display a message

-             watch_tasks(self.session, [1208], quiet=False, poll_interval=5)

+             watch_tasks(self.session, [1208], quiet=False, poll_interval=5,

+                         topurl=self.options.topurl)

          expected = ('''Watching tasks (this may be safely interrupted)...

  1208 build (f24, /users/mikem/fake.git:master): free

  1208 build (f24, /users/mikem/fake.git:master): free -> open (builder-01)
@@ -137,7 +139,7 @@ 

          with self.assertRaises(KeyboardInterrupt):

              # watch_tasks catches and re-raises it to display a message

              watch_tasks(self.session, [1208], quiet=False, poll_interval=5,

-                         ki_handler=customized_handler)

+                         ki_handler=customized_handler, topurl=self.options.topurl)

          expected = ('''Watching tasks (this may be safely interrupted)...

  1208 build (f24, /users/mikem/fake.git:master): free

  1208 build (f24, /users/mikem/fake.git:master): free -> open (builder-01)

@@ -80,7 +80,8 @@ 

          activate_session_mock.assert_called_with(session, options)

          watch_tasks_mock.assert_called_with(

              session, [self.task_id], quiet=options.quiet,

-             poll_interval=options.poll_interval)

+             poll_interval=options.poll_interval,

+             topurl=options.topurl)

  

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

      @mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -190,7 +191,8 @@ 

          activate_session_mock.assert_called_with(session, options)

          watch_tasks_mock.assert_called_with(

              session, [self.task_id], quiet=options.quiet,

-             poll_interval=options.poll_interval)

+             poll_interval=options.poll_interval,

+             topurl=options.topurl)

  

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

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

@@ -122,7 +122,8 @@ 

          self.session.logout.assert_called_once_with()

          save_failed_tree.watch_tasks.assert_called_once_with(self.session, [spawned_id],

                                                               poll_interval=options.poll_interval,

-                                                              quiet=options.quiet)

+                                                              quiet=options.quiet,

+                                                              topurl=options.topurl)

  

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

      def test_handle_save_failed_tree_errors(self, stdout):

rebased onto a8ba378

2 years ago

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

2 years ago

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

2 years ago

Commit fa56a5b fixes this pull-request

Pull-Request has been merged by mikem

2 years ago