Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ paths:
so partial success is visible to the caller.
Supports label overrides, drop/restore toggles (platform rules only),
and classification label updates.
When both classification and labels are set for a rule, classification
is applied first, then labels. These steps are not atomic: if the label
update fails after classification succeeded, the classification change
remains applied and the per-rule result reports failure.
requestBody:
required: true
content:
Expand Down Expand Up @@ -154,6 +158,141 @@ paths:
schema:
$ref: "#/components/schemas/ErrorResponse"

/rules/{ruleId}:
parameters:
- name: ruleId
in: path
required: true
schema:
type: string
description: Stable alert rule ID.
patch:
operationId: UpdateAlertRule
summary: Update a single alert rule
description: >
Updates one alert rule by its stable ID. Supports label overrides,
drop/restore toggles (platform rules only), and classification label
updates. Same mutation semantics as BulkUpdateAlertRules for a single ID.
When both classification and labels are set, classification is applied
first, then labels. These steps are not atomic: if the label update
fails after classification succeeded, the classification change remains
applied and the request returns an error.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateAlertRuleRequest"
responses:
"200":
description: >
Update result. On success statusCode is 204; the id may differ from
the path ruleId when labels change the stable ID.
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateAlertRuleResult"
"400":
description: >
Invalid request body, blank ruleId, or invalid update fields
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Missing or invalid authorization token
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (insufficient RBAC permissions)
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Alert rule not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"405":
description: Operation not allowed (e.g. rule is externally managed)
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"409":
description: Conflict (e.g. concurrent update)
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"413":
description: Request body exceeds the 1 MB limit
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Unexpected server error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
delete:
operationId: DeleteAlertRule
summary: Delete a single alert rule
description: >
Deletes one alert rule by its stable ID. Same mutation semantics as
BulkDeleteUserDefinedAlertRules for a single ID.
responses:
"204":
description: Alert rule deleted successfully
"400":
description: Invalid ruleId (e.g. blank after trimming)
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Missing or invalid authorization token
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (insufficient RBAC permissions)
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Alert rule not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"405":
description: Operation not allowed (e.g. platform or externally managed)
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"409":
description: Conflict (e.g. concurrent update)
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Unexpected server error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"

Comment thread
sradco marked this conversation as resolved.
components:
schemas:
AlertRuleSpec:
Expand Down Expand Up @@ -324,6 +463,32 @@ components:
classification:
$ref: "#/components/schemas/AlertRuleClassificationUpdate"

UpdateAlertRuleRequest:
type: object
description: >
Partial update for a single alert rule. At least one of labels,
alertingRuleEnabled, or classification must be set. alertingRuleEnabled
cannot be combined with labels or classification in the same request.
properties:
labels:
type: object
additionalProperties:
type: string
nullable: true
description: >
Label key/value pairs to set. A null or empty-string value removes
the label. Omitting this field leaves existing labels unchanged.
alertingRuleEnabled:
type: boolean
nullable: true
description: >
When false, drops the alert rule via an AlertRelabelConfig Drop
action — the rule no longer appears in Prometheus query results.
When true, restores a previously dropped rule.
Only supported for platform alert rules.
classification:
$ref: "#/components/schemas/AlertRuleClassificationUpdate"

UpdateAlertRuleResult:
type: object
required:
Expand Down
35 changes: 35 additions & 0 deletions docs/alert-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,41 @@ This is a cluster configuration choice and does not change the plugin API shape.

The plugin intentionally reads from only the in-cluster Alertmanager endpoints. Supporting multiple external Alertmanagers would introduce ambiguous alert state and silencing outcomes because each instance can apply different routing, inhibition, and silence configurations.

### Managing alert rules via the Management API

| Operation | Single | Bulk |
|---|---|---|
| Create | `POST /api/v1/alerting/rules` | n/a |
| Update (labels, drop/restore, classification) | `PATCH /api/v1/alerting/rules/{ruleId}` | `PATCH /api/v1/alerting/rules` |
| Delete | `DELETE /api/v1/alerting/rules/{ruleId}` | `DELETE /api/v1/alerting/rules` |

