#3 Fix the reported traceback
Merged 5 years ago by lruzicka. Opened 5 years ago by lruzicka.

file modified
+68 -14
@@ -16,6 +16,7 @@ 

  

  import argparse

  import json

+ import logging

  import subprocess

  import sys

  
@@ -25,6 +26,7 @@ 

          self.modlist = {}

          self.results = {}

          self.outputs = {}

+         logging.info('The test suite has been initialized.')

  

      def store_results(self, key, value):

          if key in self.results.keys():
@@ -34,23 +36,44 @@ 

  

          else:

              self.results[key] = [value]

+         logging.debug('The store_results method has stored the results into self.results.')    

          

          

      def module_list(self):

          raw = subprocess.run(['dnf', 'module', 'list'], capture_output=True)

          result = {}

+ 

          if raw.returncode == 0:

              result['dnf_module_list'] = 'pass'

+             logging.info('The DNF operation of module_list ran successfully (0)')

          else:

              result['dnf_module_list'] = raw.stderr.decode('utf-8')

+             logging.warning('The DNF operation of module_list did not run successfuly!')

                          

          raw = raw.stdout.decode('utf-8')

-         self.outputs['dnf_module_list'] = raw

-         raw = raw.split('\n')[3:-3]

-         raw = [x for x in raw if x[0] != ' ']

-         strip = [x.strip().split(' ') for x in raw]

+         

+         if raw == '':

+             logging.warning('The DNF output is empty.')

+         else:

+             logging.debug('The raw DNF output is:' + raw)

+         

+         preprocessed = raw.split('\n')[3:-3]

+         logging.debug('The preprocessed DNF output is:' + str('\n'.join(preprocessed)))

+ 

+         processed = []

+         try:  # This gets rid of all descriptive lines in the DNF output

+             for x in preprocessed:

+                 if x != '' and 'Fedora' not in x and 'Name' not in x:

+                     processed.append(x)

+             logging.debug('The cleaned DNF output is:' + str('\n'.join(processed)))

+         except IndexError:

+             logging.warning('The DNF output could not be properly parsed.')

+             raise

+         

+         strip = [x.strip().split(' ') for x in processed] # Here we split the output lines into columns

          mods = []

-         for line in strip:

+         

+         for line in strip: # Gets the modules lines from the output into a list of modules

              module = []

              for char in line:

                  if char == '' or char == '...':
@@ -58,12 +81,13 @@ 

                  else:

                      module.append(char.strip(','))

              mods.append(module)

-         for module in mods:

+         

+         for module in mods: # This will parse the module lines and chunk it into modules, streams, etc.

              try:

                  name = module[0]

                  stream = module[1]

              except IndexError:

-                 pass

+                 logging.warning('List of modules seems to be empty.')

              if name in self.modlist.keys():

                  value = self.modlist[name]

                  if isinstance(value, list):
@@ -76,7 +100,9 @@ 

                      self.modlist[name] = vlist

              else:

                  self.modlist[name] = stream

+         

          self.store_results('dnf module list', result)

+         logging.info('The "dnf module list" operation was succesful.')

          return self.modlist

  

  
@@ -88,8 +114,10 @@ 

          self.outputs[operation] = raw.stdout.decode('utf-8')

          if raw.returncode == 0:

              result[mod] = 'pass'

+             logging.info(f"The operation {key} has finished successfully.")

          else:

              result[mod] = raw.stderr.decode('utf-8')

+             logging.warning(f"The operation {key} has NOT finished successfully.")

          self.store_results(f'dnf module {operation}', result)   

          return result

  
@@ -110,8 +138,10 @@ 

                      break

                  else:

                      result[mod] = 'no'

+             logging.info(f"The operation {key} has finished successfully.")

          else:

              result[key] = raw.stderr.decode('utf-8')

+             logging.warning(f"The operation {key} has NOT finished successfully.")

          self.store_results(key, result)   

          return result

  
@@ -130,8 +160,10 @@ 

                  pass

          if c > 0:

              return (1, c)

+             logging.debug('The string was found in the DNF output.')

          else:

              return (0, c)

+             logging.debug('The string was NOT found in the DNF output.')

  

  

  class ModuleTest:
@@ -159,9 +191,11 @@ 

          if result == True:

              print(f'{key} exists in modules => yes')

              self.overall['list'] = 'pass'

+             logging.info(f"The result of {key} exists in modules is PASS.")

          else:

              print(f'{key} exists in modules => no')

              self.overall['list'] = 'fail'

+             logging.info(f"The result of {key} exists in modules is FAIL.")

          return(result)

  

      def check_install(self, module, stream):
@@ -170,8 +204,10 @@ 

          res1 = self.suite.is_listed(module, stream, 'installed')

          if res1[key] == 'pass':

              self.overall['checkinstall'] = 'pass'

+             logging.info(f"The result of {key} is PASS.")

          else:

              self.overall['checkinstall'] = 'fail'

+             logging.info(f"The result of {key} is FAIL.")

          print(' ')

  

  
@@ -186,11 +222,14 @@ 

          print(f"{key} is listed in --disabled =>", res3[key])

          if res1[key] == 'pass' and res2[key] == 'yes' and res3[key] == 'no':

              self.overall['enable'] = 'pass'

