예제 #1
0
def _validate_by_service_async(service, config_set, path, content, ctx):
    """Validates a config with an external service."""
    try:
        metadata = yield services.get_metadata_async(service.id)
    except services.DynamicMetadataError as ex:
        logging.error("Could not load dynamic metadata for %s: %s", service.id, ex)
        return

    assert metadata and metadata.validation
    url = metadata.validation.url
    if not url:
        return

    match = False
    for p in metadata.validation.patterns:
        # TODO(nodir): optimize if necessary.
        if validation.compile_pattern(p.config_set)(config_set) and validation.compile_pattern(p.path)(path):
            match = True
            break
    if not match:
        return

    res = None

    def report_error(text):
        text = ("Error during external validation: %s\n" "url: %s\n" "config_set: %s\n" "path: %s\n" "response: %r") % (
            text,
            url,
            config_set,
            path,
            res,
        )
        logging.error(text)
        ctx.critical(text)

    try:
        req = {"config_set": config_set, "path": path, "content": base64.b64encode(content)}
        res = yield net.json_request_async(url, method="POST", payload=req, scopes=net.EMAIL_SCOPE)
    except net.Error as ex:
        report_error("Net error: %s" % ex)
        return

    try:
        for msg in res.get("messages", []):
            if not isinstance(msg, dict):
                report_error("invalid response: message is not a dict: %r" % msg)
                continue
            severity = msg.get("severity") or "INFO"
            if severity not in service_config_pb2.ValidationResponseMessage.Severity.keys():
                report_error("invalid response: unexpected message severity: %s" % severity)
                continue
            # It is safe because we've validated |severity|.
            func = getattr(ctx, severity.lower())
            func(msg.get("text") or "")
    except Exception as ex:
        report_error(ex)
예제 #2
0
    def test_compile_pattern(self):
        self.assertTrue(validation.compile_pattern('abc')('abc'))
        self.assertTrue(validation.compile_pattern('text:abc')('abc'))
        self.assertFalse(validation.compile_pattern('text:abc')('abcd'))

        self.assertTrue(validation.compile_pattern('regex:abc')('abc'))
        self.assertTrue(validation.compile_pattern('regex:\w+')('abc'))
        self.assertTrue(validation.compile_pattern('regex:^(\w+)c$')('abc'))
        self.assertFalse(validation.compile_pattern('regex:\d+')('a123b'))
예제 #3
0
  def test_compile_pattern(self):
    self.assertTrue(validation.compile_pattern('abc')('abc'))
    self.assertTrue(validation.compile_pattern('text:abc')('abc'))
    self.assertFalse(validation.compile_pattern('text:abc')('abcd'))

    self.assertTrue(validation.compile_pattern('regex:abc')('abc'))
    self.assertTrue(validation.compile_pattern('regex:\w+')('abc'))
    self.assertTrue(validation.compile_pattern('regex:^(\w+)c$')('abc'))
    self.assertFalse(validation.compile_pattern('regex:\d+')('a123b'))
예제 #4
0
def _validate_by_service_async(service, config_set, path, content, ctx):
    """Validates a config with an external service."""
    try:
        metadata = yield services.get_metadata_async(service.id)
    except services.DynamicMetadataError as ex:
        logging.error('Could not load dynamic metadata for %s: %s', service.id,
                      ex)
        return

    assert metadata and metadata.validation
    url = metadata.validation.url
    if not url:
        return

    match = False
    for p in metadata.validation.patterns:
        # TODO(nodir): optimize if necessary.
        if (validation.compile_pattern(p.config_set)(config_set)
                and validation.compile_pattern(p.path)(path)):
            match = True
            break
    if not match:
        return

    res = None

    def report_error(text):
        text = ('Error during external validation: %s\n'
                'url: %s\n'
                'config_set: %s\n'
                'path: %s\n'
                'response: %r') % (text, url, config_set, path, res)
        logging.error(text)
        ctx.critical(text)

    try:
        req = {
            'config_set': config_set,
            'path': path,
            'content': base64.b64encode(content),
        }
        res = yield net.json_request_async(url,
                                           method='POST',
                                           payload=req,
                                           scopes=net.EMAIL_SCOPE)
    except net.Error as ex:
        report_error('Net error: %s' % ex)
        return

    try:
        for msg in res.get('messages', []):
            if not isinstance(msg, dict):
                report_error('invalid response: message is not a dict: %r' %
                             msg)
                continue
            severity = msg.get('severity') or 'INFO'
            if (severity not in service_config_pb2.ValidationResponseMessage.
                    Severity.keys()):
                report_error(
                    'invalid response: unexpected message severity: %s' %
                    severity)
                continue
            # It is safe because we've validated |severity|.
            func = getattr(ctx, severity.lower())
            func(msg.get('text') or '')
    except Exception as ex:
        report_error(ex)
