def _load_questions_from_dir(question_dir): # type: (str) -> Dict[str, QuestionMeta] question_files = [] for dirpath, dirnames, filenames in os.walk(question_dir): for filename in filenames: if filename.endswith(".json"): question_files.append(os.path.join(dirpath, filename)) if len(question_files) == 0: bf_logger.warn( "WARNING: no .json files found in supplied question directory: {questionDir}".format( questionDir=question_dir)) return {} questions = {} for questionFile in question_files: try: (qname, qclass) = _load_question_disk(questionFile) questions[qname] = qclass except Exception as err: bf_logger.error( "Could not load question from {questionFile}:{err}".format( questionFile=questionFile, err=err)) bf_logger.info( "Successfully loaded {numQuestions}/{numQuestionFiles} question(s) from local directory".format( numQuestions=len(questions), numQuestionFiles=len(question_files))) return questions
def load_dir_questions(questionDir, moduleName=bfq.__name__): questionFiles = [] for dirpath, dirnames, filenames in os.walk(questionDir): for filename in filenames: if filename.endswith(".json"): questionFiles.append(os.path.join(dirpath, filename)) localQuestions = set([]) if len(questionFiles) == 0: bf_logger.warn( "WARNING: no .json files found in supplied question directory: {questionDir}" .format(questionDir=questionDir)) else: numQuestions = 0 for questionFile in questionFiles: try: localQuestions.add( _load_question_disk(questionFile, module_name=moduleName)) numQuestions += 1 except ValueError as err: bf_logger.error( "Could not load question from {questionFile}:{err}".format( questionFile=questionFile, err=err)) bf_logger.info( "Successfully loaded {numQuestions}/{numQuestionFiles} question(s) from local directory" .format(numQuestions=numQuestions, numQuestionFiles=len(questionFiles))) return localQuestions
def _validateType(value, expectedType): """ Check if the input `value` have contents that matches the requirements specified by `expectedType`. Return a tuple, first element in the tuple is a boolean tells the validation result, while the second element contains the error message if there is one. :raises QuestionValidationException """ if expectedType == 'boolean': return isinstance(value, bool), None elif expectedType == 'comparator': validComparators = ['<', '<=', '==', '>=', '>', '!='] if value not in validComparators: return False, "'{}' is not a known comparator. Valid options are: '{}'".format( value, ", ".join(validComparators)) return True, None elif expectedType == 'integer': INT32_MIN = -2 ** 32 INT32_MAX = 2 ** 32 - 1 valid = (isinstance(value, integer_types) and INT32_MIN <= value <= INT32_MAX) return valid, None elif expectedType == 'float': return isinstance(value, float), None elif expectedType == 'double': return isinstance(value, float), None elif expectedType == 'interfacePropertySpec': return isinstance(value, string_types), None elif expectedType == 'interfaceSpec': return isinstance(value, string_types), None elif expectedType == 'ip': if not isinstance(value, string_types): return False, "A Batfish {} must be a string".format( expectedType) else: return _isIp(value) elif expectedType == 'ipWildcard': if not isinstance(value, string_types): return False, "A Batfish {} must be a string".format( expectedType) else: return _isIpWildcard(value) elif expectedType == 'javaRegex': if not isinstance(value, string_types): return False, "A Batfish {} must be a string".format( expectedType) return True, None elif expectedType == 'jsonPath': return _isJsonPath(value) elif expectedType == 'jsonPathRegex': if not isinstance(value, string_types): return False, "A Batfish {} must be a string".format( expectedType) return True, None elif expectedType == 'long': INT64_MIN = -2 ** 64 INT64_MAX = 2 ** 64 - 1 valid = (isinstance(value, integer_types) and INT64_MIN <= value <= INT64_MAX) return valid, None elif expectedType == 'nodePropertySpec': return isinstance(value, string_types), None elif expectedType == 'nodeSpec': return isinstance(value, string_types), None elif expectedType == 'prefix': if not isinstance(value, string_types): return False, "A Batfish {} must be a string".format( expectedType) else: return _isPrefix(value) elif expectedType == 'prefixRange': if not isinstance(value, string_types): return False, "A Batfish {} must be a string".format( expectedType) else: return _isPrefixRange(value) elif expectedType == 'question': return isinstance(value, QuestionBase), None elif expectedType == 'string': return isinstance(value, string_types), None elif expectedType == 'subrange': if isinstance(value, int): return True, None elif isinstance(value, string_types): return _isSubRange(value) else: return False, "A Batfish {} must either be a string or an integer".format( expectedType) elif expectedType == 'protocol': if not isinstance(value, string_types): return False, "A Batfish {} must be a string".format( expectedType) else: validProtocols = ['dns', 'ssh', 'tcp', 'udp'] if not value.lower() in validProtocols: return False, "'{}' is not a valid protocols. Valid options are: '{}'".format( value, ", ".join(validProtocols)) return True, None elif expectedType == 'ipProtocol': if not isinstance(value, string_types): return False, "A Batfish {} must be a string".format( expectedType) else: try: intValue = int(value) if not 0 <= intValue < 256: return False, "'{}' is not in valid ipProtocol range: 0-255".format( intValue) return True, None except ValueError: # TODO: Should be validated at server side return True, None elif expectedType in ['headerConstraint', 'pathConstraint', 'dispositionSpec']: return True, None else: bf_logger.warn( "WARNING: skipping validation for unknown argument type {}".format( expectedType)) return True, None