Ejemplo n.º 1
0
 def test_health_check_ok(self, mock_sub):
     timeout = 30
     cmd = 'success cmd'
     shell = ShellHealthCheck(cmd, timeout_secs=timeout)
     success, msg = shell()
     self.assertTrue(success)
     self.assertIsNone(msg)
     mock_sub.assert_called_once_with(['success', 'cmd'], timeout=30)
Ejemplo n.º 2
0
  def from_assigned_task(self, assigned_task, sandbox):
    """
    :param assigned_task:
    :param sandbox:
    :return: Instance of a HealthChecker.
    """
    mesos_task = mesos_task_instance_from_assigned_task(assigned_task)
    health_check_config = mesos_task.health_check_config().get()
    health_checker = health_check_config.get('health_checker', {})
    timeout_secs = health_check_config.get('timeout_secs')
    if SHELL_HEALTH_CHECK in health_checker:
      shell_command = health_checker.get(SHELL_HEALTH_CHECK, {}).get('shell_command')
      # Filling in variables eg thermos.ports[http] that could have been passed in as part of
      # shell_command.
      interpolated_command = HealthCheckerProvider.interpolate_cmd(
        task=assigned_task,
        cmd=shell_command
      )
      # If we do not want user which is job's role to execute the health shell check
      # --nosetuid-health-checks should be passed in as an argument to the executor.
      demote_to_job_role_user = None
      if not self.nosetuid_health_checks:
        pw_entry = pwd.getpwnam(assigned_task.task.job.role)
        def demote_to_job_role_user():
          os.setgid(pw_entry.pw_gid)
          os.setuid(pw_entry.pw_uid)

      shell_signaler = ShellHealthCheck(cmd=interpolated_command,
        preexec_fn=demote_to_job_role_user,
        timeout_secs=timeout_secs)
      a_health_checker = lambda: shell_signaler()
    else:
      portmap = resolve_ports(mesos_task, assigned_task.assignedPorts)
      if 'health' not in portmap:
        return None
      http_config = health_checker.get(HTTP_HEALTH_CHECK, {})
      http_endpoint = http_config.get('endpoint')
      http_expected_response = http_config.get('expected_response')
      http_expected_response_code = http_config.get('expected_response_code')

      http_signaler = HttpSignaler(
        portmap['health'],
        timeout_secs=timeout_secs)
      a_health_checker = lambda: http_signaler(
        endpoint=http_endpoint,
        expected_response=http_expected_response,
        expected_response_code=http_expected_response_code
      )

    health_checker = HealthChecker(
      a_health_checker,
      sandbox,
      interval_secs=health_check_config.get('interval_secs'),
      initial_interval_secs=health_check_config.get('initial_interval_secs'),
      max_consecutive_failures=health_check_config.get('max_consecutive_failures'))

    return health_checker
Ejemplo n.º 3
0
 def test_health_check_ok(self, mock_popen):
     shell = ShellHealthCheck('cmd', timeout_secs=30)
     success, msg = shell()
     self.assertTrue(success)
     self.assertIsNone(msg)
     mock_popen.assert_called_once_with('cmd',
                                        shell=True,
                                        timeout=30,
                                        preexec_fn=mock.ANY)
Ejemplo n.º 4
0
 def test_health_check_value_error(self, mock_popen):
   # Invalid commmand passed in raises ValueError.
   mock_popen.side_effect = ValueError('Could not read command.')
   timeout = 10
   shell = ShellHealthCheck('cmd', timeout_secs=timeout)
   success, msg = shell()
   mock_popen.assert_called_once_with('cmd', shell=True, timeout=10, preexec_fn=mock.ANY)
   self.assertFalse(success)
   self.assertEqual(msg, 'Invalid commmand.')
Ejemplo n.º 5
0
  def test_health_check_os_error(self, mock_popen):
    # Fail due to command not existing.
    mock_popen.side_effect = OSError(1, 'failed')

    shell = ShellHealthCheck('cmd', timeout_secs=30)
    success, msg = shell()
    mock_popen.assert_called_once_with('cmd', shell=True, timeout=30, preexec_fn=mock.ANY)
    self.assertFalse(success)
    self.assertEqual(msg, 'OSError: failed')
