github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/assess_resolve.py (about)

     1  #!/usr/bin/env python
     2  """ Ensure resolve command resolves hook issues.
     3  
     4  This test covers the resolve command (and the option --no-retry)
     5  
     6  The test:
     7    - Uses a simple custom charm that instruments failure in the install hook
     8    - Ensures that 'resolve' retries the failed install hook and that the
     9      followup 'start' hook is fired.
    10    - Ensures that 'resolve --no-retry' does NOT re-run the failed install hook
    11      and instead goes ahead and runs the follow up 'started' hook.
    12  """
    13  
    14  from __future__ import print_function
    15  
    16  import argparse
    17  import logging
    18  import sys
    19  
    20  from deploy_stack import (
    21      BootstrapManager,
    22      )
    23  from jujupy.models import (
    24      temporary_model,
    25      )
    26  from jujupy.wait_condition import (
    27      UnitInstallCondition,
    28      )
    29  from jujucharm import local_charm_path
    30  from utility import (
    31      add_basic_testing_arguments,
    32      configure_logging,
    33      )
    34  
    35  
    36  __metaclass__ = type
    37  
    38  
    39  log = logging.getLogger('assess_resolve')
    40  
    41  
    42  class ResolveCharmMessage:
    43      """Workload active message differs if the install hook completed."""
    44      ACTIVE_NO_INSTALL_HOOK = 'No install hook'
    45      ACTIVE_INSTALL_HOOK = 'Install hook succeeded'
    46      INSTALL_FAIL = 'hook failed: "install"'
    47  
    48  
    49  def assess_resolve(client, local_charm='simple-resolve'):
    50      local_resolve_charm = local_charm_path(
    51          charm=local_charm, juju_ver=client.version)
    52      ensure_retry_does_not_rerun_failed_hook(client, local_resolve_charm)
    53  
    54  
    55  def ensure_retry_does_not_rerun_failed_hook(client, resolve_charm):
    56          with temporary_model(client, "no-retry") as temp_client:
    57              unit_name = 'simple-resolve/0'
    58              temp_client.deploy(resolve_charm)
    59              temp_client.wait_for(UnitInstallError(unit_name))
    60              temp_client.juju('resolve', ('--no-retry', unit_name))
    61              # simple-resolve start hook sets a message when active to indicate
    62              # it ran and if the install hook ran successfully or not.
    63              # Here we make sure it's active and no install hook success.
    64              temp_client.wait_for(
    65                  UnitInstallActive(
    66                      unit_name, ResolveCharmMessage.ACTIVE_NO_INSTALL_HOOK))
    67  
    68  
    69  class UnitInstallError(UnitInstallCondition):
    70      """Wait until `unit` is in error state with message status `message`.
    71  
    72      Useful to determine when a unit is in an expected error state (the message
    73      check allows further confirmation the error reason is the one we're looking
    74      for)
    75      """
    76      def __init__(self, unit, *args, **kwargs):
    77          super(UnitInstallError, self).__init__(
    78              unit, 'error', ResolveCharmMessage.INSTALL_FAIL, *args, **kwargs)
    79  
    80  
    81  class UnitInstallActive(UnitInstallCondition):
    82      """Wait until `unit` is in active state with message status `message`
    83  
    84      Useful to determine when a unit is active for a specific reason.
    85      """
    86  
    87      def __init__(self, unit, message, *args, **kwargs):
    88          super(UnitInstallActive, self).__init__(
    89              unit, 'active', message, *args, **kwargs)
    90  
    91  
    92  def parse_args(argv):
    93      """Parse all arguments."""
    94      parser = argparse.ArgumentParser(
    95          description='Ensure the resolve command operates to spec.')
    96      add_basic_testing_arguments(parser)
    97      return parser.parse_args(argv)
    98  
    99  
   100  def main(argv=None):
   101      args = parse_args(argv)
   102      configure_logging(args.verbose)
   103      bs_manager = BootstrapManager.from_args(args)
   104      with bs_manager.booted_context(args.upload_tools):
   105          assess_resolve(bs_manager.client)
   106      return 0
   107  
   108  
   109  if __name__ == '__main__':
   110      sys.exit(main())