Пример #1
0
def dashboard_PATCH(request):
    dashboard = request.context.resource
    allowed_keys = ["public", "resource_name", "layout_config"]
    for k, v in request.unsafe_json_body.items():
        if k in allowed_keys:
            setattr(dashboard, k, v)
        else:
            return HTTPUnprocessableEntity()

    # ensure we don't have any leftover chart definitions present from
    # removed layout columns
    chart_ids = []
    for row in dashboard.layout_config:
        for col in row["columns"]:
            chart_ids.append(col["chartId"])

    for chart in dashboard.charts:
        if chart.uuid not in chart_ids:
            actions = AlertChannelActionService.by_other_id(chart.uuid)
            for action in actions:
                DBSession.delete(action)
            dashboard.charts.remove(chart)

    existing_ids = [c.uuid for c in dashboard.charts]
    for c_uuid in chart_ids:
        if c_uuid not in existing_ids:
            chart = DashboardChart(uuid=c_uuid, config=None)
            dashboard.charts.append(chart)
    request.session.flash("Dashboard updated")
    return dashboard.get_dict(request=request)
Пример #2
0
    def __init__(self, request):
        self.__acl__ = []
        self.used_uuid = False
        # used_uuid is set to true if user who is normally not authorized to
        # view the resource gains access to it because owner set it to public
        # and user knows the uuid of object

        alert_id = request.matchdict.get("alert_id",
                                         request.GET.get("alert_id"))
        self.alert = AlertChannelActionService.by_pkey(alert_id)
        if not self.alert:
            raise HTTPNotFound()

        self.chart = DashboardChartService.by_uuid(self.alert.other_id)

        if not self.chart:
            raise HTTPNotFound()

        self.resource = ResourceService.by_resource_id(self.chart.resource_id)
        if self.resource and request.user:
            self.__acl__ = self.resource.__acl__
            permissions = ResourceService.perms_for_user(
                self.resource, request.user)
            for perm_user, perm_name in permission_to_04_acls(permissions):
                self.__acl__.append(rewrite_root_perm(perm_user, perm_name))

        if self.resource and self.resource.public:
            if not request.has_permission("view", self):
                self.used_uuid = True
            self.__acl__.append((Allow, Everyone, "view"))

        add_root_superperm(request, self)
Пример #3
0
def alerting_charts():
    """
    loop that loads existing charting alert rules and issues checks
    """
    alert_rules = AlertChannelActionService.by_type("chart")
    for rule in alert_rules:
        alert_chart.delay(rule.pkey, rule.other_id)
Пример #4
0
def dashboard_DELETE(request):
    dashboard = request.context.resource
    actions = AlertChannelActionService.by_resource_id(dashboard.resource_id)
    for action in actions:
        DBSession.delete(action)
    DBSession.delete(dashboard)
    request.session.flash("Dashboard removed")
    return True
Пример #5
0
def alert_channels_rule_DELETE(request):
    """
    Removes specific alert channel rule
    """
    user = request.user
    rule_action = AlertChannelActionService.by_owner_id_and_pkey(
        user.id, request.GET.get("pkey"))
    if rule_action:
        DBSession.delete(rule_action)
        return True
    return HTTPNotFound()
Пример #6
0
def charts_PATCH(request):
    dashboard = request.context.resource

    json_body = copy.deepcopy(request.unsafe_json_body)
    chart_config = json_body["config"]
    # for now just throw error in case something weird is found

    applications = UserService.resources_with_perms(
        request.user, ["view"], resource_types=["application"])

    # CRITICAL - this ensures our resultset is limited to only the ones
    # user has view permissions
    all_possible_app_ids = set([app.resource_id for app in applications])

    schema = ChartConfigSchema().bind(resources=all_possible_app_ids)
    schema.deserialize(chart_config)

    # some processing/normalizing for new/missing variables
    if "timeRange" not in chart_config:
        chart_config["timeRange"] = "1M"
    if "startMoment" not in chart_config:
        chart_config["startMoment"] = "now"
    if "startMomentUnit" not in chart_config:
        chart_config["startMomentUnit"] = "days"
    if "startMomentValue" not in chart_config:
        chart_config["startMomentValue"] = 0
    # ensure we don't have any leftover chart definitions present from
    # removed layout columns
    chart_ids = []
    for row in dashboard.layout_config:
        for col in row["columns"]:
            chart_ids.append(col["chartId"])
    for chart in dashboard.charts:
        if chart.uuid not in chart_ids:
            actions = AlertChannelActionService.by_other_id(chart.uuid)
            for action in actions:
                DBSession.delete(action)
            dashboard.charts.remove(chart)

    chart_config["json_config_version"] = chart.json_config_version
    # make sure we set model field as dirty
    request.context.chart.name = json_body["name"]
    request.context.chart.config = None
    request.context.chart.config = chart_config
    session = DBSession()
    mark_changed(session)
    request.session.flash("Chart saved")
    return True
Пример #7
0
def alert_channels_actions_binds_DELETE(request):
    """
    Removes alert action from users channels
    """
    user = request.user
    channel = AlertChannelService.by_owner_id_and_pkey(
        user.id, request.GET.get("channel_pkey"))

    rule_action = AlertChannelActionService.by_owner_id_and_pkey(
        user.id, request.GET.get("action_pkey"))

    if channel and rule_action:
        if channel.pkey in [c.pkey for c in rule_action.channels]:
            rule_action.channels.remove(channel)
            return rule_action.get_dict(extended_info=True)
    return HTTPUnprocessableEntity()