Ejemplo n.º 6
0
  def test_health_check_timeout(self, mock_popen):
    # Fail due to command returning a non-0 exit status.
    mock_popen.side_effect = subprocess.TimeoutExpired('failed', timeout=30)

    shell = ShellHealthCheck('cmd', timeout_secs=30)
    success, msg = shell()
    mock_popen.assert_called_once_with('cmd', shell=True, timeout=30, preexec_fn=mock.ANY)

    self.assertFalse(success)
    self.assertEqual(msg, 'Health check timed out.')
Ejemplo n.º 7
0
 def test_health_check_ok(self, mock_popen):
     shell = ShellHealthCheck(raw_cmd='cmd',
                              wrapped_cmd='wrapped-cmd',
                              timeout_secs=30)
     success, msg = shell()
     self.assertTrue(success)
     self.assertIsNone(msg)
     mock_popen.assert_called_once_with('wrapped-cmd',
                                        timeout=30,
                                        preexec_fn=mock.ANY,
                                        stderr=STDOUT)
Ejemplo n.º 8
0
  def test_health_check_failed(self, mock_popen):
    cmd = 'failed'
    # Fail due to command returning a non-0 exit status.
    mock_popen.side_effect = subprocess.CalledProcessError(1, cmd)

    shell = ShellHealthCheck(cmd, timeout_secs=30)
    success, msg = shell()
    mock_popen.assert_called_once_with(cmd, shell=True, timeout=30, preexec_fn=mock.ANY)

    self.assertFalse(success)
    self.assertEqual(msg, "Command 'failed' returned non-zero exit status 1")
Ejemplo n.º 9
0
 def test_health_check_value_error(self, mock_sub):
     timeout = 30
     # Invalid commmand passed in raises ValueError.
     mock_sub.side_effect = ValueError('Could not read command.')
     cmd = 'defensive cmd'
     timeout = 10
     shell = ShellHealthCheck(cmd, timeout_secs=timeout)
     success, msg = shell()
     mock_sub.assert_called_once_with(['defensive', 'cmd'], timeout=10)
     self.assertFalse(success)
     self.assertEqual(msg, 'Invalid commmand.')
Ejemplo n.º 10
0
 def test_health_check_os_error(self, mock_sub):
     timeout = 30
     # Fail due to command not existing.
     mock_sub.side_effect = OSError(1, 'failed')
     cmd = 'cmd to not exist'
     shell = ShellHealthCheck(cmd, timeout_secs=timeout)
     success, msg = shell()
     mock_sub.assert_called_once_with(['cmd', 'to', 'not', 'exist'],
                                      timeout=30)
     self.assertFalse(success)
     self.assertEqual(msg, 'OSError: failed')
Ejemplo n.º 11
0
 def test_health_check_failed(self, mock_sub):
     timeout = 30
     # Fail due to command returning a non-0 exit status.
     mock_sub.side_effect = subprocess.CalledProcessError(1, 'failed')
     cmd = 'cmd to fail'
     shell = ShellHealthCheck(cmd, timeout_secs=timeout)
     success, msg = shell()
     mock_sub.assert_called_once_with(['cmd', 'to', 'fail'], timeout=30)
     self.assertFalse(success)
     self.assertEqual(msg,
                      "Command 'failed' returned non-zero exit status 1")
Ejemplo n.º 12
0
  def test_health_check_failed_with_wrapper(self, mock_popen):
    cmd = 'failed'
    mock_popen.side_effect = subprocess.CalledProcessError(1, cmd)

    shell = ShellHealthCheck(cmd, timeout_secs=30, wrapper_fn=lambda c: 'wrapped: %s' % c)
    success, msg = shell()
    self.assertEqual(
        mock_popen.mock_calls,
        [mock.call('wrapped: %s' % cmd, shell=True, timeout=30, preexec_fn=mock.ANY)])

    self.assertFalse(success)
    self.assertEqual(msg, "Command 'failed' returned non-zero exit status 1")
