Alerting: Guided legacy alerting upgrade dry-run (#80071)

This PR has two steps that together create a functional dry-run capability for the migration.

By enabling the feature flag alertingPreviewUpgrade when on legacy alerting it will:
    a. Allow all Grafana Alerting background services except for the scheduler to start (multiorg alertmanager, state manager, routes, …).
    b. Allow the UI to show Grafana Alerting pages alongside legacy ones (with appropriate in-app warnings that UA is not actually running).
    c. Show a new “Alerting Upgrade” page and register associated /api/v1/upgrade endpoints that will allow the user to upgrade their organization live without restart and present a summary of the upgrade in a table.
This commit is contained in:
Matthew Jacobson
2024-01-05 18:19:12 -05:00
committed by GitHub
parent 72182e02a4
commit aa03b8f8a7
42 changed files with 7403 additions and 169 deletions
+401 -3
View File
@@ -3190,6 +3190,221 @@
}
}
}
},
"/api/v1/upgrade/channels": {
"post": {
"produces": [
"application/json"
],
"tags": [
"upgrade"
],
"summary": "Upgrade all legacy notification channels for the current organization.",
"operationId": "RoutePostUpgradeAllChannels",
"parameters": [
{
"type": "boolean",
"default": false,
"description": "If true, legacy alert and notification channel upgrades from previous runs will be skipped. Otherwise, they will be replaced.",
"name": "SkipExisting",
"in": "query"
}
],
"responses": {
"200": {
"description": "OrgMigrationSummary",
"schema": {
"$ref": "#/definitions/OrgMigrationSummary"
}
}
}
}
},
"/api/v1/upgrade/channels/{ChannelID}": {
"post": {
"produces": [
"application/json"
],
"tags": [
"upgrade"
],
"summary": "Upgrade a single legacy notification channel for the current organization.",
"operationId": "RoutePostUpgradeChannel",
"parameters": [
{
"type": "string",
"description": "Channel ID of legacy notification channel.",
"name": "ChannelID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OrgMigrationSummary",
"schema": {
"$ref": "#/definitions/OrgMigrationSummary"
}
}
}
}
},
"/api/v1/upgrade/dashboards": {
"post": {
"produces": [
"application/json"
],
"tags": [
"upgrade"
],
"summary": "Upgrade all legacy dashboard alerts for the current organization.",
"operationId": "RoutePostUpgradeAllDashboards",
"responses": {
"200": {
"description": "OrgMigrationSummary",
"schema": {
"$ref": "#/definitions/OrgMigrationSummary"
}
}
}
}
},
"/api/v1/upgrade/dashboards/{DashboardID}": {
"post": {
"produces": [
"application/json"
],
"tags": [
"upgrade"
],
"summary": "Upgrade all legacy dashboard alerts on a dashboard for the current organization.",
"operationId": "RoutePostUpgradeDashboard",
"parameters": [
{
"type": "boolean",
"default": false,
"description": "If true, legacy alert and notification channel upgrades from previous runs will be skipped. Otherwise, they will be replaced.",
"name": "SkipExisting",
"in": "query"
},
{
"type": "string",
"description": "Dashboard ID of dashboard alert.",
"name": "DashboardID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OrgMigrationSummary",
"schema": {
"$ref": "#/definitions/OrgMigrationSummary"
}
}
}
}
},
"/api/v1/upgrade/dashboards/{DashboardID}/panels/{PanelID}": {
"post": {
"produces": [
"application/json"
],
"tags": [
"upgrade"
],
"summary": "Upgrade single legacy dashboard alert for the current organization.",
"operationId": "RoutePostUpgradeAlert",
"parameters": [
{
"type": "string",
"description": "Dashboard ID of dashboard alert.",
"name": "DashboardID",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Panel ID of dashboard alert.",
"name": "PanelID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OrgMigrationSummary",
"schema": {
"$ref": "#/definitions/OrgMigrationSummary"
}
}
}
}
},
"/api/v1/upgrade/org": {
"get": {
"produces": [
"application/json"
],
"tags": [
"upgrade"
],
"summary": "Get existing alerting upgrade for the current organization.",
"operationId": "RouteGetOrgUpgrade",
"responses": {
"200": {
"description": "OrgMigrationState",
"schema": {
"$ref": "#/definitions/OrgMigrationState"
}
}
}
},
"post": {
"produces": [
"application/json"
],
"tags": [
"upgrade"
],
"summary": "Upgrade all legacy alerts for the current organization.",
"operationId": "RoutePostUpgradeOrg",
"parameters": [
{
"type": "boolean",
"default": false,
"description": "If true, legacy alert and notification channel upgrades from previous runs will be skipped. Otherwise, they will be replaced.",
"name": "SkipExisting",
"in": "query"
}
],
"responses": {
"200": {
"description": "OrgMigrationSummary",
"schema": {
"$ref": "#/definitions/OrgMigrationSummary"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"upgrade"
],
"summary": "Delete existing alerting upgrade for the current organization.",
"operationId": "RouteDeleteOrgUpgrade",
"responses": {
"200": {
"description": "Ack",
"schema": {
"$ref": "#/definitions/Ack"
}
}
}
}
}
},
"definitions": {
@@ -3285,6 +3500,20 @@
}
}
},
"AlertPair": {
"type": "object",
"properties": {
"alertRule": {
"$ref": "#/definitions/AlertRuleUpgrade"
},
"error": {
"type": "string"
},
"legacyAlert": {
"$ref": "#/definitions/LegacyAlert"
}
}
},
"AlertQuery": {
"type": "object",
"title": "AlertQuery represents a single query associated with an alert definition.",
@@ -3469,6 +3698,23 @@
}
}
},
"AlertRuleUpgrade": {
"type": "object",
"properties": {
"sendsTo": {
"type": "array",
"items": {
"type": "string"
}
},
"title": {
"type": "string"
},
"uid": {
"type": "string"
}
}
},
"AlertingFileExport": {
"type": "object",
"title": "AlertingFileExport is the full provisioned file export.",
@@ -3750,6 +3996,20 @@
}
}
},
"ContactPair": {
"type": "object",
"properties": {
"contactPoint": {
"$ref": "#/definitions/ContactPointUpgrade"
},
"error": {
"type": "string"
},
"legacyChannel": {
"$ref": "#/definitions/LegacyChannel"
}
}
},
"ContactPointExport": {
"type": "object",
"title": "ContactPointExport is the provisioned file export of alerting.ContactPointV1.",
@@ -3769,6 +4029,20 @@
}
}
},
"ContactPointUpgrade": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"routeMatchers": {
"$ref": "#/definitions/ObjectMatchers"
},
"type": {
"type": "string"
}
}
},
"ContactPoints": {
"type": "array",
"items": {
@@ -3781,6 +4055,48 @@
"format": "uint8",
"title": "CounterResetHint contains the known information about a counter reset,"
},
"DashboardUpgrade": {
"type": "object",
"properties": {
"dashboardId": {
"type": "integer",
"format": "int64"
},
"dashboardName": {
"type": "string"
},
"dashboardUid": {
"type": "string"
},
"error": {
"type": "string"
},
"folderName": {
"type": "string"
},
"folderUid": {
"type": "string"
},
"migratedAlerts": {
"type": "array",
"items": {
"$ref": "#/definitions/AlertPair"
}
},
"newFolderName": {
"type": "string"
},
"newFolderUid": {
"type": "string"
},
"provisioned": {
"type": "boolean"
},
"warning": {
"type": "string"
}
}
},
"DataLink": {
"description": "DataLink define what",
"type": "object",
@@ -5025,6 +5341,41 @@
"$ref": "#/definitions/Label"
}
},
"LegacyAlert": {
"type": "object",
"properties": {
"dashboardId": {
"type": "integer",
"format": "int64"
},
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"panelId": {
"type": "integer",
"format": "int64"
}
}
},
"LegacyChannel": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"LinkTransformationConfig": {
"type": "object",
"properties": {
@@ -5402,6 +5753,50 @@
}
}
},
"OrgMigrationState": {
"type": "object",
"properties": {
"migratedChannels": {
"type": "array",
"items": {
"$ref": "#/definitions/ContactPair"
}
},
"migratedDashboards": {
"type": "array",
"items": {
"$ref": "#/definitions/DashboardUpgrade"
}
},
"orgId": {
"type": "integer",
"format": "int64"
}
}
},
"OrgMigrationSummary": {
"type": "object",
"properties": {
"hasErrors": {
"type": "boolean"
},
"newAlerts": {
"type": "integer",
"format": "int64"
},
"newChannels": {
"type": "integer",
"format": "int64"
},
"newDashboards": {
"type": "integer",
"format": "int64"
},
"removed": {
"type": "boolean"
}
}
},
"PagerdutyConfig": {
"type": "object",
"title": "PagerdutyConfig configures notifications via PagerDuty.",
@@ -7177,9 +7572,8 @@
}
},
"URL": {
"description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use the EscapedPath method, which preserves\nthe original encoding of Path.\n\nThe RawPath field is an optional field which is only set when the default\nencoding of Path is different from the escaped path. See the EscapedPath method\nfor more details.\n\nURL's String method uses the EscapedPath method to obtain the path.",
"type": "object",
"title": "A URL represents a parsed URL (technically, a URI reference).",
"title": "URL is a custom URL type that allows validation at configuration load time.",
"properties": {
"ForceQuery": {
"type": "boolean"
@@ -7444,6 +7838,7 @@
"$ref": "#/definitions/alertGroup"
},
"alertGroups": {
"description": "AlertGroups alert groups",
"type": "array",
"items": {
"$ref": "#/definitions/alertGroup"
@@ -7549,6 +7944,7 @@
}
},
"gettableAlert": {
"description": "GettableAlert gettable alert",
"type": "object",
"required": [
"labels",
@@ -7662,6 +8058,7 @@
"$ref": "#/definitions/gettableSilence"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"type": "array",
"items": {
"$ref": "#/definitions/gettableSilence"
@@ -7669,6 +8066,7 @@
"$ref": "#/definitions/gettableSilences"
},
"integration": {
"description": "Integration integration",
"type": "object",
"required": [
"name",
@@ -7813,7 +8211,6 @@
}
},
"postableSilence": {
"description": "PostableSilence postable silence",
"type": "object",
"required": [
"comment",
@@ -7852,6 +8249,7 @@
"$ref": "#/definitions/postableSilence"
},
"receiver": {
"description": "Receiver receiver",
"type": "object",
"required": [
"active",