예제 #5
0
def _validate_by_service_async(service, config_set, path, content, ctx):
  """Validates a config with an external service.

  Validation results will be stored in the validation context.

  Args:
    service (service_config_pb2.Service): service to be validated against.
    config_set (str): config set being validated.
    path (str): path of the config file being validated.
    content (str): byte-form of the content of the file being validated.
    ctx (validation.Context): context in which validation messages
      will be stored.
  """
  try:
    metadata = yield services.get_metadata_async(service.id)
  except services.DynamicMetadataError as ex:
    logging.error('Could not load dynamic metadata for %s: %s', service.id, ex)
    return

  assert metadata and metadata.validation
  url = metadata.validation.url
  if not url:
    return

  match = False
  for p in metadata.validation.patterns:
    # TODO(nodir): optimize if necessary.
    if (validation.compile_pattern(p.config_set)(config_set) and
        validation.compile_pattern(p.path)(path)):
      match = True
      break
  if not match:
    return

  res = None

  def report_error(text):
    text = (
        'Error during external validation: %s\n'
        'url: %s\n'
        'config_set: %s\n'
        'path: %s\n'
        'response: %r') % (text, url, config_set, path, res)
    logging.error(text)
    ctx.critical('%s', text)

  try:
    req = {
      'config_set': config_set,
      'path': path,
      'content': base64.b64encode(content),
    }
    res = yield net.json_request_async(
        url, method='POST', payload=req, scopes=net.EMAIL_SCOPE)
  except net.Error as ex:
    report_error('Net error: %s' % ex)
    return

  try:
    for msg in res.get('messages', []):
      if not isinstance(msg, dict):
        report_error('invalid response: message is not a dict: %r' % msg)
        continue
      severity = msg.get('severity') or 'INFO'
      # validation library for Go services sends severity as an integer
      # corresponding to Python's logging severity level.
      if severity in (logging.DEBUG, logging.INFO, logging.WARNING,
                      logging.ERROR, logging.CRITICAL):
        severity = logging.getLevelName(severity)
      if (severity not in
          service_config_pb2.ValidationResponseMessage.Severity.keys()):
        report_error(
            'invalid response: unexpected message severity: %r' % severity)
        continue
      # It is safe because we've validated |severity|.
      func = getattr(ctx, severity.lower())
      func('%s', msg.get('text') or '')
  except Exception as ex:
    report_error(ex)
예제 #6
0
def _validate_by_service_async(service, config_set, path, content, ctx):
  """Validates a config with an external service."""
  try:
    metadata = yield services.get_metadata_async(service.id)
  except services.DynamicMetadataError as ex:
    logging.error('Could not load dynamic metadata for %s: %s', service.id, ex)
    return

  assert metadata and metadata.validation
  url = metadata.validation.url
  if not url:
    return

  match = False
  for p in metadata.validation.patterns:
    # TODO(nodir): optimize if necessary.
    if (validation.compile_pattern(p.config_set)(config_set) and
        validation.compile_pattern(p.path)(path)):
      match = True
      break
  if not match:
    return

  res = None

  def report_error(text):
    text = (
        'Error during external validation: %s\n'
        'url: %s\n'
        'config_set: %s\n'
        'path: %s\n'
        'response: %r') % (text, url, config_set, path, res)
    logging.error(text)
    ctx.critical(text)

  try:
    req = {
      'config_set': config_set,
      'path': path,
      'content': base64.b64encode(content),
    }
    res = yield net.json_request_async(
        url, method='POST', payload=req, scopes=net.EMAIL_SCOPE)
  except net.Error as ex:
    report_error('Net error: %s' % ex)
    return

  try:
    for msg in res.get('messages', []):
      if not isinstance(msg, dict):
        report_error('invalid response: message is not a dict: %r' % msg)
        continue
      severity = msg.get('severity') or 'INFO'
      if (severity not in
          service_config_pb2.ValidationResponseMessage.Severity.keys()):
        report_error(
            'invalid response: unexpected message severity: %s' % severity)
        continue
      # It is safe because we've validated |severity|.
      func = getattr(ctx, severity.lower())
      func(msg.get('text') or '')
  except Exception as ex:
    report_error(ex)