Ejemplo n.º 13
0
    def from_assigned_task(self, assigned_task, sandbox):
        """
    :param assigned_task:
    :param sandbox:
    :return: Instance of a HealthChecker.
    """
        mesos_task = mesos_task_instance_from_assigned_task(assigned_task)
        health_check_config = mesos_task.health_check_config().get()
        health_checker = health_check_config.get('health_checker', {})
        timeout_secs = health_check_config.get('timeout_secs')
        if SHELL_HEALTH_CHECK in health_checker:
            shell_command = health_checker.get(SHELL_HEALTH_CHECK,
                                               {}).get('shell_command')
            shell_signaler = ShellHealthCheck(cmd=shell_command,
                                              timeout_secs=timeout_secs)
            a_health_checker = lambda: shell_signaler()
        else:
            portmap = resolve_ports(mesos_task, assigned_task.assignedPorts)
            if 'health' not in portmap:
                return None
            if HTTP_HEALTH_CHECK in health_checker:
                # Assume user has already switched over to the new config since we found the key.
                http_config = health_checker.get(HTTP_HEALTH_CHECK, {})
                http_endpoint = http_config.get('endpoint')
                http_expected_response = http_config.get('expected_response')
                http_expected_response_code = http_config.get(
                    'expected_response_code')
            else:
                # TODO (AURORA-1563): Remove this clause after we deprecate support for following keys
                # directly in HealthCheckConfig
                http_endpoint = health_check_config.get('endpoint')
                http_expected_response = health_check_config.get(
                    'expected_response')
                http_expected_response_code = health_check_config.get(
                    'expected_response_code')
            http_signaler = HttpSignaler(portmap['health'],
                                         timeout_secs=timeout_secs)
            a_health_checker = lambda: http_signaler(
                endpoint=http_endpoint,
                expected_response=http_expected_response,
                expected_response_code=http_expected_response_code)

        health_checker = HealthChecker(
            a_health_checker,
            sandbox,
            interval_secs=health_check_config.get('interval_secs'),
            initial_interval_secs=health_check_config.get(
                'initial_interval_secs'),
            max_consecutive_failures=health_check_config.get(
                'max_consecutive_failures'))

        return health_checker
Ejemplo n.º 14
0
  def from_assigned_task(self, assigned_task, sandbox):
    """
    :param assigned_task:
    :param sandbox:
    :return: Instance of a HealthChecker.
    """
    mesos_task = mesos_task_instance_from_assigned_task(assigned_task)
    health_check_config = mesos_task.health_check_config().get()
    health_checker = health_check_config.get('health_checker', {})
    timeout_secs = health_check_config.get('timeout_secs')
    if SHELL_HEALTH_CHECK in health_checker:
      shell_command = health_checker.get(SHELL_HEALTH_CHECK, {}).get('shell_command')
      # Filling in variables eg thermos.ports[http] that could have been passed in as part of
      # shell_command.
      interpolated_command = HealthCheckerProvider.interpolate_cmd(
        task=assigned_task,
        cmd=shell_command
      )
      shell_signaler = ShellHealthCheck(
        cmd=interpolated_command,
        timeout_secs=timeout_secs,
      )
      a_health_checker = lambda: shell_signaler()
    else:
      portmap = resolve_ports(mesos_task, assigned_task.assignedPorts)
      if 'health' not in portmap:
        return None
      http_config = health_checker.get(HTTP_HEALTH_CHECK, {})
      http_endpoint = http_config.get('endpoint')
      http_expected_response = http_config.get('expected_response')
      http_expected_response_code = http_config.get('expected_response_code')

      http_signaler = HttpSignaler(
        portmap['health'],
        timeout_secs=timeout_secs)
      a_health_checker = lambda: http_signaler(
        endpoint=http_endpoint,
        expected_response=http_expected_response,
        expected_response_code=http_expected_response_code
      )

    health_checker = HealthChecker(
      a_health_checker,
      sandbox,
      interval_secs=health_check_config.get('interval_secs'),
      initial_interval_secs=health_check_config.get('initial_interval_secs'),
      max_consecutive_failures=health_check_config.get('max_consecutive_failures'))

    return health_checker
