files.new_contents: 
  """ Step Classes """
  
  import os
  import re
  
  import click
  from click import echo
  
  import tmt.utils
  from tmt.options import show_step_method_hints
  from tmt.utils import GeneralError
  
  # Supported steps and actions
  STEPS = ['discover', 'provision', 'prepare', 'execute', 'report', 'finish']
  ACTIONS = ['login', 'reboot']
  
  # Step phase order
  PHASE_START = 10
  PHASE_BASE = 50
  PHASE_END = 90
  
  
  class Step(tmt.utils.Common):
      """ Common parent of all test steps """
  
      # Default implementation for all steps is shell
      # except for provision (virtual) and report (display)
      how = 'shell'
  
      def __init__(self, data=None, plan=None, name=None):
          """ Initialize and check the step data """
          super().__init__(name=name, parent=plan)
          # Initialize data
          self.plan = plan
          self.data = data or {}
          self._status = None
          self._plugins = []
  
          # Create an empty step by default (can be updated from cli)
          if self.data is None:
              self.data = [{'name': tmt.utils.DEFAULT_NAME}]
          # Convert to list if only a single config provided
          elif isinstance(self.data, dict):
              # Give it a name unless defined
              if not self.data.get('name'):
                  self.data['name'] = tmt.utils.DEFAULT_NAME
              self.data = [self.data]
          # Shout about invalid
  
  [... the rest is omitted ...]
files.new_path: tmt/steps/__init__.py
files.old_contents: 
  """ Step Classes """
  
  import os
  import re
  
  import click
  from click import echo
  
  import tmt.utils
  from tmt.options import show_step_method_hints
  from tmt.utils import GeneralError
  
  # Supported steps and actions
  STEPS = ['discover', 'provision', 'prepare', 'execute', 'report', 'finish']
  ACTIONS = ['login', 'reboot']
  
  # Step phase order
  PHASE_START = 10
  PHASE_BASE = 50
  PHASE_END = 90
  
  
  class Step(tmt.utils.Common):
      """ Common parent of all test steps """
  
      # Default implementation for all steps is shell
      # except for provision (virtual) and report (display)
      how = 'shell'
  
      def __init__(self, data=None, plan=None, name=None):
          """ Initialize and check the step data """
          super().__init__(name=name, parent=plan)
          # Initialize data
          self.plan = plan
          self.data = data or {}
          self._status = None
          self._plugins = []
  
          # Create an empty step by default (can be updated from cli)
          if self.data is None:
              self.data = [{'name': tmt.utils.DEFAULT_NAME}]
          # Convert to list if only a single config provided
          elif isinstance(self.data, dict):
              # Give it a name unless defined
              if not self.data.get('name'):
                  self.data['name'] = tmt.utils.DEFAULT_NAME
              self.data = [self.data]
          # Shout about invalid
  
  [... the rest is omitted ...]
files.old_path: tmt/steps/__init__.py
files.new_contents: import copy
  import re
  
  import click
  import fmf
  
  import tmt
  
  
  class Finish(tmt.steps.Step):
      """
      Perform the finishing tasks and clean up provisioned guests.
  
      Additional actions to be performed after the test execution has been
      completed. Counterpart of the ``prepare`` step useful for various
      cleanup actions. Also takes care of stopping and removing guests.
  
      Note that the ``finish`` step is also run when any of the previous
      steps failed (for example when the environment preparation was not
      successful) so that provisioned systems are not kept running.
      """
  
      def wake(self):
          """ Wake up the step (process workdir and command line) """
          super().wake()
  
          # Choose the right plugin and wake it up
          for data in self.data:
              plugin = FinishPlugin.delegate(self, data)
              plugin.wake()
              # Add plugin only if there are data
              if len(plugin.data.keys()) > 2:
                  self._plugins.append(plugin)
  
          # Nothing more to do if already done
          if self.status() == 'done':
              self.debug(
                  'Finish wake up complete (already done before).', level=2)
          # Save status and step data (now we know what to do)
          else:
              self.status('todo')
              self.save()
  
      def show(self):
          """ Show finish details """
          for data in self.data:
              FinishPlugin.delegate(self, data).show()
  
      def summary(self):
          """ Give a concise summary """
          tasks = fmf.utils.l
  
  [... the rest is omitted ...]