+             logging.info(f"The result of enabling {key} is PASS.")

          else:

              if self.fail == 'hard':

                  self.overall['enable'] = 'fail'

+                 logging.info(f"The result of enabling {key} is FAIL.")

              else:

                  self.overall['enable'] = 'soft'

+                 logging.info(f"The result of enabling {key} is SOFTFAIL.")

          print('')

  

      def disable_module(self, module, stream):
@@ -208,11 +247,14 @@ 

          print(f"{key} is listed in --installed =>", res4[key])

          if res1[key] == 'pass' and res2[key] == 'yes' and res3[key] == 'no' and res4[key] == 'no':

              self.overall['disable'] = 'pass'

+             logging.info(f"The result of disabling {key} is PASS.")

          else:

              if self.fail == 'hard':

                  self.overall['disable'] = 'fail'

+                 logging.info(f"The result of disabling {key} is FAIL.")

              else:

                  self.overall['disable'] = 'soft'

+                 logging.info(f"The result of disabling {key} is SOFTFAIL.")

          print('')

      

      def install_module(self, module, stream):
@@ -228,11 +270,14 @@ 

          print(f"{key} is listed in --disabled =>", res4[key])

          if res1[key] == 'pass' and res2[key] == 'yes' and res3[key] == 'yes' and res4[key] == 'no':

              self.overall['install'] = 'pass'

+             logging.info(f"The result of installing {key} is PASS.")

          else:

              if self.fail == 'hard':

                  self.overall['install'] = 'fail'

+                 logging.info(f"The result of installing {key} is FAIL.")

              else:

                  self.overall['install'] = 'soft'

+                 logging.info(f"The result of installing {key} is SOFTFAIL.")

          print('')

  

      def remove_module(self, module, stream):
@@ -247,11 +292,14 @@ 

          print(f"{key} is listed in --installed =>", res2[key])

          if res1[key] == 'pass' and res2[key] == 'no':

              self.overall['remove'] = 'pass'

+             logging.info(f"The result of removing {key} is PASS.")

          else:

              if self.fail == 'hard':

                  self.overall['remove'] = 'fail'

+                 logging.info(f"The result of removing {key} is FAIL.")

              else:

                  self.overall['remove'] = 'soft'

+                 logging.info(f"The result of removing {key} is SOFTFAIL.")

          print('')

  

      def switch_stream(self, module, oldstr, newstr):
@@ -271,11 +319,14 @@ 

          print(f"{oldkey} is listed in --disabled =>", res5[oldkey])

          if res1[newkey] == 'pass' and res2[newkey] == 'yes' and res3[oldkey] == 'no' and res4[newkey] == 'yes' and res5[oldkey] == 'yes':

              self.overall['switch'] = 'pass'

+             logging.info(f"The result of removing {key} is PASS.")

          else:

              if self.fail == 'hard':

                  self.overall['switch'] = 'fail'

+                 logging.info(f"The result of removing {key} is FAIL.")

              else:

                  self.overall['switch'] = 'soft'

+                 logging.info(f"The result of removing {key} is SOFTFAIL.")

          print('')

  

      def run_test(self, module='testmodule', stream='master', newer='dummy', fail='hard'):
@@ -308,15 +359,13 @@ 

          self.parser.add_argument('-u', '--upgrade', default='dummy', help='The name of the stream you want to switch to.')

          self.parser.add_argument('-a', '--action',default='list', help='List of actions, you want to run.')

          self.parser.add_argument('-f', '--fail',default='hard', help='Fail hard/soft at list errors.')

+         self.parser.add_argument('-l', '--log', default='info', help='Log Level use (info, warning, debug).')

      def return_args(self):

          args = self.parser.parse_args()

          return args

  

  if __name__ == '__main__':

-     

-     suite = TestSuite()

      options = Parser()

- 

      args = options.return_args()

      args = args.__dict__

      module = args['module']
@@ -324,7 +373,14 @@ 

      newstream = args['upgrade']

      action = args['action'].split(',')

      fail = args['fail']

+     log = args['log']

+     numloglevel = getattr(logging, log.upper())

  

+     logging.basicConfig(filename='modular.log', filemode='w', level=numloglevel)

+     logging.info('Script started.')

+     

+     suite = TestSuite()

+     

      test = ModuleTest(suite, action)

      test.run_test(module, oldstream, newstream, fail)

  
@@ -334,15 +390,13 @@ 

      for key in results:

          print(f"Tested functionality: {key} => {results[key]}")

      suite.outputs['total_results'] = results

-     log = json.dumps(suite.outputs, indent=4)

-     with open('/root/modular.log','w') as outfile:

-         outfile.write(log)

-     print("\nLog files have been saved.")

  

  

      if 'fail' in results.values():

+         logging.info('Script finished with exit code 1.')

          sys.exit(1)

      else:

+         logging.info('Script finished with exit code 0.')

          sys.exit(0)

  

  

The script was failing, because the DNF output changed and some
new strings appeared which it could not handle. Now it can parse
the output again. FIXES #1.

Logging support was added to log some of the information.
FIXES #2.

Pull-Request has been merged by lruzicka

5 years ago
Metadata