Пример #8
0
def alert_channels_actions_binds_POST(request):
    """
    Adds alert action to users channels
    """
    user = request.user
    json_body = request.unsafe_json_body
    channel = AlertChannelService.by_owner_id_and_pkey(
        user.id, json_body.get("channel_pkey"))

    rule_action = AlertChannelActionService.by_owner_id_and_pkey(
        user.id, json_body.get("action_pkey"))

    if channel and rule_action:
        if channel.pkey not in [c.pkey for c in rule_action.channels]:
            rule_action.channels.append(channel)
            return rule_action.get_dict(extended_info=True)
    return HTTPUnprocessableEntity()
Пример #9
0
def alert_channels_rule_PATCH(request):
    """
    Removes specific alert channel rule
    """
    user = request.user
    json_body = request.unsafe_json_body

    schema = build_rule_schema(json_body["rule"], REPORT_TYPE_MATRIX)
    try:
        schema.deserialize(json_body["rule"])
    except colander.Invalid as exc:
        return HTTPUnprocessableEntity(body=json.dumps(exc.asdict()))

    rule_action = AlertChannelActionService.by_owner_id_and_pkey(
        user.id, request.GET.get("pkey"))

    if rule_action:
        rule_action.rule = json_body["rule"]
        rule_action.resource_id = json_body["resource_id"]
        rule_action.action = json_body["action"]
        return rule_action.get_dict()
    return HTTPNotFound()
Пример #10
0
def charts_event_rules_GET(request):
    actions = AlertChannelActionService.by_other_id(request.context.chart.uuid)
    return [a.get_dict(extended_info=True) for a in actions]
Пример #11
0
def alert_chart(pkey, chart_uuid):
    start = datetime.utcnow()
    request = get_current_request()
    alert_action = AlertChannelActionService.by_pkey(pkey)
    chart = DashboardChartService.by_uuid(chart_uuid)
    chart.migrate_json_config()
    resource = chart.dashboard
    json_body = chart.config
    ids_to_override = [json_body["resource"]]
    filter_settings = build_filter_settings_from_chart_config(
        request, json_body, override_app_ids=ids_to_override
    )

    log.warning("alert_chart, resource:{}, chart:{}".format(resource, chart_uuid))

    # determine start and end date for dataset
    start_date, end_date = determine_date_boundries_json(json_body)
    if not filter_settings["start_date"]:
        filter_settings["start_date"] = start_date.replace(
            hour=0, minute=0, second=0, microsecond=0
        )

    if not filter_settings["end_date"]:
        filter_settings["end_date"] = end_date

    event_type = Event.types["chart_alert"]
    open_event = None
    latest_closed_event = None
    events_query = EventService.for_resource(
        [resource.resource_id], event_type=event_type, target_uuid=chart_uuid, limit=20
    )

    for event in events_query:
        if event.status == Event.statuses["active"] and not open_event:
            open_event = event
        if event.status == Event.statuses["closed"] and not latest_closed_event:
            latest_closed_event = event

    if latest_closed_event:
        filter_settings["start_date"] = latest_closed_event.end_date

    es_config = transform_json_to_es_config(
        request, json_body, filter_settings, ids_to_override=ids_to_override
    )

    if not es_config["index_names"]:
        return
    result = Datastores.es.search(
        body=es_config["query"], index=es_config["index_names"], doc_type="log", size=0
    )
    series, info_dict = parse_es_result(result, es_config, json_config=json_body)

    # we need to make a deepcopy since we will mutate it
    rule_config = copy.deepcopy(alert_action.rule)
    field_mappings = alert_action.config

    rule_obj = RuleService.rule_from_config(
        rule_config, field_mappings, info_dict["system_labels"]
    )
    matched_interval = None
    finished_interval = None
    for step in reversed(series):
        if rule_obj.match(step):
            log.info("matched start")
            if not matched_interval:
                matched_interval = step
                break
        else:
            finished_interval = step

    if matched_interval:
        if open_event:
            log.info("ALERT: PROGRESS: %s %s" % (event_type, resource))
            if finished_interval:
                open_event.values = copy.deepcopy(open_event.values)
                end_interval = finished_interval["key"].strftime(DATE_FORMAT)
                open_event.values["end_interval"] = end_interval
                open_event.close()
        else:
            log.warning("ALERT: OPEN: %s %s" % (event_type, resource))
            step_size = None
            parent_agg = json_body.get("parentAgg")
            if parent_agg and parent_agg["type"] == "time_histogram":
                step_size = time_deltas[parent_agg["config"]["interval"]][
                    "delta"
                ].total_seconds()
            matched_step_values = {
                "values": matched_interval,
                "labels": info_dict["system_labels"],
            }
            values_dict = {
                "matched_rule": alert_action.get_dict(),
                "matched_step_values": matched_step_values,
                "start_interval": step["key"],
                "end_interval": None,
                "resource": chart.config.get("resource"),
                "chart_name": chart.name,
                "chart_uuid": chart_uuid,
                "step_size": step_size,
                "action_name": alert_action.name,
            }
            new_event = Event(
                resource_id=resource.resource_id,
                event_type=event_type,
                status=Event.statuses["active"],
                values=values_dict,
                target_uuid=chart_uuid,
            )
            DBSession.add(new_event)
            DBSession.flush()
            new_event.send_alerts(request=request, resource=resource)
    elif open_event:
        if finished_interval:
            open_event.values = copy.deepcopy(open_event.values)
            end_interval = finished_interval["key"].strftime(DATE_FORMAT)
            open_event.values["end_interval"] = end_interval
        open_event.close()
    took = datetime.utcnow() - start
    log.warning("chart alert rule check took: {}".format(took))