files.new_path: tmt/steps/finish/__init__.py
files.old_contents: import copy
  import re
  
  import click
  import fmf
  
  import tmt
  
  
  class Finish(tmt.steps.Step):
      """
      Perform the finishing tasks and clean up provisioned guests.
  
      Additional actions to be performed after the test execution has been
      completed. Counterpart of the ``prepare`` step useful for various
      cleanup actions. Also takes care of stopping and removing guests.
  
      Note that the ``finish`` step is also run when any of the previous
      steps failed (for example when the environment preparation was not
      successful) so that provisioned systems are not kept running.
      """
  
      def wake(self):
          """ Wake up the step (process workdir and command line) """
          super().wake()
  
          # Choose the right plugin and wake it up
          for data in self.data:
              plugin = FinishPlugin.delegate(self, data)
              plugin.wake()
              # Add plugin only if there are data
              if len(plugin.data.keys()) > 2:
                  self._plugins.append(plugin)
  
          # Nothing more to do if already done
          if self.status() == 'done':
              self.debug(
                  'Finish wake up complete (already done before).', level=2)
          # Save status and step data (now we know what to do)
          else:
              self.status('todo')
              self.save()
  
      def show(self):
          """ Show finish details """
          for data in self.data:
              FinishPlugin.delegate(self, data).show()
  
      def summary(self):
          """ Give a concise summary """
          tasks = fmf.utils.l
  
  [... the rest is omitted ...]
files.old_path: tmt/steps/finish/__init__.py
files.new_contents: import collections
  import copy
  
  import click
  import fmf
  
  import tmt
  
  
  class Prepare(tmt.steps.Step):
      """
      Prepare the environment for testing.
  
      Use the 'order' attribute to select in which order preparation
      should happen if there are multiple configs. Default order is '50'.
      Default order of required packages installation is '70', for the
      recommended packages it is '75'.
      """
  
      def __init__(self, data, plan):
          """ Initialize prepare step data """
          super().__init__(data, plan)
          self.preparations_applied = 0
  
      def wake(self):
          """ Wake up the step (process workdir and command line) """
          super().wake()
  
          # Choose the right plugin and wake it up
          for data in self.data:
              plugin = PreparePlugin.delegate(self, data)
              plugin.wake()
              # Add plugin only if there are data
              if len(plugin.data.keys()) > 2:
                  self._plugins.append(plugin)
  
          # Nothing more to do if already done
          if self.status() == 'done':
              self.debug(
                  'Prepare wake up complete (already done before).', level=2)
          # Save status and step data (now we know what to do)
          else:
              self.status('todo')
              self.save()
  
      def show(self):
          """ Show discover details """
          for data in self.data:
              PreparePlugin.delegate(self, data).show()
  
      def summary(self):
          """ Give a concise summary of the preparation """
          preparations = fm
  
  [... the rest is omitted ...]
files.new_path: tmt/steps/prepare/__init__.py
files.old_contents: import collections
  import copy
  
  import click
  import fmf
  
  import tmt
  
  
  class Prepare(tmt.steps.Step):
      """
      Prepare the environment for testing.
  
      Use the 'order' attribute to select in which order preparation
      should happen if there are multiple configs. Default order is '50'.
      Default order of required packages installation is '70', for the
      recommended packages it is '75'.
      """
  
      def __init__(self, data, plan):
          """ Initialize prepare step data """
          super().__init__(data, plan)
          self.preparations_applied = 0
  
      def wake(self):
          """ Wake up the step (process workdir and command line) """
          super().wake()
  
          # Choose the right plugin and wake it up
          for data in self.data:
              plugin = PreparePlugin.delegate(self, data)
              plugin.wake()
              # Add plugin only if there are data
              if len(plugin.data.keys()) > 2:
                  self._plugins.append(plugin)
  
          # Nothing more to do if already done
          if self.status() == 'done':
              self.debug(
                  'Prepare wake up complete (already done before).', level=2)
          # Save status and step data (now we know what to do)
          else:
              self.status('todo')
              self.save()
  
      def show(self):
          """ Show discover details """
          for data in self.data:
              PreparePlugin.delegate(self, data).show()
  
      def summary(self):
          """ Give a concise summary of the preparation """
          preparations = fm
  
  [... the rest is omitted ...]