Ejemplo n.º 15
0
    def test_health_check_failed(self, mock_popen):
        cmd = 'failed'
        wrapped_cmd = 'wrapped-failed'
        # Fail due to command returning a non-0 exit status.
        mock_popen.side_effect = subprocess.CalledProcessError(
            1, wrapped_cmd, output='No file.')

        shell = ShellHealthCheck(raw_cmd=cmd,
                                 wrapped_cmd=wrapped_cmd,
                                 timeout_secs=30)
        success, msg = shell()
        mock_popen.assert_called_once_with(wrapped_cmd,
                                           timeout=30,
                                           preexec_fn=mock.ANY,
                                           stderr=STDOUT)

        self.assertFalse(success)
        self.assertEqual(
            msg,
            "Command 'failed' returned non-zero exit status 1 with output 'No file.'"
        )
Ejemplo n.º 16
0
  def from_assigned_task(self, assigned_task, sandbox):
    """
    :param assigned_task:
    :param sandbox:
    :return: Instance of a HealthChecker.
    """
    mesos_task = mesos_task_instance_from_assigned_task(assigned_task)
    health_check_config = mesos_task.health_check_config().get()
    health_checker = health_check_config.get('health_checker', {})
    timeout_secs = health_check_config.get('timeout_secs')
    if SHELL_HEALTH_CHECK in health_checker:
      shell_command = health_checker.get(SHELL_HEALTH_CHECK, {}).get('shell_command')

      # Filling in variables e.g. thermos.ports[http] that could have been passed in as part of
      # shell_command.
      interpolated_command = HealthCheckerProvider.interpolate_cmd(
        task=assigned_task,
        cmd=shell_command)

      # If we do not want the health check to execute as the user from the job's role
      # --nosetuid-health-checks should be passed as an argument to the executor.
      demote_to_job_role_user = None
      if not self._nosetuid_health_checks and not sandbox.is_filesystem_image:
        pw_entry = pwd.getpwnam(assigned_task.task.job.role)
        def demote_to_job_role_user():
          os.setgid(pw_entry.pw_gid)
          os.setuid(pw_entry.pw_uid)

      # If the task is executing in an isolated filesystem we'll want to wrap the health check
      # command within a mesos-containerizer invocation so that it's executed within that
      # filesystem.
      wrapper = None
      if sandbox.is_filesystem_image:
        health_check_user = (os.getusername() if self._nosetuid_health_checks
            else assigned_task.task.job.role)
        def wrapper(cmd):
          return wrap_with_mesos_containerizer(
              cmd,
              health_check_user,
              sandbox.container_root,
              self._mesos_containerizer_path)

      shell_signaler = ShellHealthCheck(
        cmd=interpolated_command,
        preexec_fn=demote_to_job_role_user,
        timeout_secs=timeout_secs,
        wrapper_fn=wrapper)
      a_health_checker = lambda: shell_signaler()
    else:
      portmap = resolve_ports(mesos_task, assigned_task.assignedPorts)
      if 'health' not in portmap:
        return None
      http_config = health_checker.get(HTTP_HEALTH_CHECK, {})
      http_endpoint = http_config.get('endpoint')
      http_expected_response = http_config.get('expected_response')
      http_expected_response_code = http_config.get('expected_response_code')

      http_signaler = HttpSignaler(
        portmap['health'],
        timeout_secs=timeout_secs)
      a_health_checker = lambda: http_signaler(
        endpoint=http_endpoint,
        expected_response=http_expected_response,
        expected_response_code=http_expected_response_code
      )

    health_checker = HealthChecker(
      a_health_checker,
      sandbox,
      interval_secs=health_check_config.get('interval_secs'),
      initial_interval_secs=health_check_config.get('initial_interval_secs'),
      max_consecutive_failures=health_check_config.get('max_consecutive_failures'))

    return health_checker