**Single update** (`PATCH /rules/{ruleId}`):
- Request body uses `UpdateAlertRuleRequest` (labels and/or classification, or
`alertingRuleEnabled` alone for drop/restore).
- Success: HTTP `200` with `UpdateAlertRuleResult` (`statusCode: 204`). The
returned `id` may differ from the path `ruleId` when labels change the stable ID.
- Failure: standard `ErrorResponse` with the corresponding HTTP status
(400/401/403/404/405/409/413/500). Errors include a message so callers can act on them.
- Non-atomic combined updates: when both `classification` and `labels` are set,
classification is applied first, then labels. If the label step fails, the
classification change may already be persisted and the request still returns
an error. Retry or inspect cluster state before re-applying classification.

**Bulk update** (`PATCH /rules`):
- Request body includes `ruleIds` (1–100) plus the same mutation fields.
- Always returns HTTP `200` with per-rule `statusCode`/`message` entries so
partial success is visible.
- Same non-atomic classification-then-labels behavior as single update; a failed
label step is reported on that rule's result while classification may remain.

**Single delete** (`DELETE /rules/{ruleId}`):
- Success: HTTP `204`.
- Failure: `ErrorResponse` with HTTP status (400/401/403/404/405/409/500).

**Bulk delete** (`DELETE /rules`):
- Request body includes `ruleIds` (1–100).
- Always returns HTTP `200` with per-rule results.

Comment thread
coderabbitai[bot] marked this conversation as resolved.
### Managing user-defined alert rules

| Rule ownership | Editable? | Classification? | Drop/Restore? |
Expand Down
24 changes: 16 additions & 8 deletions docs/alert-rule-classification.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,11 @@ APIs:
```
- `openshift_io_alert_rule_layer`: `cluster` or `namespace`
- To remove a classification override, set the field to `null` (e.g. `"openshift_io_alert_rule_layer": null`).
- Do not combine `classification` with `alertingRuleEnabled` in the same request.
- Response:
- 200 OK with a status payload (same format as other rule PATCH responses), where `status_code` is 204 on success.
- Standard error body on failure (400 validation, 404 not found, etc.)
- HTTP `200` with `UpdateAlertRuleResult` (`statusCode` is `204` on success).
- Standard `ErrorResponse` body on failure (400 validation, 403 forbidden,
404 not found, 405 not allowed for user-defined rules, 409 conflict, etc.).
- Bulk update:
- Method: `PATCH /api/v1/alerting/rules`
- Request body:
Expand All @@ -221,19 +223,25 @@ APIs:
}
```
- Response:
- 200 OK with per-rule results (same format as other bulk rule PATCH responses). Clients should handle partial failures.
- HTTP `200` with per-rule results (same `UpdateAlertRuleResult` shape).
Clients should handle partial failures via per-rule `statusCode`/`message`.

Direct K8s (supported for power users/GitOps):
- For platform rules: create or update the `AlertRelabelConfig` CR in `openshift-monitoring`
with the appropriate relabel configs (respect `resourceVersion` for optimistic concurrency).
- UI should check update permissions with SelfSubjectAccessReview before showing an editor.

Notes:
- These endpoints are intended for updating **classification only** (component/layer overrides),
with permissions enforced based on the rule's ownership (platform, user workload, operator-managed,
GitOps-managed).
- To update other rule fields (expr/labels/annotations/etc.), use `PATCH /api/v1/alerting/rules/{ruleId}`.
Clients that need to update both should issue two requests. The combined operation is not atomic.
- Classification overrides for platform rules are applied via AlertRelabelConfig.
User-defined rules reject ARC-based classification updates (`405`).
- To update other rule fields (labels/etc.), use the same
`PATCH /api/v1/alerting/rules/{ruleId}` endpoint with a `labels` body (or the
bulk `PATCH /rules` variant). `alertingRuleEnabled` cannot be combined with
`labels` or `classification` in one request; issue separate calls when needed.
- When a request includes both `classification` and `labels`, classification is
applied first, then labels. The two steps are not atomic: if labels fail after
classification succeeded, the classification override may already be persisted
while the API still returns an error (or a per-rule failure in bulk).

## Security Notes
- Classification overrides are stored in AlertRelabelConfig CRs in `openshift-monitoring`,
Expand Down
Loading