files.old_path: tmt/steps/prepare/__init__.py
files.new_contents: import tmt
  
  
  class ProvisionLocal(tmt.steps.provision.ProvisionPlugin):
      """
      Use local host for test execution
  
      In general it is not recommended to run tests on your local machine
      as there might be security risks. Run only those tests which you
      know are safe so that you don't destroy your laptop ;-)
  
      Example config:
  
          provision:
              how: local
  
      Note that 'tmt run' is expected to be executed under a regular user.
      If there are admin rights required (for example in the prepare step)
      you might be asked for a sudo password.
      """
  
      # Guest instance
      _guest = None
  
      # Supported methods
      _methods = [tmt.steps.Method(name='local', doc=__doc__, order=50)]
  
      def wake(self, keys=None, data=None):
          """ Wake up the plugin, process data, apply options """
          super().wake(keys=keys, data=data)
          if data:
              self._guest = GuestLocal(data, name=self.name, parent=self.step)
  
      def go(self):
          """ Provision the container """
          super().go()
  
          # Create a GuestLocal instance
          data = {'guest': 'localhost', 'role': self.get('role')}
          self._guest = GuestLocal(data, name=self.name, parent=self.step)
  
      def guest(self):
          """ Return the provisioned guest """
          return self._guest
  
      def requires(self):
          """ List of required packages needed for workdir sync """
          return GuestLocal.requires()
  
  
  class
  
  [... the rest is omitted ...]
files.new_path: tmt/steps/provision/local.py
files.old_contents: import tmt
  
  
  class ProvisionLocal(tmt.steps.provision.ProvisionPlugin):
      """
      Use local host for test execution
  
      In general it is not recommended to run tests on your local machine
      as there might be security risks. Run only those tests which you
      know are safe so that you don't destroy your laptop ;-)
  
      Example config:
  
          provision:
              how: local
  
      Note that 'tmt run' is expected to be executed under a regular user.
      If there are admin rights required (for example in the prepare step)
      you might be asked for a sudo password.
      """
  
      # Guest instance
      _guest = None
  
      # Supported methods
      _methods = [tmt.steps.Method(name='local', doc=__doc__, order=50)]
  
      def wake(self, keys=None, data=None):
          """ Wake up the plugin, process data, apply options """
          super().wake(keys=keys, data=data)
          if data:
              self._guest = GuestLocal(data, name=self.name, parent=self.step)
  
      def go(self):
          """ Provision the container """
          super().go()
  
          # Create a GuestLocal instance
          data = {'guest': 'localhost', 'role': self.get('role')}
          self._guest = GuestLocal(data, name=self.name, parent=self.step)
  
      def guest(self):
          """ Return the provisioned guest """
          return self._guest
  
      def requires(self):
          """ List of required packages needed for workdir sync """
          return GuestLocal.requires()
  
  
  class
  
  [... the rest is omitted ...]
