Skip to content
Open
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
192 changes: 192 additions & 0 deletions api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ info:
servers:
- url: /api/v1/alerting

security:
- bearerAuth: []

paths:
/rules:
patch:
Expand Down Expand Up @@ -158,6 +161,79 @@ paths:
schema:
$ref: "#/components/schemas/ErrorResponse"

/rules/preview:
post:
operationId: PreviewAlertRule
summary: Preview a single alert rule create or update
description: >
Calculates the changes required to create or update one alert rule
without modifying cluster resources. Provide alertingRule (and optional
prometheusRule) to preview creation; provide ruleId plus at least one
update field to preview an update. Works for externally managed
resources — the response indicates whether the API can persist the
change (writable) and lists the required changes.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/PreviewAlertRuleRequest"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
responses:
"200":
description: Preview of the required changes
content:
application/json:
schema:
$ref: "#/components/schemas/PreviewAlertRuleResponse"
"400":
description: Invalid request
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: Resource not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"405":
description: Operation not allowed for this rule type
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"409":
description: Conflict (e.g. duplicate rule ID)
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"

/rules/{ruleId}:
parameters:
- name: ruleId
Expand Down Expand Up @@ -519,6 +595,113 @@ components:
$ref: "#/components/schemas/UpdateAlertRuleResult"
description: Per-rule update results.

PreviewAlertRuleRequest:
type: object
description: >
Preview a single alert rule create or update. For create preview,
set alertingRule and optionally prometheusRule (omit prometheusRule for
platform rules). For update preview, set ruleId and at least one of
labels, alertingRuleEnabled, or classification.
properties:
ruleId:
type: string
description: Stable alert rule ID for update preview.
alertingRule:
$ref: "#/components/schemas/AlertRuleSpec"
prometheusRule:
$ref: "#/components/schemas/PrometheusRuleTarget"
labels:
type: object
additionalProperties:
type: string
nullable: true
description: Label overrides for update preview.
alertingRuleEnabled:
type: boolean
nullable: true
description: Drop/restore toggle for update preview (platform rules only).
classification:
$ref: "#/components/schemas/AlertRuleClassificationUpdate"

PreviewAlertRuleResponse:
type: object
required:
- writable
- resources
- desiredRule
properties:
writable:
type: boolean
description: Whether the Alerts Management API can persist this change.
managedBy:
type: string
enum: [gitops, operator]
description: External management source when the target is not writable.
resources:
type: array
items:
$ref: "#/components/schemas/PreviewResourceChange"
description: >
Kubernetes resources that would be created or modified by this
operation. A single alert operation may affect multiple resources.
desiredRule:
$ref: "#/components/schemas/AlertRuleSpec"
description: >
Effective resulting alert rule after applying the requested change.
Suitable for display without reconstructing from per-resource changes.

PreviewResourceChange:
type: object
required:
- resource
- changes
properties:
resource:
$ref: "#/components/schemas/PreviewTargetResource"
changes:
type: array
items:
$ref: "#/components/schemas/RuleChange"
desiredObject:
type: object
description: >
Complete resulting Kubernetes object for this resource entry.
Omitted when the resource would be deleted.

PreviewTargetResource:
type: object
required:
- apiVersion
- kind
- name
properties:
apiVersion:
type: string
kind:
type: string
namespace:
type: string
name:
type: string

RuleChange:
type: object
required:
- field
- operation
properties:
field:
type: string
description: >
Semantic alert-rule field path (e.g. severity, labels.severity, for, rule).
operation:
type: string
enum: [add, replace, remove]
currentValue:
description: Value before the change, for replace or remove operations.
newValue:
description: Value after the change, for add or replace operations.

ErrorResponse:
type: object
required:
Expand All @@ -527,3 +710,12 @@ components:
error:
type: string
description: Human-readable error message.

securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: >
OpenShift user bearer token in the Authorization header
(forwarded by the console bridge).
11 changes: 11 additions & 0 deletions docs/alert-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,20 @@ The plugin intentionally reads from only the in-cluster Alertmanager endpoints.
| Operation | Single | Bulk |
|---|---|---|
| Create | `POST /api/v1/alerting/rules` | n/a |
| Preview | `POST /api/v1/alerting/rules/preview` | 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` |

**Preview** (`POST /rules/preview`):
- Dry-run create or update without persisting cluster changes.
- Create preview: `alertingRule` plus optional `prometheusRule`.
- Update preview: `ruleId` plus at least one of `labels`,
`alertingRuleEnabled`, or `classification`.
- Response includes `writable`, optional `managedBy`, `resources[]`
(per-resource `changes[]` and `desiredObject`), and `desiredRule`.
- Externally managed rules return `writable: false` with `managedBy` set
so UIs can show the plan without implying the API will apply it.

**Single update** (`PATCH /rules/{ruleId}`):
- Request body uses `UpdateAlertRuleRequest` (labels and/or classification, or
`alertingRuleEnabled` alone for drop/restore).
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/evanphx/json-patch v4.12.0+incompatible
github.com/gorilla/handlers v1.5.2
github.com/gorilla/mux v1.8.1
github.com/oapi-codegen/runtime v1.7.0
github.com/openshift/api v0.0.0-20251122153900-88cca31a44c9
github.com/openshift/client-go v0.0.0-20251123231646-4685125c2287
github.com/openshift/library-go v0.0.0-20240905123346-5bdbfe35a6f5
Expand All @@ -23,6 +24,7 @@ require (
)

require (
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
Expand Down Expand Up @@ -70,7 +72,7 @@ require (
golang.org/x/sys v0.46.0 // indirect
golang.org/x/term v0.44.0 // indirect
golang.org/x/text v0.38.0 // indirect
golang.org/x/time v0.13.0 // indirect
golang.org/x/time v0.14.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
Expand Down
14 changes: 12 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDo
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI=
github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 h1:XkkQbfMyuH2jTSjQjSoihryI8GINRcs4xp8lNawg0FI=
github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0=
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/aws/aws-sdk-go-v2 v1.39.6 h1:2JrPCVgWJm7bm83BDwY5z8ietmeJUbh3O2ACnn+Xsqk=
github.com/aws/aws-sdk-go-v2 v1.39.6/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE=
github.com/aws/aws-sdk-go-v2/config v1.31.17 h1:QFl8lL6RgakNK86vusim14P2k8BFSxjvUkcWLDjgz9Y=
Expand Down Expand Up @@ -44,6 +47,7 @@ github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -129,6 +133,7 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
Expand All @@ -149,6 +154,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oapi-codegen/nullable v1.1.0 h1:eAh8JVc5430VtYVnq00Hrbpag9PFRGWLjxR1/3KntMs=
github.com/oapi-codegen/nullable v1.1.0/go.mod h1:KUZ3vUzkmEKY90ksAmit2+5juDIhIZhfDl+0PwOQlFY=
github.com/oapi-codegen/runtime v1.7.0 h1:t7358VYPvNbWJ9gdAkIK/smVeHpBf6yp8VTsaZsb/7k=
github.com/oapi-codegen/runtime v1.7.0/go.mod h1:GwV7hC2hviaMzj+ITfHVRESK5J2W/GefVwIND/bMGvU=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
Expand Down Expand Up @@ -195,6 +204,7 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
Expand Down Expand Up @@ -258,8 +268,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
Expand Down
Loading