def update_run(id_, run=None, token_info=None, user=None): """Updates a single run :param id: ID of run to update :type id: int :param body: Run :type body: dict :rtype: Run """ if not connexion.request.is_json: return "Bad request, JSON required", 400 run_dict = connexion.request.get_json() if run_dict.get("metadata", {}).get("project"): run_dict["project_id"] = get_project_id( run_dict["metadata"]["project"]) if not project_has_user(run_dict["project_id"], user): return "Forbidden", 403 run = Run.query.get(id_) if run and not project_has_user(run.project, user): return "Forbidden", 403 if not run: return "Run not found", 404 run.update(run_dict) session.add(run) session.commit() update_run_task.apply_async((id_, ), countdown=5) return run.to_dict()
def update_widget_config(id_): """Updates a single widget config :param id: ID of widget to update :type id: int :param body: Result :type body: dict :rtype: Result """ if not connexion.request.is_json: return "Bad request, JSON required", 400 widget_config = connexion.request.get_json() if widget_config.get( "widget") and widget_config["widget"] not in WIDGET_TYPES.keys(): return "Bad request, widget type does not exist", 400 # Look up the project id if widget_config.get("project"): widget_config["project"] = get_project_id(widget_config["project"]) existing_widget_config = mongo.widget_config.find_one( {"_id": ObjectId(id_)}) # add default weight of 10 if not existing_widget_config.get("weight"): existing_widget_config["weight"] = 10 # default to make views navigable if widget_config.get( "type") == "view" and not widget_config.get("navigable"): widget_config["navigable"] = "true" merge_dicts(existing_widget_config, widget_config) mongo.widget_config.replace_one({"_id": ObjectId(id_)}, widget_config) return serialize(widget_config)
def add_widget_config(widget_config=None): """Create a new widget config :param widget_config: The widget_config to save :type widget_config: dict | bytes :rtype: WidgetConfig """ if not connexion.request.is_json: return "Bad request, JSON required", 400 widget_config = connexion.request.json if widget_config["widget"] not in WIDGET_TYPES.keys(): return "Bad request, widget type does not exist", 400 # add default weight of 10 if not widget_config.get("weight"): widget_config["weight"] = 10 # Look up the project id if widget_config.get("project"): widget_config["project"] = get_project_id(widget_config["project"]) # default to make views navigable if widget_config.get( "type") == "view" and not widget_config.get("navigable"): widget_config["navigable"] = "true" mongo.widget_config.insert_one(widget_config) widget_config = serialize(widget_config) return widget_config, 201
def get_report_list(page=1, page_size=25, project=None): """Get a list of reports :param page: Set the page of items to return, defaults to 1 :type page: int :param page_size: Set the number of items per page, defaults to 25 :type page_size: int :rtype: ReportList """ params = {} if project: params["parameters.project"] = get_project_id(project) offset = (page * page_size) - page_size total_items = mongo.reports.count(params) total_pages = (total_items // page_size) + (1 if total_items % page_size > 0 else 0) reports = mongo.reports.find(params, skip=offset, limit=page_size, sort=[("created", DESCENDING)]) return { "reports": [serialize(report) for report in reports], "pagination": { "page": page, "pageSize": page_size, "totalItems": total_items, "totalPages": total_pages, }, }
def add_report(report_parameters=None): """Create a new report :param report: The report to generate :type report: dict | bytes :rtype: Report """ if not connexion.request.is_json: return "Bad request, JSON required", 400 report_parameters = connexion.request.json if report_parameters["type"] not in REPORTS: return "Bad request, report type does not exist", 400 if "project" in report_parameters: report_parameters["project"] = get_project_id( report_parameters["project"]) report = { "filename": "", "mimetype": "", "url": "", "download_url": "", "view_url": "", "parameters": report_parameters, "created": datetime.utcnow().isoformat(), } mongo.reports.insert_one(report) report = serialize(report) REPORTS[report_parameters["type"]]["func"].delay(report) return report, 201
def _build_filters(report): """Build the filters from a report object""" filters = {} if report["parameters"].get("filter"): for f in report["parameters"]["filter"].split(","): filters.update(generate_filter_object(f.strip())) if report["parameters"]["source"]: filters["source"] = {"$eq": report["parameters"]["source"]} if report["parameters"].get("project"): filters["metadata.project"] = get_project_id( report["parameters"]["project"]) return filters
def _build_query(report): """Build the filters from a report object""" query = Result.query if report["params"].get("filter"): filters = report["params"]["filter"].split(",") if filters: query = apply_filters(query, filters, Result) if report["params"]["source"]: query = query.filter(Result.source == report["params"]["source"]) if report["params"].get("project"): query = query.filter( Result.project_id == get_project_id(report["params"]["project"])) return query
def _populate_metadata(run_dict, import_record): """To reduce cognitive complexity""" if import_record.data.get("project_id"): run_dict["project_id"] = import_record.data["project_id"] elif run_dict.get("metadata", {}).get("project"): run_dict["project_id"] = get_project_id( run_dict["metadata"]["project"]) if run_dict.get("metadata", {}).get("component"): run_dict["component"] = run_dict["metadata"]["component"] if run_dict.get("metadata", {}).get("env"): run_dict["env"] = run_dict["metadata"]["env"] if import_record.data.get("source"): run_dict["source"] = import_record.data["source"]
def update_result(id_, result=None): """Updates a single result :param id: ID of result to update :type id: int :param body: Result :type body: dict :rtype: Result """ if not connexion.request.is_json: return "Bad request, JSON required", 400 result = connexion.request.get_json() if result.get("metadata", {}).get("project"): result["metadata"]["project"] = get_project_id(result["metadata"]["project"]) existing_result = mongo.results.find_one({"_id": ObjectId(id_)}) merge_dicts(existing_result, result) mongo.results.replace_one({"_id": ObjectId(id_)}, result) return serialize(result)
def add_result(result=None): """Creates a test result :param body: Result item :type body: dict | bytes :rtype: Result """ if not connexion.request.is_json: return "Bad request, JSON required", 400 result = connexion.request.get_json() if result.get("metadata", {}).get("project"): result["metadata"]["project"] = get_project_id(result["metadata"]["project"]) if "start_time" not in result: if "starttime" in result: result["start_time"] = result["starttime"] else: result["start_time"] = time.time() mongo.results.insert_one(result) return serialize(result), 201
def update_run(id_, run=None): """Updates a single run :param id: ID of run to update :type id: int :param body: Run :type body: dict :rtype: Run """ if not connexion.request.is_json: return "Bad request, JSON required", 400 run = connexion.request.get_json() if run.get("metadata") and run.get("metadata", {}).get("project"): run["metadata"]["project"] = get_project_id(run["metadata"]["project"]) existing_run = mongo.runs.find_one({"_id": ObjectId(id_)}) merge_dicts(existing_run, run) mongo.runs.replace_one({"_id": ObjectId(id_)}, run) update_run_task.delay(id_) return serialize(run)
def add_run(run=None): """Create a new run :param body: Run object :type body: dict | bytes :rtype: Run """ if not connexion.request.is_json: return "Bad request, JSON is required", 400 run_dict = connexion.request.get_json() current_time = datetime.utcnow() if "created" not in run_dict: run_dict["created"] = current_time.isoformat() if "start_time" not in run_dict: run_dict["start_time"] = current_time.timestamp() if "id" in run_dict: run_dict["_id"] = ObjectId(run_dict["id"]) if run_dict.get("metadata") and run_dict.get("metadata", {}).get("project"): run_dict["metadata"]["project"] = get_project_id(run_dict["metadata"]["project"]) mongo.runs.insert_one(run_dict) run_dict = serialize(run_dict) update_run_task.apply_async((run_dict["id"],), countdown=5) return run_dict, 201
def run_archive_import(import_): """Import a test run from an Ibutsu archive file""" # Update the status of the import import_["status"] = "running" mongo.imports.replace_one({"_id": ObjectId(import_["id"])}, import_) # Fetch the file contents try: import_file = [f for f in mongo.import_files.find({"metadata.importId": import_["id"]})][0] except KeyError: import_["status"] = "error" mongo.imports.replace_one({"_id": ObjectId(import_["id"])}, import_) return # First open the tarball and pull in the results run = None run_dict = None results = [] result_artifacts = {} current_dir = None result = None artifacts = [] start_time = None with tarfile.open(mode="r:gz", fileobj=import_file) as tar: # run through the files and dirs, skipping the first one as it is the base directory for member in tar.getmembers()[1:]: if member.isdir() and member.name != current_dir: if result: results.append(result) result_artifacts[result["id"]] = artifacts artifacts = [] result = None elif member.name.endswith("result.json"): result = json.loads(tar.extractfile(member).read()) result_start_time = result.get("start_time", result.get("starttime")) if not start_time or start_time > result_start_time: start_time = result_start_time elif member.name.endswith("run.json"): run = json.loads(tar.extractfile(member).read()) elif member.isfile(): artifacts.append(member) if result: results.append(result) result_artifacts[result["id"]] = artifacts if run: run_dict = run else: run_dict = { "duration": 0, "summary": {"errors": 0, "failures": 0, "skips": 0, "tests": 0}, } # patch things up a bit, if necessary if run_dict.get("start_time") and not run_dict.get("created"): run_dict["created"] = run_dict["start_time"] elif run_dict.get("created") and not run_dict.get("start_time"): run_dict["start_time"] = run_dict["created"] elif not run_dict.get("created") and not run_dict.get("start_time"): run_dict["created"] = start_time run_dict["start_time"] = start_time if run_dict.get("metadata", {}).get("project"): run_dict["metadata"]["project"] = get_project_id(run_dict["metadata"]["project"]) # If this run has a valid ObjectId, check if this run exists run_exists = False if run_dict.get("id") and ObjectId.is_valid(run_dict["id"]): # Just check if this exists first run_exists = mongo.runs.find_one({"_id": ObjectId(run_dict["id"])}) is not None if run_exists: mongo.run_dicts.replace_one({"_id": ObjectId(run_dict["id"])}, run_dict) else: if run_dict.get("id"): del run_dict["id"] mongo.runs.insert_one(run_dict) run_dict = serialize(run_dict) import_["run_id"] = run_dict["id"] # Now loop through all the results, and create or update them for result in results: artifacts = result_artifacts.get(result["id"], []) _create_result(tar, run_dict["id"], result, artifacts) # Update the import record import_["status"] = "done" mongo.imports.replace_one({"_id": ObjectId(import_["id"])}, import_) if run_dict: update_run.delay(run_dict["id"])
def import_run(xml_file): """Imports a JUnit XML file and creates a test run and results from it. :param xmlFile: file to upload :type xmlFile: werkzeug.datastructures.FileStorage :rtype: Run """ if not xml_file: return "Bad request, no file uploaded", 400 tree = objectify.parse(xml_file.stream) root = tree.getroot() run_dict = { "duration": root.get("time"), "summary": { "errors": root.get("errors"), "failures": root.get("failures"), "skips": root.get("skips"), "tests": root.get("tests"), }, } if run_dict.get("metadata", {}).get("project"): run_dict["metadata"]["project"] = get_project_id(run_dict["metadata"]["project"]) rec = mongo.runs.insert_one(run_dict) run_dict["id"] = str(run_dict.pop("_id")) for testcase in root.testcase: test_name = testcase.get("name").split(".")[-1] if testcase.get("classname"): test_name = testcase.get("classname").split(".")[-1] + "." + test_name result_dict = { "test_id": test_name, "start_time": 0, "duration": float(testcase.get("time")), "metadata": { "run": run_dict["id"], "fspath": testcase.get("file"), "line": testcase.get("line"), }, "params": {}, "source": root.get("name"), } traceback = None if testcase.find("failure"): result_dict["result"] = "failed" traceback = bytes(str(testcase.failure), "utf8") elif testcase.find("error"): result_dict["result"] = "error" traceback = bytes(str(testcase.error), "utf8") else: result_dict["result"] = "passed" rec = mongo.results.insert_one(result_dict) if traceback: mongo.fs.upload_from_stream( "traceback.log", traceback, metadata={"contentType": "text/plain", "resultId": str(rec.inserted_id)}, ) if testcase.find("system-out"): system_out = bytes(str(testcase["system-out"]), "utf8") mongo.fs.upload_from_stream( "system-out.log", system_out, metadata={"contentType": "text/plain", "resultId": str(rec.inserted_id)}, ) if testcase.find("system-err"): system_err = bytes(str(testcase["system-err"]), "utf8") mongo.fs.upload_from_stream( "system-err.log", system_err, metadata={"contentType": "text/plain", "resultId": str(rec.inserted_id)}, ) return run_dict, 201