files.old_path: tmt/steps/provision/local.py
files.new_contents: import os
  
  import click
  
  import tmt
  
  
  class ProvisionPodman(tmt.steps.provision.ProvisionPlugin):
      """
      Create a new container using podman
  
      Example config:
  
          provision:
              how: container
              image: fedora:latest
  
      In order to always pull the fresh container image use 'pull: true'.
      """
  
      # Guest instance
      _guest = None
  
      # Supported keys
      _keys = ["image", "container", "pull"]
  
      # Supported methods
      _methods = [tmt.steps.Method(name='container', doc=__doc__, order=50)]
  
      @classmethod
      def options(cls, how=None):
          """ Prepare command line options for connect """
          return [
              click.option(
                  '-i', '--image', metavar='IMAGE',
                  help='Select image to use. Short name or complete url.'),
              click.option(
                  '-c', '--container', metavar='NAME',
                  help='Name or id of an existing container to be used.'),
              click.option(
                  '-p', '--pull', is_flag=True,
                  help='Force pulling a fresh container image.'),
              ] + super().options(how)
  
      def default(self, option, default=None):
          """ Return default data for given option """
          # User 'fedora' as a default image
          if option == 'image':
              return 'fedora'
          # No other defaults available
          return default
  
      def wake(self, keys=None, data=None):
          """ Wake up the plugin,
  
  [... the rest is omitted ...]
files.new_path: tmt/steps/provision/podman.py
files.old_contents: import os
  
  import click
  
  import tmt
  
  
  class ProvisionPodman(tmt.steps.provision.ProvisionPlugin):
      """
      Create a new container using podman
  
      Example config:
  
          provision:
              how: container
              image: fedora:latest
  
      In order to always pull the fresh container image use 'pull: true'.
      """
  
      # Guest instance
      _guest = None
  
      # Supported keys
      _keys = ["image", "container", "pull"]
  
      # Supported methods
      _methods = [tmt.steps.Method(name='container', doc=__doc__, order=50)]
  
      @classmethod
      def options(cls, how=None):
          """ Prepare command line options for connect """
          return [
              click.option(
                  '-i', '--image', metavar='IMAGE',
                  help='Select image to use. Short name or complete url.'),
              click.option(
                  '-c', '--container', metavar='NAME',
                  help='Name or id of an existing container to be used.'),
              click.option(
                  '-p', '--pull', is_flag=True,
                  help='Force pulling a fresh container image.'),
              ] + super().options(how)
  
      def default(self, option, default=None):
          """ Return default data for given option """
          # User 'fedora' as a default image
          if option == 'image':
              return 'fedora'
          # No other defaults available
          return default
  
      def wake(self, keys=None, data=None):
          """ Wake up the plugin,
  
  [... the rest is omitted ...]
files.old_path: tmt/steps/provision/podman.py
files.new_contents: import re
  
  import click
  
  import tmt
  
  
  class Report(tmt.steps.Step):
      """ Provide test results overview and send reports. """
  
      # Default implementation for report is display
      how = 'display'
  
      def wake(self):
          """ Wake up the step (process workdir and command line) """
          super().wake()
  
          # Choose the right plugin and wake it up
          for data in self.data:
              plugin = ReportPlugin.delegate(self, data)
              plugin.wake()
              self._plugins.append(plugin)
  
          # Nothing more to do if already done
          if self.status() == 'done':
              self.debug(
                  'Report wake up complete (already done before).', level=2)
          # Save status and step data (now we know what to do)
          else:
              self.status('todo')
              self.save()
  
      def show(self):
          """ Show discover details """
          for data in self.data:
              ReportPlugin.delegate(self, data).show()
  
      def summary(self):
          """ Give a concise report summary """
          summary = tmt.base.Result.summary(self.plan.execute.results())
          self.info('summary', summary, 'green', shift=1)
  
      def go(self):
          """ Report the guests """
          super().go()
  
          # Nothing more to do if already done
          if self.status() == 'done':
              self.info('status', 'done', 'green', shift=1)
              self.summary()
              self.actions()
              return
  
          # Perform the reporting
          for plugin in self.plugins
  
  [... the rest is omitted ...]
files.new_path: tmt/steps/report/__init__.py
files.old_contents: import re
  
  import click
  
  import tmt
  
  
  class Report(tmt.steps.Step):
      """ Provide test results overview and send reports. """
  
      # Default implementation for report is display
      how = 'display'
  
      def wake(self):
          """ Wake up the step (process workdir and command line) """
          super().wake()
  
          # Choose the right plugin and wake it up
          for data in self.data:
              plugin = ReportPlugin.delegate(self, data)
              plugin.wake()
              self._plugins.append(plugin)
  
          # Nothing more to do if already done
          if self.status() == 'done':
              self.debug(
                  'Report wake up complete (already done before).', level=2)
          # Save status and step data (now we know what to do)
          else:
              self.status('todo')
              self.save()
  
      def show(self):
          """ Show discover details """
          for data in self.data:
              ReportPlugin.delegate(self, data).show()
  
      def summary(self):
          """ Give a concise report summary """
          summary = tmt.base.Result.summary(self.plan.execute.results())
          self.info('summary', summary, 'green', shift=1)
  
      def go(self):
          """ Report the guests """
          super().go()
  
          # Nothing more to do if already done
          if self.status() == 'done':
              self.info('status', 'done', 'green', shift=1)
              self.summary()
              self.actions()
              return
  
          # Perform the reporting
          for plugin in self.plugins
  
  [... the rest is omitted ...]
files.old_path: tmt/steps/report/__init__.py